aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Matt Sarett <msarett@google.com>2017-04-25 13:53:11 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-04-25 18:24:47 +0000
commitc15bb7b10736e7b8f8d4bd0207c608546206ec1b (patch)
tree423131b744b71389e17dab7a62d68e9d665397eb
parent4785897c962c02dd6f92b37850dec527f34387f8 (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.cpp53
-rw-r--r--src/core/SkColorSpaceXformer.cpp39
-rw-r--r--src/core/SkColorSpaceXformer.h4
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