Fix for SkDisplacementMap::onFilterBounds().

Two problems: we were not applying the CTM to the scale parameter when
modifying clip bounds, and the recursion for onFilterBounds() must be done
in the reverse order.

BUG=370914
R=junov@chromium.org

Review URL: https://codereview.chromium.org/272643003

git-svn-id: http://skia.googlecode.com/svn/trunk@14627 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp
index 3922244..d0f134b 100644
--- a/src/effects/SkDisplacementMapEffect.cpp
+++ b/src/effects/SkDisplacementMapEffect.cpp
@@ -257,11 +257,13 @@
 bool SkDisplacementMapEffect::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
                                    SkIRect* dst) const {
     SkIRect bounds = src;
-    if (getColorInput() && !getColorInput()->filterBounds(src, ctm, &bounds)) {
-        return false;
+    SkVector scale = SkVector::Make(fScale, fScale);
+    ctm.mapVectors(&scale, 1);
+    bounds.outset(SkScalarCeilToInt(scale.fX * SK_ScalarHalf),
+                  SkScalarCeilToInt(scale.fY * SK_ScalarHalf));
+    if (getColorInput()) {
+        return getColorInput()->filterBounds(bounds, ctm, dst);
     }
-    bounds.outset(SkScalarCeilToInt(fScale * SK_ScalarHalf),
-                  SkScalarCeilToInt(fScale * SK_ScalarHalf));
     *dst = bounds;
     return true;
 }
diff --git a/tests/ImageFilterTest.cpp b/tests/ImageFilterTest.cpp
index f8492a7..91b2c09 100644
--- a/tests/ImageFilterTest.cpp
+++ b/tests/ImageFilterTest.cpp
@@ -309,7 +309,7 @@
         { "displacement map", SkDisplacementMapEffect::Create(
               SkDisplacementMapEffect::kR_ChannelSelectorType,
               SkDisplacementMapEffect::kB_ChannelSelectorType,
-              40.0f, gradient_source.get()) },
+              20.0f, gradient_source.get()) },
         { "blur", SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1) },
         { "drop shadow", SkDropShadowImageFilter::Create(
               SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_ColorGREEN) },
@@ -335,34 +335,40 @@
     tiledResult.allocN32Pixels(width, height);
     SkCanvas tiledCanvas(tiledResult);
     SkCanvas untiledCanvas(untiledResult);
-    tiledCanvas.clear(0);
-    untiledCanvas.clear(0);
-    int tileSize = 16;
+    int tileSize = 8;
 
-    for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
-        SkPaint paint;
-        paint.setImageFilter(filters[i].fFilter);
-        paint.setTextSize(SkIntToScalar(height));
-        paint.setColor(SK_ColorWHITE);
-        SkString str;
-        const char* text = "ABC";
-        SkScalar ypos = SkIntToScalar(height);
-        untiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
-        for (int y = 0; y < height; y += tileSize) {
-            for (int x = 0; x < width; x += tileSize) {
-                tiledCanvas.save();
-                tiledCanvas.clipRect(SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize)));
-                tiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
-                tiledCanvas.restore();
+    for (int scale = 1; scale <= 2; ++scale) {
+        for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) {
+            tiledCanvas.clear(0);
+            untiledCanvas.clear(0);
+            SkPaint paint;
+            paint.setImageFilter(filters[i].fFilter);
+            paint.setTextSize(SkIntToScalar(height));
+            paint.setColor(SK_ColorWHITE);
+            SkString str;
+            const char* text = "ABC";
+            SkScalar ypos = SkIntToScalar(height);
+            untiledCanvas.save();
+            untiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
+            untiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
+            untiledCanvas.restore();
+            for (int y = 0; y < height; y += tileSize) {
+                for (int x = 0; x < width; x += tileSize) {
+                    tiledCanvas.save();
+                    tiledCanvas.clipRect(SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize)));
+                    tiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale));
+                    tiledCanvas.drawText(text, strlen(text), 0, ypos, paint);
+                    tiledCanvas.restore();
+                }
             }
-        }
-        untiledCanvas.flush();
-        tiledCanvas.flush();
-        for (int y = 0; y < height; y++) {
-            int diffs = memcmp(untiledResult.getAddr32(0, y), tiledResult.getAddr32(0, y), untiledResult.rowBytes());
-            REPORTER_ASSERT_MESSAGE(reporter, !diffs, filters[i].fName);
-            if (diffs) {
-                break;
+            untiledCanvas.flush();
+            tiledCanvas.flush();
+            for (int y = 0; y < height; y++) {
+                int diffs = memcmp(untiledResult.getAddr32(0, y), tiledResult.getAddr32(0, y), untiledResult.rowBytes());
+                REPORTER_ASSERT_MESSAGE(reporter, !diffs, filters[i].fName);
+                if (diffs) {
+                    break;
+                }
             }
         }
     }