| /* |
| * 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 <SkAndroidFrameworkUtils.h> |
| #include <SkBlendMode.h> |
| #include <SkCanvas.h> |
| #include <SkClipOp.h> |
| #include <SkImage.h> |
| #include <SkPaint.h> |
| #include <SkPath.h> |
| #include <SkPicture.h> |
| #include <SkRRect.h> |
| #include <SkRect.h> |
| #include <SkRegion.h> |
| #include <SkRuntimeEffect.h> |
| #include <SkSamplingOptions.h> |
| #include <SkVertices.h> |
| |
| #include <log/log.h> |
| |
| #include "hwui/Bitmap.h" |
| #include "CanvasProperty.h" |
| #include "CanvasOpTypes.h" |
| #include "Layer.h" |
| #include "Points.h" |
| #include "RenderNode.h" |
| |
| #include <experimental/type_traits> |
| #include <utility> |
| |
| namespace android::uirenderer { |
| |
| template <CanvasOpType T> |
| struct CanvasOp; |
| |
| struct CanvasOpTraits { |
| CanvasOpTraits() = delete; |
| |
| template<class T> |
| using draw_t = decltype(std::integral_constant<void (T::*)(SkCanvas*) const, &T::draw>{}); |
| |
| template <class T> |
| static constexpr bool can_draw = std::experimental::is_detected_v<draw_t, T>; |
| }; |
| |
| #define ASSERT_DRAWABLE() private: constexpr void _check_drawable() \ |
| { static_assert(CanvasOpTraits::can_draw<std::decay_t<decltype(*this)>>); } |
| |
| // ---------------------------------------------- |
| // State Ops |
| // --------------------------------------------- |
| |
| template <> |
| struct CanvasOp<CanvasOpType::Save> { |
| void draw(SkCanvas* canvas) const { canvas->save(); } |
| ASSERT_DRAWABLE() |
| }; |
| |
| template <> |
| struct CanvasOp<CanvasOpType::SaveLayer> { |
| SkCanvas::SaveLayerRec saveLayerRec; |
| void draw(SkCanvas* canvas) const { canvas->saveLayer(saveLayerRec); } |
| ASSERT_DRAWABLE() |
| }; |
| |
| template <> |
| struct CanvasOp<CanvasOpType::SaveBehind> { |
| SkRect bounds; |
| void draw(SkCanvas* canvas) const { SkAndroidFrameworkUtils::SaveBehind(canvas, &bounds); } |
| ASSERT_DRAWABLE() |
| }; |
| |
| template <> |
| struct CanvasOp<CanvasOpType::Restore> { |
| void draw(SkCanvas* canvas) const { canvas->restore(); } |
| ASSERT_DRAWABLE() |
| }; |
| |
| template <> |
| struct CanvasOp<CanvasOpType::BeginZ> { |
| }; |
| template <> |
| struct CanvasOp<CanvasOpType::EndZ> {}; |
| |
| // ---------------------------------------------- |
| // Clip Ops |
| // --------------------------------------------- |
| |
| template <> |
| struct CanvasOp<CanvasOpType::ClipRect> { |
| SkRect rect; |
| SkClipOp clipOp; |
| void draw(SkCanvas* canvas) const { canvas->clipRect(rect, clipOp); } |
| ASSERT_DRAWABLE() |
| }; |
| |
| template <> |
| struct CanvasOp<CanvasOpType::ClipPath> { |
| SkPath path; |
| SkClipOp op; |
| void draw(SkCanvas* canvas) const { canvas->clipPath(path, op, true); } |
| ASSERT_DRAWABLE() |
| }; |
| |
| // ---------------------------------------------- |
| // Drawing Ops |
| // --------------------------------------------- |
| |
| template<> |
| struct CanvasOp<CanvasOpType::DrawRoundRectProperty> { |
| sp<uirenderer::CanvasPropertyPrimitive> left; |
| sp<uirenderer::CanvasPropertyPrimitive> top; |
| sp<uirenderer::CanvasPropertyPrimitive> right; |
| sp<uirenderer::CanvasPropertyPrimitive> bottom; |
| sp<uirenderer::CanvasPropertyPrimitive> rx; |
| sp<uirenderer::CanvasPropertyPrimitive> ry; |
| sp<uirenderer::CanvasPropertyPaint> 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<CanvasOpType::DrawCircleProperty> { |
| sp<uirenderer::CanvasPropertyPrimitive> x; |
| sp<uirenderer::CanvasPropertyPrimitive> y; |
| sp<uirenderer::CanvasPropertyPrimitive> radius; |
| sp<uirenderer::CanvasPropertyPaint> paint; |
| |
| void draw(SkCanvas* canvas) const { |
| canvas->drawCircle(x->value, y->value, radius->value, paint->value); |
| } |
| ASSERT_DRAWABLE() |
| }; |
| |
| template <> |
| struct CanvasOp<CanvasOpType::DrawRippleDrawable> { |
| skiapipeline::RippleDrawableParams params; |
| |
| void draw(SkCanvas* canvas) const { |
| skiapipeline::AnimatedRippleDrawable::draw(canvas, params); |
| } |
| ASSERT_DRAWABLE() |
| }; |
| |
| template <> |
| struct CanvasOp<CanvasOpType::DrawColor> { |
| SkColor4f color; |
| SkBlendMode mode; |
| void draw(SkCanvas* canvas) const { canvas->drawColor(color, mode); } |
| ASSERT_DRAWABLE() |
| }; |
| |
| template <> |
| struct CanvasOp<CanvasOpType::DrawPaint> { |
| SkPaint paint; |
| void draw(SkCanvas* canvas) const { canvas->drawPaint(paint); } |
| ASSERT_DRAWABLE() |
| }; |
| |
| template <> |
| struct CanvasOp<CanvasOpType::DrawPoint> { |
| float x; |
| float y; |
| SkPaint paint; |
| void draw(SkCanvas* canvas) const { canvas->drawPoint(x, y, paint); } |
| ASSERT_DRAWABLE() |
| }; |
| |
| template <> |
| struct CanvasOp<CanvasOpType::DrawPoints> { |
| size_t count; |
| SkPaint paint; |
| sk_sp<Points> points; |
| void draw(SkCanvas* canvas) const { |
| canvas->drawPoints( |
| SkCanvas::kPoints_PointMode, |
| count, |
| points->data(), |
| paint |
| ); |
| } |
| ASSERT_DRAWABLE() |
| }; |
| |
| template <> |
| struct CanvasOp<CanvasOpType::DrawRect> { |
| SkRect rect; |
| SkPaint paint; |
| void draw(SkCanvas* canvas) const { canvas->drawRect(rect, paint); } |
| ASSERT_DRAWABLE() |
| }; |
| |
| template <> |
| struct CanvasOp<CanvasOpType::DrawRegion> { |
| SkRegion region; |
| SkPaint paint; |
| void draw(SkCanvas* canvas) const { canvas->drawRegion(region, paint); } |
| ASSERT_DRAWABLE() |
| }; |
| |
| template<> |
| struct CanvasOp<CanvasOpType::DrawRoundRect> { |
| SkRect rect; |
| SkScalar rx; |
| SkScalar ry; |
| SkPaint paint; |
| void draw(SkCanvas* canvas) const { |
| canvas->drawRoundRect(rect, rx, ry, paint); |
| } |
| ASSERT_DRAWABLE() |
| }; |
| |
| template<> |
| struct CanvasOp<CanvasOpType::DrawDoubleRoundRect> { |
| SkRRect outer; |
| SkRRect inner; |
| SkPaint paint; |
| void draw(SkCanvas* canvas) const { |
| canvas->drawDRRect(outer, inner, paint); |
| } |
| ASSERT_DRAWABLE() |
| }; |
| |
| template<> |
| struct CanvasOp<CanvasOpType::DrawCircle> { |
| SkScalar cx; |
| SkScalar cy; |
| SkScalar radius; |
| SkPaint paint; |
| void draw(SkCanvas* canvas) const { |
| canvas->drawCircle(cx, cy, radius, paint); |
| } |
| ASSERT_DRAWABLE() |
| }; |
| |
| template<> |
| struct CanvasOp<CanvasOpType::DrawOval> { |
| SkRect oval; |
| SkPaint paint; |
| void draw(SkCanvas* canvas) const { |
| canvas->drawOval(oval, paint); |
| } |
| ASSERT_DRAWABLE() |
| }; |
| |
| template<> |
| struct CanvasOp<CanvasOpType::DrawArc> { |
| 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<CanvasOpType::DrawPath> { |
| SkPath path; |
| SkPaint paint; |
| |
| void draw(SkCanvas* canvas) const { canvas->drawPath(path, paint); } |
| ASSERT_DRAWABLE() |
| }; |
| |
| template<> |
| struct CanvasOp<CanvasOpType::DrawLine> { |
| 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<CanvasOpType::DrawLines> { |
| size_t count; |
| SkPaint paint; |
| sk_sp<Points> points; |
| void draw(SkCanvas* canvas) const { |
| canvas->drawPoints( |
| SkCanvas::kLines_PointMode, |
| count, |
| points->data(), |
| paint |
| ); |
| } |
| ASSERT_DRAWABLE() |
| }; |
| |
| template<> |
| struct CanvasOp<CanvasOpType::DrawVertices> { |
| sk_sp<SkVertices> vertices; |
| SkBlendMode mode; |
| SkPaint paint; |
| void draw(SkCanvas* canvas) const { |
| canvas->drawVertices(vertices, mode, paint); |
| } |
| ASSERT_DRAWABLE() |
| }; |
| |
| template<> |
| struct CanvasOp<CanvasOpType::DrawImage> { |
| |
| CanvasOp( |
| const sk_sp<Bitmap>& 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> bitmap; |
| sk_sp<SkImage> image; |
| |
| void draw(SkCanvas* canvas) const { |
| canvas->drawImage(image, left, top, SkSamplingOptions(filter), &paint); |
| } |
| ASSERT_DRAWABLE() |
| }; |
| |
| template<> |
| struct CanvasOp<CanvasOpType::DrawImageRect> { |
| |
| CanvasOp( |
| const sk_sp<Bitmap>& 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> bitmap; |
| sk_sp<SkImage> image; |
| |
| void draw(SkCanvas* canvas) const { |
| canvas->drawImageRect(image, |
| src, |
| dst, |
| SkSamplingOptions(filter), |
| &paint, |
| SkCanvas::kFast_SrcRectConstraint |
| ); |
| } |
| ASSERT_DRAWABLE() |
| }; |
| |
| template<> |
| struct CanvasOp<CanvasOpType::DrawImageLattice> { |
| |
| CanvasOp( |
| const sk_sp<Bitmap>& 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> bitmap; |
| const sk_sp<SkImage> image; |
| |
| SkPaint paint; |
| void draw(SkCanvas* canvas) const { |
| canvas->drawImageLattice(image.get(), lattice, dst, filter, &paint); |
| } |
| ASSERT_DRAWABLE() |
| }; |
| |
| template<> |
| struct CanvasOp<CanvasOpType::DrawPicture> { |
| sk_sp<SkPicture> picture; |
| void draw(SkCanvas* canvas) const { |
| picture->playback(canvas); |
| } |
| }; |
| |
| template<> |
| struct CanvasOp<CanvasOpType::DrawLayer> { |
| sp<Layer> layer; |
| }; |
| |
| template<> |
| struct CanvasOp<CanvasOpType::DrawRenderNode> { |
| sp<RenderNode> renderNode; |
| }; |
| |
| // cleanup our macros |
| #undef ASSERT_DRAWABLE |
| |
| } // namespace android::uirenderer |