|  | /* | 
|  | * Copyright (C) 2016 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 "CanvasProperty.h" | 
|  | #ifdef __ANDROID__ // Layoutlib does not support hardware acceleration | 
|  | #include "DeferredLayerUpdater.h" | 
|  | #endif | 
|  | #include "RenderNode.h" | 
|  | #include "VectorDrawable.h" | 
|  | #include "hwui/Canvas.h" | 
|  | #include "hwui/Paint.h" | 
|  |  | 
|  | #include <SkCanvas.h> | 
|  | #include "src/core/SkArenaAlloc.h" | 
|  |  | 
|  | #include <cassert> | 
|  | #include <optional> | 
|  |  | 
|  | namespace android { | 
|  |  | 
|  | // Holds an SkCanvas reference plus additional native data. | 
|  | class SkiaCanvas : public Canvas { | 
|  | public: | 
|  | explicit SkiaCanvas(const SkBitmap& bitmap); | 
|  |  | 
|  | /** | 
|  | *  Create a new SkiaCanvas. | 
|  | * | 
|  | *  @param canvas SkCanvas to handle calls made to this SkiaCanvas. Must | 
|  | *      not be NULL. This constructor does not take ownership, so the caller | 
|  | *      must guarantee that it remains valid while the SkiaCanvas is valid. | 
|  | */ | 
|  | explicit SkiaCanvas(SkCanvas* canvas); | 
|  |  | 
|  | virtual ~SkiaCanvas(); | 
|  |  | 
|  | virtual void resetRecording(int width, int height, | 
|  | uirenderer::RenderNode* renderNode) override { | 
|  | LOG_ALWAYS_FATAL("SkiaCanvas cannot be reset as a recording canvas"); | 
|  | } | 
|  |  | 
|  | virtual uirenderer::DisplayList* finishRecording() override { | 
|  | LOG_ALWAYS_FATAL("SkiaCanvas does not produce a DisplayList"); | 
|  | return nullptr; | 
|  | } | 
|  | virtual void enableZ(bool enableZ) override { | 
|  | LOG_ALWAYS_FATAL("SkiaCanvas does not support enableZ"); | 
|  | } | 
|  |  | 
|  | virtual void setBitmap(const SkBitmap& bitmap) override; | 
|  |  | 
|  | virtual bool isOpaque() override; | 
|  | virtual int width() override; | 
|  | virtual int height() override; | 
|  |  | 
|  | virtual int getSaveCount() const override; | 
|  | virtual int save(SaveFlags::Flags flags) override; | 
|  | virtual void restore() override; | 
|  | virtual void restoreToCount(int saveCount) override; | 
|  | virtual void restoreUnclippedLayer(int saveCount, const SkPaint& paint) override; | 
|  |  | 
|  | virtual int saveLayer(float left, float top, float right, float bottom, const SkPaint* paint, | 
|  | SaveFlags::Flags flags) override; | 
|  | virtual int saveLayerAlpha(float left, float top, float right, float bottom, int alpha, | 
|  | SaveFlags::Flags flags) override; | 
|  | virtual int saveUnclippedLayer(int left, int top, int right, int bottom) override; | 
|  |  | 
|  | virtual void getMatrix(SkMatrix* outMatrix) const override; | 
|  | virtual void setMatrix(const SkMatrix& matrix) override; | 
|  | virtual void concat(const SkMatrix& matrix) override; | 
|  | virtual void rotate(float degrees) override; | 
|  | virtual void scale(float sx, float sy) override; | 
|  | virtual void skew(float sx, float sy) override; | 
|  | virtual void translate(float dx, float dy) override; | 
|  |  | 
|  | virtual bool getClipBounds(SkRect* outRect) const override; | 
|  | virtual bool quickRejectRect(float left, float top, float right, float bottom) const override; | 
|  | virtual bool quickRejectPath(const SkPath& path) const override; | 
|  | virtual bool clipRect(float left, float top, float right, float bottom, SkClipOp op) override; | 
|  | virtual bool clipPath(const SkPath* path, SkClipOp op) override; | 
|  |  | 
|  | virtual PaintFilter* getPaintFilter() override; | 
|  | virtual void setPaintFilter(sk_sp<PaintFilter> paintFilter) override; | 
|  |  | 
|  | virtual SkCanvasState* captureCanvasState() const override; | 
|  |  | 
|  | virtual void drawColor(int color, SkBlendMode mode) override; | 
|  | virtual void drawPaint(const SkPaint& paint) override; | 
|  |  | 
|  | virtual void drawPoint(float x, float y, const Paint& paint) override; | 
|  | virtual void drawPoints(const float* points, int count, const Paint& paint) override; | 
|  | virtual void drawLine(float startX, float startY, float stopX, float stopY, | 
|  | const Paint& paint) override; | 
|  | virtual void drawLines(const float* points, int count, const Paint& paint) override; | 
|  | virtual void drawRect(float left, float top, float right, float bottom, | 
|  | const Paint& paint) override; | 
|  | virtual void drawRegion(const SkRegion& region, const Paint& paint) override; | 
|  | virtual void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, | 
|  | const Paint& paint) override; | 
|  |  | 
|  | virtual void drawDoubleRoundRect(const SkRRect& outer, const SkRRect& inner, | 
|  | const Paint& paint) override; | 
|  |  | 
|  | virtual void drawCircle(float x, float y, float radius, const Paint& paint) override; | 
|  | virtual void drawOval(float left, float top, float right, float bottom, | 
|  | const Paint& paint) override; | 
|  | virtual void drawArc(float left, float top, float right, float bottom, float startAngle, | 
|  | float sweepAngle, bool useCenter, const Paint& paint) override; | 
|  | virtual void drawPath(const SkPath& path, const Paint& paint) override; | 
|  | virtual void drawVertices(const SkVertices*, SkBlendMode, const Paint& paint) override; | 
|  |  | 
|  | virtual void drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) override; | 
|  | virtual void drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const Paint* paint) override; | 
|  | virtual void drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight, | 
|  | float srcBottom, float dstLeft, float dstTop, float dstRight, | 
|  | float dstBottom, const Paint* paint) override; | 
|  | virtual void drawBitmapMesh(Bitmap& bitmap, int meshWidth, int meshHeight, | 
|  | const float* vertices, const int* colors, | 
|  | const Paint* paint) override; | 
|  | virtual void drawNinePatch(Bitmap& bitmap, const android::Res_png_9patch& chunk, float dstLeft, | 
|  | float dstTop, float dstRight, float dstBottom, | 
|  | const Paint* paint) override; | 
|  | virtual double drawAnimatedImage(AnimatedImageDrawable* imgDrawable) override; | 
|  |  | 
|  | virtual void drawVectorDrawable(VectorDrawableRoot* vectorDrawable) override; | 
|  |  | 
|  | virtual void drawRoundRect(uirenderer::CanvasPropertyPrimitive* left, | 
|  | uirenderer::CanvasPropertyPrimitive* top, | 
|  | uirenderer::CanvasPropertyPrimitive* right, | 
|  | uirenderer::CanvasPropertyPrimitive* bottom, | 
|  | uirenderer::CanvasPropertyPrimitive* rx, | 
|  | uirenderer::CanvasPropertyPrimitive* ry, | 
|  | uirenderer::CanvasPropertyPaint* paint) override; | 
|  | virtual void drawCircle(uirenderer::CanvasPropertyPrimitive* x, | 
|  | uirenderer::CanvasPropertyPrimitive* y, | 
|  | uirenderer::CanvasPropertyPrimitive* radius, | 
|  | uirenderer::CanvasPropertyPaint* paint) override; | 
|  |  | 
|  | virtual void drawLayer(uirenderer::DeferredLayerUpdater* layerHandle) override; | 
|  | virtual void drawRenderNode(uirenderer::RenderNode* renderNode) override; | 
|  | virtual void drawPicture(const SkPicture& picture) override; | 
|  |  | 
|  | protected: | 
|  | SkiaCanvas(); | 
|  | SkCanvas* asSkCanvas() { return mCanvas; } | 
|  | void reset(SkCanvas* skiaCanvas); | 
|  | void drawDrawable(SkDrawable* drawable) { mCanvas->drawDrawable(drawable); } | 
|  |  | 
|  | virtual void drawGlyphs(ReadGlyphFunc glyphFunc, int count, const Paint& paint, float x, | 
|  | float y, float totalAdvance) override; | 
|  | virtual void drawLayoutOnPath(const minikin::Layout& layout, float hOffset, float vOffset, | 
|  | const Paint& paint, const SkPath& path, size_t start, | 
|  | size_t end) override; | 
|  |  | 
|  | /** This class acts as a copy on write SkPaint. | 
|  | * | 
|  | *  Initially this will be the SkPaint passed to the contructor. | 
|  | *  The first time writable() is called this will become a copy of the | 
|  | *  initial SkPaint (or a default SkPaint if nullptr). | 
|  | */ | 
|  | struct PaintCoW { | 
|  | PaintCoW(const SkPaint& that) : mPtr(&that) {} | 
|  | PaintCoW(const SkPaint* ptr) : mPtr(ptr) {} | 
|  | PaintCoW(const PaintCoW&) = delete; | 
|  | PaintCoW(PaintCoW&&) = delete; | 
|  | PaintCoW& operator=(const PaintCoW&) = delete; | 
|  | PaintCoW& operator=(PaintCoW&&) = delete; | 
|  | SkPaint& writeable() { | 
|  | if (!mStorage) { | 
|  | if (!mPtr) { | 
|  | mStorage.emplace(); | 
|  | } else { | 
|  | mStorage.emplace(*mPtr); | 
|  | } | 
|  | mPtr = &*mStorage; | 
|  | } | 
|  | return *mStorage; | 
|  | } | 
|  | operator const SkPaint*() const { return mPtr; } | 
|  | const SkPaint* operator->() const { assert(mPtr); return mPtr; } | 
|  | const SkPaint& operator*() const { assert(mPtr); return *mPtr; } | 
|  | explicit operator bool() { return mPtr != nullptr; } | 
|  | private: | 
|  | const SkPaint* mPtr; | 
|  | std::optional<SkPaint> mStorage; | 
|  | }; | 
|  |  | 
|  | /** Filters the paint using the current paint filter. | 
|  | * | 
|  | *  @param paint the paint to filter. Will be initialized with the default | 
|  | *      SkPaint before filtering if filtering is required. | 
|  | */ | 
|  | PaintCoW&& filterPaint(PaintCoW&& paint) const; | 
|  |  | 
|  | template <typename Proc> void apply_looper(const Paint* paint, Proc proc) { | 
|  | SkPaint skp; | 
|  | SkDrawLooper* looper = nullptr; | 
|  | if (paint) { | 
|  | skp = *filterPaint(paint); | 
|  | looper = paint->getLooper(); | 
|  | } | 
|  | if (looper) { | 
|  | SkSTArenaAlloc<256> alloc; | 
|  | SkDrawLooper::Context* ctx = looper->makeContext(&alloc); | 
|  | if (ctx) { | 
|  | SkDrawLooper::Context::Info info; | 
|  | for (;;) { | 
|  | SkPaint p = skp; | 
|  | if (!ctx->next(&info, &p)) { | 
|  | break; | 
|  | } | 
|  | mCanvas->save(); | 
|  | mCanvas->translate(info.fTranslate.fX, info.fTranslate.fY); | 
|  | proc(p); | 
|  | mCanvas->restore(); | 
|  | } | 
|  | } | 
|  | } else { | 
|  | proc(skp); | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | private: | 
|  | struct SaveRec { | 
|  | int saveCount; | 
|  | SaveFlags::Flags saveFlags; | 
|  | size_t clipIndex; | 
|  | }; | 
|  |  | 
|  | const SaveRec* currentSaveRec() const; | 
|  | void recordPartialSave(SaveFlags::Flags flags); | 
|  |  | 
|  | template <typename T> | 
|  | void recordClip(const T&, SkClipOp); | 
|  | void applyPersistentClips(size_t clipStartIndex); | 
|  |  | 
|  | void drawPoints(const float* points, int count, const Paint& paint, SkCanvas::PointMode mode); | 
|  |  | 
|  | class Clip; | 
|  |  | 
|  | std::unique_ptr<SkCanvas> mCanvasOwned;    // might own a canvas we allocated | 
|  | SkCanvas* mCanvas;                         // we do NOT own this canvas, it must survive us | 
|  | // unless it is the same as mCanvasOwned.get() | 
|  | std::unique_ptr<SkDeque> mSaveStack;       // lazily allocated, tracks partial saves. | 
|  | std::vector<Clip> mClipStack;              // tracks persistent clips. | 
|  | sk_sp<PaintFilter> mPaintFilter; | 
|  | }; | 
|  |  | 
|  | }  // namespace android |