| Flutter Impeller |

dl_unittests.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 <array>
6 #include <cmath>
7 #include <memory>
8 #include <vector>
9
10 #include "flutter/display_list/dl_blend_mode.h"
11 #include "flutter/display_list/dl_builder.h"
12 #include "flutter/display_list/dl_color.h"
13 #include "flutter/display_list/dl_paint.h"
14 #include "flutter/display_list/dl_tile_mode.h"
15 #include "flutter/display_list/effects/dl_color_filter.h"
16 #include "flutter/display_list/effects/dl_color_source.h"
17 #include "flutter/display_list/effects/dl_image_filters.h"
18 #include "flutter/display_list/effects/dl_mask_filter.h"
19 #include "flutter/display_list/geometry/dl_path_builder.h"
20 #include "flutter/testing/testing.h"
21 #include "gtest/gtest.h"
22 #include "impeller/display_list/aiks_context.h"
23 #include "impeller/display_list/dl_dispatcher.h"
24 #include "impeller/display_list/dl_image_impeller.h"
25 #include "impeller/display_list/dl_playground.h"
26 #include "impeller/entity/contents/clip_contents.h"
27 #include "impeller/entity/contents/solid_color_contents.h"
28 #include "impeller/entity/contents/solid_rrect_blur_contents.h"
29 #include "impeller/geometry/constants.h"
30 #include "impeller/geometry/point.h"
31 #include "impeller/geometry/scalar.h"
32 #include "impeller/playground/widgets.h"
33 #include "third_party/imgui/imgui.h"
34
35 namespace impeller {
36 namespace testing {
37
38 flutter::DlColor toColor(const float* components) {
39 return flutter::DlColor(Color::ToIColor(
40 Color(components[0], components[1], components[2], components[3])));
41 }
42
43 using DisplayListTest = DlPlayground;
44 INSTANTIATE_PLAYGROUND_SUITE(DisplayListTest);
45
46 TEST_P(DisplayListTest, CanDrawRect) {
47 flutter::DisplayListBuilder builder;
48 builder.DrawRect(DlRect::MakeXYWH(10, 10, 100, 100),
49 flutter::DlPaint(flutter::DlColor::kBlue()));
50 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
51 }
52
53 TEST_P(DisplayListTest, CanDrawTextBlob) {
54 flutter::DisplayListBuilder builder;
55 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
56 100, 100, flutter::DlPaint(flutter::DlColor::kBlue()));
57 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
58 }
59
60 TEST_P(DisplayListTest, CanDrawTextBlobWithGradient) {
61 flutter::DisplayListBuilder builder;
62
63 std::vector<flutter::DlColor> colors = {flutter::DlColor::kBlue(),
64 flutter::DlColor::kRed()};
65 const float stops[2] = {0.0, 1.0};
66
67 auto linear = flutter::DlColorSource::MakeLinear({0.0, 0.0}, {300.0, 300.0},
68 2, colors.data(), stops,
69 flutter::DlTileMode::kClamp);
70 flutter::DlPaint paint;
71 paint.setColorSource(linear);
72
73 builder.DrawTextBlob(
74 SkTextBlob::MakeFromString("Hello World", CreateTestFont()), 100, 100,
75 paint);
76 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
77 }
78
79 TEST_P(DisplayListTest, CanDrawTextWithSaveLayer) {
80 flutter::DisplayListBuilder builder;
81 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello", CreateTestFont()),
82 100, 100, flutter::DlPaint(flutter::DlColor::kRed()));
83
84 flutter::DlPaint save_paint;
85 float alpha = 0.5;
86 save_paint.setAlpha(static_cast<uint8_t>(255 * alpha));
87 builder.SaveLayer(std::nullopt, &save_paint);
88 builder.DrawTextBlob(SkTextBlob::MakeFromString("Hello with half alpha",
89 CreateTestFontOfSize(100)),
90 100, 300, flutter::DlPaint(flutter::DlColor::kRed()));
91 builder.Restore();
92 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
93 }
94
95 TEST_P(DisplayListTest, CanDrawImage) {
96 auto texture = CreateTextureForFixture("embarcadero.jpg");
97 flutter::DisplayListBuilder builder;
98 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
99 flutter::DlImageSampling::kNearestNeighbor, nullptr);
100 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
101 }
102
103 TEST_P(DisplayListTest, CanDrawCapsAndJoins) {
104 flutter::DisplayListBuilder builder;
105 flutter::DlPaint paint;
106
107 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
108 paint.setStrokeWidth(30);
109 paint.setColor(flutter::DlColor::kRed());
110
111 flutter::DlPathBuilder path_builder;
112 path_builder.MoveTo(DlPoint(-50, 0));
113 path_builder.LineTo(DlPoint(0, -50));
114 path_builder.LineTo(DlPoint(50, 0));
115 flutter::DlPath path = path_builder.TakePath();
116
117 builder.Translate(100, 100);
118 {
119 paint.setStrokeCap(flutter::DlStrokeCap::kButt);
120 paint.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
121 paint.setStrokeMiter(4);
122 builder.DrawPath(path, paint);
123 }
124
125 {
126 builder.Save();
127 builder.Translate(0, 100);
128 // The joint in the path is 45 degrees. A miter length of 1 convert to a
129 // bevel in this case.
130 paint.setStrokeMiter(1);
131 builder.DrawPath(path, paint);
132 builder.Restore();
133 }
134
135 builder.Translate(150, 0);
136 {
137 paint.setStrokeCap(flutter::DlStrokeCap::kSquare);
138 paint.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
139 builder.DrawPath(path, paint);
140 }
141
142 builder.Translate(150, 0);
143 {
144 paint.setStrokeCap(flutter::DlStrokeCap::kRound);
145 paint.setStrokeJoin(flutter::DlStrokeJoin::kRound);
146 builder.DrawPath(path, paint);
147 }
148
149 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
150 }
151
152 TEST_P(DisplayListTest, CanDrawArc) {
153 auto callback = [&]() {
154 static float start_angle = 45;
155 static float sweep_angle = 270;
156 static float stroke_width = 10;
157 static bool use_center = true;
158
159 static int selected_cap = 0;
160 const char* cap_names[] = {"Butt", "Round", "Square"};
161 flutter::DlStrokeCap cap;
162
163 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
164 ImGui::SliderFloat("Start angle", &start_angle, -360, 360);
165 ImGui::SliderFloat("Sweep angle", &sweep_angle, -360, 360);
166 ImGui::SliderFloat("Stroke width", &stroke_width, 0, 300);
167 ImGui::Combo("Cap", &selected_cap, cap_names,
168 sizeof(cap_names) / sizeof(char*));
169 ImGui::Checkbox("Use center", &use_center);
170 ImGui::End();
171
172 switch (selected_cap) {
173 case 0:
174 cap = flutter::DlStrokeCap::kButt;
175 break;
176 case 1:
177 cap = flutter::DlStrokeCap::kRound;
178 break;
179 case 2:
180 cap = flutter::DlStrokeCap::kSquare;
181 break;
182 default:
183 cap = flutter::DlStrokeCap::kButt;
184 break;
185 }
186
187 static PlaygroundPoint point_a(Point(200, 200), 20, Color::White());
188 static PlaygroundPoint point_b(Point(400, 400), 20, Color::White());
189 auto [p1, p2] = DrawPlaygroundLine(point_a, point_b);
190
191 flutter::DisplayListBuilder builder;
192 flutter::DlPaint paint;
193
194 Vector2 scale = GetContentScale();
195 builder.Scale(scale.x, scale.y);
196 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
197 paint.setStrokeCap(cap);
198 paint.setStrokeJoin(flutter::DlStrokeJoin::kMiter);
199 paint.setStrokeMiter(10);
200 auto rect = DlRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y);
201 paint.setColor(flutter::DlColor::kGreen());
202 paint.setStrokeWidth(2);
203 builder.DrawRect(rect, paint);
204 paint.setColor(flutter::DlColor::kRed());
205 paint.setStrokeWidth(stroke_width);
206 builder.DrawArc(rect, start_angle, sweep_angle, use_center, paint);
207
208 return builder.Build();
209 };
210 ASSERT_TRUE(OpenPlaygroundHere(callback));
211 }
212
213 TEST_P(DisplayListTest, StrokedPathsDrawCorrectly) {
214 auto callback = [&]() {
215 flutter::DisplayListBuilder builder;
216 flutter::DlPaint paint;
217
218 paint.setColor(flutter::DlColor::kRed());
219 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
220
221 static float stroke_width = 10.0f;
222 static int selected_stroke_type = 0;
223 static int selected_join_type = 0;
224 const char* stroke_types[] = {"Butte", "Round", "Square"};
225 const char* join_type[] = {"kMiter", "Round", "kBevel"};
226
227 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
228 ImGui::Combo("Cap", &selected_stroke_type, stroke_types,
229 sizeof(stroke_types) / sizeof(char*));
230 ImGui::Combo("Join", &selected_join_type, join_type,
231 sizeof(join_type) / sizeof(char*));
232 ImGui::SliderFloat("Stroke Width", &stroke_width, 10.0f, 50.0f);
233 ImGui::End();
234
235 flutter::DlStrokeCap cap;
236 flutter::DlStrokeJoin join;
237 switch (selected_stroke_type) {
238 case 0:
239 cap = flutter::DlStrokeCap::kButt;
240 break;
241 case 1:
242 cap = flutter::DlStrokeCap::kRound;
243 break;
244 case 2:
245 cap = flutter::DlStrokeCap::kSquare;
246 break;
247 default:
248 cap = flutter::DlStrokeCap::kButt;
249 break;
250 }
251 switch (selected_join_type) {
252 case 0:
253 join = flutter::DlStrokeJoin::kMiter;
254 break;
255 case 1:
256 join = flutter::DlStrokeJoin::kRound;
257 break;
258 case 2:
259 join = flutter::DlStrokeJoin::kBevel;
260 break;
261 default:
262 join = flutter::DlStrokeJoin::kMiter;
263 break;
264 }
265 paint.setStrokeCap(cap);
266 paint.setStrokeJoin(join);
267 paint.setStrokeWidth(stroke_width);
268
269 // Make rendering better to watch.
270 builder.Scale(1.5f, 1.5f);
271
272 // Rectangle
273 builder.Translate(100, 100);
274 builder.DrawRect(DlRect::MakeWH(100, 100), paint);
275
276 // Rounded rectangle
277 builder.Translate(150, 0);
278 builder.DrawRoundRect(
279 DlRoundRect::MakeRectXY(DlRect::MakeWH(100, 50), 10, 10), paint);
280
281 // Double rounded rectangle
282 builder.Translate(150, 0);
283 builder.DrawDiffRoundRect(
284 DlRoundRect::MakeRectXY(DlRect::MakeWH(100, 50), 10, 10),
285 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(10, 10, 80, 30), 10, 10),
286 paint);
287
288 // Contour with duplicate join points
289 {
290 builder.Translate(150, 0);
291 flutter::DlPathBuilder path_builder;
292 path_builder.MoveTo(DlPoint(0, 0));
293 path_builder.LineTo(DlPoint(0, 0));
294 path_builder.LineTo(DlPoint(100, 0));
295 path_builder.LineTo(DlPoint(100, 0));
296 path_builder.LineTo(DlPoint(100, 100));
297 builder.DrawPath(path_builder.TakePath(), paint);
298 }
299
300 // Contour with duplicate start and end points
301
302 // Line.
303 builder.Translate(200, 0);
304 {
305 builder.Save();
306
307 flutter::DlPathBuilder line_path_builder;
308 line_path_builder.MoveTo(DlPoint(0, 0));
309 line_path_builder.MoveTo(DlPoint(0, 0));
310 line_path_builder.LineTo(DlPoint(0, 0));
311 line_path_builder.LineTo(DlPoint(0, 0));
312 line_path_builder.LineTo(DlPoint(50, 50));
313 line_path_builder.LineTo(DlPoint(50, 50));
314 line_path_builder.LineTo(DlPoint(100, 0));
315 line_path_builder.LineTo(DlPoint(100, 0));
316 DlPath line_path = line_path_builder.TakePath();
317 builder.DrawPath(line_path, paint);
318
319 builder.Translate(0, 100);
320 builder.DrawPath(line_path, paint);
321
322 builder.Translate(0, 100);
323 flutter::DlPathBuilder line_path_builder2;
324 line_path_builder2.MoveTo(DlPoint(0, 0));
325 line_path_builder2.LineTo(DlPoint(0, 0));
326 line_path_builder2.LineTo(DlPoint(0, 0));
327 builder.DrawPath(line_path_builder2.TakePath(), paint);
328
329 builder.Restore();
330 }
331
332 // Cubic.
333 builder.Translate(150, 0);
334 {
335 builder.Save();
336
337 flutter::DlPathBuilder cubic_path;
338 cubic_path.MoveTo(DlPoint(0, 0));
339 cubic_path.CubicCurveTo(DlPoint(0, 0), //
340 DlPoint(140.0, 100.0), //
341 DlPoint(140, 20));
342 builder.DrawPath(cubic_path.TakePath(), paint);
343
344 builder.Translate(0, 100);
345 flutter::DlPathBuilder cubic_path2;
346 cubic_path2.MoveTo(DlPoint(0, 0));
347 cubic_path2.CubicCurveTo(DlPoint(0, 0), //
348 DlPoint(0, 0), //
349 DlPoint(150, 150));
350 builder.DrawPath(cubic_path2.TakePath(), paint);
351
352 builder.Translate(0, 100);
353 flutter::DlPathBuilder cubic_path3;
354 cubic_path3.MoveTo(DlPoint(0, 0));
355 cubic_path3.CubicCurveTo(DlPoint(0, 0), //
356 DlPoint(0, 0), //
357 DlPoint(0, 0));
358 builder.DrawPath(cubic_path3.TakePath(), paint);
359
360 builder.Restore();
361 }
362
363 // Quad.
364 builder.Translate(200, 0);
365 {
366 builder.Save();
367
368 flutter::DlPathBuilder quad_path;
369 quad_path.MoveTo(DlPoint(0, 0));
370 quad_path.MoveTo(DlPoint(0, 0));
371 quad_path.QuadraticCurveTo(DlPoint(100, 40), DlPoint(50, 80));
372 builder.DrawPath(quad_path.TakePath(), paint);
373
374 builder.Translate(0, 150);
375 flutter::DlPathBuilder quad_path2;
376 quad_path2.MoveTo(DlPoint(0, 0));
377 quad_path2.MoveTo(DlPoint(0, 0));
378 quad_path2.QuadraticCurveTo(DlPoint(0, 0), DlPoint(100, 100));
379 builder.DrawPath(quad_path2.TakePath(), paint);
380
381 builder.Translate(0, 100);
382 flutter::DlPathBuilder quad_path3;
383 quad_path3.MoveTo(DlPoint(0, 0));
384 quad_path3.QuadraticCurveTo(DlPoint(0, 0), DlPoint(0, 0));
385 builder.DrawPath(quad_path3.TakePath(), paint);
386
387 builder.Restore();
388 }
389 return builder.Build();
390 };
391 ASSERT_TRUE(OpenPlaygroundHere(callback));
392 }
393
394 TEST_P(DisplayListTest, CanDrawWithOddPathWinding) {
395 flutter::DisplayListBuilder builder;
396 flutter::DlPaint paint;
397
398 paint.setColor(flutter::DlColor::kRed());
399 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
400
401 builder.Translate(300, 300);
402 flutter::DlPathBuilder path_builder;
403 path_builder.AddCircle(DlPoint(0, 0), 100);
404 path_builder.AddCircle(DlPoint(0, 0), 50);
405 path_builder.SetFillType(flutter::DlPathFillType::kOdd);
406 builder.DrawPath(path_builder.TakePath(), paint);
407
408 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
409 }
410
411 // Regression test for https://github.com/flutter/flutter/issues/134816.
412 //
413 // It should be possible to draw 3 lines, and not have an implicit close path.
414 TEST_P(DisplayListTest, CanDrawAnOpenPath) {
415 flutter::DisplayListBuilder builder;
416 flutter::DlPaint paint;
417
418 paint.setColor(flutter::DlColor::kRed());
419 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
420 paint.setStrokeWidth(10);
421
422 builder.Translate(300, 300);
423
424 // Move to (50, 50) and draw lines from:
425 // 1. (50, height)
426 // 2. (width, height)
427 // 3. (width, 50)
428 flutter::DlPathBuilder path_builder;
429 path_builder.MoveTo(DlPoint(50, 50));
430 path_builder.LineTo(DlPoint(50, 100));
431 path_builder.LineTo(DlPoint(100, 100));
432 path_builder.LineTo(DlPoint(100, 50));
433 builder.DrawPath(path_builder.TakePath(), paint);
434
435 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
436 }
437
438 TEST_P(DisplayListTest, CanDrawWithMaskBlur) {
439 auto texture = CreateTextureForFixture("embarcadero.jpg");
440 flutter::DisplayListBuilder builder;
441 flutter::DlPaint paint;
442
443 // Mask blurred image.
444 {
445 auto filter =
446 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
447 paint.setMaskFilter(&filter);
448 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
449 flutter::DlImageSampling::kNearestNeighbor, &paint);
450 }
451
452 // Mask blurred filled path.
453 {
454 paint.setColor(flutter::DlColor::kYellow());
455 auto filter =
456 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kOuter, 10.0f);
457 paint.setMaskFilter(&filter);
458 builder.DrawArc(DlRect::MakeXYWH(410, 110, 100, 100), 45, 270, true, paint);
459 }
460
461 // Mask blurred text.
462 {
463 auto filter =
464 flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kSolid, 10.0f);
465 paint.setMaskFilter(&filter);
466 builder.DrawTextBlob(
467 SkTextBlob::MakeFromString("Testing", CreateTestFont()), 220, 170,
468 paint);
469 }
470
471 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
472 }
473
474 TEST_P(DisplayListTest, CanDrawStrokedText) {
475 flutter::DisplayListBuilder builder;
476 flutter::DlPaint paint;
477
478 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
479 paint.setColor(flutter::DlColor::kRed());
480 builder.DrawTextBlob(
481 SkTextBlob::MakeFromString("stoked about stroked text", CreateTestFont()),
482 250, 250, paint);
483
484 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
485 }
486
487 // Regression test for https://github.com/flutter/flutter/issues/133157.
488 TEST_P(DisplayListTest, StrokedTextNotOffsetFromNormalText) {
489 flutter::DisplayListBuilder builder;
490 flutter::DlPaint paint;
491 auto const& text_blob = SkTextBlob::MakeFromString("00000", CreateTestFont());
492
493 // https://api.flutter.dev/flutter/material/Colors/blue-constant.html.
494 auto const& mat_blue = flutter::DlColor(0xFF2196f3);
495
496 // Draw a blue filled rectangle so the text is easier to see.
497 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
498 paint.setColor(mat_blue);
499 builder.DrawRect(DlRect::MakeXYWH(0, 0, 500, 500), paint);
500
501 // Draw stacked text, with stroked text on top.
502 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
503 paint.setColor(flutter::DlColor::kWhite());
504 builder.DrawTextBlob(text_blob, 250, 250, paint);
505
506 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
507 paint.setColor(flutter::DlColor::kBlack());
508 builder.DrawTextBlob(text_blob, 250, 250, paint);
509
510 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
511 }
512
513 TEST_P(DisplayListTest, IgnoreMaskFilterWhenSavingLayer) {
514 auto texture = CreateTextureForFixture("embarcadero.jpg");
515 flutter::DisplayListBuilder builder;
516 auto filter = flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
517 flutter::DlPaint paint;
518 paint.setMaskFilter(&filter);
519 builder.SaveLayer(std::nullopt, &paint);
520 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
521 flutter::DlImageSampling::kNearestNeighbor);
522 builder.Restore();
523 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
524 }
525
526 TEST_P(DisplayListTest, CanDrawWithBlendColorFilter) {
527 auto texture = CreateTextureForFixture("embarcadero.jpg");
528 flutter::DisplayListBuilder builder;
529 flutter::DlPaint paint;
530
531 // Pipeline blended image.
532 {
533 auto filter = flutter::DlColorFilter::MakeBlend(
534 flutter::DlColor::kYellow(), flutter::DlBlendMode::kModulate);
535 paint.setColorFilter(filter);
536 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
537 flutter::DlImageSampling::kNearestNeighbor, &paint);
538 }
539
540 // Advanced blended image.
541 {
542 auto filter = flutter::DlColorFilter::MakeBlend(
543 flutter::DlColor::kRed(), flutter::DlBlendMode::kScreen);
544 paint.setColorFilter(filter);
545 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(250, 250),
546 flutter::DlImageSampling::kNearestNeighbor, &paint);
547 }
548
549 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
550 }
551
552 TEST_P(DisplayListTest, CanDrawWithColorFilterImageFilter) {
553 const float invert_color_matrix[20] = {
554 -1, 0, 0, 0, 1, //
555 0, -1, 0, 0, 1, //
556 0, 0, -1, 0, 1, //
557 0, 0, 0, 1, 0, //
558 };
559 auto texture = CreateTextureForFixture("boston.jpg");
560 flutter::DisplayListBuilder builder;
561 flutter::DlPaint paint;
562
563 auto color_filter = flutter::DlColorFilter::MakeMatrix(invert_color_matrix);
564 auto image_filter = flutter::DlImageFilter::MakeColorFilter(color_filter);
565
566 paint.setImageFilter(image_filter);
567 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
568 flutter::DlImageSampling::kNearestNeighbor, &paint);
569
570 builder.Translate(0, 700);
571 paint.setColorFilter(color_filter);
572 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
573 flutter::DlImageSampling::kNearestNeighbor, &paint);
574 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
575 }
576
577 TEST_P(DisplayListTest, CanDrawWithImageBlurFilter) {
578 auto texture = CreateTextureForFixture("embarcadero.jpg");
579
580 auto callback = [&]() {
581 static float sigma[] = {10, 10};
582
583 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
584 ImGui::SliderFloat2("Sigma", sigma, 0, 100);
585 ImGui::End();
586
587 flutter::DisplayListBuilder builder;
588 flutter::DlPaint paint;
589
590 auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
591 flutter::DlTileMode::kClamp);
592 paint.setImageFilter(&filter);
593 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(200, 200),
594 flutter::DlImageSampling::kNearestNeighbor, &paint);
595
596 return builder.Build();
597 };
598
599 ASSERT_TRUE(OpenPlaygroundHere(callback));
600 }
601
602 TEST_P(DisplayListTest, CanDrawWithComposeImageFilter) {
603 auto texture = CreateTextureForFixture("boston.jpg");
604 flutter::DisplayListBuilder builder;
605 flutter::DlPaint paint;
606
607 auto dilate = std::make_shared<flutter::DlDilateImageFilter>(10.0, 10.0);
608 auto erode = std::make_shared<flutter::DlErodeImageFilter>(10.0, 10.0);
609 auto open = std::make_shared<flutter::DlComposeImageFilter>(dilate, erode);
610 auto close = std::make_shared<flutter::DlComposeImageFilter>(erode, dilate);
611
612 paint.setImageFilter(open.get());
613 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
614 flutter::DlImageSampling::kNearestNeighbor, &paint);
615 builder.Translate(0, 700);
616 paint.setImageFilter(close.get());
617 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
618 flutter::DlImageSampling::kNearestNeighbor, &paint);
619 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
620 }
621
622 TEST_P(DisplayListTest, CanClampTheResultingColorOfColorMatrixFilter) {
623 auto texture = CreateTextureForFixture("boston.jpg");
624 const float inner_color_matrix[20] = {
625 1, 0, 0, 0, 0, //
626 0, 1, 0, 0, 0, //
627 0, 0, 1, 0, 0, //
628 0, 0, 0, 2, 0, //
629 };
630 const float outer_color_matrix[20] = {
631 1, 0, 0, 0, 0, //
632 0, 1, 0, 0, 0, //
633 0, 0, 1, 0, 0, //
634 0, 0, 0, 0.5, 0, //
635 };
636 auto inner_color_filter =
637 flutter::DlColorFilter::MakeMatrix(inner_color_matrix);
638 auto outer_color_filter =
639 flutter::DlColorFilter::MakeMatrix(outer_color_matrix);
640 auto inner = flutter::DlImageFilter::MakeColorFilter(inner_color_filter);
641 auto outer = flutter::DlImageFilter::MakeColorFilter(outer_color_filter);
642 auto compose = std::make_shared<flutter::DlComposeImageFilter>(outer, inner);
643
644 flutter::DisplayListBuilder builder;
645 flutter::DlPaint paint;
646 paint.setImageFilter(compose.get());
647 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(100, 100),
648 flutter::DlImageSampling::kNearestNeighbor, &paint);
649 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
650 }
651
652 TEST_P(DisplayListTest, CanDrawBackdropFilter) {
653 auto texture = CreateTextureForFixture("embarcadero.jpg");
654
655 auto callback = [&]() {
656 static float sigma[] = {10, 10};
657 static float ctm_scale = 1;
658 static bool use_bounds = true;
659 static bool draw_circle = true;
660 static bool add_clip = true;
661
662 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
663 ImGui::SliderFloat2("Sigma", sigma, 0, 100);
664 ImGui::SliderFloat("Scale", &ctm_scale, 0, 10);
665 ImGui::NewLine();
666 ImGui::TextWrapped(
667 "If everything is working correctly, none of the options below should "
668 "impact the filter's appearance.");
669 ImGui::Checkbox("Use SaveLayer bounds", &use_bounds);
670 ImGui::Checkbox("Draw child element", &draw_circle);
671 ImGui::Checkbox("Add pre-clip", &add_clip);
672 ImGui::End();
673
674 flutter::DisplayListBuilder builder;
675
676 Vector2 scale = ctm_scale * GetContentScale();
677 builder.Scale(scale.x, scale.y);
678
679 auto filter = flutter::DlBlurImageFilter(sigma[0], sigma[1],
680 flutter::DlTileMode::kClamp);
681
682 std::optional<DlRect> bounds;
683 if (use_bounds) {
684 static PlaygroundPoint point_a(Point(350, 150), 20, Color::White());
685 static PlaygroundPoint point_b(Point(800, 600), 20, Color::White());
686 auto [p1, p2] = DrawPlaygroundLine(point_a, point_b);
687 bounds = DlRect::MakeLTRB(p1.x, p1.y, p2.x, p2.y);
688 }
689
690 // Insert a clip to test that the backdrop filter handles stencil depths > 0
691 // correctly.
692 if (add_clip) {
693 builder.ClipRect(DlRect::MakeLTRB(0, 0, 99999, 99999),
694 flutter::DlClipOp::kIntersect, true);
695 }
696
697 builder.DrawImage(DlImageImpeller::Make(texture), DlPoint(200, 200),
698 flutter::DlImageSampling::kNearestNeighbor, nullptr);
699 builder.SaveLayer(bounds, nullptr, &filter);
700
701 if (draw_circle) {
702 static PlaygroundPoint center_point(Point(500, 400), 20, Color::Red());
703 auto circle_center = DrawPlaygroundPoint(center_point);
704
705 flutter::DlPaint paint;
706 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
707 paint.setStrokeCap(flutter::DlStrokeCap::kButt);
708 paint.setStrokeJoin(flutter::DlStrokeJoin::kBevel);
709 paint.setStrokeWidth(10);
710 paint.setColor(flutter::DlColor::kRed().withAlpha(100));
711 builder.DrawCircle(DlPoint(circle_center.x, circle_center.y), 100, paint);
712 }
713
714 return builder.Build();
715 };
716
717 ASSERT_TRUE(OpenPlaygroundHere(callback));
718 }
719
720 TEST_P(DisplayListTest, CanDrawNinePatchImage) {
721 // Image is drawn with corners to scale and center pieces stretched to fit.
722 auto texture = CreateTextureForFixture("embarcadero.jpg");
723 flutter::DisplayListBuilder builder;
724 auto size = texture->GetSize();
725 builder.DrawImageNine(
726 DlImageImpeller::Make(texture),
727 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
728 size.height * 3 / 4),
729 DlRect::MakeLTRB(0, 0, size.width * 2, size.height * 2),
730 flutter::DlFilterMode::kNearest, nullptr);
731 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
732 }
733
734 TEST_P(DisplayListTest, CanDrawNinePatchImageCenterWidthBiggerThanDest) {
735 // Edge case, the width of the corners does not leave any room for the
736 // center slice. The center (across the vertical axis) is folded out of the
737 // resulting image.
738 auto texture = CreateTextureForFixture("embarcadero.jpg");
739 flutter::DisplayListBuilder builder;
740 auto size = texture->GetSize();
741 builder.DrawImageNine(
742 DlImageImpeller::Make(texture),
743 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
744 size.height * 3 / 4),
745 DlRect::MakeLTRB(0, 0, size.width / 2, size.height),
746 flutter::DlFilterMode::kNearest, nullptr);
747 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
748 }
749
750 TEST_P(DisplayListTest, CanDrawNinePatchImageCenterHeightBiggerThanDest) {
751 // Edge case, the height of the corners does not leave any room for the
752 // center slice. The center (across the horizontal axis) is folded out of the
753 // resulting image.
754 auto texture = CreateTextureForFixture("embarcadero.jpg");
755 flutter::DisplayListBuilder builder;
756 auto size = texture->GetSize();
757 builder.DrawImageNine(
758 DlImageImpeller::Make(texture),
759 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
760 size.height * 3 / 4),
761 DlRect::MakeLTRB(0, 0, size.width, size.height / 2),
762 flutter::DlFilterMode::kNearest, nullptr);
763 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
764 }
765
766 TEST_P(DisplayListTest, CanDrawNinePatchImageCenterBiggerThanDest) {
767 // Edge case, the width and height of the corners does not leave any
768 // room for the center slices. Only the corners are displayed.
769 auto texture = CreateTextureForFixture("embarcadero.jpg");
770 flutter::DisplayListBuilder builder;
771 auto size = texture->GetSize();
772 builder.DrawImageNine(
773 DlImageImpeller::Make(texture),
774 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
775 size.height * 3 / 4),
776 DlRect::MakeLTRB(0, 0, size.width / 2, size.height / 2),
777 flutter::DlFilterMode::kNearest, nullptr);
778 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
779 }
780
781 TEST_P(DisplayListTest, CanDrawNinePatchImageCornersScaledDown) {
782 // Edge case, there is not enough room for the corners to be drawn
783 // without scaling them down.
784 auto texture = CreateTextureForFixture("embarcadero.jpg");
785 flutter::DisplayListBuilder builder;
786 auto size = texture->GetSize();
787 builder.DrawImageNine(
788 DlImageImpeller::Make(texture),
789 DlIRect::MakeLTRB(size.width / 4, size.height / 4, size.width * 3 / 4,
790 size.height * 3 / 4),
791 DlRect::MakeLTRB(0, 0, size.width / 4, size.height / 4),
792 flutter::DlFilterMode::kNearest, nullptr);
793 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
794 }
795
796 TEST_P(DisplayListTest, NinePatchImagePrecision) {
797 // Draw a nine patch image with colored corners and verify that the corner
798 // color does not leak outside the intended region.
799 auto texture = CreateTextureForFixture("nine_patch_corners.png");
800 flutter::DisplayListBuilder builder;
801 builder.DrawImageNine(DlImageImpeller::Make(texture),
802 DlIRect::MakeXYWH(10, 10, 1, 1),
803 DlRect::MakeXYWH(0, 0, 200, 100),
804 flutter::DlFilterMode::kNearest, nullptr);
805 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
806 }
807
808 TEST_P(DisplayListTest, CanDrawPoints) {
809 flutter::DisplayListBuilder builder;
810 DlPoint points[7] = {
811 {0, 0}, //
812 {100, 100}, //
813 {100, 0}, //
814 {0, 100}, //
815 {0, 0}, //
816 {48, 48}, //
817 {52, 52}, //
818 };
819 std::vector<flutter::DlStrokeCap> caps = {
820 flutter::DlStrokeCap::kButt,
821 flutter::DlStrokeCap::kRound,
822 flutter::DlStrokeCap::kSquare,
823 };
824 flutter::DlPaint paint =
825 flutter::DlPaint() //
826 .setColor(flutter::DlColor::kYellow().withAlpha(127)) //
827 .setStrokeWidth(20);
828 builder.Translate(50, 50);
829 for (auto cap : caps) {
830 paint.setStrokeCap(cap);
831 builder.Save();
832 builder.DrawPoints(flutter::DlPointMode::kPoints, 7, points, paint);
833 builder.Translate(150, 0);
834 builder.DrawPoints(flutter::DlPointMode::kLines, 5, points, paint);
835 builder.Translate(150, 0);
836 builder.DrawPoints(flutter::DlPointMode::kPolygon, 5, points, paint);
837 builder.Restore();
838 builder.Translate(0, 150);
839 }
840 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
841 }
842
843 TEST_P(DisplayListTest, CanDrawZeroLengthLine) {
844 flutter::DisplayListBuilder builder;
845 std::vector<flutter::DlStrokeCap> caps = {
846 flutter::DlStrokeCap::kButt,
847 flutter::DlStrokeCap::kRound,
848 flutter::DlStrokeCap::kSquare,
849 };
850 flutter::DlPaint paint =
851 flutter::DlPaint() //
852 .setColor(flutter::DlColor::kYellow().withAlpha(127)) //
853 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
854 .setStrokeCap(flutter::DlStrokeCap::kButt) //
855 .setStrokeWidth(20);
856 DlPath path = DlPath::MakeLine({150, 50}, {150, 50});
857 for (auto cap : caps) {
858 paint.setStrokeCap(cap);
859 builder.DrawLine(DlPoint(50, 50), DlPoint(50, 50), paint);
860 builder.DrawPath(path, paint);
861 builder.Translate(0, 150);
862 }
863 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
864 }
865
866 TEST_P(DisplayListTest, CanDrawShadow) {
867 flutter::DisplayListBuilder builder;
868 flutter::DlPaint paint;
869
870 auto content_scale = GetContentScale() * 0.8;
871 builder.Scale(content_scale.x, content_scale.y);
872
873 constexpr size_t star_spikes = 5;
874 constexpr DlScalar half_spike_rotation = kPi / star_spikes;
875 constexpr DlScalar radius = 40;
876 constexpr DlScalar spike_size = 10;
877 constexpr DlScalar outer_radius = radius + spike_size;
878 constexpr DlScalar inner_radius = radius - spike_size;
879 std::array<DlPoint, star_spikes * 2> star;
880 for (size_t i = 0; i < star_spikes; i++) {
881 const DlScalar rotation = half_spike_rotation * i * 2;
882 star[i * 2] = DlPoint(50 + std::sin(rotation) * outer_radius,
883 50 - std::cos(rotation) * outer_radius);
884 star[i * 2 + 1] =
885 DlPoint(50 + std::sin(rotation + half_spike_rotation) * inner_radius,
886 50 - std::cos(rotation + half_spike_rotation) * inner_radius);
887 }
888
889 std::array<DlPath, 4> paths = {
890 DlPath::MakeRect(DlRect::MakeXYWH(0, 0, 200, 100)),
891 DlPath::MakeRoundRectXY(DlRect::MakeXYWH(20, 0, 200, 100), 30, 30),
892 DlPath::MakeCircle(DlPoint(100, 50), 50),
893 DlPath::MakePoly(star.data(), star.size(), true),
894 };
895 paint.setColor(flutter::DlColor::kWhite());
896 builder.DrawPaint(paint);
897 paint.setColor(flutter::DlColor::kCyan());
898 builder.Translate(100, 50);
899 for (size_t x = 0; x < paths.size(); x++) {
900 builder.Save();
901 for (size_t y = 0; y < 6; y++) {
902 builder.DrawShadow(paths[x], flutter::DlColor::kBlack(), 3 + y * 8, false,
903 1);
904 builder.DrawPath(paths[x], paint);
905 builder.Translate(0, 150);
906 }
907 builder.Restore();
908 builder.Translate(250, 0);
909 }
910
911 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
912 }
913
914 TEST_P(DisplayListTest, CanDrawZeroWidthLine) {
915 flutter::DisplayListBuilder builder;
916 std::vector<flutter::DlStrokeCap> caps = {
917 flutter::DlStrokeCap::kButt,
918 flutter::DlStrokeCap::kRound,
919 flutter::DlStrokeCap::kSquare,
920 };
921 flutter::DlPaint paint = //
922 flutter::DlPaint() //
923 .setColor(flutter::DlColor::kWhite()) //
924 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
925 .setStrokeWidth(0);
926 flutter::DlPaint outline_paint = //
927 flutter::DlPaint() //
928 .setColor(flutter::DlColor::kYellow()) //
929 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
930 .setStrokeCap(flutter::DlStrokeCap::kSquare) //
931 .setStrokeWidth(1);
932 DlPath path = DlPath::MakeLine({150, 50}, {160, 50});
933 for (auto cap : caps) {
934 paint.setStrokeCap(cap);
935 builder.DrawLine(DlPoint(50, 50), DlPoint(60, 50), paint);
936 builder.DrawRect(DlRect::MakeLTRB(45, 45, 65, 55), outline_paint);
937 builder.DrawLine(DlPoint{100, 50}, DlPoint{100, 50}, paint);
938 if (cap != flutter::DlStrokeCap::kButt) {
939 builder.DrawRect(DlRect::MakeLTRB(95, 45, 105, 55), outline_paint);
940 }
941 builder.DrawPath(path, paint);
942 builder.DrawRect(path.GetBounds().Expand(5, 5), outline_paint);
943 builder.Translate(0, 150);
944 }
945 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
946 }
947
948 TEST_P(DisplayListTest, CanDrawWithMatrixFilter) {
949 auto boston = CreateTextureForFixture("boston.jpg");
950
951 auto callback = [&]() {
952 static int selected_matrix_type = 0;
953 const char* matrix_type_names[] = {"Matrix", "Local Matrix"};
954
955 static float ctm_translation[2] = {200, 200};
956 static float ctm_scale[2] = {0.65, 0.65};
957 static float ctm_skew[2] = {0, 0};
958
959 static bool enable = true;
960 static float translation[2] = {100, 100};
961 static float scale[2] = {0.8, 0.8};
962 static float skew[2] = {0.2, 0.2};
963
964 static bool enable_savelayer = true;
965
966 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
967 {
968 ImGui::Combo("Filter type", &selected_matrix_type, matrix_type_names,
969 sizeof(matrix_type_names) / sizeof(char*));
970
971 ImGui::TextWrapped("Current Transform");
972 ImGui::SliderFloat2("CTM Translation", ctm_translation, 0, 1000);
973 ImGui::SliderFloat2("CTM Scale", ctm_scale, 0, 3);
974 ImGui::SliderFloat2("CTM Skew", ctm_skew, -3, 3);
975
976 ImGui::TextWrapped(
977 "MatrixFilter and LocalMatrixFilter modify the CTM in the same way. "
978 "The only difference is that MatrixFilter doesn't affect the effect "
979 "transform, whereas LocalMatrixFilter does.");
980 // Note: See this behavior in:
981 // https://fiddle.skia.org/c/6cbb551ab36d06f163db8693972be954
982 ImGui::Checkbox("Enable", &enable);
983 ImGui::SliderFloat2("Filter Translation", translation, 0, 1000);
984 ImGui::SliderFloat2("Filter Scale", scale, 0, 3);
985 ImGui::SliderFloat2("Filter Skew", skew, -3, 3);
986
987 ImGui::TextWrapped(
988 "Rendering the filtered image within a layer can expose bounds "
989 "issues. If the rendered image gets cut off when this setting is "
990 "enabled, there's a coverage bug in the filter.");
991 ImGui::Checkbox("Render in layer", &enable_savelayer);
992 }
993 ImGui::End();
994
995 flutter::DisplayListBuilder builder;
996 flutter::DlPaint paint;
997
998 if (enable_savelayer) {
999 builder.SaveLayer(std::nullopt, nullptr);
1000 }
1001 {
1002 auto content_scale = GetContentScale();
1003 builder.Scale(content_scale.x, content_scale.y);
1004
1005 // Set the current transform
1006 auto ctm_matrix = Matrix::MakeRow(
1007 ctm_scale[0], ctm_skew[0], 0.0f, ctm_translation[0], //
1008 ctm_skew[1], ctm_scale[1], 0.0f, ctm_translation[1], //
1009 0, 0, 1, 0, //
1010 0, 0, 0, 1);
1011 builder.Transform(ctm_matrix);
1012
1013 // Set the matrix filter
1014 auto filter_matrix =
1015 Matrix::MakeRow(scale[0], skew[0], 0.0f, translation[0], //
1016 skew[1], scale[1], 0.0f, translation[1], //
1017 0.0f, 0.0f, 1.0f, 0.0f, //
1018 0.0f, 0.0f, 0.0f, 1.0f);
1019
1020 if (enable) {
1021 switch (selected_matrix_type) {
1022 case 0: {
1023 auto filter = flutter::DlMatrixImageFilter(
1024 filter_matrix, flutter::DlImageSampling::kLinear);
1025 paint.setImageFilter(&filter);
1026 break;
1027 }
1028 case 1: {
1029 auto internal_filter =
1030 flutter::DlBlurImageFilter(10, 10, flutter::DlTileMode::kDecal)
1031 .shared();
1032 auto filter = flutter::DlLocalMatrixImageFilter(filter_matrix,
1033 internal_filter);
1034 paint.setImageFilter(&filter);
1035 break;
1036 }
1037 }
1038 }
1039
1040 builder.DrawImage(DlImageImpeller::Make(boston), DlPoint(),
1041 flutter::DlImageSampling::kLinear, &paint);
1042 }
1043 if (enable_savelayer) {
1044 builder.Restore();
1045 }
1046
1047 return builder.Build();
1048 };
1049
1050 ASSERT_TRUE(OpenPlaygroundHere(callback));
1051 }
1052
1053 TEST_P(DisplayListTest, CanDrawWithMatrixFilterWhenSavingLayer) {
1054 auto callback = [&]() {
1055 static float translation[2] = {0, 0};
1056 static bool enable_save_layer = true;
1057
1058 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1059 ImGui::SliderFloat2("Translation", translation, -130, 130);
1060 ImGui::Checkbox("Enable save layer", &enable_save_layer);
1061 ImGui::End();
1062
1063 flutter::DisplayListBuilder builder;
1064 builder.Save();
1065 builder.Scale(2.0, 2.0);
1066 flutter::DlPaint paint;
1067 paint.setColor(flutter::DlColor::kYellow());
1068 builder.DrawRect(DlRect::MakeWH(300, 300), paint);
1069 paint.setStrokeWidth(1.0);
1070 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
1071 paint.setColor(flutter::DlColor::kBlack().withAlpha(0x80));
1072 builder.DrawLine(DlPoint(150, 0), DlPoint(150, 300), paint);
1073 builder.DrawLine(DlPoint(0, 150), DlPoint(300, 150), paint);
1074
1075 flutter::DlPaint save_paint;
1076 DlRect bounds = DlRect::MakeXYWH(100, 100, 100, 100);
1077 Matrix translate_matrix =
1078 Matrix::MakeTranslation({translation[0], translation[1]});
1079 if (enable_save_layer) {
1080 auto filter = flutter::DlMatrixImageFilter(
1081 translate_matrix, flutter::DlImageSampling::kNearestNeighbor);
1082 save_paint.setImageFilter(filter.shared());
1083 builder.SaveLayer(bounds, &save_paint);
1084 } else {
1085 builder.Save();
1086 builder.Transform(translate_matrix);
1087 }
1088
1089 Matrix filter_matrix;
1090 filter_matrix.Translate({150, 150});
1091 filter_matrix.Scale({0.2f, 0.2f});
1092 filter_matrix.Translate({-150, -150});
1093 auto filter = flutter::DlMatrixImageFilter(
1094 filter_matrix, flutter::DlImageSampling::kNearestNeighbor);
1095
1096 save_paint.setImageFilter(filter.shared());
1097
1098 builder.SaveLayer(bounds, &save_paint);
1099 flutter::DlPaint paint2;
1100 paint2.setColor(flutter::DlColor::kBlue());
1101 builder.DrawRect(bounds, paint2);
1102 builder.Restore();
1103 builder.Restore();
1104 return builder.Build();
1105 };
1106
1107 ASSERT_TRUE(OpenPlaygroundHere(callback));
1108 }
1109
1110 TEST_P(DisplayListTest, CanDrawRectWithLinearToSrgbColorFilter) {
1111 flutter::DlPaint paint;
1112 paint.setColor(flutter::DlColor(0xFF2196F3).withAlpha(128));
1113 flutter::DisplayListBuilder builder;
1114 paint.setColorFilter(flutter::DlColorFilter::MakeLinearToSrgbGamma());
1115 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), paint);
1116 builder.Translate(0, 200);
1117
1118 paint.setColorFilter(flutter::DlColorFilter::MakeSrgbToLinearGamma());
1119 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), paint);
1120
1121 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1122 }
1123
1124 TEST_P(DisplayListTest, CanDrawPaintWithColorSource) {
1125 const flutter::DlColor colors[2] = {
1126 flutter::DlColor(0xFFF44336),
1127 flutter::DlColor(0xFF2196F3),
1128 };
1129 const float stops[2] = {0.0, 1.0};
1130 flutter::DlPaint paint;
1131 flutter::DisplayListBuilder builder;
1132 auto clip_bounds = DlRect::MakeWH(300.0, 300.0);
1133 builder.Save();
1134 builder.Translate(100, 100);
1135 builder.ClipRect(clip_bounds, flutter::DlClipOp::kIntersect, false);
1136 auto linear =
1137 flutter::DlColorSource::MakeLinear({0.0, 0.0}, {100.0, 100.0}, 2, colors,
1138 stops, flutter::DlTileMode::kRepeat);
1139 paint.setColorSource(linear);
1140 builder.DrawPaint(paint);
1141 builder.Restore();
1142
1143 builder.Save();
1144 builder.Translate(500, 100);
1145 builder.ClipRect(clip_bounds, flutter::DlClipOp::kIntersect, false);
1146 auto radial = flutter::DlColorSource::MakeRadial(
1147 {100.0, 100.0}, 100.0, 2, colors, stops, flutter::DlTileMode::kRepeat);
1148 paint.setColorSource(radial);
1149 builder.DrawPaint(paint);
1150 builder.Restore();
1151
1152 builder.Save();
1153 builder.Translate(100, 500);
1154 builder.ClipRect(clip_bounds, flutter::DlClipOp::kIntersect, false);
1155 auto sweep =
1156 flutter::DlColorSource::MakeSweep({100.0, 100.0}, 180.0, 270.0, 2, colors,
1157 stops, flutter::DlTileMode::kRepeat);
1158 paint.setColorSource(sweep);
1159 builder.DrawPaint(paint);
1160 builder.Restore();
1161
1162 builder.Save();
1163 builder.Translate(500, 500);
1164 builder.ClipRect(clip_bounds, flutter::DlClipOp::kIntersect, false);
1165 auto texture = CreateTextureForFixture("table_mountain_nx.png");
1166 auto image = flutter::DlColorSource::MakeImage(DlImageImpeller::Make(texture),
1167 flutter::DlTileMode::kRepeat,
1168 flutter::DlTileMode::kRepeat);
1169 paint.setColorSource(image);
1170 builder.DrawPaint(paint);
1171 builder.Restore();
1172
1173 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1174 }
1175
1176 TEST_P(DisplayListTest, CanBlendDstOverAndDstCorrectly) {
1177 flutter::DisplayListBuilder builder;
1178
1179 {
1180 builder.SaveLayer(std::nullopt, nullptr);
1181 builder.Translate(100, 100);
1182 flutter::DlPaint paint;
1183 paint.setColor(flutter::DlColor::kRed());
1184 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1185 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1186 paint.setBlendMode(flutter::DlBlendMode::kSrcOver);
1187 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1188 builder.Restore();
1189 }
1190 {
1191 builder.SaveLayer(std::nullopt, nullptr);
1192 builder.Translate(300, 100);
1193 flutter::DlPaint paint;
1194 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1195 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1196 paint.setColor(flutter::DlColor::kRed());
1197 paint.setBlendMode(flutter::DlBlendMode::kDstOver);
1198 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1199 builder.Restore();
1200 }
1201 {
1202 builder.SaveLayer(std::nullopt, nullptr);
1203 builder.Translate(100, 300);
1204 flutter::DlPaint paint;
1205 paint.setColor(flutter::DlColor::kRed());
1206 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1207 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1208 paint.setBlendMode(flutter::DlBlendMode::kSrc);
1209 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1210 builder.Restore();
1211 }
1212 {
1213 builder.SaveLayer(std::nullopt, nullptr);
1214 builder.Translate(300, 300);
1215 flutter::DlPaint paint;
1216 paint.setColor(flutter::DlColor::kBlue().withAlpha(127));
1217 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1218 paint.setColor(flutter::DlColor::kRed());
1219 paint.setBlendMode(flutter::DlBlendMode::kDst);
1220 builder.DrawRect(DlRect::MakeWH(200, 200), paint);
1221 builder.Restore();
1222 }
1223
1224 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1225 }
1226
1227 TEST_P(DisplayListTest, CanDrawCorrectlyWithColorFilterAndImageFilter) {
1228 flutter::DisplayListBuilder builder;
1229 const float green_color_matrix[20] = {
1230 0, 0, 0, 0, 0, //
1231 0, 0, 0, 0, 1, //
1232 0, 0, 0, 0, 0, //
1233 0, 0, 0, 1, 0, //
1234 };
1235 const float blue_color_matrix[20] = {
1236 0, 0, 0, 0, 0, //
1237 0, 0, 0, 0, 0, //
1238 0, 0, 0, 0, 1, //
1239 0, 0, 0, 1, 0, //
1240 };
1241 auto green_color_filter =
1242 flutter::DlColorFilter::MakeMatrix(green_color_matrix);
1243 auto blue_color_filter =
1244 flutter::DlColorFilter::MakeMatrix(blue_color_matrix);
1245 auto blue_image_filter =
1246 flutter::DlImageFilter::MakeColorFilter(blue_color_filter);
1247
1248 flutter::DlPaint paint;
1249 paint.setColor(flutter::DlColor::kRed());
1250 paint.setColorFilter(green_color_filter);
1251 paint.setImageFilter(blue_image_filter);
1252 builder.DrawRect(DlRect::MakeLTRB(100, 100, 500, 500), paint);
1253 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1254 }
1255
1256 TEST_P(DisplayListTest, MaskBlursApplyCorrectlyToColorSources) {
1257 auto blur_filter = std::make_shared<flutter::DlBlurMaskFilter>(
1258 flutter::DlBlurStyle::kNormal, 10);
1259
1260 flutter::DisplayListBuilder builder;
1261
1262 std::array<flutter::DlColor, 2> colors = {flutter::DlColor::kBlue(),
1263 flutter::DlColor::kGreen()};
1264 std::array<float, 2> stops = {0, 1};
1265 auto texture = CreateTextureForFixture("airplane.jpg");
1266 auto matrix = flutter::DlMatrix::MakeTranslation({-300, -110});
1267 std::array<std::shared_ptr<flutter::DlColorSource>, 2> color_sources = {
1268 flutter::DlColorSource::MakeImage(
1269 DlImageImpeller::Make(texture), flutter::DlTileMode::kRepeat,
1270 flutter::DlTileMode::kRepeat, flutter::DlImageSampling::kLinear,
1271 &matrix),
1272 flutter::DlColorSource::MakeLinear(
1273 flutter::DlPoint(0, 0), flutter::DlPoint(100, 50), 2, colors.data(),
1274 stops.data(), flutter::DlTileMode::kClamp),
1275 };
1276
1277 builder.Save();
1278 builder.Translate(0, 100);
1279 for (const auto& color_source : color_sources) {
1280 flutter::DlPaint paint;
1281 paint.setColorSource(color_source);
1282 paint.setMaskFilter(blur_filter);
1283
1284 builder.Save();
1285 builder.Translate(100, 0);
1286 paint.setDrawStyle(flutter::DlDrawStyle::kFill);
1287 builder.DrawRoundRect(
1288 DlRoundRect::MakeRectXY(DlRect::MakeWH(100, 50), 30, 30), paint);
1289
1290 paint.setDrawStyle(flutter::DlDrawStyle::kStroke);
1291 paint.setStrokeWidth(10);
1292 builder.Translate(200, 0);
1293 builder.DrawRoundRect(
1294 DlRoundRect::MakeRectXY(DlRect::MakeWH(100, 50), 30, 30), paint);
1295
1296 builder.Restore();
1297 builder.Translate(0, 100);
1298 }
1299 builder.Restore();
1300
1301 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1302 }
1303
1304 TEST_P(DisplayListTest, DrawShapes) {
1305 flutter::DisplayListBuilder builder;
1306 std::vector<flutter::DlStrokeJoin> joins = {
1307 flutter::DlStrokeJoin::kBevel,
1308 flutter::DlStrokeJoin::kRound,
1309 flutter::DlStrokeJoin::kMiter,
1310 };
1311 flutter::DlPaint paint = //
1312 flutter::DlPaint() //
1313 .setColor(flutter::DlColor::kWhite()) //
1314 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1315 .setStrokeWidth(10);
1316 flutter::DlPaint stroke_paint = //
1317 flutter::DlPaint() //
1318 .setColor(flutter::DlColor::kWhite()) //
1319 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1320 .setStrokeWidth(10);
1321 DlPath path = DlPath::MakeLine({150, 50}, {160, 50});
1322
1323 builder.Translate(300, 50);
1324 builder.Scale(0.8, 0.8);
1325 for (auto join : joins) {
1326 paint.setStrokeJoin(join);
1327 stroke_paint.setStrokeJoin(join);
1328 builder.DrawRect(DlRect::MakeXYWH(0, 0, 100, 100), paint);
1329 builder.DrawRect(DlRect::MakeXYWH(0, 150, 100, 100), stroke_paint);
1330 builder.DrawRoundRect(
1331 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(150, 0, 100, 100), 30, 30),
1332 paint);
1333 builder.DrawRoundRect(
1334 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(150, 150, 100, 100), 30, 30),
1335 stroke_paint);
1336 builder.DrawCircle(DlPoint(350, 50), 50, paint);
1337 builder.DrawCircle(DlPoint(350, 200), 50, stroke_paint);
1338 builder.Translate(0, 300);
1339 }
1340 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1341 }
1342
1343 TEST_P(DisplayListTest, ClipDrawRRectWithNonCircularRadii) {
1344 flutter::DisplayListBuilder builder;
1345
1346 flutter::DlPaint fill_paint = //
1347 flutter::DlPaint() //
1348 .setColor(flutter::DlColor::kBlue()) //
1349 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1350 .setStrokeWidth(10);
1351 flutter::DlPaint stroke_paint = //
1352 flutter::DlPaint() //
1353 .setColor(flutter::DlColor::kGreen()) //
1354 .setDrawStyle(flutter::DlDrawStyle::kStroke) //
1355 .setStrokeWidth(10);
1356
1357 builder.DrawRoundRect(
1358 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(500, 100, 300, 300), 120, 40),
1359 fill_paint);
1360 builder.DrawRoundRect(
1361 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(500, 100, 300, 300), 120, 40),
1362 stroke_paint);
1363
1364 builder.DrawRoundRect(
1365 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(100, 500, 300, 300), 40, 120),
1366 fill_paint);
1367 builder.DrawRoundRect(
1368 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(100, 500, 300, 300), 40, 120),
1369 stroke_paint);
1370
1371 flutter::DlPaint reference_paint = //
1372 flutter::DlPaint() //
1373 .setColor(flutter::DlColor::kMidGrey()) //
1374 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1375 .setStrokeWidth(10);
1376
1377 builder.DrawRoundRect(
1378 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(500, 500, 300, 300), 40, 40),
1379 reference_paint);
1380 builder.DrawRoundRect(
1381 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(100, 100, 300, 300), 120, 120),
1382 reference_paint);
1383
1384 flutter::DlPaint clip_fill_paint = //
1385 flutter::DlPaint() //
1386 .setColor(flutter::DlColor::kCyan()) //
1387 .setDrawStyle(flutter::DlDrawStyle::kFill) //
1388 .setStrokeWidth(10);
1389
1390 builder.Save();
1391 builder.ClipRoundRect(
1392 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(900, 100, 300, 300), 120, 40));
1393 builder.DrawPaint(clip_fill_paint);
1394 builder.Restore();
1395
1396 builder.Save();
1397 builder.ClipRoundRect(
1398 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(100, 900, 300, 300), 40, 120));
1399 builder.DrawPaint(clip_fill_paint);
1400 builder.Restore();
1401
1402 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1403 }
1404
1405 TEST_P(DisplayListTest, DrawVerticesBlendModes) {
1406 std::vector<const char*> blend_mode_names;
1407 std::vector<flutter::DlBlendMode> blend_mode_values;
1408 {
1409 const std::vector<std::tuple<const char*, flutter::DlBlendMode>> blends = {
1410 // Pipeline blends (Porter-Duff alpha compositing)
1411 {"Clear", flutter::DlBlendMode::kClear},
1412 {"Source", flutter::DlBlendMode::kSrc},
1413 {"Destination", flutter::DlBlendMode::kDst},
1414 {"SourceOver", flutter::DlBlendMode::kSrcOver},
1415 {"DestinationOver", flutter::DlBlendMode::kDstOver},
1416 {"SourceIn", flutter::DlBlendMode::kSrcIn},
1417 {"DestinationIn", flutter::DlBlendMode::kDstIn},
1418 {"SourceOut", flutter::DlBlendMode::kSrcOut},
1419 {"DestinationOut", flutter::DlBlendMode::kDstOut},
1420 {"SourceATop", flutter::DlBlendMode::kSrcATop},
1421 {"DestinationATop", flutter::DlBlendMode::kDstATop},
1422 {"Xor", flutter::DlBlendMode::kXor},
1423 {"Plus", flutter::DlBlendMode::kPlus},
1424 {"Modulate", flutter::DlBlendMode::kModulate},
1425 // Advanced blends (color component blends)
1426 {"Screen", flutter::DlBlendMode::kScreen},
1427 {"Overlay", flutter::DlBlendMode::kOverlay},
1428 {"Darken", flutter::DlBlendMode::kDarken},
1429 {"Lighten", flutter::DlBlendMode::kLighten},
1430 {"ColorDodge", flutter::DlBlendMode::kColorDodge},
1431 {"ColorBurn", flutter::DlBlendMode::kColorBurn},
1432 {"HardLight", flutter::DlBlendMode::kHardLight},
1433 {"SoftLight", flutter::DlBlendMode::kSoftLight},
1434 {"Difference", flutter::DlBlendMode::kDifference},
1435 {"Exclusion", flutter::DlBlendMode::kExclusion},
1436 {"Multiply", flutter::DlBlendMode::kMultiply},
1437 {"Hue", flutter::DlBlendMode::kHue},
1438 {"Saturation", flutter::DlBlendMode::kSaturation},
1439 {"Color", flutter::DlBlendMode::kColor},
1440 {"Luminosity", flutter::DlBlendMode::kLuminosity},
1441 };
1442 assert(blends.size() ==
1443 static_cast<size_t>(flutter::DlBlendMode::kLastMode) + 1);
1444 for (const auto& [name, mode] : blends) {
1445 blend_mode_names.push_back(name);
1446 blend_mode_values.push_back(mode);
1447 }
1448 }
1449
1450 auto callback = [&]() {
1451 static int current_blend_index = 3;
1452 static float dst_alpha = 1;
1453 static float src_alpha = 1;
1454 static float color0[4] = {1.0f, 0.0f, 0.0f, 1.0f};
1455 static float color1[4] = {0.0f, 1.0f, 0.0f, 1.0f};
1456 static float color2[4] = {0.0f, 0.0f, 1.0f, 1.0f};
1457 static float src_color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
1458
1459 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
1460 {
1461 ImGui::ListBox("Blending mode", &current_blend_index,
1462 blend_mode_names.data(), blend_mode_names.size());
1463 ImGui::SliderFloat("Source alpha", &src_alpha, 0, 1);
1464 ImGui::ColorEdit4("Color A", color0);
1465 ImGui::ColorEdit4("Color B", color1);
1466 ImGui::ColorEdit4("Color C", color2);
1467 ImGui::ColorEdit4("Source Color", src_color);
1468 ImGui::SliderFloat("Destination alpha", &dst_alpha, 0, 1);
1469 }
1470 ImGui::End();
1471
1472 std::vector<DlPoint> positions = {DlPoint(100, 300), //
1473 DlPoint(200, 100), //
1474 DlPoint(300, 300)};
1475 std::vector<flutter::DlColor> colors = {
1476 toColor(color0).modulateOpacity(dst_alpha),
1477 toColor(color1).modulateOpacity(dst_alpha),
1478 toColor(color2).modulateOpacity(dst_alpha)};
1479
1480 auto vertices = flutter::DlVertices::Make(
1481 flutter::DlVertexMode::kTriangles, 3, positions.data(),
1482 /*texture_coordinates=*/nullptr, colors.data());
1483
1484 flutter::DisplayListBuilder builder;
1485 flutter::DlPaint paint;
1486
1487 paint.setColor(toColor(src_color).modulateOpacity(src_alpha));
1488 builder.DrawVertices(vertices, blend_mode_values[current_blend_index],
1489 paint);
1490 return builder.Build();
1491 };
1492
1493 ASSERT_TRUE(OpenPlaygroundHere(callback));
1494 }
1495
1496 TEST_P(DisplayListTest, DrawPaintIgnoresMaskFilter) {
1497 flutter::DisplayListBuilder builder;
1498 builder.DrawPaint(flutter::DlPaint().setColor(flutter::DlColor::kWhite()));
1499
1500 auto filter = flutter::DlBlurMaskFilter(flutter::DlBlurStyle::kNormal, 10.0f);
1501 builder.DrawCircle(DlPoint(300, 300), 200,
1502 flutter::DlPaint().setMaskFilter(&filter));
1503
1504 std::vector<flutter::DlColor> colors = {flutter::DlColor::kGreen(),
1505 flutter::DlColor::kGreen()};
1506 const float stops[2] = {0.0, 1.0};
1507 auto linear = flutter::DlColorSource::MakeLinear(
1508 {100.0, 100.0}, {300.0, 300.0}, 2, colors.data(), stops,
1509 flutter::DlTileMode::kRepeat);
1510 flutter::DlPaint blend_paint =
1511 flutter::DlPaint() //
1512 .setColorSource(linear) //
1513 .setBlendMode(flutter::DlBlendMode::kScreen);
1514 builder.DrawPaint(blend_paint);
1515
1516 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1517 }
1518
1519 TEST_P(DisplayListTest, DrawMaskBlursThatMightUseSaveLayers) {
1520 flutter::DisplayListBuilder builder;
1521 builder.DrawColor(flutter::DlColor::kWhite(), flutter::DlBlendMode::kSrc);
1522 Vector2 scale = GetContentScale();
1523 builder.Scale(scale.x, scale.y);
1524
1525 builder.Save();
1526 // We need a small transform op to avoid a deferred save
1527 builder.Translate(1.0f, 1.0f);
1528 auto solid_filter =
1529 flutter::DlBlurMaskFilter::Make(flutter::DlBlurStyle::kSolid, 5.0f);
1530 flutter::DlPaint solid_alpha_paint =
1531 flutter::DlPaint() //
1532 .setMaskFilter(solid_filter) //
1533 .setColor(flutter::DlColor::kBlue()) //
1534 .setAlpha(0x7f);
1535 for (int x = 1; x <= 4; x++) {
1536 for (int y = 1; y <= 4; y++) {
1537 builder.DrawRect(DlRect::MakeXYWH(x * 100, y * 100, 80, 80),
1538 solid_alpha_paint);
1539 }
1540 }
1541 builder.Restore();
1542
1543 builder.Save();
1544 builder.Translate(500.0f, 0.0f);
1545 auto normal_filter =
1546 flutter::DlBlurMaskFilter::Make(flutter::DlBlurStyle::kNormal, 5.0f);
1547 auto rotate_if = flutter::DlMatrixImageFilter::Make(
1548 Matrix::MakeRotationZ(Degrees(10)), flutter::DlImageSampling::kLinear);
1549 flutter::DlPaint normal_if_paint =
1550 flutter::DlPaint() //
1551 .setMaskFilter(solid_filter) //
1552 .setImageFilter(rotate_if) //
1553 .setColor(flutter::DlColor::kGreen()) //
1554 .setAlpha(0x7f);
1555 for (int x = 1; x <= 4; x++) {
1556 for (int y = 1; y <= 4; y++) {
1557 builder.DrawRect(DlRect::MakeXYWH(x * 100, y * 100, 80, 80),
1558 normal_if_paint);
1559 }
1560 }
1561 builder.Restore();
1562
1563 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1564 }
1565
1566 } // namespace testing
1567 } // namespace impeller
aiks_context.h
use_center
bool use_center
Definition: aiks_dl_basic_unittests.cc:764
impeller::DlImageImpeller::Make
static sk_sp< DlImageImpeller > Make(std::shared_ptr< Texture > texture, OwningContext owning_context=OwningContext::kIO)
Definition: dl_image_impeller.cc:23
impeller::DlPlayground
Definition: dl_playground.h:16
clip_contents.h
dl_dispatcher.h
x
int32_t x
Definition: dl_golden_unittests.cc:458
dl_image_impeller.h
dl_playground.h
constants.h
impeller::testing::TEST_P
TEST_P(AiksTest, DrawAtlasNoColor)
Definition: aiks_dl_atlas_unittests.cc:60
impeller::testing::toColor
flutter::DlColor toColor(const float *components)
Definition: dl_unittests.cc:38
impeller::testing::INSTANTIATE_PLAYGROUND_SUITE
INSTANTIATE_PLAYGROUND_SUITE(AiksTest)
impeller
Definition: allocation.cc:12
impeller::DlRect
flutter::DlRect DlRect
Definition: dl_dispatcher.h:25
impeller::kPi
constexpr float kPi
Definition: constants.h:26
impeller::DrawPlaygroundPoint
Point DrawPlaygroundPoint(PlaygroundPoint &point)
Definition: widgets.cc:9
impeller::DrawPlaygroundLine
std::tuple< Point, Point > DrawPlaygroundLine(PlaygroundPoint &point_a, PlaygroundPoint &point_b)
Definition: widgets.cc:50
impeller::Point
TPoint< Scalar > Point
Definition: point.h:327
impeller::DlPoint
flutter::DlPoint DlPoint
Definition: dl_dispatcher.h:24
impeller::DlPath
flutter::DlPath DlPath
Definition: dl_dispatcher.h:29
impeller::DlScalar
flutter::DlScalar DlScalar
Definition: dl_dispatcher.h:23
point.h
scalar.h
solid_color_contents.h
solid_rrect_blur_contents.h
impeller::Color
Definition: color.h:124
impeller::Color::ToIColor
static uint32_t ToIColor(Color color)
Convert this color to a 32-bit representation.
Definition: color.h:159
impeller::Color::White
static constexpr Color White()
Definition: color.h:264
impeller::Color::Red
static constexpr Color Red()
Definition: color.h:272
impeller::Degrees
Definition: scalar.h:76
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::Matrix::MakeTranslation
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:95
impeller::Matrix::Translate
constexpr Matrix Translate(const Vector3 &t) const
Definition: matrix.h:263
impeller::Matrix::MakeRow
static constexpr Matrix MakeRow(Scalar m0, Scalar m1, Scalar m2, Scalar m3, Scalar m4, Scalar m5, Scalar m6, Scalar m7, Scalar m8, Scalar m9, Scalar m10, Scalar m11, Scalar m12, Scalar m13, Scalar m14, Scalar m15)
Definition: matrix.h:83
impeller::Matrix::Scale
constexpr Matrix Scale(const Vector3 &s) const
Definition: matrix.h:275
impeller::Matrix::MakeRotationZ
static Matrix MakeRotationZ(Radians r)
Definition: matrix.h:223
impeller::PlaygroundPoint
Definition: widgets.h:21
impeller::TPoint< Scalar >
impeller::TPoint::y
Type y
Definition: point.h:31
impeller::TPoint::x
Type x
Definition: point.h:30
points
std::vector< Point > points
Definition: tessellator_libtess.cc:76
widgets.h