diff --git a/expectations/gm/ignored-tests.txt b/expectations/gm/ignored-tests.txt index 776cf93d07..77c8e43928 100644 --- a/expectations/gm/ignored-tests.txt +++ b/expectations/gm/ignored-tests.txt @@ -50,4 +50,9 @@ complexclip2_rrect_aa rrect_clip_bw rrect_clip_aa rrect_bw -rrect_aa \ No newline at end of file +rrect_aa + +# Need to rebaseline all platforms due to new test cases added in +# https://codereview.chromium.org/168283006/ +imagefiltersclipped +imagefiltersscaled diff --git a/gm/imagefiltersclipped.cpp b/gm/imagefiltersclipped.cpp index 331ea49061..757cd1bf27 100644 --- a/gm/imagefiltersclipped.cpp +++ b/gm/imagefiltersclipped.cpp @@ -14,8 +14,12 @@ #include "SkGradientShader.h" #include "SkMorphologyImageFilter.h" #include "SkOffsetImageFilter.h" +#include "SkResizeImageFilter.h" #include "SkScalar.h" +#define RESIZE_FACTOR_X SkIntToScalar(2) +#define RESIZE_FACTOR_Y SkIntToScalar(5) + namespace skiagm { class ImageFiltersClippedGM : public GM { @@ -96,6 +100,7 @@ protected: new SkDilateImageFilter(2, 2, checkerboard.get()), new SkErodeImageFilter(2, 2, checkerboard.get()), new SkOffsetImageFilter(SkIntToScalar(-16), SkIntToScalar(32)), + new SkResizeImageFilter(RESIZE_FACTOR_X, RESIZE_FACTOR_Y, SkPaint::kNone_FilterLevel), }; SkRect r = SkRect::MakeWH(SkIntToScalar(64), SkIntToScalar(64)); @@ -113,8 +118,11 @@ protected: paint.setAntiAlias(true); canvas->save(); canvas->clipRect(bounds); - if (i == 5) { + if (5 == i) { canvas->translate(SkIntToScalar(16), SkIntToScalar(-32)); + } else if (6 == i) { + canvas->scale(SkScalarInvert(RESIZE_FACTOR_X), + SkScalarInvert(RESIZE_FACTOR_Y)); } canvas->drawCircle(r.centerX(), r.centerY(), SkScalarDiv(r.width()*2, SkIntToScalar(5)), paint); diff --git a/gm/imagefiltersscaled.cpp b/gm/imagefiltersscaled.cpp index 28b3c9f171..6ccaece7ef 100644 --- a/gm/imagefiltersscaled.cpp +++ b/gm/imagefiltersscaled.cpp @@ -14,8 +14,11 @@ #include "SkGradientShader.h" #include "SkMorphologyImageFilter.h" #include "SkOffsetImageFilter.h" +#include "SkResizeImageFilter.h" #include "SkScalar.h" +#define RESIZE_FACTOR SkIntToScalar(4) + namespace skiagm { class ImageFiltersScaledGM : public GM { @@ -30,7 +33,7 @@ protected: } virtual SkISize onISize() { - return make_isize(860, 500); + return make_isize(1020, 500); } void make_checkerboard() { @@ -96,6 +99,7 @@ protected: new SkDilateImageFilter(1, 1, checkerboard.get()), new SkErodeImageFilter(1, 1, checkerboard.get()), new SkOffsetImageFilter(SkIntToScalar(32), 0), + new SkResizeImageFilter(RESIZE_FACTOR, RESIZE_FACTOR, SkPaint::kNone_FilterLevel), }; SkVector scales[] = { @@ -122,6 +126,9 @@ protected: canvas->scale(scales[j].fX, scales[j].fY); if (5 == i) { canvas->translate(SkIntToScalar(-32), 0); + } else if (6 == i) { + canvas->scale(SkScalarInvert(RESIZE_FACTOR), + SkScalarInvert(RESIZE_FACTOR)); } canvas->drawCircle(r.centerX(), r.centerY(), SkScalarDiv(r.width()*2, SkIntToScalar(5)), paint); diff --git a/gm/imageresizetiled.cpp b/gm/imageresizetiled.cpp new file mode 100644 index 0000000000..a54c811cca --- /dev/null +++ b/gm/imageresizetiled.cpp @@ -0,0 +1,77 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "gm.h" +#include "SkResizeImageFilter.h" +#include "SkRandom.h" + +#define WIDTH 640 +#define HEIGHT 480 + +#define RESIZE_FACTOR SkIntToScalar(2) + +namespace skiagm { + +class ImageResizeTiledGM : public GM { +public: + ImageResizeTiledGM() { + } + +protected: + virtual SkString onShortName() SK_OVERRIDE { + return SkString("imageresizetiled"); + } + + virtual SkISize onISize() SK_OVERRIDE { + return make_isize(WIDTH, HEIGHT); + } + + virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { + SkPaint paint; + SkAutoTUnref imageFilter( + new SkResizeImageFilter(RESIZE_FACTOR, RESIZE_FACTOR, SkPaint::kNone_FilterLevel)); + paint.setImageFilter(imageFilter.get()); + const SkScalar tile_size = SkIntToScalar(100); + SkRect bounds; + canvas->getClipBounds(&bounds); + for (SkScalar y = 0; y < HEIGHT; y += tile_size) { + for (SkScalar x = 0; x < WIDTH; x += tile_size) { + canvas->save(); + canvas->clipRect(SkRect::MakeXYWH(x, y, tile_size, tile_size)); + canvas->scale(SkScalarInvert(RESIZE_FACTOR), + SkScalarInvert(RESIZE_FACTOR)); + canvas->saveLayer(NULL, &paint); + const char* str[] = { + "The quick", + "brown fox", + "jumped over", + "the lazy dog.", + }; + SkPaint textPaint; + textPaint.setAntiAlias(true); + textPaint.setTextSize(SkIntToScalar(100)); + int posY = 0; + for (unsigned i = 0; i < SK_ARRAY_COUNT(str); i++) { + posY += 100; + canvas->drawText(str[i], strlen(str[i]), SkIntToScalar(0), + SkIntToScalar(posY), textPaint); + } + canvas->restore(); + canvas->restore(); + } + } + } + +private: + typedef GM INHERITED; +}; + +////////////////////////////////////////////////////////////////////////////// + +DEF_GM(return new ImageResizeTiledGM(); ) + +} diff --git a/gyp/gmslides.gypi b/gyp/gmslides.gypi index e95f59b34c..8a9d36b5e4 100644 --- a/gyp/gmslides.gypi +++ b/gyp/gmslides.gypi @@ -91,6 +91,7 @@ '../gm/imageblur.cpp', '../gm/imageblurtiled.cpp', '../gm/imagemagnifier.cpp', + '../gm/imageresizetiled.cpp', '../gm/inversepaths.cpp', '../gm/lerpmode.cpp', '../gm/lighting.cpp', diff --git a/include/effects/SkResizeImageFilter.h b/include/effects/SkResizeImageFilter.h index cc02a01d03..0a8fb14647 100644 --- a/include/effects/SkResizeImageFilter.h +++ b/include/effects/SkResizeImageFilter.h @@ -32,6 +32,7 @@ public: SkResizeImageFilter(SkScalar sx, SkScalar sy, SkPaint::FilterLevel filterLevel, SkImageFilter* input = NULL); virtual ~SkResizeImageFilter(); + virtual void computeFastBounds(const SkRect&, SkRect*) const SK_OVERRIDE; SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkResizeImageFilter) @@ -41,6 +42,8 @@ protected: virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&, SkBitmap* result, SkIPoint* loc) const SK_OVERRIDE; + virtual bool onFilterBounds(const SkIRect& src, const SkMatrix&, + SkIRect* dst) const SK_OVERRIDE; private: SkScalar fSx, fSy; diff --git a/src/effects/SkResizeImageFilter.cpp b/src/effects/SkResizeImageFilter.cpp index 4a3f4b56ee..51c1d6d6b4 100644 --- a/src/effects/SkResizeImageFilter.cpp +++ b/src/effects/SkResizeImageFilter.cpp @@ -42,12 +42,12 @@ SkResizeImageFilter::~SkResizeImageFilter() { bool SkResizeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source, - const SkMatrix& matrix, + const SkMatrix& ctm, SkBitmap* result, SkIPoint* offset) const { SkBitmap src = source; SkIPoint srcOffset = SkIPoint::Make(0, 0); - if (getInput(0) && !getInput(0)->filterImage(proxy, source, matrix, &src, &srcOffset)) { + if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctm, &src, &srcOffset)) { return false; } @@ -56,9 +56,13 @@ bool SkResizeImageFilter::onFilterImage(Proxy* proxy, src.getBounds(&srcBounds); srcBounds.offset(srcOffset); SkRect srcRect = SkRect::Make(srcBounds); - SkMatrix dstMatrix; - dstMatrix.setScale(fSx, fSy); - dstMatrix.mapRect(&dstRect, srcRect); + SkMatrix matrix; + if (!ctm.invert(&matrix)) { + return false; + } + matrix.postScale(fSx, fSy); + matrix.postConcat(ctm); + matrix.mapRect(&dstRect, srcRect); dstRect.roundOut(&dstBounds); SkAutoTUnref device(proxy->createDevice(dstBounds.width(), dstBounds.height())); @@ -67,12 +71,11 @@ bool SkResizeImageFilter::onFilterImage(Proxy* proxy, } SkCanvas canvas(device.get()); - canvas.translate(-SkIntToScalar(dstBounds.fLeft), -SkIntToScalar(dstBounds.fTop)); + canvas.scale(fSx, fSy); SkPaint paint; paint.setXfermodeMode(SkXfermode::kSrc_Mode); paint.setFilterLevel(fFilterLevel); - canvas.concat(dstMatrix); canvas.drawBitmap(src, srcRect.left(), srcRect.top(), &paint); *result = device.get()->accessBitmap(false); @@ -80,3 +83,31 @@ bool SkResizeImageFilter::onFilterImage(Proxy* proxy, offset->fY = dstBounds.fTop; return true; } + +void SkResizeImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const { + SkRect bounds = src; + if (getInput(0)) { + getInput(0)->computeFastBounds(src, &bounds); + } + dst->setXYWH(bounds.x(), bounds.y(), bounds.width() * fSx, bounds.height() * fSy); +} + +bool SkResizeImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, + SkIRect* dst) const { + SkMatrix matrix; + if (!ctm.invert(&matrix)) { + return false; + } + matrix.postScale(SkScalarInvert(fSx), SkScalarInvert(fSy)); + matrix.postConcat(ctm); + SkRect floatBounds; + matrix.mapRect(&floatBounds, SkRect::Make(src)); + SkIRect bounds; + floatBounds.roundOut(&bounds); + if (getInput(0) && !getInput(0)->filterBounds(bounds, ctm, &bounds)) { + return false; + } + + *dst = bounds; + return true; +}