clipShader -- raster implementation

1. pass shader+op down to device
2. bitmapdevice pass it down to rasterclip
3. rasterclip only ever stores at most one shader
   - if there is a ctm, fold that into (another) shader
   - if the op is difference, invert the sense of alpha
   - if there was a previous shader, compose with it
4. pass through to rasterpipelineblitter
5. it prepends the colorPipeline with the clipShader, and stashes its
   results in a buffer (fClipShaderBuffer)
6. in each blit, scale/lerp from the buffer before storing the result

Change-Id: I07c7a8a20b9ae95cdcc9954237d115e63819f7c1
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/275798
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
diff --git a/gm/complexclip.cpp b/gm/complexclip.cpp
index 944251a..faceb6b 100644
--- a/gm/complexclip.cpp
+++ b/gm/complexclip.cpp
@@ -20,6 +20,7 @@
 #include "include/core/SkTypeface.h"
 #include "include/core/SkTypes.h"
 #include "src/core/SkClipOpPriv.h"
+#include "tools/Resources.h"
 #include "tools/ToolUtils.h"
 
 #include <string.h>
@@ -209,3 +210,39 @@
 DEF_GM(return new ComplexClipGM(true, true, false);)
 DEF_GM(return new ComplexClipGM(true, true, true);)
 }
+
+DEF_SIMPLE_GM(clip_shader, canvas, 840, 650) {
+    auto img = GetResourceAsImage("images/yellow_rose.png");
+    auto sh = img->makeShader();
+
+    SkRect r = SkRect::MakeIWH(img->width(), img->height());
+    SkPaint p;
+
+    canvas->translate(10, 10);
+    canvas->drawImage(img, 0, 0, nullptr);
+
+    canvas->save();
+    canvas->translate(img->width() + 10, 0);
+    canvas->clipShader(sh, SkClipOp::kIntersect);
+    p.setColor(SK_ColorRED);
+    canvas->drawRect(r, p);
+    canvas->restore();
+
+    canvas->save();
+    canvas->translate(0, img->height() + 10);
+    canvas->clipShader(sh, SkClipOp::kDifference);
+    p.setColor(SK_ColorGREEN);
+    canvas->drawRect(r, p);
+    canvas->restore();
+
+    canvas->save();
+    canvas->translate(img->width() + 10, img->height() + 10);
+    canvas->clipShader(sh, SkClipOp::kIntersect);
+    canvas->save();
+    SkMatrix lm = SkMatrix::MakeScale(1.0f / 5);
+    canvas->clipShader(img->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat, &lm));
+    canvas->drawImage(img, 0, 0, nullptr);
+
+    canvas->restore();
+    canvas->restore();
+}