This patch implements a crop rect for SkImageFilter. It has been implemented for SkColorFilterImageFilter and SkBlurImageFilter as examples.

In order to preserve the immutability of SkImageFilters, the crop rect is passed as a constructor parameter. If NULL (the default), the bounds of the input image are used, as before.

This also tightens up the boundary handling for SkImageBlurFilter on the GPU backend. Where we were previously using clamping semantics, we now respect decal semantics (so we don't oversaturate the edges). This brings the GPU and raster backends into closer alignment, but will require some new baselines for the GPU tests.

At a minimum, the following tests will need new baselines: imageblur, imagefiltersbase, imagefilterscropped, spritebitmap.

R=reed@google.com

Committed: https://code.google.com/p/skia/source/detail?r=10251

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

git-svn-id: http://skia.googlecode.com/svn/trunk/include@10338 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/core/SkImageFilter.h b/core/SkImageFilter.h
index fe383ae..e467761 100644
--- a/core/SkImageFilter.h
+++ b/core/SkImageFilter.h
@@ -9,13 +9,13 @@
 #define SkImageFilter_DEFINED
 
 #include "SkFlattenable.h"
+#include "SkRect.h"
 
 class SkBitmap;
 class SkColorFilter;
 class SkDevice;
 class SkMatrix;
 struct SkIPoint;
-struct SkIRect;
 class SkShader;
 class GrEffectRef;
 class GrTexture;
@@ -139,14 +139,25 @@
         return fInputs[i];
     }
 
+    /**
+     *  Returns the crop rectangle of this filter. This is set at construction
+     *  time, and determines which pixels from the input image will
+     *  be processed. The size of this rectangle should be used as the size
+     *  of the destination image. The origin of this rect should be used to
+     *  offset access to the input images, and should also be added to the
+     *  "offset" parameter in onFilterImage and filterImageGPU(). (The latter
+     *  ensures that the resulting buffer is drawn in the correct location.)
+     */
+    const SkIRect& cropRect() const { return fCropRect; }
+
 protected:
-    SkImageFilter(int inputCount, SkImageFilter** inputs);
+    SkImageFilter(int inputCount, SkImageFilter** inputs, const SkIRect* cropRect = NULL);
 
     // Convenience constructor for 1-input filters.
-    explicit SkImageFilter(SkImageFilter* input);
+    explicit SkImageFilter(SkImageFilter* input, const SkIRect* cropRect = NULL);
 
     // Convenience constructor for 2-input filters.
-    SkImageFilter(SkImageFilter* input1, SkImageFilter* input2);
+    SkImageFilter(SkImageFilter* input1, SkImageFilter* input2, const SkIRect* cropRect = NULL);
 
     virtual ~SkImageFilter();
 
@@ -160,10 +171,15 @@
     // Default impl copies src into dst and returns true
     virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*);
 
+    // Sets rect to the intersection of rect and the crop rect. If there
+    // is no overlap, returns false and leaves rect unchanged.
+    bool applyCropRect(SkIRect* rect) const;
+
 private:
     typedef SkFlattenable INHERITED;
     int fInputCount;
     SkImageFilter** fInputs;
+    SkIRect fCropRect;
 };
 
 #endif
diff --git a/core/SkRect.h b/core/SkRect.h
index b2f5151..9f3b59a 100644
--- a/core/SkRect.h
+++ b/core/SkRect.h
@@ -26,6 +26,12 @@
         return r;
     }
 
+    static SkIRect SK_WARN_UNUSED_RESULT MakeLargest() {
+        SkIRect r;
+        r.setLargest();
+        return r;
+    }
+
     static SkIRect SK_WARN_UNUSED_RESULT MakeWH(int32_t w, int32_t h) {
         SkIRect r;
         r.set(0, 0, w, h);
@@ -94,6 +100,11 @@
      */
     bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
 
+    bool isLargest() const { return SK_MinS32 == fLeft &&
+                                    SK_MinS32 == fTop &&
+                                    SK_MaxS32 == fRight &&
+                                    SK_MaxS32 == fBottom; }
+
     friend bool operator==(const SkIRect& a, const SkIRect& b) {
         return !memcmp(&a, &b, sizeof(a));
     }
diff --git a/effects/SkBlurImageFilter.h b/effects/SkBlurImageFilter.h
index 56b1f35..f267735 100644
--- a/effects/SkBlurImageFilter.h
+++ b/effects/SkBlurImageFilter.h
@@ -13,7 +13,10 @@
 
 class SK_API SkBlurImageFilter : public SkImageFilter {
 public:
-    SkBlurImageFilter(SkScalar sigmaX, SkScalar sigmaY, SkImageFilter* input = NULL);
+    SkBlurImageFilter(SkScalar sigmaX,
+                      SkScalar sigmaY,
+                      SkImageFilter* input = NULL,
+                      const SkIRect* cropRect = NULL);
 
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurImageFilter)
 
diff --git a/effects/SkColorFilterImageFilter.h b/effects/SkColorFilterImageFilter.h
index 2e5e59c..314ab07 100755
--- a/effects/SkColorFilterImageFilter.h
+++ b/effects/SkColorFilterImageFilter.h
@@ -14,7 +14,9 @@
 
 class SK_API SkColorFilterImageFilter : public SkImageFilter {
 public:
-    static SkColorFilterImageFilter* Create(SkColorFilter* cf, SkImageFilter* input = NULL);
+    static SkColorFilterImageFilter* Create(SkColorFilter* cf,
+                                            SkImageFilter* input = NULL,
+                                            const SkIRect* cropRect = NULL);
     virtual ~SkColorFilterImageFilter();
 
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkColorFilterImageFilter)
@@ -29,7 +31,9 @@
     virtual bool asColorFilter(SkColorFilter**) const SK_OVERRIDE;
 
 private:
-    SkColorFilterImageFilter(SkColorFilter* cf, SkImageFilter* input);
+    SkColorFilterImageFilter(SkColorFilter* cf,
+                             SkImageFilter* input,
+                             const SkIRect* cropRect = NULL);
     SkColorFilter*  fColorFilter;
 
     typedef SkImageFilter INHERITED;