Flutter Engine
The Flutter Engine
dl_test_snippets.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "flutter/display_list/testing/dl_test_snippets.h"
6#include "flutter/display_list/dl_builder.h"
7#include "flutter/display_list/dl_op_receiver.h"
10#include "txt/platform.h"
11
12namespace flutter {
13namespace testing {
14
17 builder.DrawRect(SkRect::MakeXYWH(10, 10, 80, 80), DlPaint(DlColor::kRed()));
18 return builder.Build();
19}
20
24 for (int y = 10; y <= 60; y += 10) {
25 for (int x = 10; x <= 60; x += 10) {
26 paint.setColor(((x + y) % 20) == 10 ? DlColor(SK_ColorRED)
28 builder.DrawRect(SkRect::MakeXYWH(x, y, 80, 80), paint);
29 }
30 }
31 DisplayListBuilder outer_builder(SkRect::MakeWH(150, 100));
32 outer_builder.DrawDisplayList(builder.Build());
33 return outer_builder.Build();
34}
35
38 for (int i = 0; i < ops; i++) {
40 }
41 return builder.Build();
42}
43
44// ---------------
45// Test Suite data
46// ---------------
47
48std::vector<DisplayListInvocationGroup> CreateAllAttributesOps() {
49 return {
50 {"SetAntiAlias",
51 {
52 {0, 8, 0, [](DlOpReceiver& r) { r.setAntiAlias(true); }},
53 {0, 0, 0, [](DlOpReceiver& r) { r.setAntiAlias(false); }},
54 }},
55 {"SetInvertColors",
56 {
57 {0, 8, 0, [](DlOpReceiver& r) { r.setInvertColors(true); }},
58 {0, 0, 0, [](DlOpReceiver& r) { r.setInvertColors(false); }},
59 }},
60 {"SetStrokeCap",
61 {
62 {0, 8, 0,
63 [](DlOpReceiver& r) { r.setStrokeCap(DlStrokeCap::kRound); }},
64 {0, 8, 0,
65 [](DlOpReceiver& r) { r.setStrokeCap(DlStrokeCap::kSquare); }},
66 {0, 0, 0,
67 [](DlOpReceiver& r) { r.setStrokeCap(DlStrokeCap::kButt); }},
68 }},
69 {"SetStrokeJoin",
70 {
71 {0, 8, 0,
72 [](DlOpReceiver& r) { r.setStrokeJoin(DlStrokeJoin::kBevel); }},
73 {0, 8, 0,
74 [](DlOpReceiver& r) { r.setStrokeJoin(DlStrokeJoin::kRound); }},
75 {0, 0, 0,
76 [](DlOpReceiver& r) { r.setStrokeJoin(DlStrokeJoin::kMiter); }},
77 }},
78 {"SetStyle",
79 {
80 {0, 8, 0,
81 [](DlOpReceiver& r) { r.setDrawStyle(DlDrawStyle::kStroke); }},
82 {0, 8, 0,
83 [](DlOpReceiver& r) {
84 r.setDrawStyle(DlDrawStyle::kStrokeAndFill);
85 }},
86 {0, 0, 0,
87 [](DlOpReceiver& r) { r.setDrawStyle(DlDrawStyle::kFill); }},
88 }},
89 {"SetStrokeWidth",
90 {
91 {0, 8, 0, [](DlOpReceiver& r) { r.setStrokeWidth(1.0); }},
92 {0, 8, 0, [](DlOpReceiver& r) { r.setStrokeWidth(5.0); }},
93 {0, 0, 0, [](DlOpReceiver& r) { r.setStrokeWidth(0.0); }},
94 }},
95 {"SetStrokeMiter",
96 {
97 {0, 8, 0, [](DlOpReceiver& r) { r.setStrokeMiter(0.0); }},
98 {0, 8, 0, [](DlOpReceiver& r) { r.setStrokeMiter(5.0); }},
99 {0, 0, 0, [](DlOpReceiver& r) { r.setStrokeMiter(4.0); }},
100 }},
101 {"SetColor",
102 {
103 {0, 8, 0,
104 [](DlOpReceiver& r) { r.setColor(DlColor(SK_ColorGREEN)); }},
105 {0, 8, 0,
106 [](DlOpReceiver& r) { r.setColor(DlColor(SK_ColorBLUE)); }},
107 {0, 0, 0,
108 [](DlOpReceiver& r) { r.setColor(DlColor(SK_ColorBLACK)); }},
109 }},
110 {"SetBlendMode",
111 {
112 {0, 8, 0,
113 [](DlOpReceiver& r) { r.setBlendMode(DlBlendMode::kSrcIn); }},
114 {0, 8, 0,
115 [](DlOpReceiver& r) { r.setBlendMode(DlBlendMode::kDstIn); }},
116 {0, 0, 0,
117 [](DlOpReceiver& r) { r.setBlendMode(DlBlendMode::kSrcOver); }},
118 }},
119 {"SetColorSource",
120 {
121 {0, 96, 0, [](DlOpReceiver& r) { r.setColorSource(&kTestSource1); }},
122 // stop_count * (sizeof(float) + sizeof(uint32_t)) = 80
123 {0, 80 + 6 * 4, 0,
124 [](DlOpReceiver& r) { r.setColorSource(kTestSource2.get()); }},
125 {0, 80 + 6 * 4, 0,
126 [](DlOpReceiver& r) { r.setColorSource(kTestSource3.get()); }},
127 {0, 88 + 6 * 4, 0,
128 [](DlOpReceiver& r) { r.setColorSource(kTestSource4.get()); }},
129 {0, 80 + 6 * 4, 0,
130 [](DlOpReceiver& r) { r.setColorSource(kTestSource5.get()); }},
131 {0, 0, 0, [](DlOpReceiver& r) { r.setColorSource(nullptr); }},
132 }},
133 {"SetImageFilter",
134 {
135 {0, 32, 0,
136 [](DlOpReceiver& r) { r.setImageFilter(&kTestBlurImageFilter1); }},
137 {0, 32, 0,
138 [](DlOpReceiver& r) { r.setImageFilter(&kTestBlurImageFilter2); }},
139 {0, 32, 0,
140 [](DlOpReceiver& r) { r.setImageFilter(&kTestBlurImageFilter3); }},
141 {0, 32, 0,
142 [](DlOpReceiver& r) { r.setImageFilter(&kTestBlurImageFilter4); }},
143 {0, 24, 0,
144 [](DlOpReceiver& r) {
145 r.setImageFilter(&kTestDilateImageFilter1);
146 }},
147 {0, 24, 0,
148 [](DlOpReceiver& r) {
149 r.setImageFilter(&kTestDilateImageFilter2);
150 }},
151 {0, 24, 0,
152 [](DlOpReceiver& r) {
153 r.setImageFilter(&kTestDilateImageFilter3);
154 }},
155 {0, 24, 0,
156 [](DlOpReceiver& r) { r.setImageFilter(&kTestErodeImageFilter1); }},
157 {0, 24, 0,
158 [](DlOpReceiver& r) { r.setImageFilter(&kTestErodeImageFilter2); }},
159 {0, 24, 0,
160 [](DlOpReceiver& r) { r.setImageFilter(&kTestErodeImageFilter3); }},
161 {0, 64, 0,
162 [](DlOpReceiver& r) {
163 r.setImageFilter(&kTestMatrixImageFilter1);
164 }},
165 {0, 64, 0,
166 [](DlOpReceiver& r) {
167 r.setImageFilter(&kTestMatrixImageFilter2);
168 }},
169 {0, 64, 0,
170 [](DlOpReceiver& r) {
171 r.setImageFilter(&kTestMatrixImageFilter3);
172 }},
173 {0, 24, 0,
174 [](DlOpReceiver& r) {
175 r.setImageFilter(&kTestComposeImageFilter1);
176 }},
177 {0, 24, 0,
178 [](DlOpReceiver& r) {
179 r.setImageFilter(&kTestComposeImageFilter2);
180 }},
181 {0, 24, 0,
182 [](DlOpReceiver& r) {
183 r.setImageFilter(&kTestComposeImageFilter3);
184 }},
185 {0, 24, 0,
186 [](DlOpReceiver& r) { r.setImageFilter(&kTestCFImageFilter1); }},
187 {0, 24, 0,
188 [](DlOpReceiver& r) { r.setImageFilter(&kTestCFImageFilter2); }},
189 {0, 0, 0, [](DlOpReceiver& r) { r.setImageFilter(nullptr); }},
190 {0, 24, 0,
191 [](DlOpReceiver& r) {
192 r.setImageFilter(
194 .makeWithLocalMatrix(SkMatrix::Translate(2, 2))
195 .get());
196 }},
197 }},
198 {"SetColorFilter",
199 {
200 {0, 24, 0,
201 [](DlOpReceiver& r) { r.setColorFilter(&kTestBlendColorFilter1); }},
202 {0, 24, 0,
203 [](DlOpReceiver& r) { r.setColorFilter(&kTestBlendColorFilter2); }},
204 {0, 24, 0,
205 [](DlOpReceiver& r) { r.setColorFilter(&kTestBlendColorFilter3); }},
206 {0, 96, 0,
207 [](DlOpReceiver& r) {
208 r.setColorFilter(&kTestMatrixColorFilter1);
209 }},
210 {0, 96, 0,
211 [](DlOpReceiver& r) {
212 r.setColorFilter(&kTestMatrixColorFilter2);
213 }},
214 {0, 16, 0,
215 [](DlOpReceiver& r) {
217 }},
218 {0, 16, 0,
219 [](DlOpReceiver& r) {
221 }},
222 {0, 0, 0, [](DlOpReceiver& r) { r.setColorFilter(nullptr); }},
223 }},
224 {"SetMaskFilter",
225 {
226 {0, 32, 0,
227 [](DlOpReceiver& r) { r.setMaskFilter(&kTestMaskFilter1); }, 0u,
228 2u},
229 {0, 32, 0,
230 [](DlOpReceiver& r) { r.setMaskFilter(&kTestMaskFilter2); }, 0u,
231 2u},
232 {0, 32, 0,
233 [](DlOpReceiver& r) { r.setMaskFilter(&kTestMaskFilter3); }, 0u,
234 2u},
235 {0, 32, 0,
236 [](DlOpReceiver& r) { r.setMaskFilter(&kTestMaskFilter4); }, 0u,
237 2u},
238 {0, 32, 0,
239 [](DlOpReceiver& r) { r.setMaskFilter(&kTestMaskFilter5); }, 0u,
240 2u},
241 {0, 0, 0, [](DlOpReceiver& r) { r.setMaskFilter(nullptr); }, 0u, 1u},
242 }},
243 };
244}
245
246std::vector<DisplayListInvocationGroup> CreateAllSaveRestoreOps() {
247 return {
248 {"Save(Layer)+Restore",
249 {
250 // There are many reasons that save and restore can elide content,
251 // including whether or not there are any draw operations between
252 // them, whether or not there are any state changes to restore, and
253 // whether group rendering (opacity) optimizations can allow
254 // attributes to be distributed to the children. To prevent those
255 // cases we include at least one clip operation and 2 overlapping
256 // rendering primitives between each save/restore pair.
257 {5, 96, 2,
258 [](DlOpReceiver& r) {
259 r.save();
260 r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true);
261 r.drawRect({5, 5, 15, 15});
262 r.drawRect({10, 10, 20, 20});
263 r.restore();
264 }},
265 {5, 120, 3,
266 [](DlOpReceiver& r) {
267 r.saveLayer(nullptr, SaveLayerOptions::kNoAttributes);
268 r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true);
269 r.drawRect({5, 5, 15, 15});
270 r.drawRect({10, 10, 20, 20});
271 r.restore();
272 }},
273 {5, 120, 3,
274 [](DlOpReceiver& r) {
275 r.saveLayer(nullptr, SaveLayerOptions::kWithAttributes);
276 r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true);
277 r.drawRect({5, 5, 15, 15});
278 r.drawRect({10, 10, 20, 20});
279 r.restore();
280 }},
281 // For saveLayer calls with bounds, we need at least one unclipped
282 // draw command so that the bounds are not reduced in size to the
283 // clip dimensions on the re-dispatch.
284 {5, 120, 3,
285 [](DlOpReceiver& r) {
287 r.drawRect(kTestBounds);
288 r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true);
289 r.drawRect({10, 10, 20, 20});
290 r.restore();
291 }},
292 {5, 120, 3,
293 [](DlOpReceiver& r) {
295 r.drawRect(kTestBounds);
296 r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true);
297 r.drawRect({10, 10, 20, 20});
298 r.restore();
299 }},
300 {5, 136, 3,
301 [](DlOpReceiver& r) {
302 r.saveLayer(nullptr, SaveLayerOptions::kNoAttributes,
304 r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true);
305 r.drawRect({5, 5, 15, 15});
306 r.drawRect({10, 10, 20, 20});
307 r.restore();
308 }},
309 {5, 136, 3,
310 [](DlOpReceiver& r) {
311 r.saveLayer(nullptr, SaveLayerOptions::kWithAttributes,
313 r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true);
314 r.drawRect({5, 5, 15, 15});
315 r.drawRect({10, 10, 20, 20});
316 r.restore();
317 }},
318 {5, 136, 3,
319 [](DlOpReceiver& r) {
322 r.drawRect(kTestBounds);
323 r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true);
324 r.drawRect({10, 10, 20, 20});
325 r.restore();
326 }},
327 {5, 136, 3,
328 [](DlOpReceiver& r) {
331 r.drawRect(kTestBounds);
332 r.clipRect({0, 0, 25, 25}, DlCanvas::ClipOp::kIntersect, true);
333 r.drawRect({10, 10, 20, 20});
334 r.restore();
335 }},
336 }},
337 };
338}
339
340std::vector<DisplayListInvocationGroup> CreateAllTransformOps() {
341 return {
342 {"Translate",
343 {
344 {1, 16, 0, [](DlOpReceiver& r) { r.translate(10, 10); }},
345 {1, 16, 0, [](DlOpReceiver& r) { r.translate(10, 15); }},
346 {1, 16, 0, [](DlOpReceiver& r) { r.translate(15, 10); }},
347 {0, 0, 0, [](DlOpReceiver& r) { r.translate(0, 0); }},
348 }},
349 {"Scale",
350 {
351 {1, 16, 0, [](DlOpReceiver& r) { r.scale(2, 2); }},
352 {1, 16, 0, [](DlOpReceiver& r) { r.scale(2, 3); }},
353 {1, 16, 0, [](DlOpReceiver& r) { r.scale(3, 2); }},
354 {0, 0, 0, [](DlOpReceiver& r) { r.scale(1, 1); }},
355 }},
356 {"Rotate",
357 {
358 {1, 8, 0, [](DlOpReceiver& r) { r.rotate(30); }},
359 {1, 8, 0, [](DlOpReceiver& r) { r.rotate(45); }},
360 {0, 0, 0, [](DlOpReceiver& r) { r.rotate(0); }},
361 {0, 0, 0, [](DlOpReceiver& r) { r.rotate(360); }},
362 }},
363 {"Skew",
364 {
365 {1, 16, 0, [](DlOpReceiver& r) { r.skew(0.1, 0.1); }},
366 {1, 16, 0, [](DlOpReceiver& r) { r.skew(0.1, 0.2); }},
367 {1, 16, 0, [](DlOpReceiver& r) { r.skew(0.2, 0.1); }},
368 {0, 0, 0, [](DlOpReceiver& r) { r.skew(0, 0); }},
369 }},
370 {"Transform2DAffine",
371 {
372 {1, 32, 0,
373 [](DlOpReceiver& r) { r.transform2DAffine(0, 1, 12, 1, 0, 33); }},
374 // r.transform(identity) is ignored
375 {0, 0, 0,
376 [](DlOpReceiver& r) { r.transform2DAffine(1, 0, 0, 0, 1, 0); }},
377 }},
378 {"TransformFullPerspective",
379 {
380 {1, 72, 0,
381 [](DlOpReceiver& r) {
382 r.transformFullPerspective(0, 1, 0, 12, 1, 0, 0, 33, 3, 2, 5, 29,
383 0, 0, 0, 12);
384 }},
385 // r.transform(2D affine) is reduced to 2x3
386 {1, 32, 0,
387 [](DlOpReceiver& r) {
388 r.transformFullPerspective(2, 1, 0, 4, 1, 3, 0, 5, 0, 0, 1, 0, 0,
389 0, 0, 1);
390 }},
391 // r.transform(identity) is ignored
392 {0, 0, 0,
393 [](DlOpReceiver& r) {
394 r.transformFullPerspective(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
395 0, 0, 1);
396 }},
397 }},
398 };
399}
400
401std::vector<DisplayListInvocationGroup> CreateAllClipOps() {
402 return {
403 {"ClipRect",
404 {
405 {1, 24, 0,
406 [](DlOpReceiver& r) {
407 r.clipRect(kTestBounds, DlCanvas::ClipOp::kIntersect, true);
408 }},
409 {1, 24, 0,
410 [](DlOpReceiver& r) {
411 r.clipRect(kTestBounds.makeOffset(1, 1),
413 }},
414 {1, 24, 0,
415 [](DlOpReceiver& r) {
416 r.clipRect(kTestBounds, DlCanvas::ClipOp::kIntersect, false);
417 }},
418 {1, 24, 0,
419 [](DlOpReceiver& r) {
421 }},
422 {1, 24, 0,
423 [](DlOpReceiver& r) {
424 r.clipRect(kTestBounds, DlCanvas::ClipOp::kDifference, false);
425 }},
426 }},
427 {"ClipRRect",
428 {
429 {1, 64, 0,
430 [](DlOpReceiver& r) {
431 r.clipRRect(kTestRRect, DlCanvas::ClipOp::kIntersect, true);
432 }},
433 {1, 64, 0,
434 [](DlOpReceiver& r) {
435 r.clipRRect(kTestRRect.makeOffset(1, 1),
437 }},
438 {1, 64, 0,
439 [](DlOpReceiver& r) {
440 r.clipRRect(kTestRRect, DlCanvas::ClipOp::kIntersect, false);
441 }},
442 {1, 64, 0,
443 [](DlOpReceiver& r) {
444 r.clipRRect(kTestRRect, DlCanvas::ClipOp::kDifference, true);
445 }},
446 {1, 64, 0,
447 [](DlOpReceiver& r) {
448 r.clipRRect(kTestRRect, DlCanvas::ClipOp::kDifference, false);
449 }},
450 }},
451 {"ClipPath",
452 {
453 {1, 40, 0,
454 [](DlOpReceiver& r) {
455 r.clipPath(kTestPath1, DlCanvas::ClipOp::kIntersect, true);
456 }},
457 {1, 40, 0,
458 [](DlOpReceiver& r) {
459 r.clipPath(kTestPath2, DlCanvas::ClipOp::kIntersect, true);
460 }},
461 {1, 40, 0,
462 [](DlOpReceiver& r) {
463 r.clipPath(kTestPath3, DlCanvas::ClipOp::kIntersect, true);
464 }},
465 {1, 40, 0,
466 [](DlOpReceiver& r) {
467 r.clipPath(kTestPath1, DlCanvas::ClipOp::kIntersect, false);
468 }},
469 {1, 40, 0,
470 [](DlOpReceiver& r) {
471 r.clipPath(kTestPath1, DlCanvas::ClipOp::kDifference, true);
472 }},
473 {1, 40, 0,
474 [](DlOpReceiver& r) {
475 r.clipPath(kTestPath1, DlCanvas::ClipOp::kDifference, false);
476 }},
477 // clipPath(rect) becomes clipRect
478 {1, 24, 0,
479 [](DlOpReceiver& r) {
481 }},
482 // clipPath(oval) becomes clipRRect
483 {1, 64, 0,
484 [](DlOpReceiver& r) {
486 }},
487 }},
488 };
489}
490
491std::vector<DisplayListInvocationGroup> CreateAllRenderingOps() {
492 return {
493 {"DrawPaint",
494 {
495 {1, 8, 1, [](DlOpReceiver& r) { r.drawPaint(); }},
496 }},
497 {"DrawColor",
498 {
499 {1, 16, 1,
500 [](DlOpReceiver& r) {
502 }},
503 {1, 16, 1,
504 [](DlOpReceiver& r) {
506 }},
507 {1, 16, 1,
508 [](DlOpReceiver& r) {
510 }},
511 }},
512 {"DrawLine",
513 {
514 {1, 24, 1,
515 [](DlOpReceiver& r) {
516 r.drawLine({0, 0}, {10, 10});
517 }},
518 {1, 24, 1,
519 [](DlOpReceiver& r) {
520 r.drawLine({1, 0}, {10, 10});
521 }},
522 {1, 24, 1,
523 [](DlOpReceiver& r) {
524 r.drawLine({0, 1}, {10, 10});
525 }},
526 {1, 24, 1,
527 [](DlOpReceiver& r) {
528 r.drawLine({0, 0}, {20, 10});
529 }},
530 {1, 24, 1,
531 [](DlOpReceiver& r) {
532 r.drawLine({0, 0}, {10, 20});
533 }},
534 }},
535 {"DrawDashedLine",
536 {
537 {1, 32, 1,
538 [](DlOpReceiver& r) {
539 r.drawDashedLine({0, 0}, {10, 10}, 4.0f, 2.0f);
540 }},
541 {1, 32, 1,
542 [](DlOpReceiver& r) {
543 r.drawDashedLine({1, 0}, {10, 10}, 4.0f, 2.0f);
544 }},
545 {1, 32, 1,
546 [](DlOpReceiver& r) {
547 r.drawDashedLine({0, 1}, {10, 10}, 4.0f, 2.0f);
548 }},
549 {1, 32, 1,
550 [](DlOpReceiver& r) {
551 r.drawDashedLine({0, 0}, {20, 10}, 4.0f, 2.0f);
552 }},
553 {1, 32, 1,
554 [](DlOpReceiver& r) {
555 r.drawDashedLine({0, 0}, {10, 20}, 4.0f, 2.0f);
556 }},
557 {1, 32, 1,
558 [](DlOpReceiver& r) {
559 r.drawDashedLine({0, 0}, {10, 10}, 5.0f, 2.0f);
560 }},
561 {1, 32, 1,
562 [](DlOpReceiver& r) {
563 r.drawDashedLine({0, 0}, {10, 10}, 4.0f, 3.0f);
564 }},
565 }},
566 {"DrawRect",
567 {
568 {1, 24, 1,
569 [](DlOpReceiver& r) {
570 r.drawRect({0, 0, 10, 10});
571 }},
572 {1, 24, 1,
573 [](DlOpReceiver& r) {
574 r.drawRect({0, 1, 10, 10});
575 }},
576 {1, 24, 1,
577 [](DlOpReceiver& r) {
578 r.drawRect({0, 0, 20, 10});
579 }},
580 {1, 24, 1,
581 [](DlOpReceiver& r) {
582 r.drawRect({0, 0, 10, 20});
583 }},
584 }},
585 {"DrawOval",
586 {
587 {1, 24, 1,
588 [](DlOpReceiver& r) {
589 r.drawOval({0, 0, 10, 10});
590 }},
591 {1, 24, 1,
592 [](DlOpReceiver& r) {
593 r.drawOval({0, 1, 10, 10});
594 }},
595 {1, 24, 1,
596 [](DlOpReceiver& r) {
597 r.drawOval({0, 0, 20, 10});
598 }},
599 {1, 24, 1,
600 [](DlOpReceiver& r) {
601 r.drawOval({0, 0, 10, 20});
602 }},
603 }},
604 {"DrawCircle",
605 {
606 {1, 16, 1,
607 [](DlOpReceiver& r) {
608 r.drawCircle({0, 0}, 10);
609 }},
610 {1, 16, 1,
611 [](DlOpReceiver& r) {
612 r.drawCircle({0, 5}, 10);
613 }},
614 {1, 16, 1,
615 [](DlOpReceiver& r) {
616 r.drawCircle({0, 0}, 20);
617 }},
618 }},
619 {"DrawRRect",
620 {
621 {1, 56, 1, [](DlOpReceiver& r) { r.drawRRect(kTestRRect); }},
622 {1, 56, 1,
623 [](DlOpReceiver& r) { r.drawRRect(kTestRRect.makeOffset(5, 5)); }},
624 }},
625 {"DrawDRRect",
626 {
627 {1, 112, 1,
628 [](DlOpReceiver& r) { r.drawDRRect(kTestRRect, kTestInnerRRect); }},
629 {1, 112, 1,
630 [](DlOpReceiver& r) {
631 r.drawDRRect(kTestRRect.makeOffset(5, 5),
633 }},
634 }},
635 {"DrawPath",
636 {
637 {1, 40, 1, [](DlOpReceiver& r) { r.drawPath(kTestPath1); }},
638 {1, 40, 1, [](DlOpReceiver& r) { r.drawPath(kTestPath2); }},
639 {1, 40, 1, [](DlOpReceiver& r) { r.drawPath(kTestPath3); }},
640 {1, 40, 1, [](DlOpReceiver& r) { r.drawPath(kTestPathRect); }},
641 {1, 40, 1, [](DlOpReceiver& r) { r.drawPath(kTestPathOval); }},
642 }},
643 {"DrawArc",
644 {
645 {1, 32, 1,
646 [](DlOpReceiver& r) { r.drawArc(kTestBounds, 45, 270, false); }},
647 {1, 32, 1,
648 [](DlOpReceiver& r) {
649 r.drawArc(kTestBounds.makeOffset(1, 1), 45, 270, false);
650 }},
651 {1, 32, 1,
652 [](DlOpReceiver& r) { r.drawArc(kTestBounds, 30, 270, false); }},
653 {1, 32, 1,
654 [](DlOpReceiver& r) { r.drawArc(kTestBounds, 45, 260, false); }},
655 {1, 32, 1,
656 [](DlOpReceiver& r) { r.drawArc(kTestBounds, 45, 270, true); }},
657 }},
658 {"DrawPoints",
659 {
660 {1, 8 + TestPointCount * 8, 1,
661 [](DlOpReceiver& r) {
664 }},
665 {1, 8 + (TestPointCount - 1) * 8, 1,
666 [](DlOpReceiver& r) {
669 }},
670 {1, 8 + TestPointCount * 8, 1,
671 [](DlOpReceiver& r) {
674 }},
675 {1, 8 + TestPointCount * 8, 1,
676 [](DlOpReceiver& r) {
679 }},
680 }},
681 {"DrawVertices",
682 {
683 {1, 112, 1,
684 [](DlOpReceiver& r) {
685 r.drawVertices(TestVertices1.get(), DlBlendMode::kSrcIn);
686 }},
687 {1, 112, 1,
688 [](DlOpReceiver& r) {
689 r.drawVertices(TestVertices1.get(), DlBlendMode::kDstIn);
690 }},
691 {1, 112, 1,
692 [](DlOpReceiver& r) {
693 r.drawVertices(TestVertices2.get(), DlBlendMode::kSrcIn);
694 }},
695 }},
696 {"DrawImage",
697 {
698 {1, 24, 1,
699 [](DlOpReceiver& r) {
700 r.drawImage(TestImage1, {10, 10}, kNearestSampling, false);
701 }},
702 {1, 24, 1,
703 [](DlOpReceiver& r) {
704 r.drawImage(TestImage1, {10, 10}, kNearestSampling, true);
705 }},
706 {1, 24, 1,
707 [](DlOpReceiver& r) {
708 r.drawImage(TestImage1, {20, 10}, kNearestSampling, false);
709 }},
710 {1, 24, 1,
711 [](DlOpReceiver& r) {
712 r.drawImage(TestImage1, {10, 20}, kNearestSampling, false);
713 }},
714 {1, 24, 1,
715 [](DlOpReceiver& r) {
716 r.drawImage(TestImage1, {10, 10}, kLinearSampling, false);
717 }},
718 {1, 24, 1,
719 [](DlOpReceiver& r) {
720 r.drawImage(TestImage2, {10, 10}, kNearestSampling, false);
721 }},
722 {1, 24, 1,
723 [](DlOpReceiver& r) {
724 auto dl_image = DlImage::Make(TestSkImage);
725 r.drawImage(dl_image, {10, 10}, kNearestSampling, false);
726 }},
727 }},
728 {"DrawImageRect",
729 {
730 {1, 56, 1,
731 [](DlOpReceiver& r) {
732 r.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80},
733 kNearestSampling, false,
735 }},
736 {1, 56, 1,
737 [](DlOpReceiver& r) {
738 r.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80},
739 kNearestSampling, true,
741 }},
742 {1, 56, 1,
743 [](DlOpReceiver& r) {
744 r.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80},
745 kNearestSampling, false,
747 }},
748 {1, 56, 1,
749 [](DlOpReceiver& r) {
750 r.drawImageRect(TestImage1, {10, 10, 25, 20}, {10, 10, 80, 80},
751 kNearestSampling, false,
753 }},
754 {1, 56, 1,
755 [](DlOpReceiver& r) {
756 r.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 85, 80},
757 kNearestSampling, false,
759 }},
760 {1, 56, 1,
761 [](DlOpReceiver& r) {
762 r.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80},
763 kLinearSampling, false,
765 }},
766 {1, 56, 1,
767 [](DlOpReceiver& r) {
768 r.drawImageRect(TestImage2, {10, 10, 15, 15}, {10, 10, 80, 80},
769 kNearestSampling, false,
771 }},
772 {1, 56, 1,
773 [](DlOpReceiver& r) {
774 auto dl_image = DlImage::Make(TestSkImage);
775 r.drawImageRect(dl_image, {10, 10, 15, 15}, {10, 10, 80, 80},
776 kNearestSampling, false,
778 }},
779 }},
780 {"DrawImageNine",
781 {
782 {1, 48, 1,
783 [](DlOpReceiver& r) {
784 r.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80},
786 }},
787 {1, 48, 1,
788 [](DlOpReceiver& r) {
789 r.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80},
791 }},
792 {1, 48, 1,
793 [](DlOpReceiver& r) {
794 r.drawImageNine(TestImage1, {10, 10, 25, 20}, {10, 10, 80, 80},
796 }},
797 {1, 48, 1,
798 [](DlOpReceiver& r) {
799 r.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 85, 80},
801 }},
802 {1, 48, 1,
803 [](DlOpReceiver& r) {
804 r.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80},
805 DlFilterMode::kLinear, false);
806 }},
807 {1, 48, 1,
808 [](DlOpReceiver& r) {
809 r.drawImageNine(TestImage2, {10, 10, 15, 15}, {10, 10, 80, 80},
811 }},
812 {1, 48, 1,
813 [](DlOpReceiver& r) {
814 auto dl_image = DlImage::Make(TestSkImage);
815 r.drawImageNine(dl_image, {10, 10, 15, 15}, {10, 10, 80, 80},
817 }},
818 }},
819 {"DrawAtlas",
820 {
821 {1, 48 + 32 + 8, 1,
822 [](DlOpReceiver& r) {
823 static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
824 static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}};
825 r.drawAtlas(TestImage1, xforms, texs, nullptr, 2,
827 false);
828 }},
829 {1, 48 + 32 + 8, 1,
830 [](DlOpReceiver& r) {
831 static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
832 static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}};
833 r.drawAtlas(TestImage1, xforms, texs, nullptr, 2,
834 DlBlendMode::kSrcIn, kNearestSampling, nullptr, true);
835 }},
836 {1, 48 + 32 + 8, 1,
837 [](DlOpReceiver& r) {
838 static SkRSXform xforms[] = {{0, 1, 0, 0}, {0, 1, 0, 0}};
839 static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}};
840 r.drawAtlas(TestImage1, xforms, texs, nullptr, 2,
842 false);
843 }},
844 {1, 48 + 32 + 8, 1,
845 [](DlOpReceiver& r) {
846 static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
847 static SkRect texs[] = {{10, 10, 20, 20}, {20, 25, 30, 30}};
848 r.drawAtlas(TestImage1, xforms, texs, nullptr, 2,
850 false);
851 }},
852 {1, 48 + 32 + 8, 1,
853 [](DlOpReceiver& r) {
854 static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
855 static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}};
856 r.drawAtlas(TestImage1, xforms, texs, nullptr, 2,
857 DlBlendMode::kSrcIn, kLinearSampling, nullptr, false);
858 }},
859 {1, 48 + 32 + 8, 1,
860 [](DlOpReceiver& r) {
861 static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
862 static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}};
863 r.drawAtlas(TestImage1, xforms, texs, nullptr, 2,
865 false);
866 }},
867 {1, 64 + 32 + 8, 1,
868 [](DlOpReceiver& r) {
869 static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
870 static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}};
871 static SkRect cull_rect = {0, 0, 200, 200};
872 r.drawAtlas(TestImage2, xforms, texs, nullptr, 2,
874 false);
875 }},
876 {1, 48 + 32 + 8 + 8, 1,
877 [](DlOpReceiver& r) {
878 static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
879 static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}};
881 r.drawAtlas(TestImage1, xforms, texs, colors, 2,
883 false);
884 }},
885 {1, 64 + 32 + 8 + 8, 1,
886 [](DlOpReceiver& r) {
887 static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
888 static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}};
890 static SkRect cull_rect = {0, 0, 200, 200};
891 r.drawAtlas(TestImage1, xforms, texs, colors, 2,
893 false);
894 }},
895 {1, 48 + 32 + 8, 1,
896 [](DlOpReceiver& r) {
897 auto dl_image = DlImage::Make(TestSkImage);
898 static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}};
899 static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}};
900 r.drawAtlas(dl_image, xforms, texs, nullptr, 2,
902 false);
903 }},
904 }},
905 {"DrawDisplayList",
906 {
907 {1, 16, 1,
908 [](DlOpReceiver& r) { r.drawDisplayList(TestDisplayList1, 1.0); },
909 1u},
910 {1, 16, 1,
911 [](DlOpReceiver& r) { r.drawDisplayList(TestDisplayList1, 0.5); },
912 1u},
913 {1, 16, 1,
914 [](DlOpReceiver& r) { r.drawDisplayList(TestDisplayList2, 1.0); },
915 1u},
916 {1, 16, 1,
917 [](DlOpReceiver& r) {
918 r.drawDisplayList(MakeTestDisplayList(10, 10, SK_ColorRED), 1.0);
919 },
920 1u},
921 }},
922 {"DrawTextBlob",
923 {
924 {1, 24, 1,
925 [](DlOpReceiver& r) {
926 r.drawTextBlob(GetTestTextBlob(1), 10, 10);
927 }},
928 {1, 24, 1,
929 [](DlOpReceiver& r) {
930 r.drawTextBlob(GetTestTextBlob(1), 20, 10);
931 }},
932 {1, 24, 1,
933 [](DlOpReceiver& r) {
934 r.drawTextBlob(GetTestTextBlob(1), 10, 20);
935 }},
936 {1, 24, 1,
937 [](DlOpReceiver& r) {
938 r.drawTextBlob(GetTestTextBlob(2), 10, 10);
939 }},
940 }},
941 {"DrawShadow",
942 {
943 {1, 48, 1,
944 [](DlOpReceiver& r) {
945 r.drawShadow(kTestPath1, DlColor(SK_ColorGREEN), 1.0, false, 1.0);
946 }},
947 {1, 48, 1,
948 [](DlOpReceiver& r) {
949 r.drawShadow(kTestPath2, DlColor(SK_ColorGREEN), 1.0, false, 1.0);
950 }},
951 {1, 48, 1,
952 [](DlOpReceiver& r) {
953 r.drawShadow(kTestPath1, DlColor(SK_ColorBLUE), 1.0, false, 1.0);
954 }},
955 {1, 48, 1,
956 [](DlOpReceiver& r) {
957 r.drawShadow(kTestPath1, DlColor(SK_ColorGREEN), 2.0, false, 1.0);
958 }},
959 {1, 48, 1,
960 [](DlOpReceiver& r) {
961 r.drawShadow(kTestPath1, DlColor(SK_ColorGREEN), 1.0, true, 1.0);
962 }},
963 {1, 48, 1,
964 [](DlOpReceiver& r) {
965 r.drawShadow(kTestPath1, DlColor(SK_ColorGREEN), 1.0, false, 2.5);
966 }},
967 }},
968 };
969}
970
971std::vector<DisplayListInvocationGroup> CreateAllGroups() {
972 std::vector<DisplayListInvocationGroup> result;
973 auto all_attribute_ops = CreateAllAttributesOps();
974 std::move(all_attribute_ops.begin(), all_attribute_ops.end(),
975 std::back_inserter(result));
976 auto all_save_restore_ops = CreateAllSaveRestoreOps();
977 std::move(all_save_restore_ops.begin(), all_save_restore_ops.end(),
978 std::back_inserter(result));
979 auto all_transform_ops = CreateAllTransformOps();
980 std::move(all_transform_ops.begin(), all_transform_ops.end(),
981 std::back_inserter(result));
982 auto all_clip_ops = CreateAllClipOps();
983 std::move(all_clip_ops.begin(), all_clip_ops.end(),
984 std::back_inserter(result));
985 auto all_rendering_ops = CreateAllRenderingOps();
986 std::move(all_rendering_ops.begin(), all_rendering_ops.end(),
987 std::back_inserter(result));
988 return result;
989}
990
992 static constexpr const char* kTestFontFixture = "Roboto-Regular.ttf";
993 auto mapping = flutter::testing::OpenFixtureAsSkData(kTestFontFixture);
994 FML_CHECK(mapping);
995 return SkFont{txt::GetDefaultFontManager()->makeFromData(mapping), scalar};
996}
997
999 static std::map<int, sk_sp<SkTextBlob>> text_blobs;
1000 auto it = text_blobs.find(index);
1001 if (it != text_blobs.end()) {
1002 return it->second;
1003 }
1004 std::string text = "TestBlob" + std::to_string(index);
1005 sk_sp<SkTextBlob> blob =
1006 SkTextBlob::MakeFromText(text.c_str(), text.size(),
1008 text_blobs.insert(std::make_pair(index, blob));
1009 return blob;
1010}
1011
1012} // namespace testing
1013} // namespace flutter
SkPathOp ops[]
constexpr SkColor SK_ColorCYAN
Definition: SkColor.h:143
constexpr SkColor SK_ColorBLUE
Definition: SkColor.h:135
constexpr SkColor SK_ColorRED
Definition: SkColor.h:126
constexpr SkColor SK_ColorBLACK
Definition: SkColor.h:103
constexpr SkColor SK_ColorGREEN
Definition: SkColor.h:131
@ kUTF8
uses bytes to represent UTF-8 or ASCII
sk_sp< SkTypeface > makeFromData(sk_sp< SkData >, int ttcIndex=0) const
Definition: SkFontMgr.cpp:120
Definition: SkFont.h:35
static SkMatrix Translate(SkScalar dx, SkScalar dy)
Definition: SkMatrix.h:91
SkRRect makeOffset(SkScalar dx, SkScalar dy) const
Definition: SkRRect.h:397
static sk_sp< SkTextBlob > MakeFromText(const void *text, size_t byteLength, const SkFont &font, SkTextEncoding encoding=SkTextEncoding::kUTF8)
Definition: SkTextBlob.cpp:788
sk_sp< DisplayList > Build()
Definition: dl_builder.cc:67
void DrawDisplayList(const sk_sp< DisplayList > display_list, SkScalar opacity=SK_Scalar1) override
Definition: dl_builder.cc:1535
@ kLines
draw each separate pair of points as a line segment
@ kPolygon
draw each pair of overlapping points as a line segment
@ kPoints
draw each point separately
static sk_sp< DlImage > Make(const SkImage *image)
Definition: dl_image.cc:11
static const std::shared_ptr< DlLinearToSrgbGammaColorFilter > kInstance
Internal API for rendering recorded display lists to backends.
virtual void drawPoints(PointMode mode, uint32_t count, const SkPoint points[])=0
static const std::shared_ptr< DlSrgbToLinearGammaColorFilter > kInstance
static const SaveLayerOptions kNoAttributes
Definition: display_list.h:155
static const SaveLayerOptions kWithAttributes
Definition: display_list.h:154
const Paint & paint
Definition: color_source.cc:38
#define TestPointCount
float SkScalar
Definition: extension.cpp:12
GAsyncResult * result
#define FML_CHECK(condition)
Definition: logging.h:85
std::u16string text
double y
double x
PODArray< SkRect > texs
Definition: SkRecords.h:333
PODArray< SkRSXform > xforms
Definition: SkRecords.h:332
PODArray< SkColor > colors
Definition: SkRecords.h:276
static const DlComposeImageFilter kTestComposeImageFilter2(kTestBlurImageFilter2, kTestMatrixImageFilter1)
std::vector< DisplayListInvocationGroup > CreateAllClipOps()
static const DlDilateImageFilter kTestDilateImageFilter2(6.0, 5.0)
std::vector< DisplayListInvocationGroup > CreateAllTransformOps()
static const std::shared_ptr< DlColorSource > kTestSource3
constexpr SkRect kTestBounds
static auto TestSkImage
static const DlMatrixImageFilter kTestMatrixImageFilter1(SkMatrix::RotateDeg(45), kNearestSampling)
SkFont CreateTestFontOfSize(SkScalar scalar)
static const DlBlurMaskFilter kTestMaskFilter1(DlBlurStyle::kNormal, 3.0)
std::vector< DisplayListInvocationGroup > CreateAllSaveRestoreOps()
static const std::shared_ptr< DlColorSource > kTestSource4
static const SkRRect kTestInnerRRect
static const DlBlurMaskFilter kTestMaskFilter4(DlBlurStyle::kInner, 3.0)
static const SkPath kTestPath1
static const DlComposeImageFilter kTestComposeImageFilter1(kTestBlurImageFilter1, kTestMatrixImageFilter1)
static std::shared_ptr< const DlVertices > TestVertices2
static const DlColorFilterImageFilter kTestCFImageFilter2(kTestBlendColorFilter2)
static const DlErodeImageFilter kTestErodeImageFilter2(4.0, 3.0)
static const DlMatrixColorFilter kTestMatrixColorFilter2(kInvertColorMatrix)
sk_sp< SkData > OpenFixtureAsSkData(const std::string &fixture_name)
Opens a fixture of the given file name and returns a Skia SkData holding its contents.
Definition: testing.cc:64
static const DlBlurMaskFilter kTestMaskFilter3(DlBlurStyle::kSolid, 3.0)
static const DlImageColorSource kTestSource1(TestImage1, DlTileMode::kClamp, DlTileMode::kMirror, kLinearSampling)
static const DlBlurImageFilter kTestBlurImageFilter4(5.0, 5.0, DlTileMode::kDecal)
static const DlErodeImageFilter kTestErodeImageFilter3(3.0, 4.0)
static const DlMatrixImageFilter kTestMatrixImageFilter3(SkMatrix::RotateDeg(45), kLinearSampling)
static const DlColorFilterImageFilter kTestCFImageFilter1(kTestBlendColorFilter1)
static constexpr SkPoint kTestPoints[2]
static const std::shared_ptr< DlColorSource > kTestSource5
std::vector< DisplayListInvocationGroup > CreateAllAttributesOps()
static const DlErodeImageFilter kTestErodeImageFilter1(4.0, 4.0)
static const SkRRect kTestRRect
sk_sp< DisplayList > GetSampleDisplayList()
static const std::shared_ptr< DlColorSource > kTestSource2
static const DlBlurMaskFilter kTestMaskFilter2(DlBlurStyle::kNormal, 5.0)
static const DlBlurImageFilter kTestBlurImageFilter2(6.0, 5.0, DlTileMode::kClamp)
static const DlBlendColorFilter kTestBlendColorFilter2(DlColor::kBlue(), DlBlendMode::kDstATop)
static const DlBlendColorFilter kTestBlendColorFilter1(DlColor::kRed(), DlBlendMode::kDstATop)
static auto TestImage1
static const DlMatrixColorFilter kTestMatrixColorFilter1(kRotateColorMatrix)
static const DlBlendColorFilter kTestBlendColorFilter3(DlColor::kRed(), DlBlendMode::kDstIn)
static DlImageSampling kLinearSampling
static sk_sp< DisplayList > TestDisplayList2
static const DlMatrixImageFilter kTestMatrixImageFilter2(SkMatrix::RotateDeg(85), kNearestSampling)
static std::shared_ptr< const DlVertices > TestVertices1
static const SkPath kTestPath2
static const DlBlurImageFilter kTestBlurImageFilter3(5.0, 6.0, DlTileMode::kClamp)
std::vector< DisplayListInvocationGroup > CreateAllRenderingOps()
static const SkPath kTestPathRect
static const DlDilateImageFilter kTestDilateImageFilter1(5.0, 5.0)
sk_sp< DisplayList > GetSampleNestedDisplayList()
static DlImageSampling kNearestSampling
static const DlBlurMaskFilter kTestMaskFilter5(DlBlurStyle::kOuter, 3.0)
sk_sp< SkTextBlob > GetTestTextBlob(int index)
static const DlDilateImageFilter kTestDilateImageFilter3(5.0, 6.0)
static sk_sp< DisplayList > MakeTestDisplayList(int w, int h, SkColor color)
static const DlBlurImageFilter kTestBlurImageFilter1(5.0, 5.0, DlTileMode::kClamp)
static auto TestImage2
static const SkPath kTestPathOval
std::vector< DisplayListInvocationGroup > CreateAllGroups()
static const DlComposeImageFilter kTestComposeImageFilter3(kTestBlurImageFilter1, kTestMatrixImageFilter2)
static const SkPath kTestPath3
static sk_sp< DisplayList > TestDisplayList1
@ kMiter
extends to miter limit
@ kBevel
connects outside edges
@ kRound
adds circle
@ kButt
no stroke extension
@ kSquare
adds square
@ kStrokeAndFill
both strokes and fills shapes
@ kStroke
strokes boundary of shapes
@ kFill
fills interior of shapes
@ kSrcOver
r = s + (1-sa)*d
@ kDstOut
r = d * (1-sa)
const myers::Point & get(const myers::Segment &)
flutter::DlColor DlColor
flutter::DlPaint DlPaint
sk_sp< SkFontMgr > GetDefaultFontManager(uint32_t font_initialization_data)
Definition: platform.cc:17
static SkString to_string(int n)
Definition: nanobench.cpp:119
constexpr SkRect makeOffset(float dx, float dy) const
Definition: SkRect.h:965
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition: SkRect.h:659
static constexpr SkRect MakeWH(float w, float h)
Definition: SkRect.h:609
static constexpr DlColor kBlue()
Definition: dl_color.h:26
static constexpr DlColor kRed()
Definition: dl_color.h:24
static constexpr DlColor kGreen()
Definition: dl_color.h:25