Change SkImageFilter's cropRect from SkIRect to a CropRect struct, containing an SkRect and flags indicating which parameters are set.

NOTE: this will require SK_CROP_RECT_IS_INT=1 to be set in Chrome until Blink has been updated to use SkImageFilter::CropRect. Include https://codereview.chromium.org/26528002/ with the Skia roll.

Note also that SK_CROP_RECT_IS_INT is a temporary measure until all call sites in Blink have been updated to use SkRect.

R=reed@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@11692 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gm/imagefilterscropped.cpp b/gm/imagefilterscropped.cpp
index 767973d..bdf925c 100644
--- a/gm/imagefilterscropped.cpp
+++ b/gm/imagefilterscropped.cpp
@@ -133,8 +133,13 @@
 
         SkAutoTUnref<SkColorFilter> cf(
             SkColorFilter::CreateModeFilter(SK_ColorBLUE, SkXfermode::kSrcIn_Mode));
+#ifdef SK_CROP_RECT_IS_INT
         SkIRect cropRect = SkIRect::MakeXYWH(10, 10, 44, 44);
         SkIRect bogusRect = SkIRect::MakeXYWH(-100, -100, 10, 10);
+#else
+        SkImageFilter::CropRect cropRect(SkRect::Make(SkIRect::MakeXYWH(10, 10, 44, 44)), SkImageFilter::CropRect::kHasAll_CropEdge);
+        SkImageFilter::CropRect bogusRect(SkRect::Make(SkIRect::MakeXYWH(-100, -100, 10, 10)), SkImageFilter::CropRect::kHasAll_CropEdge);
+#endif
 
         SkAutoTUnref<SkImageFilter> offset(new SkOffsetImageFilter(
             SkIntToScalar(-10), SkIntToScalar(-10)));
diff --git a/gm/lighting.cpp b/gm/lighting.cpp
index 891d63a..50dceb4 100644
--- a/gm/lighting.cpp
+++ b/gm/lighting.cpp
@@ -85,11 +85,15 @@
         SkColor white(0xFFFFFFFF);
         SkPaint paint;
 
+#ifdef SK_CROP_RECT_IS_INT
         SkIRect cropRect = SkIRect::MakeXYWH(20, 10, 60, 65);
+#else
+        SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(20, 10, 60, 65));
+#endif
 
         int y = 0;
         for (int i = 0; i < 2; i++) {
-            const SkIRect* cr = (i == 0) ? NULL : &cropRect;
+            const SkImageFilter::CropRect* cr = (i == 0) ? NULL : &cropRect;
             paint.setImageFilter(SkLightingImageFilter::CreatePointLitDiffuse(pointLocation, white, surfaceScale, kd, NULL, cr))->unref();
             drawClippedBitmap(canvas, paint, 0, y);
 
diff --git a/gm/morphology.cpp b/gm/morphology.cpp
index 2150689..9e67bfa 100644
--- a/gm/morphology.cpp
+++ b/gm/morphology.cpp
@@ -70,11 +70,15 @@
             {  24,  24,  25,  25 },
         };
         SkPaint paint;
+#ifdef SK_CROP_RECT_IS_INT
         SkIRect cropRect = SkIRect::MakeXYWH(25, 20, 100, 80);
