diff options
author | Fredrik Söderquist <fs@opera.com> | 2017-10-26 13:54:16 +0200 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2017-10-26 13:10:07 +0000 |
commit | b87f798e5a629284cc008b4986bb2ddba7ed9cb1 (patch) | |
tree | cb3b9545f6f99a089a6e4ce8a02471a987955e49 | |
parent | 154beea85961f73ed7f0da047b7ebd16d2a2d829 (diff) |
Consistently round fOffset in SkOffsetImageFilter
Since SkScalarRoundToInt rounds differently depending on the sign of the
value, care must be taken to perform rounding before any potential
change to the sign - like in SkOffsetImageFilter::onFilterNodeBounds.
Bug: chromium:778204
Change-Id: I3debff7565f45022c7b8566662927149850b1bea
Reviewed-on: https://skia-review.googlesource.com/64020
Reviewed-by: Stephen White <senorblanco@chromium.org>
Commit-Queue: Robert Phillips <robertphillips@google.com>
-rw-r--r-- | src/effects/SkOffsetImageFilter.cpp | 19 | ||||
-rw-r--r-- | tests/ImageFilterTest.cpp | 15 |
2 files changed, 26 insertions, 8 deletions
diff --git a/src/effects/SkOffsetImageFilter.cpp b/src/effects/SkOffsetImageFilter.cpp index f25ffdc7ca..0c2949f0e3 100644 --- a/src/effects/SkOffsetImageFilter.cpp +++ b/src/effects/SkOffsetImageFilter.cpp @@ -15,6 +15,11 @@ #include "SkSpecialSurface.h" #include "SkWriteBuffer.h" +static SkIPoint map_offset_vector(const SkMatrix& ctm, const SkVector& offset) { + SkVector vec = ctm.mapVector(offset.fX, offset.fY); + return SkIPoint::Make(SkScalarRoundToInt(vec.fX), SkScalarRoundToInt(vec.fY)); +} + sk_sp<SkImageFilter> SkOffsetImageFilter::Make(SkScalar dx, SkScalar dy, sk_sp<SkImageFilter> input, const CropRect* cropRect) { @@ -34,12 +39,11 @@ sk_sp<SkSpecialImage> SkOffsetImageFilter::onFilterImage(SkSpecialImage* source, return nullptr; } - SkVector vec; - ctx.ctm().mapVectors(&vec, &fOffset, 1); + SkIPoint vec = map_offset_vector(ctx.ctm(), fOffset); if (!this->cropRectIsSet()) { - offset->fX = srcOffset.fX + SkScalarRoundToInt(vec.fX); - offset->fY = srcOffset.fY + SkScalarRoundToInt(vec.fY); + offset->fX = srcOffset.fX + vec.fX; + offset->fY = srcOffset.fY + vec.fY; return input; } else { SkIRect bounds; @@ -65,7 +69,7 @@ sk_sp<SkSpecialImage> SkOffsetImageFilter::onFilterImage(SkSpecialImage* source, canvas->translate(SkIntToScalar(srcOffset.fX - bounds.fLeft), SkIntToScalar(srcOffset.fY - bounds.fTop)); - input->draw(canvas, vec.x(), vec.y(), &paint); + input->draw(canvas, vec.fX, vec.fY, &paint); offset->fX = bounds.fLeft; offset->fY = bounds.fTop; @@ -92,13 +96,12 @@ SkRect SkOffsetImageFilter::computeFastBounds(const SkRect& src) const { SkIRect SkOffsetImageFilter::onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm, MapDirection direction) const { - SkVector vec; - ctm.mapVectors(&vec, &fOffset, 1); + SkIPoint vec = map_offset_vector(ctm, fOffset); if (kReverse_MapDirection == direction) { vec.negate(); } - return src.makeOffset(SkScalarCeilToInt(vec.fX), SkScalarCeilToInt(vec.fY)); + return src.makeOffset(vec.fX, vec.fY); } sk_sp<SkFlattenable> SkOffsetImageFilter::CreateProc(SkReadBuffer& buffer) { diff --git a/tests/ImageFilterTest.cpp b/tests/ImageFilterTest.cpp index c39cc2ee83..59f0f2853b 100644 --- a/tests/ImageFilterTest.cpp +++ b/tests/ImageFilterTest.cpp @@ -1998,6 +1998,21 @@ DEF_TEST(XfermodeImageFilterBounds, reporter) { REPORTER_ASSERT(reporter, bounds.isEmpty()); } +DEF_TEST(OffsetImageFilterBounds, reporter) { + SkIRect src = SkIRect::MakeXYWH(0, 0, 100, 100); + sk_sp<SkImageFilter> offset(SkOffsetImageFilter::Make(-50.5f, -50.5f, nullptr)); + + SkIRect expectedForward = SkIRect::MakeXYWH(-50, -50, 100, 100); + SkIRect boundsForward = offset->filterBounds(src, SkMatrix::I(), + SkImageFilter::kForward_MapDirection); + REPORTER_ASSERT(reporter, boundsForward == expectedForward); + + SkIRect expectedReverse = SkIRect::MakeXYWH(50, 50, 100, 100); + SkIRect boundsReverse = offset->filterBounds(src, SkMatrix::I(), + SkImageFilter::kReverse_MapDirection); + REPORTER_ASSERT(reporter, boundsReverse == expectedReverse); +} + static void test_arithmetic_bounds(skiatest::Reporter* reporter, float k1, float k2, float k3, float k4, sk_sp<SkImageFilter> background, sk_sp<SkImageFilter> foreground, |