/* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "hwui/Bitmap.h" #include "CanvasProperty.h" #include "CanvasOpTypes.h" #include "Layer.h" #include "Points.h" #include "RenderNode.h" #include #include namespace android::uirenderer { template struct CanvasOp; struct CanvasOpTraits { CanvasOpTraits() = delete; template using draw_t = decltype(std::integral_constant{}); template static constexpr bool can_draw = std::experimental::is_detected_v; }; #define ASSERT_DRAWABLE() private: constexpr void _check_drawable() \ { static_assert(CanvasOpTraits::can_draw>); } // ---------------------------------------------- // State Ops // --------------------------------------------- template <> struct CanvasOp { void draw(SkCanvas* canvas) const { canvas->save(); } ASSERT_DRAWABLE() }; template <> struct CanvasOp { SkCanvas::SaveLayerRec saveLayerRec; void draw(SkCanvas* canvas) const { canvas->saveLayer(saveLayerRec); } ASSERT_DRAWABLE() }; template <> struct CanvasOp { SkRect bounds; void draw(SkCanvas* canvas) const { SkAndroidFrameworkUtils::SaveBehind(canvas, &bounds); } ASSERT_DRAWABLE() }; template <> struct CanvasOp { void draw(SkCanvas* canvas) const { canvas->restore(); } ASSERT_DRAWABLE() }; template <> struct CanvasOp { }; template <> struct CanvasOp {}; // ---------------------------------------------- // Clip Ops // --------------------------------------------- template <> struct CanvasOp { SkRect rect; SkClipOp clipOp; void draw(SkCanvas* canvas) const { canvas->clipRect(rect, clipOp); } ASSERT_DRAWABLE() }; template <> struct CanvasOp { SkPath path; SkClipOp op; void draw(SkCanvas* canvas) const { canvas->clipPath(path, op, true); } ASSERT_DRAWABLE() }; // ---------------------------------------------- // Drawing Ops // --------------------------------------------- template<> struct CanvasOp { sp left; sp top; sp right; sp bottom; sp rx; sp ry; sp paint; void draw(SkCanvas* canvas) const { SkRect rect = SkRect::MakeLTRB(left->value, top->value, right->value, bottom->value); canvas->drawRoundRect(rect, rx->value, ry->value, paint->value); } ASSERT_DRAWABLE() }; template<> struct CanvasOp { sp x; sp y; sp radius; sp paint; void draw(SkCanvas* canvas) const { canvas->drawCircle(x->value, y->value, radius->value, paint->value); } ASSERT_DRAWABLE() }; template <> struct CanvasOp { skiapipeline::RippleDrawableParams params; void draw(SkCanvas* canvas) const { skiapipeline::AnimatedRippleDrawable::draw(canvas, params); } ASSERT_DRAWABLE() }; template <> struct CanvasOp { SkColor4f color; SkBlendMode mode; void draw(SkCanvas* canvas) const { canvas->drawColor(color, mode); } ASSERT_DRAWABLE() }; template <> struct CanvasOp { SkPaint paint; void draw(SkCanvas* canvas) const { canvas->drawPaint(paint); } ASSERT_DRAWABLE() }; template <> struct CanvasOp { float x; float y; SkPaint paint; void draw(SkCanvas* canvas) const { canvas->drawPoint(x, y, paint); } ASSERT_DRAWABLE() }; template <> struct CanvasOp { size_t count; SkPaint paint; sk_sp points; void draw(SkCanvas* canvas) const { canvas->drawPoints( SkCanvas::kPoints_PointMode, count, points->data(), paint ); } ASSERT_DRAWABLE() }; template <> struct CanvasOp { SkRect rect; SkPaint paint; void draw(SkCanvas* canvas) const { canvas->drawRect(rect, paint); } ASSERT_DRAWABLE() }; template <> struct CanvasOp { SkRegion region; SkPaint paint; void draw(SkCanvas* canvas) const { canvas->drawRegion(region, paint); } ASSERT_DRAWABLE() }; template<> struct CanvasOp { SkRect rect; SkScalar rx; SkScalar ry; SkPaint paint; void draw(SkCanvas* canvas) const { canvas->drawRoundRect(rect, rx, ry, paint); } ASSERT_DRAWABLE() }; template<> struct CanvasOp { SkRRect outer; SkRRect inner; SkPaint paint; void draw(SkCanvas* canvas) const { canvas->drawDRRect(outer, inner, paint); } ASSERT_DRAWABLE() }; template<> struct CanvasOp { SkScalar cx; SkScalar cy; SkScalar radius; SkPaint paint; void draw(SkCanvas* canvas) const { canvas->drawCircle(cx, cy, radius, paint); } ASSERT_DRAWABLE() }; template<> struct CanvasOp { SkRect oval; SkPaint paint; void draw(SkCanvas* canvas) const { canvas->drawOval(oval, paint); } ASSERT_DRAWABLE() }; template<> struct CanvasOp { SkRect oval; SkScalar startAngle; SkScalar sweepAngle; bool useCenter; SkPaint paint; void draw(SkCanvas* canvas) const { canvas->drawArc(oval, startAngle, sweepAngle, useCenter, paint); } ASSERT_DRAWABLE() }; template<> struct CanvasOp { SkPath path; SkPaint paint; void draw(SkCanvas* canvas) const { canvas->drawPath(path, paint); } ASSERT_DRAWABLE() }; template<> struct CanvasOp { float startX; float startY; float endX; float endY; SkPaint paint; void draw(SkCanvas* canvas) const { canvas->drawLine(startX, startY, endX, endY, paint); } ASSERT_DRAWABLE() }; template<> struct CanvasOp { size_t count; SkPaint paint; sk_sp points; void draw(SkCanvas* canvas) const { canvas->drawPoints( SkCanvas::kLines_PointMode, count, points->data(), paint ); } ASSERT_DRAWABLE() }; template<> struct CanvasOp { sk_sp vertices; SkBlendMode mode; SkPaint paint; void draw(SkCanvas* canvas) const { canvas->drawVertices(vertices, mode, paint); } ASSERT_DRAWABLE() }; template<> struct CanvasOp { CanvasOp( const sk_sp& bitmap, float left, float top, SkFilterMode filter, SkPaint paint ) : left(left), top(top), filter(filter), paint(std::move(paint)), bitmap(bitmap), image(bitmap->makeImage()) { } float left; float top; SkFilterMode filter; SkPaint paint; sk_sp bitmap; sk_sp image; void draw(SkCanvas* canvas) const { canvas->drawImage(image, left, top, SkSamplingOptions(filter), &paint); } ASSERT_DRAWABLE() }; template<> struct CanvasOp { CanvasOp( const sk_sp& bitmap, SkRect src, SkRect dst, SkFilterMode filter, SkPaint paint ) : src(src), dst(dst), filter(filter), paint(std::move(paint)), bitmap(bitmap), image(bitmap->makeImage()) { } SkRect src; SkRect dst; SkFilterMode filter; SkPaint paint; sk_sp bitmap; sk_sp image; void draw(SkCanvas* canvas) const { canvas->drawImageRect(image, src, dst, SkSamplingOptions(filter), &paint, SkCanvas::kFast_SrcRectConstraint ); } ASSERT_DRAWABLE() }; template<> struct CanvasOp { CanvasOp( const sk_sp& bitmap, SkRect dst, SkCanvas::Lattice lattice, SkFilterMode filter, SkPaint paint ): dst(dst), lattice(lattice), filter(filter), bitmap(bitmap), image(bitmap->makeImage()), paint(std::move(paint)) {} SkRect dst; SkCanvas::Lattice lattice; SkFilterMode filter; const sk_sp bitmap; const sk_sp image; SkPaint paint; void draw(SkCanvas* canvas) const { canvas->drawImageLattice(image.get(), lattice, dst, filter, &paint); } ASSERT_DRAWABLE() }; template<> struct CanvasOp { sk_sp picture; void draw(SkCanvas* canvas) const { picture->playback(canvas); } }; template<> struct CanvasOp { sp layer; }; template<> struct CanvasOp { sp renderNode; }; // cleanup our macros #undef ASSERT_DRAWABLE } // namespace android::uirenderer