diff options
author | 2016-10-20 11:58:40 -0400 | |
---|---|---|
committer | 2016-10-20 16:57:35 +0000 | |
commit | d2fe3bce079671b0210d5c7cddcc712988d0b686 (patch) | |
tree | 7026a72db56291aec557115186435a7889166736 /gm/reveal.cpp | |
parent | ddb37d67ba4db42fa5c6012b58d0f4985b454dc0 (diff) |
Fix bug in raster implementation of SkRRectsGaussianEdgeMaskFilter
The bug was the raster version didn't correctly handle the CTM.
This CL also adds a way to test the behavior (by translating the
reveal GM around in SampleApp)
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=3729
Change-Id: Iaacc905167d20b453203307e5ef840f552fdbb38
Reviewed-on: https://skia-review.googlesource.com/3729
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
Diffstat (limited to 'gm/reveal.cpp')
-rw-r--r-- | gm/reveal.cpp | 57 |
1 files changed, 45 insertions, 12 deletions
diff --git a/gm/reveal.cpp b/gm/reveal.cpp index ef374d3119..b88e7fe62c 100644 --- a/gm/reveal.cpp +++ b/gm/reveal.cpp @@ -28,7 +28,9 @@ constexpr int kClipOffset = 32; class Object { public: virtual ~Object() {} - virtual bool asRRect(SkRRect* rr) const = 0; + // When it returns true, this call will have placed a device-space _circle, rect or + // simple circular_ RRect in "rr" + virtual bool asDevSpaceRRect(const SkMatrix& ctm, SkRRect* rr) const = 0; virtual SkPath asPath(SkScalar inset) const = 0; virtual void draw(SkCanvas* canvas, const SkPaint& paint) const = 0; virtual void clip(SkCanvas* canvas) const = 0; @@ -44,8 +46,24 @@ public: fRRect = SkRRect::MakeRectXY(r, 4*kPad, 4*kPad); } - bool asRRect(SkRRect* rr) const override { - *rr = fRRect; + bool asDevSpaceRRect(const SkMatrix& ctm, SkRRect* rr) const override { + if (!ctm.isSimilarity()) { // the corners have to remain circular + return false; + } + + SkScalar scales[2]; + if (!ctm.getMinMaxScales(scales)) { + return false; + } + + SkASSERT(SkScalarNearlyEqual(scales[0], scales[1])); + + SkRect devRect; + ctm.mapRect(&devRect, fRRect.rect()); + + SkScalar scaledRad = scales[0] * fRRect.getSimpleRadii().fX; + + *rr = SkRRect::MakeRectXY(devRect, scaledRad, scaledRad); return true; } @@ -88,7 +106,7 @@ public: fStrokedBounds = r.makeOutset(kPad, kPad); } - bool asRRect(SkRRect* rr) const override { + bool asDevSpaceRRect(const SkMatrix& ctm, SkRRect* rr) const override { return false; } @@ -144,8 +162,14 @@ public: fRRect = SkRRect::MakeOval(r); } - bool asRRect(SkRRect* rr) const override { - *rr = fRRect; + bool asDevSpaceRRect(const SkMatrix& ctm, SkRRect* rr) const override { + if (!ctm.isSimilarity()) { // circles have to remain circles + return false; + } + + SkRect devRect; + ctm.mapRect(&devRect, fRRect.rect()); + *rr = SkRRect::MakeOval(devRect); return true; } @@ -186,8 +210,14 @@ class Rect : public Object { public: Rect(const SkRect& r) : fRect(r) { } - bool asRRect(SkRRect* rr) const override { - *rr = SkRRect::MakeRect(fRect); + bool asDevSpaceRRect(const SkMatrix& ctm, SkRRect* rr) const override { + if (!ctm.rectStaysRect()) { + return false; + } + + SkRect devRect; + ctm.mapRect(&devRect, fRect); + *rr = SkRRect::MakeRect(devRect); return true; } @@ -246,7 +276,7 @@ public: fPath.close(); } - bool asRRect(SkRRect* rr) const override { + bool asDevSpaceRRect(const SkMatrix& ctm, SkRRect* rr) const override { return false; } @@ -311,6 +341,7 @@ public: } protected: + bool runAsBench() const override { return true; } SkString onShortName() override { return SkString("reveal"); @@ -393,10 +424,12 @@ protected: SkPaint paint; - SkRRect clipRR, drawnRR; + SkRRect devSpaceClipRR, devSpaceDrawnRR; - if (clipObj->asRRect(&clipRR) && drawObj->asRRect(&drawnRR)) { - paint.setMaskFilter(SkRRectsGaussianEdgeMaskFilter::Make(clipRR, drawnRR, + if (clipObj->asDevSpaceRRect(canvas->getTotalMatrix(), &devSpaceClipRR) && + drawObj->asDevSpaceRRect(canvas->getTotalMatrix(), &devSpaceDrawnRR)) { + paint.setMaskFilter(SkRRectsGaussianEdgeMaskFilter::Make(devSpaceClipRR, + devSpaceDrawnRR, fBlurRadius)); } |