Make SkImageFilter::applyCropRect() optionally compute srcBounds.

BUG=skia:4526

Review URL: https://codereview.chromium.org/1410553007
diff --git a/include/core/SkImageFilter.h b/include/core/SkImageFilter.h
index 0c3d4c2..d90df29 100644
--- a/include/core/SkImageFilter.h
+++ b/include/core/SkImageFilter.h
@@ -368,14 +368,18 @@
         return false;
     }
 
-    /** Computes source bounds as the src bitmap bounds offset by srcOffset.
-     *  Apply the transformed crop rect to the bounds if any of the
-     *  corresponding edge flags are set. Intersects the result against the
-     *  context's clipBounds, and returns the result in "bounds". If there is
-     *  no intersection, returns false and leaves "bounds" unchanged.
+    /** Given a "src" bitmap and its "srcOffset", computes source and
+     *  destination bounds for this filter. Initial bounds are the
+     *  "src" bitmap bounds offset by "srcOffset". "dstBounds" are
+     *  computed by transforming the crop rect by the context's CTM,
+     *  applying it to the initial bounds, and intersecting the result
+     *  with the context's clip bounds.  "srcBounds" (if non-null) are
+     *  computed by intersecting the initial bounds with "dstBounds", to
+     *  ensure that we never sample outside of the crop rect (this restriction
+     *  may be relaxed in the future).
      */
     bool applyCropRect(const Context&, const SkBitmap& src, const SkIPoint& srcOffset,
-                       SkIRect* bounds) const;
+                       SkIRect* dstBounds, SkIRect* srcBounds = nullptr) const;
 
     /** Same as the above call, except that if the resulting crop rect is not
      *  entirely contained by the source bitmap's bounds, it creates a new
diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp
index 9579302..25eecb0 100644
--- a/src/core/SkImageFilter.cpp
+++ b/src/core/SkImageFilter.cpp
@@ -391,11 +391,15 @@
 }
 
 bool SkImageFilter::applyCropRect(const Context& ctx, const SkBitmap& src,
-                                  const SkIPoint& srcOffset, SkIRect* bounds) const {
-    SkIRect srcBounds;
-    src.getBounds(&srcBounds);
-    srcBounds.offset(srcOffset);
-    return fCropRect.applyTo(srcBounds, ctx, bounds);
+                                  const SkIPoint& srcOffset, SkIRect* dstBounds,
+                                  SkIRect* srcBounds) const {
+    SkIRect storage;
+    if (!srcBounds) {
+        srcBounds = &storage;
+    }
+    src.getBounds(srcBounds);
+    srcBounds->offset(srcOffset);
+    return fCropRect.applyTo(*srcBounds, ctx, dstBounds) && srcBounds->intersect(*dstBounds);
 }
 
 bool SkImageFilter::applyCropRect(const Context& ctx, Proxy* proxy, const SkBitmap& src,