+#else
+        SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(25, 20, 100, 80));
+#endif
 
         for (unsigned j = 0; j < 4; ++j) {
             for (unsigned i = 0; i < SK_ARRAY_COUNT(samples); ++i) {
-                const SkIRect* cr = j & 0x02 ? &cropRect : NULL;
+                const SkImageFilter::CropRect* cr = j & 0x02 ? &cropRect : NULL;
                 if (j & 0x01) {
                     paint.setImageFilter(new SkErodeImageFilter(
                         samples[i].fRadiusX,
diff --git a/gm/offsetimagefilter.cpp b/gm/offsetimagefilter.cpp
index ee4ae35..52a8b81 100644
--- a/gm/offsetimagefilter.cpp
+++ b/gm/offsetimagefilter.cpp
@@ -92,11 +92,16 @@
                                                  y + i * 8,
                                                  bitmap->width() - i * 8,
                                                  bitmap->height() - i * 12);
+#ifdef SK_CROP_RECT_IS_INT
+            SkIRect rect = cropRect;
+#else
+            SkImageFilter::CropRect rect(SkRect::Make(cropRect));
+#endif
             SkAutoTUnref<SkImageFilter> tileInput(SkNEW_ARGS(SkBitmapSource, (*bitmap)));
             SkScalar dx = SkIntToScalar(i*5);
             SkScalar dy = SkIntToScalar(i*10);
             SkAutoTUnref<SkImageFilter> filter(SkNEW_ARGS(
-                SkOffsetImageFilter, (dx, dy, tileInput, &cropRect)));
+                SkOffsetImageFilter, (dx, dy, tileInput, &rect)));
             paint.setImageFilter(filter);
             drawClippedBitmap(canvas, *bitmap, paint, SkIntToScalar(x), SkIntToScalar(y));
             x += bitmap->width() + MARGIN;
diff --git a/gm/xfermodeimagefilter.cpp b/gm/xfermodeimagefilter.cpp
index ef2958a..1e9e4d8 100644
--- a/gm/xfermodeimagefilter.cpp
+++ b/gm/xfermodeimagefilter.cpp
@@ -207,9 +207,14 @@
                                                  y + offsets[i][1],
                                                  fBitmap.width()  + offsets[i][2],
                                                  fBitmap.height() + offsets[i][3]);
+#ifdef SK_CROP_RECT_IS_INT
+            SkIRect rect = cropRect;
+#else
+            SkImageFilter::CropRect rect(SkRect::Make(cropRect));
+#endif
             mode.reset(SkXfermode::Create(sampledModes[i]));
             filter.reset(SkNEW_ARGS(SkXfermodeImageFilter,
-                                    (mode, offsetBackground, offsetForeground, &cropRect)));
+                                    (mode, offsetBackground, offsetForeground, &rect)));
             paint.setImageFilter(filter);
             canvas->save();
             canvas->clipRect(SkRect::MakeXYWH(SkIntToScalar(x),
diff --git a/include/core/SkImageFilter.h b/include/core/SkImageFilter.h
index 3dc145c..9f0e299 100644
--- a/include/core/SkImageFilter.h
+++ b/include/core/SkImageFilter.h
@@ -31,6 +31,28 @@
 public:
     SK_DECLARE_INST_COUNT(SkImageFilter)
 
+#ifdef SK_CROP_RECT_IS_INT
+    typedef SkIRect CropRect;
+#else
+    struct CropRect {
+        SkRect fRect;
+        uint32_t fFlags;
+        enum CropEdge {
+            kHasLeft_CropEdge   = 0x01,
+            kHasTop_CropEdge    = 0x02,
+            kHasRight_CropEdge  = 0x04,
+            kHasBottom_CropEdge = 0x08,
+            kHasAll_CropEdge    = 0x0F,
+        };
+        CropRect() {}
+        explicit CropRect(const SkRect& rect, uint32_t flags = kHasAll_CropEdge) : fRect(rect), fFlags(flags) {}
+        bool isSet() const
+        {
+            return fFlags != 0x0;
+        }
+    };
+#endif
+
     class Proxy {
     public:
         virtual ~Proxy() {};
@@ -138,16 +160,20 @@
      *  "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; }
+#ifdef SK_CROP_RECT_IS_INT
+    bool cropRectIsSet() const { return !fCropRect.isLargest(); }
+#else
+    bool cropRectIsSet() const { return fCropRect.isSet(); }
+#endif
 
 protected:
-    SkImageFilter(int inputCount, SkImageFilter** inputs, const SkIRect* cropRect = NULL);
+    SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect = NULL);
 
     // Convenience constructor for 1-input filters.
-    explicit SkImageFilter(SkImageFilter* input, const SkIRect* cropRect = NULL);
+    explicit SkImageFilter(SkImageFilter* input, const CropRect* cropRect = NULL);
 
     // Convenience constructor for 2-input filters.
-    SkImageFilter(SkImageFilter* input1, SkImageFilter* input2, const SkIRect* cropRect = NULL);
+    SkImageFilter(SkImageFilter* input1, SkImageFilter* input2, const CropRect* cropRect = NULL);
 
     virtual ~SkImageFilter();
 
@@ -170,7 +196,7 @@
     typedef SkFlattenable INHERITED;
     int fInputCount;
     SkImageFilter** fInputs;
-    SkIRect fCropRect;
+    CropRect fCropRect;
 };
 
 #endif
diff --git a/include/core/SkRect.h b/include/core/SkRect.h
index d8919ae..c615603 100644
--- a/include/core/SkRect.h
+++ b/include/core/SkRect.h
@@ -371,6 +371,12 @@
         return r;
     }
 
