Flutter Engine
The Flutter Engine
graphitestart.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2021 Google LLC
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"
15#include "include/core/SkPath.h"
20#include "tools/DecodeUtils.h"
21#include "tools/GpuToolUtils.h"
22#include "tools/Resources.h"
23#include "tools/ToolUtils.h"
24
25namespace {
26
27sk_sp<SkShader> create_gradient_shader(SkRect r,
28 const std::array<SkColor, 3>& colors,
29 const std::array<float, 3>& offsets) {
30 SkPoint pts[2] = { {r.fLeft, r.fTop}, {r.fRight, r.fTop} };
31
32 return SkGradientShader::MakeLinear(pts, colors.data(), offsets.data(), std::size(colors),
34}
35
36sk_sp<SkShader> create_image_shader(SkCanvas* destCanvas, SkTileMode tmX, SkTileMode tmY) {
38
39 {
41 bitmap.allocPixels(ii);
42 bitmap.eraseColor(SK_ColorWHITE);
43
44 SkCanvas tmpCanvas(bitmap);
45
46 SkColor colors[3][3] = {
50 };
51
52 for (int y = 0; y < 3; ++y) {
53 for (int x = 0; x < 3; ++x) {
55 paint.setColor(colors[y][x]);
56 tmpCanvas.drawRect(SkRect::MakeXYWH(x*21, y*21, 22, 22), paint);
57 }
58 }
59
60 bitmap.setAlphaType(kOpaque_SkAlphaType);
61 bitmap.setImmutable();
62 }
63
65 img = ToolUtils::MakeTextureImage(destCanvas, std::move(img));
66 if (img) {
67 return img->makeShader(tmX, tmY, SkSamplingOptions());
68 } else {
69 return nullptr;
70 }
71}
72
73sk_sp<SkShader> create_blend_shader(SkCanvas* destCanvas, SkBlendMode bm) {
74 constexpr SkColor4f kTransYellow = {1.0f, 1.0f, 0.0f, 0.5f};
75
76 sk_sp<SkShader> dst = SkShaders::Color(kTransYellow, nullptr);
77 return SkShaders::Blend(bm,
78 std::move(dst),
79 create_image_shader(destCanvas,
81}
82
83sk_sp<SkColorFilter> create_grayscale_colorfilter() {
84 float matrix[20] = {};
85 matrix[0] = matrix[5] = matrix[10] = 0.2126f;
86 matrix[1] = matrix[6] = matrix[11] = 0.7152f;
87 matrix[2] = matrix[7] = matrix[12] = 0.0722f;
88 matrix[18] = 1.0f;
90}
91
92void draw_image_shader_tile(SkCanvas* canvas, SkRect clipRect) {
93 SkPaint p;
94 p.setShader(create_image_shader(canvas, SkTileMode::kClamp, SkTileMode::kRepeat));
95
97 path.moveTo(1, 1);
98 path.lineTo(32, 127);
99 path.lineTo(96, 127);
100 path.lineTo(127, 1);
101 path.lineTo(63, 32);
102 path.close();
103
104 canvas->save();
105 canvas->clipRect(clipRect);
106 canvas->scale(0.5f, 0.5f);
107 canvas->drawPath(path, p);
108
109 canvas->save();
110 canvas->concat(SkMatrix::RotateDeg(90, {64, 64}));
111 canvas->translate(128, 0);
112 canvas->drawPath(path, p);
113 canvas->restore();
114 canvas->restore();
115}
116
117void draw_gradient_tile(SkCanvas* canvas, SkRect clipRect) {
118 SkRect r{1, 1, 127, 127};
119 SkPaint p;
120 p.setShader(create_gradient_shader(r,
122 { 0.0f, 0.75f, 1.0f }));
123
124 canvas->save();
125 canvas->clipRect(clipRect);
126 canvas->translate(128, 0);
127 canvas->scale(0.5f, 0.5f);
128 canvas->drawRect(r, p);
129
130 canvas->save();
131 canvas->concat(SkMatrix::RotateDeg(90, {64, 64}));
132 canvas->translate(128, 0);
133 canvas->drawRect(r, p);
134 canvas->restore();
135 canvas->restore();
136}
137
138void draw_colorfilter_swatches(SkCanvas* canvas, SkRect clipRect) {
139 static constexpr int kNumTilesPerSide = 3;
140
141 SkSize tileSize = { clipRect.width() / kNumTilesPerSide, clipRect.height() / kNumTilesPerSide };
142
143 // Quantize to four colors
144 uint8_t table1[256];
145 for (int i = 0; i < 256; ++i) {
146 table1[i] = (i/64) * 85;
147 }
148
149 // table2 is a band-pass filter for 85-170.
150 // table3 re-expands that range to 0..255
151 uint8_t table2[256], table3[256];
152 for (int i = 0; i < 256; ++i) {
153 if (i >= 85 && i <= 170) {
154 table2[i] = i;
155 table3[i] = ((i - 85) / 85.0f) * 255.0f;
156 } else {
157 table2[i] = 0;
158 table3[i] = 0;
159 }
160 }
161
162 constexpr SkColor SK_ColorGREY = SkColorSetARGB(0xFF, 0x80, 0x80, 0x80);
163
164 sk_sp<SkColorFilter> colorFilters[kNumTilesPerSide*kNumTilesPerSide];
165 static const std::array<SkColor, 3> kGradientColors[kNumTilesPerSide*kNumTilesPerSide] = {
166 { SK_ColorBLACK, SK_ColorGREY, SK_ColorWHITE },
167 { SK_ColorBLACK, SK_ColorGREY, SK_ColorWHITE },
168 { SK_ColorBLACK, SK_ColorGREY, SK_ColorWHITE },
169 { SK_ColorBLACK, SK_ColorGREY, SK_ColorWHITE },
170 { 0x00000000, 0x80000000, 0xFF000000 }, // the Gaussian CF uses alpha only
171 { SK_ColorBLACK, SK_ColorGREY, SK_ColorWHITE },
172 { SK_ColorBLACK, SK_ColorGREY, SK_ColorWHITE },
173 { SK_ColorBLACK, SK_ColorGREY, SK_ColorWHITE },
174 { SK_ColorBLACK, SK_ColorGREY, SK_ColorWHITE },
175 };
176
177 colorFilters[0] = SkColorFilters::Lighting(SK_ColorLTGRAY, 0xFF440000);
178 colorFilters[1] = SkColorFilters::Table(table1);
179 colorFilters[2] = SkColorFilters::Compose(SkColorFilters::TableARGB(nullptr, table3,
180 table3, table3),
181 SkColorFilters::TableARGB(nullptr, table2,
182 table2, table2));
184 colorFilters[4] = SkColorFilterPriv::MakeGaussian();
185
186 colorFilters[5] = SkColorFilters::LinearToSRGBGamma();
187 colorFilters[6] = SkColorFilters::SRGBToLinearGamma();
188
189 SkPaint p;
190
191 canvas->save();
192 canvas->clipRect(clipRect);
193 canvas->translate(clipRect.fLeft, clipRect.fTop);
194
195 for (int y = 0; y < kNumTilesPerSide; ++y) {
196 for (int x = 0; x < kNumTilesPerSide; ++x) {
197 SkRect r = SkRect::MakeXYWH(x * tileSize.width(), y * tileSize.height(),
198 tileSize.width(), tileSize.height()).makeInset(1.0f,
199 1.0f);
200 int colorFilterIndex = x*kNumTilesPerSide+y;
201 p.setShader(create_gradient_shader(r,
202 kGradientColors[colorFilterIndex],
203 { 0.0f, 0.5f, 1.0f }));
204 p.setColorFilter(colorFilters[colorFilterIndex]);
205 canvas->drawRect(r, p);
206 }
207 }
208
209 canvas->restore();
210}
211
212void draw_blend_mode_swatches(SkCanvas* canvas, SkRect clipRect) {
213 static const int kTileHeight = 16;
214 static const int kTileWidth = 16;
215 static const SkColor4f kOpaqueWhite { 1.0f, 1.0f, 1.0f, 1.0f };
216 static const SkColor4f kTransBluish { 0.0f, 0.5f, 1.0f, 0.5f };
217 static const SkColor4f kTransWhite { 1.0f, 1.0f, 1.0f, 0.75f };
218
219 SkPaint dstPaint;
220 dstPaint.setColor(kOpaqueWhite);
222 dstPaint.setAntiAlias(false);
223
224 SkPaint srcPaint;
225 srcPaint.setColor(kTransBluish);
226 srcPaint.setAntiAlias(false);
227
229
230 // For the first pass we draw: transparent bluish on top of opaque white
231 // For the second pass we draw: transparent white on top of transparent bluish
232 for (int passes = 0; passes < 2; ++passes) {
233 for (int i = 0; i <= (int)SkBlendMode::kLastCoeffMode; ++i) {
234 if (r.fLeft+kTileWidth > clipRect.fRight) {
235 r.offsetTo(clipRect.fLeft, r.fTop+kTileHeight);
236 }
237
238 canvas->drawRect(r.makeInset(1.0f, 1.0f), dstPaint);
239 srcPaint.setBlendMode(static_cast<SkBlendMode>(i));
240 canvas->drawRect(r.makeInset(2.0f, 2.0f), srcPaint);
241
242 r.offset(kTileWidth, 0.0f);
243 }
244
245 r.offsetTo(clipRect.fLeft, r.fTop+kTileHeight);
246 srcPaint.setColor(kTransWhite);
247 dstPaint.setColor(kTransBluish);
248 }
249}
250
251} // anonymous namespace
252
253namespace skiagm {
254
255// This is just for bootstrapping Graphite.
256class GraphiteStartGM : public GM {
257public:
258 GraphiteStartGM() = default;
259
260protected:
261 static constexpr int kTileWidth = 128;
262 static constexpr int kTileHeight = 128;
263 static constexpr int kWidth = 3 * kTileWidth;
264 static constexpr int kHeight = 3 * kTileHeight;
265 static constexpr int kClipInset = 4;
266
267 void onOnceBeforeDraw() override {
269 ToolUtils::GetResourceAsBitmap("images/color_wheel.gif", &fBitmap);
270 }
271
272 SkString getName() const override { return SkString("graphitestart"); }
273
274 SkISize getISize() override { return SkISize::Make(kWidth, kHeight); }
275
276 void onDraw(SkCanvas* canvas) override {
277
279
280 canvas->save();
281 canvas->clipRRect(SkRRect::MakeRectXY(clipRect, 32.f, 32.f), true);
282
283 // Upper-left corner
284 draw_image_shader_tile(canvas, SkRect::MakeXYWH(0, 0, kTileWidth, kTileHeight));
285
286 // Upper-middle tile
287 draw_gradient_tile(canvas, SkRect::MakeXYWH(kTileWidth, 0, kTileWidth, kTileHeight));
288
289 // Upper-right corner
290 draw_colorfilter_swatches(canvas, SkRect::MakeXYWH(2*kTileWidth, 0,
292
293 // Middle-left tile
294 {
295 SkPaint p;
296 p.setColor(SK_ColorRED);
297
299 canvas->drawRect(r.makeInset(1.0f, 1.0f), p);
300 }
301
302 // Middle-middle tile
303 {
304 SkPaint p;
305 p.setShader(create_blend_shader(canvas, SkBlendMode::kModulate));
306
308 canvas->drawRect(r.makeInset(1.0f, 1.0f), p);
309 }
310
311 // Middle-right tile
312 {
313 sk_sp<SkImage> image(ToolUtils::GetResourceAsImage("images/mandrill_128.png"));
314 sk_sp<SkShader> shader;
315
316 if (image) {
318 shader = shader->makeWithColorFilter(create_grayscale_colorfilter());
319 }
320
321 SkPaint p;
322 p.setShader(std::move(shader));
323
325 canvas->drawRect(r.makeInset(1.0f, 1.0f), p);
326 }
327
328 canvas->restore();
329
330 // Bottom-left corner
331#if defined(SK_GRAPHITE)
332 // TODO: failing serialize test on Linux, not sure what's going on
333 canvas->writePixels(fBitmap, 0, 2*kTileHeight);
334#endif
335
336 // Bottom-middle tile
337 draw_blend_mode_swatches(canvas, SkRect::MakeXYWH(kTileWidth, 2*kTileHeight,
339
340 // Bottom-right corner
341 {
344
345 SkPaint circlePaint;
346 circlePaint.setColor(SK_ColorBLUE);
347 circlePaint.setBlendMode(SkBlendMode::kSrc);
348
349 canvas->clipRect(kTile);
350 canvas->drawRect(kTile.makeInset(10, 20), circlePaint);
351
352 SkPaint restorePaint;
353 restorePaint.setBlendMode(SkBlendMode::kPlus);
354
355 canvas->saveLayer(nullptr, &restorePaint);
356 circlePaint.setColor(SK_ColorRED);
357 circlePaint.setBlendMode(SkBlendMode::kSrc);
358
359 canvas->drawRect(kTile.makeInset(15, 25), circlePaint);
360 canvas->restore();
361 }
362 }
363
364private:
365 SkBitmap fBitmap;
366};
367
368//////////////////////////////////////////////////////////////////////////////
369
370DEF_GM(return new GraphiteStartGM;)
371
372} // namespace skiagm
@ kOpaque_SkAlphaType
pixel is opaque
Definition: SkAlphaType.h:28
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
SkBlendMode
Definition: SkBlendMode.h:38
@ kPlus
r = min(s + d, 1)
@ kModulate
r = s*d
@ kMultiply
r = s*(1-da) + d*(1-sa) + s*d
@ kLastCoeffMode
last porter duff blend mode
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition: SkColorType.h:24
constexpr SkColor SK_ColorYELLOW
Definition: SkColor.h:139
constexpr SkColor SK_ColorLTGRAY
Definition: SkColor.h:118
constexpr SkColor SK_ColorMAGENTA
Definition: SkColor.h:147
uint32_t SkColor
Definition: SkColor.h:37
constexpr SkColor SK_ColorCYAN
Definition: SkColor.h:143
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
constexpr SkColor SK_ColorWHITE
Definition: SkColor.h:122
constexpr SkColor SK_ColorDKGRAY
Definition: SkColor.h:108
SkTileMode
Definition: SkTileMode.h:13
int saveLayer(const SkRect *bounds, const SkPaint *paint)
Definition: SkCanvas.cpp:496
void drawRect(const SkRect &rect, const SkPaint &paint)
Definition: SkCanvas.cpp:1673
void clipRect(const SkRect &rect, SkClipOp op, bool doAntiAlias)
Definition: SkCanvas.cpp:1361
void restore()
Definition: SkCanvas.cpp:461
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278
bool writePixels(const SkImageInfo &info, const void *pixels, size_t rowBytes, int x, int y)
Definition: SkCanvas.cpp:399
int save()
Definition: SkCanvas.cpp:447
void drawPath(const SkPath &path, const SkPaint &paint)
Definition: SkCanvas.cpp:1747
void scale(SkScalar sx, SkScalar sy)
Definition: SkCanvas.cpp:1289
void concat(const SkMatrix &matrix)
Definition: SkCanvas.cpp:1318
void clipRRect(const SkRRect &rrect, SkClipOp op, bool doAntiAlias)
Definition: SkCanvas.cpp:1439
static sk_sp< SkColorFilter > MakeGaussian()
static sk_sp< SkColorFilter > Compose(const sk_sp< SkColorFilter > &outer, sk_sp< SkColorFilter > inner)
Definition: SkColorFilter.h:92
static sk_sp< SkColorFilter > Blend(const SkColor4f &c, sk_sp< SkColorSpace >, SkBlendMode mode)
static sk_sp< SkColorFilter > Table(const uint8_t table[256])
static sk_sp< SkColorFilter > Matrix(const SkColorMatrix &)
static sk_sp< SkColorFilter > Lighting(SkColor mul, SkColor add)
static sk_sp< SkColorFilter > SRGBToLinearGamma()
static sk_sp< SkColorFilter > LinearToSRGBGamma()
static sk_sp< SkColorFilter > TableARGB(const uint8_t tableA[256], const uint8_t tableR[256], const uint8_t tableG[256], const uint8_t tableB[256])
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)
sk_sp< SkShader > makeShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions &, const SkMatrix *localMatrix=nullptr) const
Definition: SkImage.cpp:179
static SkMatrix RotateDeg(SkScalar deg)
Definition: SkMatrix.h:104
void setColor(SkColor color)
Definition: SkPaint.cpp:119
void setAntiAlias(bool aa)
Definition: SkPaint.h:170
void setBlendMode(SkBlendMode mode)
Definition: SkPaint.cpp:151
Definition: SkPath.h:59
static SkRRect MakeRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
Definition: SkRRect.h:180
sk_sp< SkShader > makeWithColorFilter(sk_sp< SkColorFilter >) const
Definition: SkShader.cpp:43
Definition: gm.h:110
void setBGColor(SkColor)
Definition: gm.cpp:159
void onDraw(SkCanvas *canvas) override
static constexpr int kTileWidth
static constexpr int kWidth
SkISize getISize() override
static constexpr int kClipInset
static constexpr int kHeight
SkString getName() const override
static constexpr int kTileHeight
void onOnceBeforeDraw() override
const Paint & paint
Definition: color_source.cc:38
static constexpr SkScalar kTileHeight
static constexpr SkScalar kTileWidth
double y
double x
SK_API sk_sp< SkImage > RasterFromBitmap(const SkBitmap &bitmap)
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
clipRect(r.rect, r.opAA.op(), r.opAA.aa())) template<> void Draw
sk_sp< const SkImage > image
Definition: SkRecords.h:269
PODArray< SkColor > colors
Definition: SkRecords.h:276
SK_API sk_sp< SkShader > Blend(SkBlendMode mode, sk_sp< SkShader > dst, sk_sp< SkShader > src)
SK_API sk_sp< SkShader > Color(SkColor)
sk_sp< SkImage > MakeTextureImage(SkCanvas *canvas, sk_sp< SkImage > orig)
sk_sp< SkImage > GetResourceAsImage(const char *resource)
Definition: DecodeUtils.h:25
bool GetResourceAsBitmap(const char *resource, SkBitmap *dst)
Definition: DecodeUtils.h:21
Definition: bitmap.py:1
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
dst
Definition: cp.py:12
list offsets
Definition: mskp_parser.py:37
DEF_GM(return F(C(clipbox), 0.0f, 0.0f, {})) DEF_GM(return F(C(clipbox)
SkSamplingOptions(SkFilterMode::kLinear))
Definition: SkSize.h:16
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)
void offsetTo(float newX, float newY)
Definition: SkRect.h:1043
SkScalar fLeft
smaller x-axis bounds
Definition: extension.cpp:14
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition: SkRect.h:659
SkRect makeInset(float dx, float dy) const
Definition: SkRect.h:987
SkScalar fRight
larger x-axis bounds
Definition: extension.cpp:16
void offset(float dx, float dy)
Definition: SkRect.h:1016
static constexpr SkRect MakeWH(float w, float h)
Definition: SkRect.h:609
SkScalar fTop
smaller y-axis bounds
Definition: extension.cpp:15
Definition: SkSize.h:52
SkScalar width() const
Definition: SkSize.h:76
SkScalar height() const
Definition: SkSize.h:77