Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0ed10bed authored by Ben Wagner's avatar Ben Wagner
Browse files

Replace SkDrawFilter with PaintFilter.

Skia is removing SkDrawFilter.

Test: refactoring CL. Existing unit tests still pass.
Change-Id: If81c1a2feabf7d377ae1d7bcb3e8cf0f599ad3ce
parent 9fb99abd
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -126,7 +126,6 @@ cc_library_shared {
        "android/graphics/Camera.cpp",
        "android/graphics/CanvasProperty.cpp",
        "android/graphics/ColorFilter.cpp",
        "android/graphics/DrawFilter.cpp",
        "android/graphics/FontFamily.cpp",
        "android/graphics/FontUtils.cpp",
        "android/graphics/CreateJavaOutputStreamAdaptor.cpp",
@@ -143,6 +142,7 @@ cc_library_shared {
        "android/graphics/NinePatch.cpp",
        "android/graphics/NinePatchPeeker.cpp",
        "android/graphics/Paint.cpp",
        "android/graphics/PaintFilter.cpp",
        "android/graphics/Path.cpp",
        "android/graphics/PathMeasure.cpp",
        "android/graphics/PathEffect.cpp",
+33 −26
Original line number Diff line number Diff line
@@ -15,36 +15,43 @@
** limitations under the License.
*/

// This file was generated from the C++ include file: SkColorFilter.h
// Any changes made to this file will be discarded by the build.
// To change this file, either edit the include, or device/tools/gluemaker/main.cpp, 
// or one of the auxilary file specifications in device/tools/gluemaker.

#include "jni.h"
#include "GraphicsJNI.h"
#include <android_runtime/AndroidRuntime.h>

#include "core_jni_helpers.h"

#include "SkDrawFilter.h"
#include "SkPaintFlagsDrawFilter.h"
#include "hwui/PaintFilter.h"
#include "SkPaint.h"

namespace android {

// Custom version of SkPaintFlagsDrawFilter that also calls setFilterQuality.
class CompatFlagsDrawFilter : public SkPaintFlagsDrawFilter {
class PaintFlagsFilter : public PaintFilter {
public:
    PaintFlagsFilter(uint32_t clearFlags, uint32_t setFlags) {
        fClearFlags = static_cast<uint16_t>(clearFlags & SkPaint::kAllFlags);
        fSetFlags = static_cast<uint16_t>(setFlags & SkPaint::kAllFlags);
    }
    void filter(SkPaint* paint) override {
        paint->setFlags((paint->getFlags() & ~fClearFlags) | fSetFlags);
    }

private:
    uint16_t fClearFlags;
    uint16_t fSetFlags;
};

// Custom version of PaintFlagsDrawFilter that also calls setFilterQuality.
class CompatPaintFlagsFilter : public PaintFlagsFilter {
public:
    CompatFlagsDrawFilter(uint32_t clearFlags, uint32_t setFlags,
            SkFilterQuality desiredQuality)
    : SkPaintFlagsDrawFilter(clearFlags, setFlags)
    CompatPaintFlagsFilter(uint32_t clearFlags, uint32_t setFlags, SkFilterQuality desiredQuality)
    : PaintFlagsFilter(clearFlags, setFlags)
    , fDesiredQuality(desiredQuality) {
    }

    virtual bool filter(SkPaint* paint, Type type) {
        SkPaintFlagsDrawFilter::filter(paint, type);
    virtual void filter(SkPaint* paint) {
        PaintFlagsFilter::filter(paint);
        paint->setFilterQuality(fDesiredQuality);
        return true;
    }

private:
@@ -61,15 +68,15 @@ static inline bool hadFiltering(jint& flags) {
    return result;
}

class SkDrawFilterGlue {
class PaintFilterGlue {
public:

    static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle) {
        SkDrawFilter* obj = reinterpret_cast<SkDrawFilter*>(objHandle);
        PaintFilter* obj = reinterpret_cast<PaintFilter*>(objHandle);
        SkSafeUnref(obj);
    }

    static jlong CreatePaintFlagsDF(JNIEnv* env, jobject clazz,
    static jlong CreatePaintFlagsFilter(JNIEnv* env, jobject clazz,
                                        jint clearFlags, jint setFlags) {
        if (clearFlags | setFlags) {
            // Mask both groups of flags to remove FILTER_BITMAP_FLAG, which no
@@ -79,16 +86,16 @@ public:
            const bool turnFilteringOn = hadFiltering(setFlags);
            const bool turnFilteringOff = hadFiltering(clearFlags);

            SkDrawFilter* filter;
            PaintFilter* filter;
            if (turnFilteringOn) {
                // Turning filtering on overrides turning it off.
                filter = new CompatFlagsDrawFilter(clearFlags, setFlags,
                filter = new CompatPaintFlagsFilter(clearFlags, setFlags,
                        kLow_SkFilterQuality);
            } else if (turnFilteringOff) {
                filter = new CompatFlagsDrawFilter(clearFlags, setFlags,
                filter = new CompatPaintFlagsFilter(clearFlags, setFlags,
                        kNone_SkFilterQuality);
            } else {
                filter = new SkPaintFlagsDrawFilter(clearFlags, setFlags);
                filter = new PaintFlagsFilter(clearFlags, setFlags);
            }
            return reinterpret_cast<jlong>(filter);
        } else {
@@ -98,11 +105,11 @@ public:
};

static const JNINativeMethod drawfilter_methods[] = {
    {"nativeDestructor", "(J)V", (void*) SkDrawFilterGlue::finalizer}
    {"nativeDestructor", "(J)V", (void*) PaintFilterGlue::finalizer}
};

static const JNINativeMethod paintflags_methods[] = {
    {"nativeConstructor","(II)J", (void*) SkDrawFilterGlue::CreatePaintFlagsDF}
    {"nativeConstructor","(II)J", (void*) PaintFilterGlue::CreatePaintFlagsFilter}
};

int register_android_graphics_DrawFilter(JNIEnv* env) {
+5 −4
Original line number Diff line number Diff line
@@ -22,13 +22,13 @@
#include <androidfw/ResourceTypes.h>
#include <hwui/Canvas.h>
#include <hwui/Paint.h>
#include <hwui/PaintFilter.h>
#include <hwui/Typeface.h>
#include <minikin/Layout.h>
#include <nativehelper/ScopedPrimitiveArray.h>
#include <nativehelper/ScopedStringChars.h>

#include "Bitmap.h"
#include "SkDrawFilter.h"
#include "SkGraphics.h"
#include "SkRegion.h"
#include "SkVertices.h"
@@ -582,8 +582,9 @@ static void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstri
    env->ReleaseStringChars(text, jchars);
}

static void setDrawFilter(jlong canvasHandle, jlong filterHandle) {
    get_canvas(canvasHandle)->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
static void setPaintFilter(jlong canvasHandle, jlong filterHandle) {
    PaintFilter* paintFilter = reinterpret_cast<PaintFilter*>(filterHandle);
    get_canvas(canvasHandle)->setPaintFilter(sk_ref_sp(paintFilter));
}

static void freeCaches(JNIEnv* env, jobject) {
@@ -633,7 +634,7 @@ static const JNINativeMethod gMethods[] = {
    {"nQuickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
    {"nClipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect},
    {"nClipPath","(JJI)Z", (void*) CanvasJNI::clipPath},
    {"nSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setDrawFilter},
    {"nSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setPaintFilter},
};

// If called from Canvas these are regular JNI
+58 −53
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include "VectorDrawable.h"
#include "hwui/Bitmap.h"
#include "hwui/MinikinUtils.h"
#include "hwui/PaintFilter.h"
#include "pipeline/skia/AnimatedDrawables.h"

#include <SkAnimatedImage.h>
@@ -28,7 +29,6 @@
#include <SkColorFilter.h>
#include <SkColorSpaceXformCanvas.h>
#include <SkDeque.h>
#include <SkDrawFilter.h>
#include <SkDrawable.h>
#include <SkGraphics.h>
#include <SkImage.h>
@@ -40,6 +40,8 @@
#include <SkTextBlob.h>

#include <memory>
#include <optional>
#include <utility>

namespace android {

@@ -211,7 +213,7 @@ public:
    Clip(const SkRRect& rrect, SkClipOp op, const SkMatrix& m)
            : mType(Type::RRect), mOp(op), mMatrix(m), mRRect(rrect) {}
    Clip(const SkPath& path, SkClipOp op, const SkMatrix& m)
            : mType(Type::Path), mOp(op), mMatrix(m), mPath(&path) {}
            : mType(Type::Path), mOp(op), mMatrix(m), mPath(std::in_place, path) {}

    void apply(SkCanvas* canvas) const {
        canvas->setMatrix(mMatrix);
@@ -223,7 +225,7 @@ public:
                canvas->clipRRect(mRRect, mOp);
                break;
            case Type::Path:
                canvas->clipPath(*mPath.get(), mOp);
                canvas->clipPath(mPath.value(), mOp);
                break;
        }
    }
@@ -240,7 +242,7 @@ private:
    SkMatrix mMatrix;

    // These are logically a union (tracked separately due to non-POD path).
    SkTLazy<SkPath> mPath;
    std::optional<SkPath> mPath;
    SkRRect mRRect;
};

@@ -400,12 +402,12 @@ bool SkiaCanvas::clipPath(const SkPath* path, SkClipOp op) {
// Canvas state operations: Filters
// ----------------------------------------------------------------------------

SkDrawFilter* SkiaCanvas::getDrawFilter() {
    return mCanvas->getDrawFilter();
PaintFilter* SkiaCanvas::getPaintFilter() {
    return mPaintFilter.get();
}

void SkiaCanvas::setDrawFilter(SkDrawFilter* drawFilter) {
    mCanvas->setDrawFilter(drawFilter);
void SkiaCanvas::setPaintFilter(sk_sp<PaintFilter> paintFilter) {
    mPaintFilter = std::move(paintFilter);
}

// ----------------------------------------------------------------------------
@@ -439,8 +441,15 @@ void SkiaCanvas::drawColor(int color, SkBlendMode mode) {
    mCanvas->drawColor(color, mode);
}

SkiaCanvas::PaintCoW&& SkiaCanvas::filterPaint(PaintCoW&& paint) const {
    if (mPaintFilter) {
        mPaintFilter->filter(&paint.writeable());
    }
    return std::move(paint);
}

void SkiaCanvas::drawPaint(const SkPaint& paint) {
    mCanvas->drawPaint(paint);
    mCanvas->drawPaint(*filterPaint(paint));
}

// ----------------------------------------------------------------------------
@@ -457,53 +466,53 @@ void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint
        pts[i].set(points[0], points[1]);
        points += 2;
    }
    mCanvas->drawPoints(mode, count, pts.get(), paint);
    mCanvas->drawPoints(mode, count, pts.get(), *filterPaint(paint));
}

void SkiaCanvas::drawPoint(float x, float y, const SkPaint& paint) {
    mCanvas->drawPoint(x, y, paint);
    mCanvas->drawPoint(x, y, *filterPaint(paint));
}

void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint) {
    this->drawPoints(points, count, paint, SkCanvas::kPoints_PointMode);
    this->drawPoints(points, count, *filterPaint(paint), SkCanvas::kPoints_PointMode);
}

void SkiaCanvas::drawLine(float startX, float startY, float stopX, float stopY,
                          const SkPaint& paint) {
    mCanvas->drawLine(startX, startY, stopX, stopY, paint);
    mCanvas->drawLine(startX, startY, stopX, stopY, *filterPaint(paint));
}

void SkiaCanvas::drawLines(const float* points, int count, const SkPaint& paint) {
    if (CC_UNLIKELY(count < 4 || paint.nothingToDraw())) return;
    this->drawPoints(points, count, paint, SkCanvas::kLines_PointMode);
    this->drawPoints(points, count, *filterPaint(paint), SkCanvas::kLines_PointMode);
}

void SkiaCanvas::drawRect(float left, float top, float right, float bottom, const SkPaint& paint) {
    if (CC_UNLIKELY(paint.nothingToDraw())) return;
    mCanvas->drawRect({left, top, right, bottom}, paint);
    mCanvas->drawRect({left, top, right, bottom}, *filterPaint(paint));
}

void SkiaCanvas::drawRegion(const SkRegion& region, const SkPaint& paint) {
    if (CC_UNLIKELY(paint.nothingToDraw())) return;
    mCanvas->drawRegion(region, paint);
    mCanvas->drawRegion(region, *filterPaint(paint));
}

void SkiaCanvas::drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
                               const SkPaint& paint) {
    if (CC_UNLIKELY(paint.nothingToDraw())) return;
    SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
    mCanvas->drawRoundRect(rect, rx, ry, paint);
    mCanvas->drawRoundRect(rect, rx, ry, *filterPaint(paint));
}

void SkiaCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) {
    if (CC_UNLIKELY(radius <= 0 || paint.nothingToDraw())) return;
    mCanvas->drawCircle(x, y, radius, paint);
    mCanvas->drawCircle(x, y, radius, *filterPaint(paint));
}

void SkiaCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) {
    if (CC_UNLIKELY(paint.nothingToDraw())) return;
    SkRect oval = SkRect::MakeLTRB(left, top, right, bottom);
    mCanvas->drawOval(oval, paint);
    mCanvas->drawOval(oval, *filterPaint(paint));
}

void SkiaCanvas::drawArc(float left, float top, float right, float bottom, float startAngle,
@@ -511,9 +520,9 @@ void SkiaCanvas::drawArc(float left, float top, float right, float bottom, float
    if (CC_UNLIKELY(paint.nothingToDraw())) return;
    SkRect arc = SkRect::MakeLTRB(left, top, right, bottom);
    if (fabs(sweepAngle) >= 360.0f) {
        mCanvas->drawOval(arc, paint);
        mCanvas->drawOval(arc, *filterPaint(paint));
    } else {
        mCanvas->drawArc(arc, startAngle, sweepAngle, useCenter, paint);
        mCanvas->drawArc(arc, startAngle, sweepAngle, useCenter, *filterPaint(paint));
    }
}

@@ -522,19 +531,19 @@ void SkiaCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
    if (CC_UNLIKELY(path.isEmpty() && (!path.isInverseFillType()))) {
        return;
    }
    mCanvas->drawPath(path, paint);
    mCanvas->drawPath(path, *filterPaint(paint));
}

void SkiaCanvas::drawVertices(const SkVertices* vertices, SkBlendMode mode, const SkPaint& paint) {
    mCanvas->drawVertices(vertices, mode, paint);
    mCanvas->drawVertices(vertices, mode, *filterPaint(paint));
}

// ----------------------------------------------------------------------------
// Canvas draw operations: Bitmaps
// ----------------------------------------------------------------------------

const SkPaint* SkiaCanvas::addFilter(const SkPaint* origPaint, SkPaint* tmpPaint,
                                     sk_sp<SkColorFilter> colorSpaceFilter) {
SkiaCanvas::PaintCoW&& SkiaCanvas::filterBitmap(PaintCoW&& paint,
                                                sk_sp<SkColorFilter> colorSpaceFilter) const {
    /* We don't apply the colorSpace filter if this canvas is already wrapped with
     * a SkColorSpaceXformCanvas since it already takes care of converting the
     * contents of the bitmap into the appropriate colorspace.  The mCanvasWrapper
@@ -542,39 +551,31 @@ const SkPaint* SkiaCanvas::addFilter(const SkPaint* origPaint, SkPaint* tmpPaint
     * to have a non-sRGB colorspace.
     */
    if (!mCanvasWrapper && colorSpaceFilter) {
        if (origPaint) {
            *tmpPaint = *origPaint;
        }

        if (tmpPaint->getColorFilter()) {
            tmpPaint->setColorFilter(
                    SkColorFilter::MakeComposeFilter(tmpPaint->refColorFilter(), colorSpaceFilter));
            LOG_ALWAYS_FATAL_IF(!tmpPaint->getColorFilter());
        SkPaint& tmpPaint = paint.writeable();
        if (tmpPaint.getColorFilter()) {
            tmpPaint.setColorFilter(SkColorFilter::MakeComposeFilter(tmpPaint.refColorFilter(),
                                                                     std::move(colorSpaceFilter)));
            LOG_ALWAYS_FATAL_IF(!tmpPaint.getColorFilter());
        } else {
            tmpPaint->setColorFilter(colorSpaceFilter);
            tmpPaint.setColorFilter(std::move(colorSpaceFilter));
        }

        return tmpPaint;
    } else {
        return origPaint;
    }
    return filterPaint(std::move(paint));
}

void SkiaCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) {
    SkPaint tmpPaint;
    sk_sp<SkColorFilter> colorFilter;
    sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
    mCanvas->drawImage(image, left, top, addFilter(paint, &tmpPaint, colorFilter));
    mCanvas->drawImage(image, left, top, filterBitmap(paint, std::move(colorFilter)));
}

void SkiaCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) {
    SkAutoCanvasRestore acr(mCanvas, true);
    mCanvas->concat(matrix);

    SkPaint tmpPaint;
    sk_sp<SkColorFilter> colorFilter;
    sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
    mCanvas->drawImage(image, 0, 0, addFilter(paint, &tmpPaint, colorFilter));
    mCanvas->drawImage(image, 0, 0, filterBitmap(paint, std::move(colorFilter)));
}

void SkiaCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float srcRight,
@@ -583,10 +584,9 @@ void SkiaCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop, float s
    SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
    SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);

    SkPaint tmpPaint;
    sk_sp<SkColorFilter> colorFilter;
    sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
    mCanvas->drawImageRect(image, srcRect, dstRect, addFilter(paint, &tmpPaint, colorFilter),
    mCanvas->drawImageRect(image, srcRect, dstRect, filterBitmap(paint, std::move(colorFilter)),
                           SkCanvas::kFast_SrcRectConstraint);
}

@@ -665,21 +665,20 @@ void SkiaCanvas::drawBitmapMesh(Bitmap& bitmap, int meshWidth, int meshHeight,
#endif

    // cons-up a shader for the bitmap
    SkPaint tmpPaint;
    if (paint) {
        tmpPaint = *paint;
    }
    PaintCoW paintCoW(paint);
    SkPaint& tmpPaint = paintCoW.writeable();

    sk_sp<SkColorFilter> colorFilter;
    sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
    sk_sp<SkShader> shader =
            image->makeShader(SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
    if (colorFilter) {
        shader = shader->makeWithColorFilter(colorFilter);
        shader = shader->makeWithColorFilter(std::move(colorFilter));
    }
    tmpPaint.setShader(shader);
    tmpPaint.setShader(std::move(shader));

    mCanvas->drawVertices(builder.detach(), SkBlendMode::kModulate, tmpPaint);
    mCanvas->drawVertices(builder.detach(), SkBlendMode::kModulate,
                          *filterPaint(std::move(paintCoW)));
}

void SkiaCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, float dstLeft,
@@ -706,10 +705,10 @@ void SkiaCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& chunk, floa
    lattice.fBounds = nullptr;
    SkRect dst = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);

    SkPaint tmpPaint;
    sk_sp<SkColorFilter> colorFilter;
    sk_sp<SkImage> image = bitmap.makeImage(&colorFilter);
    mCanvas->drawImageLattice(image.get(), lattice, dst, addFilter(paint, &tmpPaint, colorFilter));
    mCanvas->drawImageLattice(image.get(), lattice, dst,
                              filterBitmap(paint, std::move(colorFilter)));
}

double SkiaCanvas::drawAnimatedImage(AnimatedImageDrawable* imgDrawable) {
@@ -732,6 +731,9 @@ void SkiaCanvas::drawGlyphs(ReadGlyphFunc glyphFunc, int count, const SkPaint& p
    // glyphs centered or right-aligned; the offset above takes
    // care of all alignment.
    SkPaint paintCopy(paint);
    if (mPaintFilter) {
        mPaintFilter->filter(&paintCopy);
    }
    paintCopy.setTextAlign(SkPaint::kLeft_Align);
    SkASSERT(paintCopy.getTextEncoding() == SkPaint::kGlyphID_TextEncoding);
    // Stroke with a hairline is drawn on HW with a fill style for compatibility with Android O and
@@ -760,6 +762,9 @@ void SkiaCanvas::drawLayoutOnPath(const minikin::Layout& layout, float hOffset,
    // glyphs centered or right-aligned; the offsets take care of
    // that portion of the alignment.
    SkPaint paintCopy(paint);
    if (mPaintFilter) {
        mPaintFilter->filter(&paintCopy);
    }
    paintCopy.setTextAlign(SkPaint::kLeft_Align);
    SkASSERT(paintCopy.getTextEncoding() == SkPaint::kGlyphID_TextEncoding);

+55 −5
Original line number Diff line number Diff line
@@ -22,7 +22,9 @@
#include "hwui/Canvas.h"

#include <SkCanvas.h>
#include <SkTLazy.h>

#include <cassert>
#include <optional>

namespace android {

@@ -87,8 +89,8 @@ public:
    virtual bool clipRect(float left, float top, float right, float bottom, SkClipOp op) override;
    virtual bool clipPath(const SkPath* path, SkClipOp op) override;

    virtual SkDrawFilter* getDrawFilter() override;
    virtual void setDrawFilter(SkDrawFilter* drawFilter) override;
    virtual PaintFilter* getPaintFilter() override;
    virtual void setPaintFilter(sk_sp<PaintFilter> paintFilter) override;

    virtual SkCanvasState* captureCanvasState() const override;

@@ -158,6 +160,46 @@ protected:
                                  const SkPaint& 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;

private:
    struct SaveRec {
        int saveCount;
@@ -174,8 +216,15 @@ private:

    void drawPoints(const float* points, int count, const SkPaint& paint, SkCanvas::PointMode mode);

    const SkPaint* addFilter(const SkPaint* origPaint, SkPaint* tmpPaint,
                             sk_sp<SkColorFilter> colorSpaceFilter);
    /** Filters the paint for bitmap drawing.
     *
     *  After filtering the paint for bitmap drawing,
     *  also calls filterPaint on the paint.
     *
     *  @param paint the paint to filter. Will be initialized with the default
     *      SkPaint before filtering if filtering is required.
     */
    PaintCoW&& filterBitmap(PaintCoW&& paint, sk_sp<SkColorFilter> colorSpaceFilter) const;

    class Clip;

@@ -185,6 +234,7 @@ private:
                                               // 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
Loading