+    static SkRect SK_WARN_UNUSED_RESULT MakeLargest() {
+        SkRect r;
+        r.setLargest();
+        return r;
+    }
+
     static SkRect SK_WARN_UNUSED_RESULT MakeWH(SkScalar w, SkScalar h) {
         SkRect r;
         r.set(0, 0, w, h);
@@ -419,6 +425,11 @@
      */
     bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; }
 
+    bool isLargest() const { return SK_ScalarMin == fLeft &&
+                                    SK_ScalarMin == fTop &&
+                                    SK_ScalarMax == fRight &&
+                                    SK_ScalarMax == fBottom; }
+
     /**
      *  Returns true iff all values in the rect are finite. If any are
      *  infinite or NaN (or SK_FixedNaN when SkScalar is fixed) then this
diff --git a/include/effects/SkBlurImageFilter.h b/include/effects/SkBlurImageFilter.h
index ef03a99..f087254 100644
--- a/include/effects/SkBlurImageFilter.h
+++ b/include/effects/SkBlurImageFilter.h
@@ -16,7 +16,7 @@
     SkBlurImageFilter(SkScalar sigmaX,
                       SkScalar sigmaY,
                       SkImageFilter* input = NULL,
-                      const SkIRect* cropRect = NULL);
+                      const CropRect* cropRect = NULL);
 
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkBlurImageFilter)
 
diff --git a/include/effects/SkColorFilterImageFilter.h b/include/effects/SkColorFilterImageFilter.h
index 314ab07..c4ac6b2 100755
--- a/include/effects/SkColorFilterImageFilter.h
+++ b/include/effects/SkColorFilterImageFilter.h
@@ -16,7 +16,7 @@
 public:
     static SkColorFilterImageFilter* Create(SkColorFilter* cf,
                                             SkImageFilter* input = NULL,
-                                            const SkIRect* cropRect = NULL);
+                                            const CropRect* cropRect = NULL);
     virtual ~SkColorFilterImageFilter();
 
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkColorFilterImageFilter)
@@ -33,7 +33,7 @@
 private:
     SkColorFilterImageFilter(SkColorFilter* cf,
                              SkImageFilter* input,
-                             const SkIRect* cropRect = NULL);
+                             const CropRect* cropRect = NULL);
     SkColorFilter*  fColorFilter;
 
     typedef SkImageFilter INHERITED;
diff --git a/include/effects/SkLightingImageFilter.h b/include/effects/SkLightingImageFilter.h
index 9c90cd9..529ae9d 100644
--- a/include/effects/SkLightingImageFilter.h
+++ b/include/effects/SkLightingImageFilter.h
@@ -52,24 +52,24 @@
 public:
     static SkImageFilter* CreateDistantLitDiffuse(const SkPoint3& direction,
         SkColor lightColor, SkScalar surfaceScale, SkScalar kd,
-        SkImageFilter* input = NULL, const SkIRect* cropRect = NULL);
+        SkImageFilter* input = NULL, const CropRect* cropRect = NULL);
     static SkImageFilter* CreatePointLitDiffuse(const SkPoint3& location,
         SkColor lightColor, SkScalar surfaceScale, SkScalar kd,
-        SkImageFilter* input = NULL, const SkIRect* cropRect = NULL);
+        SkImageFilter* input = NULL, const CropRect* cropRect = NULL);
     static SkImageFilter* CreateSpotLitDiffuse(const SkPoint3& location,
         const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle,
         SkColor lightColor, SkScalar surfaceScale, SkScalar kd,
-        SkImageFilter* input = NULL, const SkIRect* cropRect = NULL);
+        SkImageFilter* input = NULL, const CropRect* cropRect = NULL);
     static SkImageFilter* CreateDistantLitSpecular(const SkPoint3& direction,
         SkColor lightColor, SkScalar surfaceScale, SkScalar ks,
-        SkScalar shininess, SkImageFilter* input = NULL, const SkIRect* cropRect = NULL);
+        SkScalar shininess, SkImageFilter* input = NULL, const CropRect* cropRect = NULL);
     static SkImageFilter* CreatePointLitSpecular(const SkPoint3& location,
         SkColor lightColor, SkScalar surfaceScale, SkScalar ks,
-        SkScalar shininess, SkImageFilter* input = NULL, const SkIRect* cropRect = NULL);
+        SkScalar shininess, SkImageFilter* input = NULL, const CropRect* cropRect = NULL);
     static SkImageFilter* CreateSpotLitSpecular(const SkPoint3& location,
         const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle,
         SkColor lightColor, SkScalar surfaceScale, SkScalar ks,
-        SkScalar shininess, SkImageFilter* input = NULL, const SkIRect* cropRect = NULL);
+        SkScalar shininess, SkImageFilter* input = NULL, const CropRect* cropRect = NULL);
     ~SkLightingImageFilter();
 
     SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
@@ -78,7 +78,7 @@
     SkLightingImageFilter(SkLight* light,
                           SkScalar surfaceScale,
                           SkImageFilter* input,
-                          const SkIRect* cropRect = NULL);
+                          const CropRect* cropRect = NULL);
     explicit SkLightingImageFilter(SkFlattenableReadBuffer& buffer);
     virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
     const SkLight* light() const { return fLight; }
diff --git a/include/effects/SkMergeImageFilter.h b/include/effects/SkMergeImageFilter.h
index 310c6cd..ad464d3 100755
--- a/include/effects/SkMergeImageFilter.h
+++ b/include/effects/SkMergeImageFilter.h
@@ -16,10 +16,10 @@
 public:
     SkMergeImageFilter(SkImageFilter* first, SkImageFilter* second,
                        SkXfermode::Mode = SkXfermode::kSrcOver_Mode,
-                       const SkIRect* cropRect = NULL);
+                       const CropRect* cropRect = NULL);
     SkMergeImageFilter(SkImageFilter* filters[], int count,
                        const SkXfermode::Mode modes[] = NULL,
-                       const SkIRect* cropRect = NULL);
+                       const CropRect* cropRect = NULL);
     virtual ~SkMergeImageFilter();
 
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkMergeImageFilter)
diff --git a/include/effects/SkMorphologyImageFilter.h b/include/effects/SkMorphologyImageFilter.h
index d63f49d..880fc2e 100644
--- a/include/effects/SkMorphologyImageFilter.h
+++ b/include/effects/SkMorphologyImageFilter.h
@@ -14,7 +14,7 @@
 
 class SK_API SkMorphologyImageFilter : public SkImageFilter {
 public:
-    SkMorphologyImageFilter(int radiusX, int radiusY, SkImageFilter* input, const SkIRect* cropRect);
+    SkMorphologyImageFilter(int radiusX, int radiusY, SkImageFilter* input, const CropRect* cropRect);
 
 protected:
     SkMorphologyImageFilter(SkFlattenableReadBuffer& buffer);
@@ -34,7 +34,7 @@
 public:
     SkDilateImageFilter(int radiusX, int radiusY,
                         SkImageFilter* input = NULL,
-                        const SkIRect* cropRect = NULL)
+                        const CropRect* cropRect = NULL)
     : INHERITED(radiusX, radiusY, input, cropRect) {}
 
     virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
@@ -57,7 +57,7 @@
 public:
     SkErodeImageFilter(int radiusX, int radiusY,
                        SkImageFilter* input = NULL,
-                       const SkIRect* cropRect = NULL)
+                       const CropRect* cropRect = NULL)
     : INHERITED(radiusX, radiusY, input, cropRect) {}
 
     virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
diff --git a/include/effects/SkOffsetImageFilter.h b/include/effects/SkOffsetImageFilter.h
index 0b8c900..7059033 100644
--- a/include/effects/SkOffsetImageFilter.h
+++ b/include/effects/SkOffsetImageFilter.h
@@ -16,7 +16,7 @@
 
 public:
     SkOffsetImageFilter(SkScalar dx, SkScalar dy, SkImageFilter* input = NULL,
-                        const SkIRect* cropRect = NULL);
+                        const CropRect* cropRect = NULL);
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkOffsetImageFilter)
 
 protected:
diff --git a/include/effects/SkXfermodeImageFilter.h b/include/effects/SkXfermodeImageFilter.h
index 4a5d7fa..6343c4b 100644
--- a/include/effects/SkXfermodeImageFilter.h
+++ b/include/effects/SkXfermodeImageFilter.h
@@ -22,7 +22,7 @@
 
 public:
     SkXfermodeImageFilter(SkXfermode* mode, SkImageFilter* background,
-                          SkImageFilter* foreground = NULL, const SkIRect* cropRect = NULL);
+                          SkImageFilter* foreground = NULL, const CropRect* cropRect = NULL);
 
     virtual ~SkXfermodeImageFilter();
 
@@ -34,7 +34,7 @@
                                SkBitmap* dst,
                                SkIPoint* offset) SK_OVERRIDE;
 #if SK_SUPPORT_GPU
-    virtual bool canFilterImageGPU() const SK_OVERRIDE { return cropRect().isLargest(); }
+    virtual bool canFilterImageGPU() const SK_OVERRIDE { return !cropRectIsSet(); }
     virtual bool filterImageGPU(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
                                 SkBitmap* result, SkIPoint* offset) SK_OVERRIDE;
 #endif
diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp
index 502613b..3b7de25 100644
--- a/src/core/SkImageFilter.cpp
+++ b/src/core/SkImageFilter.cpp
@@ -18,27 +18,39 @@
 
 SK_DEFINE_INST_COUNT(SkImageFilter)
 
-SkImageFilter::SkImageFilter(int inputCount, SkImageFilter** inputs, const SkIRect* cropRect)
+SkImageFilter::SkImageFilter(int inputCount, SkImageFilter** inputs, const CropRect* cropRect)
   : fInputCount(inputCount),
     fInputs(new SkImageFilter*[inputCount]),
+#ifdef SK_CROP_RECT_IS_INT
     fCropRect(cropRect ? *cropRect : SkIRect::MakeLargest()) {
+#else
+    fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)) {
+#endif
     for (int i = 0; i < inputCount; ++i) {
         fInputs[i] = inputs[i];
         SkSafeRef(fInputs[i]);
     }
 }
 
-SkImageFilter::SkImageFilter(SkImageFilter* input, const SkIRect* cropRect)
+SkImageFilter::SkImageFilter(SkImageFilter* input, const CropRect* cropRect)
   : fInputCount(1),
     fInputs(new SkImageFilter*[1]),
+#ifdef SK_CROP_RECT_IS_INT
     fCropRect(cropRect ? *cropRect : SkIRect::MakeLargest()) {
+#else
+    fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)) {
+#endif
     fInputs[0] = input;
     SkSafeRef(fInputs[0]);
 }
 
-SkImageFilter::SkImageFilter(SkImageFilter* input1, SkImageFilter* input2, const SkIRect* cropRect)
+SkImageFilter::SkImageFilter(SkImageFilter* input1, SkImageFilter* input2, const CropRect* cropRect)
   : fInputCount(2), fInputs(new SkImageFilter*[2]),
-  fCropRect(cropRect ? *cropRect : SkIRect::MakeLargest()) {
+#ifdef SK_CROP_RECT_IS_INT
+    fCropRect(cropRect ? *cropRect : SkIRect::MakeLargest()) {
+#else
+    fCropRect(cropRect ? *cropRect : CropRect(SkRect(), 0x0)) {
+#endif
     fInputs[0] = input1;
     fInputs[1] = input2;
     SkSafeRef(fInputs[0]);
@@ -61,7 +73,12 @@
             fInputs[i] = NULL;
         }
     }
+#ifdef SK_CROP_RECT_IS_INT
     buffer.readIRect(&fCropRect);
+#else
+    buffer.readRect(&fCropRect.fRect);
+    fCropRect.fFlags = buffer.readUInt();
+#endif
 }
 
 void SkImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
@@ -73,7 +90,12 @@
             buffer.writeFlattenable(input);
         }
     }
+#ifdef SK_CROP_RECT_IS_INT
     buffer.writeIRect(fCropRect);
+#else
+    buffer.writeRect(fCropRect.fRect);
+    buffer.writeUInt(fCropRect.fFlags);
+#endif
 }
 
 bool SkImageFilter::filterImage(Proxy* proxy, const SkBitmap& src,
@@ -156,6 +178,7 @@
 
 bool SkImageFilter::applyCropRect(SkIRect* rect, const SkMatrix& matrix) const {
     SkRect cropRect;
+#ifdef SK_CROP_RECT_IS_INT
     matrix.mapRect(&cropRect, SkRect::Make(fCropRect));
     SkIRect cropRectI;
     cropRect.roundOut(&cropRectI);
@@ -164,6 +187,16 @@
     if (fCropRect.fTop == SK_MinS32) cropRectI.fTop = SK_MinS32;
     if (fCropRect.fRight == SK_MaxS32) cropRectI.fRight = SK_MaxS32;
     if (fCropRect.fBottom == SK_MaxS32) cropRectI.fBottom = SK_MaxS32;
+#else
+    matrix.mapRect(&cropRect, fCropRect.fRect);
+    SkIRect cropRectI;
+    cropRect.roundOut(&cropRectI);
+    // If the original crop rect edges were unset, max out the new crop edges
+    if (!(fCropRect.fFlags & CropRect::kHasLeft_CropEdge)) cropRectI.fLeft = SK_MinS32;
+    if (!(fCropRect.fFlags & CropRect::kHasTop_CropEdge)) cropRectI.fTop = SK_MinS32;
+    if (!(fCropRect.fFlags & CropRect::kHasRight_CropEdge)) cropRectI.fRight = SK_MaxS32;
+    if (!(fCropRect.fFlags & CropRect::kHasBottom_CropEdge)) cropRectI.fBottom = SK_MaxS32;
+#endif
     return rect->intersect(cropRectI);
 }
 
diff --git a/src/effects/SkBlurImageFilter.cpp b/src/effects/SkBlurImageFilter.cpp
index 3f97ddd..abbf971 100644
--- a/src/effects/SkBlurImageFilter.cpp
+++ b/src/effects/SkBlurImageFilter.cpp
@@ -24,7 +24,7 @@
 SkBlurImageFilter::SkBlurImageFilter(SkScalar sigmaX,
                                      SkScalar sigmaY,
                                      SkImageFilter* input,
-                                     const SkIRect* cropRect)
+                                     const CropRect* cropRect)
     : INHERITED(input, cropRect), fSigma(SkSize::Make(sigmaX, sigmaY)) {
     SkASSERT(sigmaX >= 0 && sigmaY >= 0);
 }
diff --git a/src/effects/SkColorFilterImageFilter.cpp b/src/effects/SkColorFilterImageFilter.cpp
index cfda0b7..a756a47 100755
--- a/src/effects/SkColorFilterImageFilter.cpp
+++ b/src/effects/SkColorFilterImageFilter.cpp
@@ -57,7 +57,7 @@
 };
 
 SkColorFilterImageFilter* SkColorFilterImageFilter::Create(SkColorFilter* cf,
-        SkImageFilter* input, const SkIRect* cropRect) {
+        SkImageFilter* input, const CropRect* cropRect) {
     SkASSERT(cf);
     SkScalar colorMatrix[20], inputMatrix[20];
     SkColorFilter* inputColorFilter;
@@ -76,7 +76,7 @@
 }
 
 SkColorFilterImageFilter::SkColorFilterImageFilter(SkColorFilter* cf,
-        SkImageFilter* input, const SkIRect* cropRect)
+        SkImageFilter* input, const CropRect* cropRect)
     : INHERITED(input, cropRect), fColorFilter(cf) {
     SkASSERT(cf);
     SkSafeRef(cf);
@@ -126,7 +126,7 @@
 }
 
 bool SkColorFilterImageFilter::asColorFilter(SkColorFilter** filter) const {
-    if (cropRect().isLargest()) {
+    if (!cropRectIsSet()) {
         if (filter) {
             *filter = fColorFilter;
             fColorFilter->ref();
diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp
index aac5462..c28b317 100644
--- a/src/effects/SkLightingImageFilter.cpp
+++ b/src/effects/SkLightingImageFilter.cpp
@@ -260,7 +260,7 @@
 class SkDiffuseLightingImageFilter : public SkLightingImageFilter {
 public:
     SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale,
-                                 SkScalar kd, SkImageFilter* input, const SkIRect* cropRect);
+                                 SkScalar kd, SkImageFilter* input, const CropRect* cropRect);
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiffuseLightingImageFilter)
 
 #if SK_SUPPORT_GPU
@@ -282,7 +282,7 @@
 
 class SkSpecularLightingImageFilter : public SkLightingImageFilter {
 public:
-    SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess, SkImageFilter* input, const SkIRect* cropRect);
+    SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess, SkImageFilter* input, const CropRect* cropRect);
     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpecularLightingImageFilter)
 
 #if SK_SUPPORT_GPU
@@ -797,7 +797,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-SkLightingImageFilter::SkLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkImageFilter* input, const SkIRect* cropRect)
+SkLightingImageFilter::SkLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkImageFilter* input, const CropRect* cropRect)
   : INHERITED(input, cropRect),
     fLight(light),
     fSurfaceScale(SkScalarDiv(surfaceScale, SkIntToScalar(255)))
@@ -809,7 +809,7 @@
 
 SkImageFilter* SkLightingImageFilter::CreateDistantLitDiffuse(
     const SkPoint3& direction, SkColor lightColor, SkScalar surfaceScale,
-    SkScalar kd, SkImageFilter* input, const SkIRect* cropRect) {
+    SkScalar kd, SkImageFilter* input, const CropRect* cropRect) {
     return SkNEW_ARGS(SkDiffuseLightingImageFilter,
         (SkNEW_ARGS(SkDistantLight, (direction, lightColor)), surfaceScale, kd,
         input, cropRect));
@@ -817,7 +817,7 @@
 
 SkImageFilter* SkLightingImageFilter::CreatePointLitDiffuse(
     const SkPoint3& location, SkColor lightColor, SkScalar surfaceScale,
-    SkScalar kd, SkImageFilter* input, const SkIRect* cropRect) {
+    SkScalar kd, SkImageFilter* input, const CropRect* cropRect) {
     return SkNEW_ARGS(SkDiffuseLightingImageFilter,
         (SkNEW_ARGS(SkPointLight, (location, lightColor)), surfaceScale, kd,
         input, cropRect));
@@ -827,7 +827,7 @@
     const SkPoint3& location, const SkPoint3& target,
     SkScalar specularExponent, SkScalar cutoffAngle,
     SkColor lightColor, SkScalar surfaceScale, SkScalar kd,
-    SkImageFilter* input, const SkIRect* cropRect) {
+    SkImageFilter* input, const CropRect* cropRect) {
     return SkNEW_ARGS(SkDiffuseLightingImageFilter,
         (SkNEW_ARGS(SkSpotLight, (location, target, specularExponent,
                                   cutoffAngle, lightColor)),
@@ -836,7 +836,7 @@
 
 SkImageFilter* SkLightingImageFilter::CreateDistantLitSpecular(
     const SkPoint3& direction, SkColor lightColor, SkScalar surfaceScale,
-    SkScalar ks, SkScalar shininess, SkImageFilter* input, const SkIRect* cropRect) {
+    SkScalar ks, SkScalar shininess, SkImageFilter* input, const CropRect* cropRect) {
     return SkNEW_ARGS(SkSpecularLightingImageFilter,
         (SkNEW_ARGS(SkDistantLight, (direction, lightColor)),
         surfaceScale, ks, shininess, input, cropRect));
@@ -844,7 +844,7 @@
 
 SkImageFilter* SkLightingImageFilter::CreatePointLitSpecular(
     const SkPoint3& location, SkColor lightColor, SkScalar surfaceScale,
-    SkScalar ks, SkScalar shininess, SkImageFilter* input, const SkIRect* cropRect) {
+    SkScalar ks, SkScalar shininess, SkImageFilter* input, const CropRect* cropRect) {
     return SkNEW_ARGS(SkSpecularLightingImageFilter,
         (SkNEW_ARGS(SkPointLight, (location, lightColor)),
         surfaceScale, ks, shininess, input, cropRect));
@@ -854,7 +854,7 @@
     const SkPoint3& location, const SkPoint3& target,
     SkScalar specularExponent, SkScalar cutoffAngle,
     SkColor lightColor, SkScalar surfaceScale,
-    SkScalar ks, SkScalar shininess, SkImageFilter* input, const SkIRect* cropRect) {
+    SkScalar ks, SkScalar shininess, SkImageFilter* input, const CropRect* cropRect) {
     return SkNEW_ARGS(SkSpecularLightingImageFilter,
         (SkNEW_ARGS(SkSpotLight, (location, target, specularExponent, cutoffAngle, lightColor)),
         surfaceScale, ks, shininess, input, cropRect));
@@ -879,7 +879,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar kd, SkImageFilter* input, const SkIRect* cropRect = NULL)
+SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar kd, SkImageFilter* input, const CropRect* cropRect = NULL)
   : SkLightingImageFilter(light, surfaceScale, input, cropRect),
     fKD(kd)
 {
@@ -954,7 +954,7 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess, SkImageFilter* input, const SkIRect* cropRect)
+SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess, SkImageFilter* input, const CropRect* cropRect)
   : SkLightingImageFilter(light, surfaceScale, input, cropRect),
     fKS(ks),
     fShininess(shininess)
diff --git a/src/effects/SkMergeImageFilter.cpp b/src/effects/SkMergeImageFilter.cpp
index 0205330..7d12ebe 100755
--- a/src/effects/SkMergeImageFilter.cpp
+++ b/src/effects/SkMergeImageFilter.cpp
@@ -40,7 +40,7 @@
 
 SkMergeImageFilter::SkMergeImageFilter(SkImageFilter* first, SkImageFilter* second,
                                        SkXfermode::Mode mode,
-                                       const SkIRect* cropRect) : INHERITED(first, second, cropRect) {
+                                       const CropRect* cropRect) : INHERITED(first, second, cropRect) {
     if (SkXfermode::kSrcOver_Mode != mode) {
         SkXfermode::Mode modes[] = { mode, mode };
         this->initModes(modes);
@@ -51,7 +51,7 @@
 
 SkMergeImageFilter::SkMergeImageFilter(SkImageFilter* filters[], int count,
                                        const SkXfermode::Mode modes[],
-                                       const SkIRect* cropRect) : INHERITED(count, filters, cropRect) {
+                                       const CropRect* cropRect) : INHERITED(count, filters, cropRect) {
     this->initModes(modes);
 }
 
diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp
index 8b314c8..d02e8ca 100644
--- a/src/effects/SkMorphologyImageFilter.cpp
+++ b/src/effects/SkMorphologyImageFilter.cpp
@@ -25,7 +25,7 @@
     fRadius.fHeight = buffer.readInt();
 }
 
-SkMorphologyImageFilter::SkMorphologyImageFilter(int radiusX, int radiusY, SkImageFilter* input, const SkIRect* cropRect)
+SkMorphologyImageFilter::SkMorphologyImageFilter(int radiusX, int radiusY, SkImageFilter* input, const CropRect* cropRect)
     : INHERITED(input, cropRect), fRadius(SkISize::Make(radiusX, radiusY)) {
 }
 
diff --git a/src/effects/SkOffsetImageFilter.cpp b/src/effects/SkOffsetImageFilter.cpp
index 3b98160..d684ded 100644
--- a/src/effects/SkOffsetImageFilter.cpp
+++ b/src/effects/SkOffsetImageFilter.cpp
@@ -19,7 +19,7 @@
                                         SkIPoint* loc) {
     SkImageFilter* input = getInput(0);
     SkBitmap src = source;
-    if (cropRect().isLargest()) {
+    if (!cropRectIsSet()) {
         if (input && !input->filterImage(proxy, source, matrix, &src, loc)) {
             return false;
         }
@@ -71,7 +71,7 @@
 }
 
 SkOffsetImageFilter::SkOffsetImageFilter(SkScalar dx, SkScalar dy, SkImageFilter* input,
-                                         const SkIRect* cropRect) : INHERITED(input, cropRect) {
+                                         const CropRect* cropRect) : INHERITED(input, cropRect) {
     fOffset.set(dx, dy);
 }
 
diff --git a/src/effects/SkXfermodeImageFilter.cpp b/src/effects/SkXfermodeImageFilter.cpp
index 8491292..5175fd4 100644
--- a/src/effects/SkXfermodeImageFilter.cpp
+++ b/src/effects/SkXfermodeImageFilter.cpp
@@ -23,7 +23,7 @@
 SkXfermodeImageFilter::SkXfermodeImageFilter(SkXfermode* mode,
                                              SkImageFilter* background,
                                              SkImageFilter* foreground,
-                                             const SkIRect* cropRect)
+                                             const CropRect* cropRect)
   : INHERITED(background, foreground, cropRect), fMode(mode) {
     SkSafeRef(fMode);
 }
diff --git a/tests/ImageFilterTest.cpp b/tests/ImageFilterTest.cpp
index 99b5a72..4165f2f 100644
--- a/tests/ImageFilterTest.cpp
+++ b/tests/ImageFilterTest.cpp
@@ -67,7 +67,7 @@
         return SkColorFilterImageFilter::Create(filter, input);
     }
 
-    static SkImageFilter* make_grayscale(SkImageFilter* input = NULL, const SkIRect* cropRect = NULL) {
+    static SkImageFilter* make_grayscale(SkImageFilter* input = NULL, const SkImageFilter::CropRect* cropRect = NULL) {
         SkScalar matrix[20];
         memset(matrix, 0, 20 * sizeof(SkScalar));
         matrix[0] = matrix[5] = matrix[10] = SkFloatToScalar(0.2126f);
@@ -109,7 +109,11 @@
         {
             // Check that a color filter image filter with a crop rect cannot
             // be expressed as a color filter.
+#ifdef SK_CROP_RECT_IS_INT
             SkIRect cropRect = SkIRect::MakeXYWH(0, 0, 100, 100);
+#else
+            SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(0, 0, 100, 100));
+#endif
             SkAutoTUnref<SkImageFilter> grayWithCrop(make_grayscale(NULL, &cropRect));
             REPORTER_ASSERT(reporter, false == grayWithCrop->asColorFilter(NULL));
         }