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