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