1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2012 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/SkBitmap.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBlendMode.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorPriv.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageInfo.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkShader.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkString.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTileMode.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/private/base/SkTDArray.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkTLazy.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "tools/GpuToolUtils.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "tools/ToolUtils.h"
32*c8dee2aaSAndroid Build Coastguard Worker
33*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
34*c8dee2aaSAndroid Build Coastguard Worker
make_shader(SkBlendMode mode)35*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> make_shader(SkBlendMode mode) {
36*c8dee2aaSAndroid Build Coastguard Worker SkPoint pts[2];
37*c8dee2aaSAndroid Build Coastguard Worker SkColor colors[2];
38*c8dee2aaSAndroid Build Coastguard Worker
39*c8dee2aaSAndroid Build Coastguard Worker pts[0].set(0, 0);
40*c8dee2aaSAndroid Build Coastguard Worker pts[1].set(SkIntToScalar(100), 0);
41*c8dee2aaSAndroid Build Coastguard Worker colors[0] = SK_ColorRED;
42*c8dee2aaSAndroid Build Coastguard Worker colors[1] = SK_ColorBLUE;
43*c8dee2aaSAndroid Build Coastguard Worker auto shaderA = SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp);
44*c8dee2aaSAndroid Build Coastguard Worker
45*c8dee2aaSAndroid Build Coastguard Worker pts[0].set(0, 0);
46*c8dee2aaSAndroid Build Coastguard Worker pts[1].set(0, SkIntToScalar(100));
47*c8dee2aaSAndroid Build Coastguard Worker colors[0] = SK_ColorBLACK;
48*c8dee2aaSAndroid Build Coastguard Worker colors[1] = SkColorSetARGB(0x80, 0, 0, 0);
49*c8dee2aaSAndroid Build Coastguard Worker auto shaderB = SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp);
50*c8dee2aaSAndroid Build Coastguard Worker
51*c8dee2aaSAndroid Build Coastguard Worker return SkShaders::Blend(mode, std::move(shaderA), std::move(shaderB));
52*c8dee2aaSAndroid Build Coastguard Worker }
53*c8dee2aaSAndroid Build Coastguard Worker
54*c8dee2aaSAndroid Build Coastguard Worker class ComposeShaderGM : public skiagm::GM {
55*c8dee2aaSAndroid Build Coastguard Worker protected:
onOnceBeforeDraw()56*c8dee2aaSAndroid Build Coastguard Worker void onOnceBeforeDraw() override {
57*c8dee2aaSAndroid Build Coastguard Worker fShader = make_shader(SkBlendMode::kDstIn);
58*c8dee2aaSAndroid Build Coastguard Worker }
59*c8dee2aaSAndroid Build Coastguard Worker
getName() const60*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override { return SkString("composeshader"); }
61*c8dee2aaSAndroid Build Coastguard Worker
getISize()62*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return SkISize::Make(120, 120); }
63*c8dee2aaSAndroid Build Coastguard Worker
onDraw(SkCanvas * canvas)64*c8dee2aaSAndroid Build Coastguard Worker void onDraw(SkCanvas* canvas) override {
65*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
66*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(SK_ColorGREEN);
67*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(SkRect::MakeWH(100, 100), paint);
68*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(fShader);
69*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(SkRect::MakeWH(100, 100), paint);
70*c8dee2aaSAndroid Build Coastguard Worker }
71*c8dee2aaSAndroid Build Coastguard Worker
72*c8dee2aaSAndroid Build Coastguard Worker protected:
73*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> fShader;
74*c8dee2aaSAndroid Build Coastguard Worker
75*c8dee2aaSAndroid Build Coastguard Worker private:
76*c8dee2aaSAndroid Build Coastguard Worker typedef GM INHERITED ;
77*c8dee2aaSAndroid Build Coastguard Worker };
78*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new ComposeShaderGM; )
79*c8dee2aaSAndroid Build Coastguard Worker
80*c8dee2aaSAndroid Build Coastguard Worker class ComposeShaderAlphaGM : public skiagm::GM {
81*c8dee2aaSAndroid Build Coastguard Worker public:
ComposeShaderAlphaGM()82*c8dee2aaSAndroid Build Coastguard Worker ComposeShaderAlphaGM() {}
83*c8dee2aaSAndroid Build Coastguard Worker
84*c8dee2aaSAndroid Build Coastguard Worker protected:
getName() const85*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override { return SkString("composeshader_alpha"); }
86*c8dee2aaSAndroid Build Coastguard Worker
getISize()87*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override { return SkISize::Make(750, 220); }
88*c8dee2aaSAndroid Build Coastguard Worker
onDraw(SkCanvas * canvas)89*c8dee2aaSAndroid Build Coastguard Worker void onDraw(SkCanvas* canvas) override {
90*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> shaders[] = {
91*c8dee2aaSAndroid Build Coastguard Worker make_shader(SkBlendMode::kDstIn),
92*c8dee2aaSAndroid Build Coastguard Worker make_shader(SkBlendMode::kSrcOver),
93*c8dee2aaSAndroid Build Coastguard Worker };
94*c8dee2aaSAndroid Build Coastguard Worker
95*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
96*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(SK_ColorGREEN);
97*c8dee2aaSAndroid Build Coastguard Worker
98*c8dee2aaSAndroid Build Coastguard Worker const SkRect r = SkRect::MakeXYWH(5, 5, 100, 100);
99*c8dee2aaSAndroid Build Coastguard Worker
100*c8dee2aaSAndroid Build Coastguard Worker for (size_t y = 0; y < std::size(shaders); ++y) {
101*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
102*c8dee2aaSAndroid Build Coastguard Worker for (int alpha = 0xFF; alpha > 0; alpha -= 0x28) {
103*c8dee2aaSAndroid Build Coastguard Worker paint.setAlphaf(1.0f);
104*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(nullptr);
105*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
106*c8dee2aaSAndroid Build Coastguard Worker
107*c8dee2aaSAndroid Build Coastguard Worker paint.setAlpha(alpha);
108*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(shaders[y]);
109*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
110*c8dee2aaSAndroid Build Coastguard Worker
111*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(r.width() + 5, 0);
112*c8dee2aaSAndroid Build Coastguard Worker }
113*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
114*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, r.height() + 5);
115*c8dee2aaSAndroid Build Coastguard Worker }
116*c8dee2aaSAndroid Build Coastguard Worker }
117*c8dee2aaSAndroid Build Coastguard Worker
118*c8dee2aaSAndroid Build Coastguard Worker private:
119*c8dee2aaSAndroid Build Coastguard Worker typedef GM INHERITED ;
120*c8dee2aaSAndroid Build Coastguard Worker };
DEF_GM(return new ComposeShaderAlphaGM;)121*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new ComposeShaderAlphaGM; )
122*c8dee2aaSAndroid Build Coastguard Worker
123*c8dee2aaSAndroid Build Coastguard Worker // creates a square bitmap with red background and a green circle in the center
124*c8dee2aaSAndroid Build Coastguard Worker static void draw_color_bm(SkBitmap* bm, int length) {
125*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
126*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(SK_ColorGREEN);
127*c8dee2aaSAndroid Build Coastguard Worker
128*c8dee2aaSAndroid Build Coastguard Worker bm->allocN32Pixels(length, length);
129*c8dee2aaSAndroid Build Coastguard Worker bm->eraseColor(SK_ColorRED);
130*c8dee2aaSAndroid Build Coastguard Worker
131*c8dee2aaSAndroid Build Coastguard Worker SkCanvas canvas(*bm);
132*c8dee2aaSAndroid Build Coastguard Worker canvas.drawCircle(SkIntToScalar(length/2), SkIntToScalar(length/2), SkIntToScalar(length/2),
133*c8dee2aaSAndroid Build Coastguard Worker paint);
134*c8dee2aaSAndroid Build Coastguard Worker }
135*c8dee2aaSAndroid Build Coastguard Worker
136*c8dee2aaSAndroid Build Coastguard Worker // creates a square alpha8 bitmap with transparent background and an opaque circle in the center
draw_alpha8_bm(SkBitmap * bm,int length)137*c8dee2aaSAndroid Build Coastguard Worker static void draw_alpha8_bm(SkBitmap* bm, int length) {
138*c8dee2aaSAndroid Build Coastguard Worker SkPaint circlePaint;
139*c8dee2aaSAndroid Build Coastguard Worker circlePaint.setColor(SK_ColorBLACK);
140*c8dee2aaSAndroid Build Coastguard Worker
141*c8dee2aaSAndroid Build Coastguard Worker bm->allocPixels(SkImageInfo::MakeA8(length, length));
142*c8dee2aaSAndroid Build Coastguard Worker bm->eraseColor(SK_ColorTRANSPARENT);
143*c8dee2aaSAndroid Build Coastguard Worker
144*c8dee2aaSAndroid Build Coastguard Worker SkCanvas canvas(*bm);
145*c8dee2aaSAndroid Build Coastguard Worker canvas.drawCircle(SkIntToScalar(length/2), SkIntToScalar(length/2), SkIntToScalar(length/4),
146*c8dee2aaSAndroid Build Coastguard Worker circlePaint);
147*c8dee2aaSAndroid Build Coastguard Worker }
148*c8dee2aaSAndroid Build Coastguard Worker
149*c8dee2aaSAndroid Build Coastguard Worker // creates a linear gradient shader
make_linear_gradient_shader(int length)150*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> make_linear_gradient_shader(int length) {
151*c8dee2aaSAndroid Build Coastguard Worker SkPoint pts[2];
152*c8dee2aaSAndroid Build Coastguard Worker SkColor colors[2];
153*c8dee2aaSAndroid Build Coastguard Worker pts[0].set(0, 0);
154*c8dee2aaSAndroid Build Coastguard Worker pts[1].set(SkIntToScalar(length), 0);
155*c8dee2aaSAndroid Build Coastguard Worker colors[0] = SK_ColorBLUE;
156*c8dee2aaSAndroid Build Coastguard Worker colors[1] = SkColorSetARGB(0, 0, 0, 0xFF);
157*c8dee2aaSAndroid Build Coastguard Worker return SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp);
158*c8dee2aaSAndroid Build Coastguard Worker }
159*c8dee2aaSAndroid Build Coastguard Worker
160*c8dee2aaSAndroid Build Coastguard Worker
161*c8dee2aaSAndroid Build Coastguard Worker class ComposeShaderBitmapGM : public skiagm::GM {
162*c8dee2aaSAndroid Build Coastguard Worker public:
ComposeShaderBitmapGM(bool use_lm)163*c8dee2aaSAndroid Build Coastguard Worker ComposeShaderBitmapGM(bool use_lm) : fUseLocalMatrix(use_lm) {}
164*c8dee2aaSAndroid Build Coastguard Worker
165*c8dee2aaSAndroid Build Coastguard Worker protected:
getName() const166*c8dee2aaSAndroid Build Coastguard Worker SkString getName() const override {
167*c8dee2aaSAndroid Build Coastguard Worker return SkStringPrintf("composeshader_bitmap%s", fUseLocalMatrix ? "_lm" : "");
168*c8dee2aaSAndroid Build Coastguard Worker }
169*c8dee2aaSAndroid Build Coastguard Worker
getISize()170*c8dee2aaSAndroid Build Coastguard Worker SkISize getISize() override {
171*c8dee2aaSAndroid Build Coastguard Worker return SkISize::Make(7 * (squareLength + 5), 2 * (squareLength + 5));
172*c8dee2aaSAndroid Build Coastguard Worker }
173*c8dee2aaSAndroid Build Coastguard Worker
onDraw(SkCanvas * canvas)174*c8dee2aaSAndroid Build Coastguard Worker void onDraw(SkCanvas* canvas) override {
175*c8dee2aaSAndroid Build Coastguard Worker if (!fInitialized) {
176*c8dee2aaSAndroid Build Coastguard Worker draw_color_bm(&fColorBitmap, squareLength);
177*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> img = SkImages::RasterFromBitmap(fColorBitmap);
178*c8dee2aaSAndroid Build Coastguard Worker img = ToolUtils::MakeTextureImage(canvas, std::move(img));
179*c8dee2aaSAndroid Build Coastguard Worker if (img) {
180*c8dee2aaSAndroid Build Coastguard Worker fColorBitmapShader = img->makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat,
181*c8dee2aaSAndroid Build Coastguard Worker SkSamplingOptions(), SkMatrix::I());
182*c8dee2aaSAndroid Build Coastguard Worker }
183*c8dee2aaSAndroid Build Coastguard Worker draw_alpha8_bm(&fAlpha8Bitmap, squareLength);
184*c8dee2aaSAndroid Build Coastguard Worker img = SkImages::RasterFromBitmap(fAlpha8Bitmap);
185*c8dee2aaSAndroid Build Coastguard Worker img = ToolUtils::MakeTextureImage(canvas, std::move(img));
186*c8dee2aaSAndroid Build Coastguard Worker if (img) {
187*c8dee2aaSAndroid Build Coastguard Worker fAlpha8BitmapShader = fAlpha8Bitmap.makeShader(SkTileMode::kRepeat,
188*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kRepeat,
189*c8dee2aaSAndroid Build Coastguard Worker SkSamplingOptions(),
190*c8dee2aaSAndroid Build Coastguard Worker SkMatrix::I());
191*c8dee2aaSAndroid Build Coastguard Worker }
192*c8dee2aaSAndroid Build Coastguard Worker fLinearGradientShader = make_linear_gradient_shader(squareLength);
193*c8dee2aaSAndroid Build Coastguard Worker fInitialized = true;
194*c8dee2aaSAndroid Build Coastguard Worker }
195*c8dee2aaSAndroid Build Coastguard Worker
196*c8dee2aaSAndroid Build Coastguard Worker SkBlendMode mode = SkBlendMode::kDstOver;
197*c8dee2aaSAndroid Build Coastguard Worker
198*c8dee2aaSAndroid Build Coastguard Worker SkMatrix lm = SkMatrix::Translate(0, squareLength * 0.5f);
199*c8dee2aaSAndroid Build Coastguard Worker
200*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> shaders[] = {
201*c8dee2aaSAndroid Build Coastguard Worker // gradient should appear over color bitmap
202*c8dee2aaSAndroid Build Coastguard Worker SkShaders::Blend(mode, fLinearGradientShader, fColorBitmapShader),
203*c8dee2aaSAndroid Build Coastguard Worker // gradient should appear over alpha8 bitmap colorized by the paint color
204*c8dee2aaSAndroid Build Coastguard Worker SkShaders::Blend(mode, fLinearGradientShader, fAlpha8BitmapShader),
205*c8dee2aaSAndroid Build Coastguard Worker };
206*c8dee2aaSAndroid Build Coastguard Worker if (fUseLocalMatrix) {
207*c8dee2aaSAndroid Build Coastguard Worker for (unsigned i = 0; i < std::size(shaders); ++i) {
208*c8dee2aaSAndroid Build Coastguard Worker shaders[i] = shaders[i] ? shaders[i]->makeWithLocalMatrix(lm) : nullptr;
209*c8dee2aaSAndroid Build Coastguard Worker }
210*c8dee2aaSAndroid Build Coastguard Worker }
211*c8dee2aaSAndroid Build Coastguard Worker
212*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
213*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(SK_ColorYELLOW);
214*c8dee2aaSAndroid Build Coastguard Worker
215*c8dee2aaSAndroid Build Coastguard Worker const SkRect r = SkRect::MakeIWH(squareLength, squareLength);
216*c8dee2aaSAndroid Build Coastguard Worker
217*c8dee2aaSAndroid Build Coastguard Worker for (size_t y = 0; y < std::size(shaders); ++y) {
218*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
219*c8dee2aaSAndroid Build Coastguard Worker for (int alpha = 0xFF; alpha > 0; alpha -= 0x28) {
220*c8dee2aaSAndroid Build Coastguard Worker paint.setAlpha(alpha);
221*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(shaders[y]);
222*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
223*c8dee2aaSAndroid Build Coastguard Worker
224*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(r.width() + 5, 0);
225*c8dee2aaSAndroid Build Coastguard Worker }
226*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
227*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, r.height() + 5);
228*c8dee2aaSAndroid Build Coastguard Worker }
229*c8dee2aaSAndroid Build Coastguard Worker }
230*c8dee2aaSAndroid Build Coastguard Worker
231*c8dee2aaSAndroid Build Coastguard Worker private:
232*c8dee2aaSAndroid Build Coastguard Worker /** This determines the length and width of the bitmaps used in the ComposeShaders. Values
233*c8dee2aaSAndroid Build Coastguard Worker * above 20 may cause an SkASSERT to fail in SkSmallAllocator. However, larger values will
234*c8dee2aaSAndroid Build Coastguard Worker * work in a release build. You can change this parameter and then compile a release build
235*c8dee2aaSAndroid Build Coastguard Worker * to have this GM draw larger bitmaps for easier visual inspection.
236*c8dee2aaSAndroid Build Coastguard Worker */
237*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int squareLength = 20;
238*c8dee2aaSAndroid Build Coastguard Worker
239*c8dee2aaSAndroid Build Coastguard Worker const bool fUseLocalMatrix;
240*c8dee2aaSAndroid Build Coastguard Worker
241*c8dee2aaSAndroid Build Coastguard Worker bool fInitialized = false;
242*c8dee2aaSAndroid Build Coastguard Worker SkBitmap fColorBitmap;
243*c8dee2aaSAndroid Build Coastguard Worker SkBitmap fAlpha8Bitmap;
244*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> fColorBitmapShader;
245*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> fAlpha8BitmapShader;
246*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> fLinearGradientShader;
247*c8dee2aaSAndroid Build Coastguard Worker
248*c8dee2aaSAndroid Build Coastguard Worker using INHERITED = GM;
249*c8dee2aaSAndroid Build Coastguard Worker };
250*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new ComposeShaderBitmapGM(false); )
DEF_GM(return new ComposeShaderBitmapGM (true);)251*c8dee2aaSAndroid Build Coastguard Worker DEF_GM( return new ComposeShaderBitmapGM(true); )
252*c8dee2aaSAndroid Build Coastguard Worker
253*c8dee2aaSAndroid Build Coastguard Worker DEF_SIMPLE_GM(composeshader_bitmap2, canvas, 200, 200) {
254*c8dee2aaSAndroid Build Coastguard Worker int width = 255;
255*c8dee2aaSAndroid Build Coastguard Worker int height = 255;
256*c8dee2aaSAndroid Build Coastguard Worker SkTDArray<uint8_t> dst8Storage;
257*c8dee2aaSAndroid Build Coastguard Worker dst8Storage.resize(width * height);
258*c8dee2aaSAndroid Build Coastguard Worker SkTDArray<uint32_t> dst32Storage;
259*c8dee2aaSAndroid Build Coastguard Worker dst32Storage.resize(width * height * sizeof(int32_t));
260*c8dee2aaSAndroid Build Coastguard Worker for (int y = 0; y < height; ++y) {
261*c8dee2aaSAndroid Build Coastguard Worker for (int x = 0; x < width; ++x) {
262*c8dee2aaSAndroid Build Coastguard Worker dst8Storage[y * width + x] = (y + x) / 2;
263*c8dee2aaSAndroid Build Coastguard Worker dst32Storage[y * width + x] = SkPackARGB32(0xFF, x, y, 0);
264*c8dee2aaSAndroid Build Coastguard Worker }
265*c8dee2aaSAndroid Build Coastguard Worker }
266*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
267*c8dee2aaSAndroid Build Coastguard Worker paint.setAntiAlias(true);
268*c8dee2aaSAndroid Build Coastguard Worker paint.setColor(SK_ColorBLUE);
269*c8dee2aaSAndroid Build Coastguard Worker SkRect r = {0, 0, SkIntToScalar(width), SkIntToScalar(height)};
270*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
271*c8dee2aaSAndroid Build Coastguard Worker SkBitmap skBitmap, skMask;
272*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo imageInfo = SkImageInfo::Make(width, height,
273*c8dee2aaSAndroid Build Coastguard Worker SkColorType::kN32_SkColorType, kPremul_SkAlphaType);
274*c8dee2aaSAndroid Build Coastguard Worker skBitmap.installPixels(imageInfo, dst32Storage.begin(), width * sizeof(int32_t),
275*c8dee2aaSAndroid Build Coastguard Worker nullptr, nullptr);
276*c8dee2aaSAndroid Build Coastguard Worker imageInfo = SkImageInfo::Make(width, height,
277*c8dee2aaSAndroid Build Coastguard Worker SkColorType::kAlpha_8_SkColorType, kPremul_SkAlphaType);
278*c8dee2aaSAndroid Build Coastguard Worker skMask.installPixels(imageInfo, dst8Storage.begin(), width, nullptr, nullptr);
279*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> skSrc = skBitmap.asImage();
280*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkImage> skMaskImage = skMask.asImage();
281*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(
282*c8dee2aaSAndroid Build Coastguard Worker SkShaders::Blend(SkBlendMode::kSrcIn,
283*c8dee2aaSAndroid Build Coastguard Worker skMaskImage->makeShader(SkSamplingOptions()),
284*c8dee2aaSAndroid Build Coastguard Worker skSrc->makeShader(SkSamplingOptions())));
285*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, paint);
286*c8dee2aaSAndroid Build Coastguard Worker }
287*c8dee2aaSAndroid Build Coastguard Worker
288*c8dee2aaSAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////////////////////////////////
289*c8dee2aaSAndroid Build Coastguard Worker
make_src_shader(SkScalar size)290*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> make_src_shader(SkScalar size) {
291*c8dee2aaSAndroid Build Coastguard Worker const SkPoint pts[] = { { 0, 0 }, { 0, size } };
292*c8dee2aaSAndroid Build Coastguard Worker const SkColor colors[] = { 0xFF0000FF, 0x000000FF };
293*c8dee2aaSAndroid Build Coastguard Worker return SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp);
294*c8dee2aaSAndroid Build Coastguard Worker }
295*c8dee2aaSAndroid Build Coastguard Worker
make_dst_shader(SkScalar size)296*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkShader> make_dst_shader(SkScalar size) {
297*c8dee2aaSAndroid Build Coastguard Worker const SkPoint pts[] = { { 0, 0 }, { size, 0 } };
298*c8dee2aaSAndroid Build Coastguard Worker const SkColor colors[] = { SK_ColorRED, 0x00FF0000 };
299*c8dee2aaSAndroid Build Coastguard Worker return SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp);
300*c8dee2aaSAndroid Build Coastguard Worker }
301*c8dee2aaSAndroid Build Coastguard Worker
302*c8dee2aaSAndroid Build Coastguard Worker const SkScalar gCellSize = 100;
303*c8dee2aaSAndroid Build Coastguard Worker
draw_cell(SkCanvas * canvas,sk_sp<SkShader> src,sk_sp<SkShader> dst,SkBlendMode mode,SkAlpha alpha)304*c8dee2aaSAndroid Build Coastguard Worker static void draw_cell(SkCanvas* canvas, sk_sp<SkShader> src, sk_sp<SkShader> dst,
305*c8dee2aaSAndroid Build Coastguard Worker SkBlendMode mode, SkAlpha alpha) {
306*c8dee2aaSAndroid Build Coastguard Worker const SkRect r = SkRect::MakeWH(gCellSize, gCellSize);
307*c8dee2aaSAndroid Build Coastguard Worker SkPaint p;
308*c8dee2aaSAndroid Build Coastguard Worker p.setAlpha(alpha);
309*c8dee2aaSAndroid Build Coastguard Worker
310*c8dee2aaSAndroid Build Coastguard Worker SkAutoCanvasRestore acr(canvas, false);
311*c8dee2aaSAndroid Build Coastguard Worker canvas->saveLayer(&r, &p);
312*c8dee2aaSAndroid Build Coastguard Worker p.setAlpha(0xFF);
313*c8dee2aaSAndroid Build Coastguard Worker
314*c8dee2aaSAndroid Build Coastguard Worker p.setShader(dst);
315*c8dee2aaSAndroid Build Coastguard Worker p.setBlendMode(SkBlendMode::kSrc);
316*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, p);
317*c8dee2aaSAndroid Build Coastguard Worker
318*c8dee2aaSAndroid Build Coastguard Worker p.setShader(src);
319*c8dee2aaSAndroid Build Coastguard Worker p.setBlendMode(mode);
320*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, p);
321*c8dee2aaSAndroid Build Coastguard Worker }
322*c8dee2aaSAndroid Build Coastguard Worker
draw_composed(SkCanvas * canvas,sk_sp<SkShader> src,sk_sp<SkShader> dst,SkBlendMode mode,SkAlpha alpha)323*c8dee2aaSAndroid Build Coastguard Worker static void draw_composed(SkCanvas* canvas, sk_sp<SkShader> src, sk_sp<SkShader> dst,
324*c8dee2aaSAndroid Build Coastguard Worker SkBlendMode mode, SkAlpha alpha) {
325*c8dee2aaSAndroid Build Coastguard Worker SkPaint p;
326*c8dee2aaSAndroid Build Coastguard Worker p.setAlpha(alpha);
327*c8dee2aaSAndroid Build Coastguard Worker p.setShader(SkShaders::Blend(mode, dst, src));
328*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(SkRect::MakeWH(gCellSize, gCellSize), p);
329*c8dee2aaSAndroid Build Coastguard Worker }
330*c8dee2aaSAndroid Build Coastguard Worker
draw_pair(SkCanvas * canvas,sk_sp<SkShader> src,sk_sp<SkShader> dst,SkBlendMode mode)331*c8dee2aaSAndroid Build Coastguard Worker static void draw_pair(SkCanvas* canvas, sk_sp<SkShader> src, sk_sp<SkShader> dst,
332*c8dee2aaSAndroid Build Coastguard Worker SkBlendMode mode) {
333*c8dee2aaSAndroid Build Coastguard Worker SkAutoCanvasRestore acr(canvas, true);
334*c8dee2aaSAndroid Build Coastguard Worker
335*c8dee2aaSAndroid Build Coastguard Worker const SkScalar gap = 4;
336*c8dee2aaSAndroid Build Coastguard Worker SkRect r = SkRect::MakeWH(2 * gCellSize + gap, 2 * gCellSize + gap);
337*c8dee2aaSAndroid Build Coastguard Worker r.outset(gap + 1.5f, gap + 1.5f);
338*c8dee2aaSAndroid Build Coastguard Worker SkPaint p;
339*c8dee2aaSAndroid Build Coastguard Worker p.setStyle(SkPaint::kStroke_Style);
340*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(r, p); // border
341*c8dee2aaSAndroid Build Coastguard Worker
342*c8dee2aaSAndroid Build Coastguard Worker SkAlpha alpha = 0xFF;
343*c8dee2aaSAndroid Build Coastguard Worker for (int y = 0; y < 2; ++y) {
344*c8dee2aaSAndroid Build Coastguard Worker draw_cell(canvas, src, dst, mode, alpha);
345*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
346*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(gCellSize + gap, 0);
347*c8dee2aaSAndroid Build Coastguard Worker draw_composed(canvas, src, dst, mode, alpha);
348*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
349*c8dee2aaSAndroid Build Coastguard Worker
350*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, gCellSize + gap);
351*c8dee2aaSAndroid Build Coastguard Worker alpha = 0x80;
352*c8dee2aaSAndroid Build Coastguard Worker }
353*c8dee2aaSAndroid Build Coastguard Worker }
354*c8dee2aaSAndroid Build Coastguard Worker
355*c8dee2aaSAndroid Build Coastguard Worker DEF_SIMPLE_GM(composeshader_grid, canvas, 882, 882) {
356*c8dee2aaSAndroid Build Coastguard Worker auto src = make_src_shader(gCellSize);
357*c8dee2aaSAndroid Build Coastguard Worker auto dst = make_dst_shader(gCellSize);
358*c8dee2aaSAndroid Build Coastguard Worker
359*c8dee2aaSAndroid Build Coastguard Worker const SkScalar margin = 15;
360*c8dee2aaSAndroid Build Coastguard Worker const SkScalar dx = 2*gCellSize + margin;
361*c8dee2aaSAndroid Build Coastguard Worker const SkScalar dy = 2*gCellSize + margin;
362*c8dee2aaSAndroid Build Coastguard Worker
363*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(margin, margin);
364*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
365*c8dee2aaSAndroid Build Coastguard Worker for (int m = 0; m < 16; ++m) {
366*c8dee2aaSAndroid Build Coastguard Worker SkBlendMode mode = static_cast<SkBlendMode>(m);
367*c8dee2aaSAndroid Build Coastguard Worker draw_pair(canvas, src, dst, mode);
368*c8dee2aaSAndroid Build Coastguard Worker if ((m % 4) == 3) {
369*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
370*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(0, dy);
371*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
372*c8dee2aaSAndroid Build Coastguard Worker } else {
373*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(dx, 0);
374*c8dee2aaSAndroid Build Coastguard Worker }
375*c8dee2aaSAndroid Build Coastguard Worker }
376*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
377*c8dee2aaSAndroid Build Coastguard Worker }
378