Bounds fixes for SkXfermodeImageFilter:
authorsenorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Thu, 12 Dec 2013 21:00:58 +0000 (21:00 +0000)
committersenorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Thu, 12 Dec 2013 21:00:58 +0000 (21:00 +0000)
1) Change the default bounds to the union of the foreground and background bounds.
2) Use a canvas translate instead of manually offsetting the foreground and background bounds by the union.
3) Apply the transfer mode to all pixels, including those outside the foreground rect by using a difference clip.

Covered by the offset test cases in the xfermodeimagefilter GM (will need rebaselines).

R=reed@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@12652 2bbb7eff-a529-9590-31e7-b0007b416f81

expectations/gm/ignored-tests.txt
src/effects/SkXfermodeImageFilter.cpp

index f3edab2..ac67f63 100644 (file)
@@ -75,3 +75,5 @@ clipped-bitmap-shaders-clamp-hq_angle
 clipped-bitmap-shaders-mirror-hq_angle
 clipped-bitmap-shaders-tile-hq_angle
 
+# Added by senorblanco to accomodate bounds fixes for SkXfermodeImageFilter in https://codereview.chromium.org/112683004.
+xfermodeimagefilter
index 3ab5295..4674ff4 100644 (file)
@@ -61,21 +61,22 @@ bool SkXfermodeImageFilter::onFilterImage(Proxy* proxy,
         return false;
     }
 
-    SkIRect bounds;
+    SkIRect bounds, foregroundBounds;
     background.getBounds(&bounds);
+    bounds.offset(backgroundOffset);
+    foreground.getBounds(&foregroundBounds);
+    foregroundBounds.offset(foregroundOffset);
+    bounds.join(foregroundBounds);
     if (!applyCropRect(&bounds, ctm)) {
         return false;
     }
-    backgroundOffset.fX -= bounds.left();
-    backgroundOffset.fY -= bounds.top();
-    foregroundOffset.fX -= bounds.left();
-    foregroundOffset.fY -= bounds.top();
 
     SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
     if (NULL == device.get()) {
         return false;
     }
     SkCanvas canvas(device);
+    canvas.translate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
     SkPaint paint;
     paint.setXfermodeMode(SkXfermode::kSrc_Mode);
     canvas.drawBitmap(background, SkIntToScalar(backgroundOffset.fX),
@@ -83,6 +84,9 @@ bool SkXfermodeImageFilter::onFilterImage(Proxy* proxy,
     paint.setXfermode(fMode);
     canvas.drawBitmap(foreground, SkIntToScalar(foregroundOffset.fX),
                       SkIntToScalar(foregroundOffset.fY), &paint);
+    canvas.clipRect(SkRect::Make(foregroundBounds), SkRegion::kDifference_Op);
+    paint.setColor(SK_ColorTRANSPARENT);
+    canvas.drawPaint(paint);
     *dst = device->accessBitmap(false);
     offset->fX += bounds.left();
     offset->fY += bounds.top();