add filterImage() entry-point to SkDevice, to allow it to specialize on subclasses
of SkImageFilter. If that returns false, then the filter itself is invoked.



git-svn-id: http://skia.googlecode.com/svn/trunk@2977 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/effects/SkTestImageFilters.cpp b/src/effects/SkTestImageFilters.cpp
index c974365..a772f64 100755
--- a/src/effects/SkTestImageFilters.cpp
+++ b/src/effects/SkTestImageFilters.cpp
@@ -1,7 +1,15 @@
 #include "SkTestImageFilters.h"
 #include "SkCanvas.h"
+#include "SkDevice.h"
 
-bool SkOffsetImageFilter::onFilterImage(const SkBitmap& src,
+class OwnDeviceCanvas : public SkCanvas {
+public:
+    OwnDeviceCanvas(SkDevice* device) : SkCanvas(device) {
+        SkSafeUnref(device);
+    }
+};
+
+bool SkOffsetImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
                                         const SkMatrix& matrix,
                                         SkBitmap* result,
                                         SkIPoint* loc) {
@@ -46,7 +54,8 @@
     SkSafeUnref(fOuter);
 }
 
-bool SkComposeImageFilter::onFilterImage(const SkBitmap& src,
+bool SkComposeImageFilter::onFilterImage(Proxy* proxy,
+                                         const SkBitmap& src,
                                          const SkMatrix& ctm,
                                          SkBitmap* result,
                                          SkIPoint* loc) {
@@ -55,12 +64,12 @@
     }
     
     if (!fOuter || !fInner) {
-        return (fOuter ? fOuter : fInner)->filterImage(src, ctm, result, loc);
+        return (fOuter ? fOuter : fInner)->filterImage(proxy, src, ctm, result, loc);
     }
     
     SkBitmap tmp;
-    return fInner->filterImage(src, ctm, &tmp, loc) &&
-    fOuter->filterImage(tmp, ctm, result, loc);
+    return fInner->filterImage(proxy, src, ctm, &tmp, loc) &&
+           fOuter->filterImage(proxy, tmp, ctm, result, loc);
 }
 
 bool SkComposeImageFilter::onFilterBounds(const SkIRect& src,
@@ -186,7 +195,8 @@
     return true;
 }
 
-bool SkMergeImageFilter::onFilterImage(const SkBitmap& src, const SkMatrix& ctm,
+bool SkMergeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
+                                       const SkMatrix& ctm,
                                        SkBitmap* result, SkIPoint* loc) {
     if (fCount < 1) {
         return false;
@@ -202,12 +212,11 @@
     const int x0 = bounds.left();
     const int y0 = bounds.top();
 
-    SkBitmap dst;
-    dst.setConfig(SkBitmap::kARGB_8888_Config, bounds.width(), bounds.height());
-    dst.allocPixels();
-    dst.eraseColor(0);
-
-    SkCanvas canvas(dst);
+    SkDevice* dst = proxy->createDevice(bounds.width(), bounds.height());
+    if (NULL == dst) {
+        return false;
+    }
+    OwnDeviceCanvas canvas(dst);
     SkPaint paint;
 
     for (int i = 0; i < fCount; ++i) {
@@ -216,7 +225,7 @@
         SkIPoint pos = *loc;
         SkImageFilter* filter = fFilters[i];
         if (filter) {
-            if (!filter->filterImage(src, ctm, &tmp, &pos)) {
+            if (!filter->filterImage(proxy, src, ctm, &tmp, &pos)) {
                 return false;
             }
             srcPtr = &tmp;
@@ -233,7 +242,7 @@
     }
 
     loc->set(bounds.left(), bounds.top());
-    result->swap(dst);
+    *result = dst->accessBitmap(false);
     return true;
 }
 
@@ -285,36 +294,28 @@
     SkSafeUnref(fColorFilter);
 }
 
-bool SkColorFilterImageFilter::onFilterImage(const SkBitmap& src,
+bool SkColorFilterImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
                                              const SkMatrix& matrix,
                                              SkBitmap* result,
                                              SkIPoint* loc) {
-    if (SkBitmap::kARGB_8888_Config != src.config()) {
-        return false;
-    }
-
     SkColorFilter* cf = fColorFilter;
     if (NULL == cf) {
         *result = src;
         return true;
     }
 
-    SkAutoLockPixels alpsrc(src);
-    if (!src.readyToDraw()) {
+    SkDevice* dev = proxy->createDevice(src.width(), src.height());
+    if (NULL == dev) {
         return false;
     }
+    OwnDeviceCanvas canvas(dev);
+    SkPaint paint;
 
-    SkBitmap dst(src);
-    dst.allocPixels();
-    if (!dst.readyToDraw()) {
-        return false;
-    }
-    
-    for (int y = 0; y < src.height(); ++y) {
-        cf->filterSpan(src.getAddr32(0, y), src.width(), dst.getAddr32(0, y));
-    }
-    
-    result->swap(dst);
+    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
+    paint.setColorFilter(fColorFilter);
+    canvas.drawSprite(src, 0, 0, &paint);
+
+    *result = dev->accessBitmap(false);
     return true;
 }
 
@@ -334,7 +335,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-bool SkDownSampleImageFilter::onFilterImage(const SkBitmap& src,
+bool SkDownSampleImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
                                             const SkMatrix& matrix,
                                             SkBitmap* result, SkIPoint*) {
     SkScalar scale = fScale;
@@ -350,32 +351,36 @@
     if (dstH < 1) {
         dstH = 1;
     }
-    
-    SkBitmap dst;
-    dst.setConfig(SkBitmap::kARGB_8888_Config, dstW, dstH);
-    dst.allocPixels();
-    dst.eraseColor(0);
-    
+
+    SkBitmap tmp;
+
     // downsample
     {
+        SkDevice* dev = proxy->createDevice(dstW, dstH);
+        if (NULL == dev) {
+            return false;
+        }
+        OwnDeviceCanvas canvas(dev);
         SkPaint paint;
+
         paint.setFilterBitmap(true);
-        
-        SkCanvas canvas(dst);
         canvas.scale(scale, scale);
         canvas.drawBitmap(src, 0, 0, &paint);
+        tmp = dev->accessBitmap(false);
     }
-    
-    result->setConfig(SkBitmap::kARGB_8888_Config, src.width(), src.height());
-    result->allocPixels();
-    result->eraseColor(0);
-    
+
     // upscale
     {
-        SkRect r = SkRect::MakeWH(SkIntToScalar(result->width()),
-                                  SkIntToScalar(result->height()));
-        SkCanvas canvas(*result);
-        canvas.drawBitmapRect(dst, NULL, r, NULL);
+        SkDevice* dev = proxy->createDevice(src.width(), src.height());
+        if (NULL == dev) {
+            return false;
+        }
+        OwnDeviceCanvas canvas(dev);
+
+        SkRect r = SkRect::MakeWH(SkIntToScalar(src.width()),
+                                  SkIntToScalar(src.height()));
+        canvas.drawBitmapRect(tmp, NULL, r, NULL);
+        *result = dev->accessBitmap(false);
     }
     return true;
 }