diff options
author | Matt Sarett <msarett@google.com> | 2017-04-25 13:53:11 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-04-25 18:24:47 +0000 |
commit | c15bb7b10736e7b8f8d4bd0207c608546206ec1b (patch) | |
tree | 423131b744b71389e17dab7a62d68e9d665397eb | |
parent | 4785897c962c02dd6f92b37850dec527f34387f8 (diff) |
Make SkColorSpaceXformer::apply(SkPaint) safe to call recursively
Before, we would stomp on the original paint in the recursive call.
This fixes 4 gbr-8888 gms. Currently, this only affects loopers
and SkPaintImageFilter.
Bug: skia:6516
Change-Id: Ic47d637a912370c0a1ae8ef3282ad7d15d9902e3
Reviewed-on: https://skia-review.googlesource.com/14182
Commit-Queue: Matt Sarett <msarett@google.com>
Reviewed-by: Mike Klein <mtklein@chromium.org>
-rw-r--r-- | src/core/SkColorSpaceXformCanvas.cpp | 53 | ||||
-rw-r--r-- | src/core/SkColorSpaceXformer.cpp | 39 | ||||
-rw-r--r-- | src/core/SkColorSpaceXformer.h | 4 |
3 files changed, 40 insertions, 56 deletions
diff --git a/src/core/SkColorSpaceXformCanvas.cpp b/src/core/SkColorSpaceXformCanvas.cpp index 9486a4ed56..f026c6d176 100644 --- a/src/core/SkColorSpaceXformCanvas.cpp +++ b/src/core/SkColorSpaceXformCanvas.cpp @@ -15,6 +15,18 @@ #include "SkMakeUnique.h" #include "SkNoDrawCanvas.h" #include "SkSurface.h" +#include "SkTLazy.h" + +namespace { + struct MaybePaint { + SkTLazy<SkPaint> fStorage; + const SkPaint* fPaint = nullptr; + MaybePaint(const SkPaint* p, SkColorSpaceXformer* xformer) { + if (p) { fPaint = fStorage.set(xformer->apply(*p)); } + } + operator const SkPaint*() const { return fPaint; } + }; +}; class SkColorSpaceXformCanvas : public SkNoDrawCanvas { public: @@ -126,30 +138,26 @@ public: void onDrawImage(const SkImage* img, SkScalar l, SkScalar t, const SkPaint* paint) override { - fTarget->drawImage(fXformer->apply(img).get(), - l, t, - fXformer->apply(paint)); + fTarget->drawImage(fXformer->apply(img).get(), l, t, MaybePaint(paint, fXformer.get())); } void onDrawImageRect(const SkImage* img, const SkRect* src, const SkRect& dst, const SkPaint* paint, SrcRectConstraint constraint) override { fTarget->drawImageRect(fXformer->apply(img).get(), src ? *src : SkRect::MakeIWH(img->width(), img->height()), dst, - fXformer->apply(paint), constraint); + MaybePaint(paint, fXformer.get()), constraint); } void onDrawImageNine(const SkImage* img, const SkIRect& center, const SkRect& dst, const SkPaint* paint) override { - fTarget->drawImageNine(fXformer->apply(img).get(), - center, dst, - fXformer->apply(paint)); + fTarget->drawImageNine(fXformer->apply(img).get(), center, dst, + MaybePaint(paint, fXformer.get())); } void onDrawImageLattice(const SkImage* img, const Lattice& lattice, const SkRect& dst, const SkPaint* paint) override { - fTarget->drawImageLattice(fXformer->apply(img).get(), - lattice, dst, - fXformer->apply(paint)); + fTarget->drawImageLattice(fXformer->apply(img).get(), lattice, dst, + MaybePaint(paint, fXformer.get())); } void onDrawAtlas(const SkImage* atlas, const SkRSXform* xforms, const SkRect* tex, const SkColor* colors, int count, SkBlendMode mode, @@ -160,19 +168,18 @@ public: fXformer->apply(xformed.begin(), colors, count); colors = xformed.begin(); } - fTarget->drawAtlas(fXformer->apply(atlas).get(), xforms, tex, colors, count, mode, cull, - fXformer->apply(paint)); + MaybePaint(paint, fXformer.get())); } void onDrawBitmap(const SkBitmap& bitmap, SkScalar l, SkScalar t, const SkPaint* paint) override { if (this->skipXform(bitmap)) { - return fTarget->drawBitmap(bitmap, l, t, fXformer->apply(paint)); + return fTarget->drawBitmap(bitmap, l, t, MaybePaint(paint, fXformer.get())); } - fTarget->drawImage(fXformer->apply(bitmap).get(), l, t, fXformer->apply(paint)); + fTarget->drawImage(fXformer->apply(bitmap).get(), l, t, MaybePaint(paint, fXformer.get())); } void onDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src, const SkRect& dst, @@ -180,39 +187,41 @@ public: if (this->skipXform(bitmap)) { return fTarget->drawBitmapRect(bitmap, src ? *src : SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst, - fXformer->apply(paint), constraint); + MaybePaint(paint, fXformer.get()), constraint); } fTarget->drawImageRect(fXformer->apply(bitmap).get(), src ? *src : SkRect::MakeIWH(bitmap.width(), bitmap.height()), dst, - fXformer->apply(paint), constraint); + MaybePaint(paint, fXformer.get()), constraint); } void onDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, const SkPaint* paint) override { if (this->skipXform(bitmap)) { - return fTarget->drawBitmapNine(bitmap, center, dst, fXformer->apply(paint)); + return fTarget->drawBitmapNine(bitmap, center, dst, MaybePaint(paint, fXformer.get())); } - fTarget->drawImageNine(fXformer->apply(bitmap).get(), center, dst, fXformer->apply(paint)); + fTarget->drawImageNine(fXformer->apply(bitmap).get(), center, dst, + MaybePaint(paint, fXformer.get())); } void onDrawBitmapLattice(const SkBitmap& bitmap, const Lattice& lattice, const SkRect& dst, const SkPaint* paint) override { if (this->skipXform(bitmap)) { - return fTarget->drawBitmapLattice(bitmap, lattice, dst, fXformer->apply(paint)); + return fTarget->drawBitmapLattice(bitmap, lattice, dst, + MaybePaint(paint, fXformer.get())); } fTarget->drawImageLattice(fXformer->apply(bitmap).get(), lattice, dst, - fXformer->apply(paint)); + MaybePaint(paint, fXformer.get())); } void onDrawPicture(const SkPicture* pic, const SkMatrix* matrix, const SkPaint* paint) override { - SkCanvas::onDrawPicture(pic, matrix, fXformer->apply(paint)); + SkCanvas::onDrawPicture(pic, matrix, MaybePaint(paint, fXformer.get())); } void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override { SkCanvas::onDrawDrawable(drawable, matrix); @@ -222,7 +231,7 @@ public: sk_sp<SkImageFilter> backdrop = rec.fBackdrop ? fXformer->apply(rec.fBackdrop) : nullptr; fTarget->saveLayer({ rec.fBounds, - fXformer->apply(rec.fPaint), + MaybePaint(rec.fPaint, fXformer.get()), backdrop.get(), rec.fSaveLayerFlags, }); diff --git a/src/core/SkColorSpaceXformer.cpp b/src/core/SkColorSpaceXformer.cpp index 0db303b41c..ce6fff679e 100644 --- a/src/core/SkColorSpaceXformer.cpp +++ b/src/core/SkColorSpaceXformer.cpp @@ -79,52 +79,29 @@ SkColor SkColorSpaceXformer::apply(SkColor srgb) { return xformed; } -const SkPaint& SkColorSpaceXformer::apply(const SkPaint& src) { - const SkPaint* result = &src; - auto get_dst = [&] { - if (result == &src) { - fDstPaint = src; - result = &fDstPaint; - } - return &fDstPaint; - }; +SkPaint SkColorSpaceXformer::apply(const SkPaint& src) { + SkPaint dst = src; // All SkColorSpaces have the same black point. if (src.getColor() & 0xffffff) { - get_dst()->setColor(this->apply(src.getColor())); + dst.setColor(this->apply(src.getColor())); } if (auto shader = src.getShader()) { - auto replacement = shader->makeColorSpace(this); - if (replacement.get() != shader) { - get_dst()->setShader(std::move(replacement)); - } + dst.setShader(shader->makeColorSpace(this)); } if (auto cf = src.getColorFilter()) { - auto replacement = this->apply(cf); - if (replacement.get() != cf) { - get_dst()->setColorFilter(std::move(replacement)); - } + dst.setColorFilter(this->apply(cf)); } if (auto looper = src.getDrawLooper()) { - auto replacement = looper->makeColorSpace(this); - if (replacement.get() != looper) { - get_dst()->setDrawLooper(std::move(replacement)); - } + dst.setDrawLooper(looper->makeColorSpace(this)); } if (auto imageFilter = src.getImageFilter()) { - auto replacement = this->apply(imageFilter); - if (replacement.get() != imageFilter) { - get_dst()->setImageFilter(std::move(replacement)); - } + dst.setImageFilter(this->apply(imageFilter)); } - return *result; -} - -const SkPaint* SkColorSpaceXformer::apply(const SkPaint* src) { - return src ? &this->apply(*src) : nullptr; + return dst; } diff --git a/src/core/SkColorSpaceXformer.h b/src/core/SkColorSpaceXformer.h index d357743d22..914e83932b 100644 --- a/src/core/SkColorSpaceXformer.h +++ b/src/core/SkColorSpaceXformer.h @@ -20,8 +20,7 @@ public: sk_sp<SkImage> apply(const SkBitmap& bitmap); sk_sp<SkColorFilter> apply(const SkColorFilter* filter); sk_sp<SkImageFilter> apply(const SkImageFilter* filter); - const SkPaint* apply(const SkPaint* src); - const SkPaint& apply(const SkPaint& src); + SkPaint apply(const SkPaint& src); void apply(SkColor dst[], const SkColor src[], int n); SkColor apply(SkColor srgb); @@ -32,7 +31,6 @@ private: sk_sp<SkColorSpace> fDst; std::unique_ptr<SkColorSpaceXform> fFromSRGB; - SkPaint fDstPaint; }; #endif |