Change SkMatrix::decomposeScale to use preScale

While most callers of decomposeScale only depend on the scale factors
that are returned, image filter decomposition depends on the remaining
matrix as well. Hence, the following necessary updates to work with
the new behavior of decomposeScale:

* Update imagefilter DAG sample to reflect prescaling
* Correct embedded matrix in SkApplyCTMToFilter
* Add comment to clipRectBounds() clarifying coordinate spaces and image filters

But, we want to have decomposeScale using preScale() because it then
produces a remainder matrix that can be used as the transform for the
image filter draw, instead of wrapping the image filter in an
SkMatrixImageFilter as currently done by SkApplyCTMToFilter.

Bug: skia:7211
Change-Id: If14570afb4189cebc75f3815e8ccdde05cb074e1
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/228438
Reviewed-by: Mike Reed <reed@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index b6e9d19..251e71b 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -828,6 +828,20 @@
 
 bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveLayerFlags saveLayerFlags,
                               SkIRect* intersection, const SkImageFilter* imageFilter) {
+    // clipRectBounds() is called to determine the input layer size needed for a given image filter.
+    // The coordinate space of the rectangle passed to filterBounds(kReverse) is meant to be in the
+    // filtering layer space. Here, 'clipBounds' is always in the true device space. When an image
+    // filter does not require a decomposed CTM matrix, the filter space and device space are the
+    // same. When it has been decomposed, we want the original image filter node to process the
+    // bounds in the layer space represented by the decomposed scale matrix. 'imageFilter' is no
+    // longer the original filter, but has the remainder matrix baked into it, and passing in the
+    // the true device clip bounds ensures that the matrix image filter provides a layer clip bounds
+    // to the original filter node (barring inflation from consecutive calls to mapRect). While
+    // initially counter-intuitive given the apparent inconsistency of coordinate spaces, always
+    // passing getDeviceClipBounds() to 'imageFilter' is correct.
+    // FIXME (michaelludwig) - When the remainder matrix is instead applied as a final draw, it will
+    // be important to more accurately calculate the clip bounds in the layer space for the original
+    // image filter (similar to how matrix image filter does it, but ideally without the inflation).
     SkIRect clipBounds = this->getDeviceClipBounds();
     if (clipBounds.isEmpty()) {
         return false;