1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2011 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "gm/gm.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFont.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFontTypes.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageFilter.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkShader.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTileMode.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypeface.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkGradientShader.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkImageFilters.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkRuntimeEffect.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "tools/fonts/FontToolUtils.h"
32*c8dee2aaSAndroid Build Coastguard Worker
33*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
34*c8dee2aaSAndroid Build Coastguard Worker
make_src(int w,int h)35*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkImage> make_src(int w, int h) {
36*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(w, h)));
37*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = surface->getCanvas();
38*c8dee2aaSAndroid Build Coastguard Worker
39*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
40*c8dee2aaSAndroid Build Coastguard Worker SkPoint pts[] = { {0, 0}, {SkIntToScalar(w), SkIntToScalar(h)} };
41*c8dee2aaSAndroid Build Coastguard Worker SkColor colors[] = {
42*c8dee2aaSAndroid Build Coastguard Worker SK_ColorTRANSPARENT, SK_ColorGREEN, SK_ColorCYAN,
43*c8dee2aaSAndroid Build Coastguard Worker SK_ColorRED, SK_ColorMAGENTA, SK_ColorWHITE,
44*c8dee2aaSAndroid Build Coastguard Worker };
45*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, std::size(colors),
46*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kClamp));
47*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPaint(paint);
48*c8dee2aaSAndroid Build Coastguard Worker return surface->makeImageSnapshot();
49*c8dee2aaSAndroid Build Coastguard Worker }
50*c8dee2aaSAndroid Build Coastguard Worker
make_dst(int w,int h)51*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkImage> make_dst(int w, int h) {
52*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(w, h)));
53*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = surface->getCanvas();
54*c8dee2aaSAndroid Build Coastguard Worker
55*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
56*c8dee2aaSAndroid Build Coastguard Worker SkPoint pts[] = { {0, SkIntToScalar(h)}, {SkIntToScalar(w), 0} };
57*c8dee2aaSAndroid Build Coastguard Worker SkColor colors[] = {
58*c8dee2aaSAndroid Build Coastguard Worker SK_ColorBLUE, SK_ColorYELLOW, SK_ColorBLACK, SK_ColorGREEN,
59*c8dee2aaSAndroid Build Coastguard Worker SK_ColorGRAY,
60*c8dee2aaSAndroid Build Coastguard Worker };
61*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, std::size(colors),
62*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kClamp));
63*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPaint(paint);
64*c8dee2aaSAndroid Build Coastguard Worker return surface->makeImageSnapshot();
65*c8dee2aaSAndroid Build Coastguard Worker }
66*c8dee2aaSAndroid Build Coastguard Worker
show_k_text(SkCanvas * canvas,SkScalar x,SkScalar y,const SkScalar k[])67*c8dee2aaSAndroid Build Coastguard Worker static void show_k_text(SkCanvas* canvas, SkScalar x, SkScalar y, const SkScalar k[]) {
68*c8dee2aaSAndroid Build Coastguard Worker SkFont font(ToolUtils::DefaultPortableTypeface(), 24);
69*c8dee2aaSAndroid Build Coastguard Worker font.setEdging(SkFont::Edging::kAntiAlias);
70*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
71*c8dee2aaSAndroid Build Coastguard Worker paint.setAntiAlias(true);
72*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 4; ++i) {
73*c8dee2aaSAndroid Build Coastguard Worker SkString str;
74*c8dee2aaSAndroid Build Coastguard Worker str.appendScalar(k[i]);
75*c8dee2aaSAndroid Build Coastguard Worker SkScalar width = font.measureText(str.c_str(), str.size(), SkTextEncoding::kUTF8);
76*c8dee2aaSAndroid Build Coastguard Worker canvas->drawString(str, x, y + font.getSize(), font, paint);
77*c8dee2aaSAndroid Build Coastguard Worker x += width + SkIntToScalar(10);
78*c8dee2aaSAndroid Build Coastguard Worker }
79*c8dee2aaSAndroid Build Coastguard Worker }
80*c8dee2aaSAndroid Build Coastguard Worker
81*c8dee2aaSAndroid Build Coastguard Worker class ArithmodeGM : public skiagm::GM {
getName() const82*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override { return SkString("arithmode"); }
83*c8dee2aaSAndroid Build Coastguard Worker
getISize()84*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return {640, 572}; }
85*c8dee2aaSAndroid Build Coastguard Worker
onDraw(SkCanvas * canvas)86*c8dee2aaSAndroid Build Coastguard Worker void onDraw(SkCanvas* canvas) override {
87*c8dee2aaSAndroid Build Coastguard Worker constexpr int WW = 100,
88*c8dee2aaSAndroid Build Coastguard Worker HH = 32;
89*c8dee2aaSAndroid Build Coastguard Worker
90*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> src = make_src(WW, HH);
91*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> dst = make_dst(WW, HH);
92*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImageFilter> srcFilter = SkImageFilters::Image(src, {SkFilterMode::kLinear});
93*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImageFilter> dstFilter = SkImageFilters::Image(dst, {SkFilterMode::kLinear});
94*c8dee2aaSAndroid Build Coastguard Worker
95*c8dee2aaSAndroid Build Coastguard Worker constexpr SkScalar one = SK_Scalar1;
96*c8dee2aaSAndroid Build Coastguard Worker constexpr SkScalar K[] = {
97*c8dee2aaSAndroid Build Coastguard Worker 0, 0, 0, 0,
98*c8dee2aaSAndroid Build Coastguard Worker 0, 0, 0, one,
99*c8dee2aaSAndroid Build Coastguard Worker 0, one, 0, 0,
100*c8dee2aaSAndroid Build Coastguard Worker 0, 0, one, 0,
101*c8dee2aaSAndroid Build Coastguard Worker 0, one, one, 0,
102*c8dee2aaSAndroid Build Coastguard Worker 0, one, -one, 0,
103*c8dee2aaSAndroid Build Coastguard Worker 0, one/2, one/2, 0,
104*c8dee2aaSAndroid Build Coastguard Worker 0, one/2, one/2, one/4,
105*c8dee2aaSAndroid Build Coastguard Worker 0, one/2, one/2, -one/4,
106*c8dee2aaSAndroid Build Coastguard Worker one/4, one/2, one/2, 0,
107*c8dee2aaSAndroid Build Coastguard Worker -one/4, one/2, one/2, 0,
108*c8dee2aaSAndroid Build Coastguard Worker };
109*c8dee2aaSAndroid Build Coastguard Worker
110*c8dee2aaSAndroid Build Coastguard Worker const SkScalar* k = K;
111*c8dee2aaSAndroid Build Coastguard Worker const SkScalar* stop = k + std::size(K);
112*c8dee2aaSAndroid Build Coastguard Worker // Many of the Arithmetic filters have a 4th coefficient that's not zero, which means they
113*c8dee2aaSAndroid Build Coastguard Worker // affect transparent black. 'rect' is used as a crop filter to make sure they don't
114*c8dee2aaSAndroid Build Coastguard Worker // overwrite each other.
115*c8dee2aaSAndroid Build Coastguard Worker const SkRect rect = SkRect::MakeWH(WW, HH);
116*c8dee2aaSAndroid Build Coastguard Worker SkScalar gap = SkIntToScalar(WW + 20);
117*c8dee2aaSAndroid Build Coastguard Worker while (k < stop) {
118*c8dee2aaSAndroid Build Coastguard Worker {
119*c8dee2aaSAndroid Build Coastguard Worker SkAutoCanvasRestore acr(canvas, true);
120*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(src, 0, 0);
121*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(gap, 0);
122*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(dst, 0, 0);
123*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(gap, 0);
124*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
125*c8dee2aaSAndroid Build Coastguard Worker paint.setImageFilter(SkImageFilters::Arithmetic(k[0], k[1], k[2], k[3], true,
126*c8dee2aaSAndroid Build Coastguard Worker dstFilter, srcFilter, rect));
127*c8dee2aaSAndroid Build Coastguard Worker canvas->saveLayer(nullptr, &paint);
128*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
129*c8dee2aaSAndroid Build Coastguard Worker
130*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(gap, 0);
131*c8dee2aaSAndroid Build Coastguard Worker show_k_text(canvas, 0, 0, k);
132*c8dee2aaSAndroid Build Coastguard Worker }
133*c8dee2aaSAndroid Build Coastguard Worker
134*c8dee2aaSAndroid Build Coastguard Worker k += 4;
135*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, HH + 12);
136*c8dee2aaSAndroid Build Coastguard Worker }
137*c8dee2aaSAndroid Build Coastguard Worker
138*c8dee2aaSAndroid Build Coastguard Worker // Draw two special cases to test enforcePMColor. In these cases, we
139*c8dee2aaSAndroid Build Coastguard Worker // draw the dst bitmap twice, the first time it is halved and inverted,
140*c8dee2aaSAndroid Build Coastguard Worker // leading to invalid premultiplied colors. If we enforcePMColor, these
141*c8dee2aaSAndroid Build Coastguard Worker // invalid values should be clamped, and will not contribute to the
142*c8dee2aaSAndroid Build Coastguard Worker // second draw.
143*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 2; i++) {
144*c8dee2aaSAndroid Build Coastguard Worker const bool enforcePMColor = (i == 0);
145*c8dee2aaSAndroid Build Coastguard Worker
146*c8dee2aaSAndroid Build Coastguard Worker {
147*c8dee2aaSAndroid Build Coastguard Worker SkAutoCanvasRestore acr(canvas, true);
148*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(gap, 0);
149*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(dst, 0, 0);
150*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(gap, 0);
151*c8dee2aaSAndroid Build Coastguard Worker
152*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImageFilter> bg =
153*c8dee2aaSAndroid Build Coastguard Worker SkImageFilters::Arithmetic(0, 0, -one / 2, 1, enforcePMColor, dstFilter,
154*c8dee2aaSAndroid Build Coastguard Worker nullptr, nullptr);
155*c8dee2aaSAndroid Build Coastguard Worker SkPaint p;
156*c8dee2aaSAndroid Build Coastguard Worker p.setImageFilter(SkImageFilters::Arithmetic(0, one / 2, -one, 1, true,
157*c8dee2aaSAndroid Build Coastguard Worker std::move(bg), dstFilter, rect));
158*c8dee2aaSAndroid Build Coastguard Worker canvas->saveLayer(nullptr, &p);
159*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
160*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(gap, 0);
161*c8dee2aaSAndroid Build Coastguard Worker
162*c8dee2aaSAndroid Build Coastguard Worker // Label
163*c8dee2aaSAndroid Build Coastguard Worker SkFont font(ToolUtils::DefaultPortableTypeface(), 24);
164*c8dee2aaSAndroid Build Coastguard Worker SkString str(enforcePMColor ? "enforcePM" : "no enforcePM");
165*c8dee2aaSAndroid Build Coastguard Worker canvas->drawString(str, 0, font.getSize(), font, SkPaint());
166*c8dee2aaSAndroid Build Coastguard Worker }
167*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, HH + 12);
168*c8dee2aaSAndroid Build Coastguard Worker }
169*c8dee2aaSAndroid Build Coastguard Worker }
170*c8dee2aaSAndroid Build Coastguard Worker
171*c8dee2aaSAndroid Build Coastguard Worker private:
172*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = GM;
173*c8dee2aaSAndroid Build Coastguard Worker };
174*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new ArithmodeGM; )
175*c8dee2aaSAndroid Build Coastguard Worker
176*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////
177*c8dee2aaSAndroid Build Coastguard Worker
178*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkBlenders.h"
179*c8dee2aaSAndroid Build Coastguard Worker
180*c8dee2aaSAndroid Build Coastguard Worker class ArithmodeBlenderGM : public skiagm::GM {
181*c8dee2aaSAndroid Build Coastguard Worker float fK1, fK2, fK3, fK4;
182*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> fSrc, fDst, fChecker;
183*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> fSrcShader, fDstShader;
184*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkRuntimeEffect> fRuntimeEffect;
185*c8dee2aaSAndroid Build Coastguard Worker
getName() const186*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override { return SkString("arithmode_blender"); }
187*c8dee2aaSAndroid Build Coastguard Worker
188*c8dee2aaSAndroid Build Coastguard Worker static constexpr int W = 200;
189*c8dee2aaSAndroid Build Coastguard Worker static constexpr int H = 200;
190*c8dee2aaSAndroid Build Coastguard Worker
getISize()191*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return {(W + 30) * 2, (H + 30) * 4}; }
192*c8dee2aaSAndroid Build Coastguard Worker
onOnceBeforeDraw()193*c8dee2aaSAndroid Build Coastguard Worker void onOnceBeforeDraw() override {
194*c8dee2aaSAndroid Build Coastguard Worker // Prepare a runtime effect for this blend.
195*c8dee2aaSAndroid Build Coastguard Worker static constexpr char kShader[] = R"(
196*c8dee2aaSAndroid Build Coastguard Worker uniform shader srcImage;
197*c8dee2aaSAndroid Build Coastguard Worker uniform shader dstImage;
198*c8dee2aaSAndroid Build Coastguard Worker uniform blender arithBlend;
199*c8dee2aaSAndroid Build Coastguard Worker half4 main(float2 xy) {
200*c8dee2aaSAndroid Build Coastguard Worker return arithBlend.eval(srcImage.eval(xy), dstImage.eval(xy));
201*c8dee2aaSAndroid Build Coastguard Worker }
202*c8dee2aaSAndroid Build Coastguard Worker )";
203*c8dee2aaSAndroid Build Coastguard Worker auto [effect, error] = SkRuntimeEffect::MakeForShader(SkString(kShader));
204*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(effect);
205*c8dee2aaSAndroid Build Coastguard Worker fRuntimeEffect = effect;
206*c8dee2aaSAndroid Build Coastguard Worker
207*c8dee2aaSAndroid Build Coastguard Worker // Start with interesting K-values, in case we're drawn without calling onAnimate().
208*c8dee2aaSAndroid Build Coastguard Worker fK1 = -0.25f;
209*c8dee2aaSAndroid Build Coastguard Worker fK2 = 0.25f;
210*c8dee2aaSAndroid Build Coastguard Worker fK3 = 0.25f;
211*c8dee2aaSAndroid Build Coastguard Worker fK4 = 0;
212*c8dee2aaSAndroid Build Coastguard Worker
213*c8dee2aaSAndroid Build Coastguard Worker fSrc = make_src(W, H);
214*c8dee2aaSAndroid Build Coastguard Worker fDst = make_dst(W, H);
215*c8dee2aaSAndroid Build Coastguard Worker fSrcShader = fSrc->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions());
216*c8dee2aaSAndroid Build Coastguard Worker fDstShader = fDst->makeShader(SkTileMode::kClamp, SkTileMode::kClamp, SkSamplingOptions());
217*c8dee2aaSAndroid Build Coastguard Worker
218*c8dee2aaSAndroid Build Coastguard Worker fChecker = ToolUtils::create_checkerboard_image(W, H, 0xFFBBBBBB, 0xFFEEEEEE, 8);
219*c8dee2aaSAndroid Build Coastguard Worker }
220*c8dee2aaSAndroid Build Coastguard Worker
onAnimate(double nanos)221*c8dee2aaSAndroid Build Coastguard Worker bool onAnimate(double nanos) override {
222*c8dee2aaSAndroid Build Coastguard Worker double theta = nanos * 1e-6 * 0.001;
223*c8dee2aaSAndroid Build Coastguard Worker fK1 = sin(theta + 0) * 0.25;
224*c8dee2aaSAndroid Build Coastguard Worker fK2 = cos(theta + 1) * 0.25;
225*c8dee2aaSAndroid Build Coastguard Worker fK3 = sin(theta + 2) * 0.25;
226*c8dee2aaSAndroid Build Coastguard Worker fK4 = 0.5;
227*c8dee2aaSAndroid Build Coastguard Worker return true;
228*c8dee2aaSAndroid Build Coastguard Worker }
229*c8dee2aaSAndroid Build Coastguard Worker
onDraw(SkCanvas * canvas)230*c8dee2aaSAndroid Build Coastguard Worker void onDraw(SkCanvas* canvas) override {
231*c8dee2aaSAndroid Build Coastguard Worker const SkRect rect = SkRect::MakeWH(W, H);
232*c8dee2aaSAndroid Build Coastguard Worker
233*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(fSrc, 10, 10);
234*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(fDst, 10, 10 + H + 10);
235*c8dee2aaSAndroid Build Coastguard Worker
236*c8dee2aaSAndroid Build Coastguard Worker SkSamplingOptions sampling;
237*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkBlender> blender = SkBlenders::Arithmetic(fK1, fK2, fK3, fK4,
238*c8dee2aaSAndroid Build Coastguard Worker /*enforcePremul=*/true);
239*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(10 + W + 10, 10);
240*c8dee2aaSAndroid Build Coastguard Worker
241*c8dee2aaSAndroid Build Coastguard Worker // All three images drawn below should appear identical.
242*c8dee2aaSAndroid Build Coastguard Worker // Draw via blend step
243*c8dee2aaSAndroid Build Coastguard Worker SkPaint blenderPaint;
244*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(fChecker, 0, 0);
245*c8dee2aaSAndroid Build Coastguard Worker canvas->saveLayer(&rect, nullptr);
246*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(fDst, 0, 0);
247*c8dee2aaSAndroid Build Coastguard Worker blenderPaint.setBlender(blender);
248*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(fSrc, 0, 0, sampling, &blenderPaint);
249*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
250*c8dee2aaSAndroid Build Coastguard Worker
251*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, 10 + H);
252*c8dee2aaSAndroid Build Coastguard Worker
253*c8dee2aaSAndroid Build Coastguard Worker // Draw via SkImageFilters::Blend (should appear the same as above)
254*c8dee2aaSAndroid Build Coastguard Worker SkPaint imageFilterPaint;
255*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(fChecker, 0, 0);
256*c8dee2aaSAndroid Build Coastguard Worker imageFilterPaint.setImageFilter(
257*c8dee2aaSAndroid Build Coastguard Worker SkImageFilters::Blend(blender,
258*c8dee2aaSAndroid Build Coastguard Worker /*background=*/nullptr,
259*c8dee2aaSAndroid Build Coastguard Worker /*foreground=*/SkImageFilters::Image(fSrc, sampling)));
260*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(fDst, 0, 0, sampling, &imageFilterPaint);
261*c8dee2aaSAndroid Build Coastguard Worker
262*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, 10 + H);
263*c8dee2aaSAndroid Build Coastguard Worker
264*c8dee2aaSAndroid Build Coastguard Worker // Draw via SkShaders::Blend (should still appear the same as above)
265*c8dee2aaSAndroid Build Coastguard Worker SkPaint shaderBlendPaint;
266*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(fChecker, 0, 0);
267*c8dee2aaSAndroid Build Coastguard Worker shaderBlendPaint.setShader(SkShaders::Blend(blender, fDstShader, fSrcShader));
268*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(rect, shaderBlendPaint);
269*c8dee2aaSAndroid Build Coastguard Worker
270*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, 10 + H);
271*c8dee2aaSAndroid Build Coastguard Worker
272*c8dee2aaSAndroid Build Coastguard Worker // Draw via runtime effect (should still appear the same as above)
273*c8dee2aaSAndroid Build Coastguard Worker SkPaint runtimePaint;
274*c8dee2aaSAndroid Build Coastguard Worker canvas->drawImage(fChecker, 0, 0);
275*c8dee2aaSAndroid Build Coastguard Worker SkRuntimeEffect::ChildPtr children[] = {fSrcShader, fDstShader, blender};
276*c8dee2aaSAndroid Build Coastguard Worker runtimePaint.setShader(fRuntimeEffect->makeShader(/*uniforms=*/{}, children));
277*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(rect, runtimePaint);
278*c8dee2aaSAndroid Build Coastguard Worker }
279*c8dee2aaSAndroid Build Coastguard Worker
280*c8dee2aaSAndroid Build Coastguard Worker private:
281*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = GM;
282*c8dee2aaSAndroid Build Coastguard Worker };
283*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new ArithmodeBlenderGM; )
284