| Flutter Impeller |

aiks_dl_path_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 "display_list/dl_sampling_options.h"
6 #include "display_list/dl_tile_mode.h"
7 #include "display_list/effects/dl_color_source.h"
8 #include "display_list/effects/dl_mask_filter.h"
9 #include "flutter/impeller/display_list/aiks_unittests.h"
10
11 #include "flutter/display_list/dl_blend_mode.h"
12 #include "flutter/display_list/dl_builder.h"
13 #include "flutter/display_list/dl_color.h"
14 #include "flutter/display_list/dl_paint.h"
15 #include "flutter/display_list/effects/dl_color_filter.h"
16 #include "flutter/display_list/geometry/dl_path_builder.h"
17 #include "flutter/testing/testing.h"
18 #include "impeller/display_list/dl_image_impeller.h"
19 #include "impeller/playground/widgets.h"
20 #include "impeller/tessellator/path_tessellator.h"
21
22 namespace impeller {
23 namespace testing {
24
25 using namespace flutter;
26
27 TEST_P(AiksTest, RotateColorFilteredPath) {
28 DisplayListBuilder builder;
29 builder.Transform(DlMatrix::MakeTranslation(DlPoint(300, 300)) *
30 DlMatrix::MakeRotationZ(DlDegrees(90)));
31
32 DlPathBuilder arrow_stem;
33 DlPathBuilder arrow_head;
34
35 arrow_stem.MoveTo(DlPoint(120, 190)).LineTo(DlPoint(120, 50));
36 arrow_head.MoveTo(DlPoint(50, 120))
37 .LineTo(DlPoint(120, 190))
38 .LineTo(DlPoint(190, 120));
39
40 auto filter =
41 DlColorFilter::MakeBlend(DlColor::kAliceBlue(), DlBlendMode::kSrcIn);
42
43 DlPaint paint;
44 paint.setStrokeWidth(15.0);
45 paint.setStrokeCap(DlStrokeCap::kRound);
46 paint.setStrokeJoin(DlStrokeJoin::kRound);
47 paint.setDrawStyle(DlDrawStyle::kStroke);
48 paint.setColorFilter(filter);
49 paint.setColor(DlColor::kBlack());
50
51 builder.DrawPath(arrow_stem.TakePath(), paint);
52 builder.DrawPath(arrow_head.TakePath(), paint);
53
54 auto dl = builder.Build();
55 ASSERT_TRUE(OpenPlaygroundHere(dl));
56 }
57
58 TEST_P(AiksTest, CanRenderStrokes) {
59 DisplayListBuilder builder;
60 DlPaint paint;
61 paint.setColor(DlColor::kRed());
62 paint.setStrokeWidth(20);
63 paint.setDrawStyle(DlDrawStyle::kStroke);
64
65 builder.DrawPath(DlPath::MakeLine(DlPoint(200, 100), DlPoint(800, 100)),
66 paint);
67
68 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
69 }
70
71 TEST_P(AiksTest, CanRenderCurvedStrokes) {
72 DisplayListBuilder builder;
73 DlPaint paint;
74 paint.setColor(DlColor::kRed());
75 paint.setStrokeWidth(25);
76 paint.setDrawStyle(DlDrawStyle::kStroke);
77
78 builder.DrawPath(DlPath::MakeCircle(DlPoint(500, 500), 250), paint);
79
80 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
81 }
82
83 TEST_P(AiksTest, CanRenderThickCurvedStrokes) {
84 DisplayListBuilder builder;
85 DlPaint paint;
86 paint.setColor(DlColor::kRed());
87 paint.setStrokeWidth(100);
88 paint.setDrawStyle(DlDrawStyle::kStroke);
89
90 builder.DrawPath(DlPath::MakeCircle(DlPoint(100, 100), 50), paint);
91
92 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
93 }
94
95 TEST_P(AiksTest, CanRenderThinCurvedStrokes) {
96 DisplayListBuilder builder;
97 DlPaint paint;
98 paint.setColor(DlColor::kRed());
99 paint.setStrokeWidth(0.01);
100 paint.setDrawStyle(DlDrawStyle::kStroke);
101
102 builder.DrawPath(DlPath::MakeCircle(DlPoint(100, 100), 50), paint);
103
104 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
105 }
106
107 TEST_P(AiksTest, CanRenderStrokePathThatEndsAtSharpTurn) {
108 DisplayListBuilder builder;
109 DlPaint paint;
110 paint.setColor(DlColor::kRed());
111 paint.setStrokeWidth(200);
112 paint.setDrawStyle(DlDrawStyle::kStroke);
113
114 DlPath path = DlPath::MakeArc(DlRect::MakeXYWH(100, 100, 200, 200), //
115 DlDegrees(0), DlDegrees(90), false);
116
117 builder.DrawPath(path, paint);
118
119 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
120 }
121
122 TEST_P(AiksTest, CanRenderStrokePathWithCubicLine) {
123 DisplayListBuilder builder;
124
125 DlPaint paint;
126 paint.setColor(DlColor::kRed());
127 paint.setStrokeWidth(20);
128 paint.setDrawStyle(DlDrawStyle::kStroke);
129
130 DlPathBuilder path_builder;
131 path_builder.MoveTo(DlPoint(0, 200));
132 path_builder.CubicCurveTo(DlPoint(50, 400), DlPoint(350, 0),
133 DlPoint(400, 200));
134
135 builder.DrawPath(path_builder.TakePath(), paint);
136 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
137 }
138
139 TEST_P(AiksTest, CanRenderQuadraticStrokeWithInstantTurn) {
140 DisplayListBuilder builder;
141
142 DlPaint paint;
143 paint.setColor(DlColor::kRed());
144 paint.setStrokeWidth(50);
145 paint.setDrawStyle(DlDrawStyle::kStroke);
146 paint.setStrokeCap(DlStrokeCap::kRound);
147
148 // Should draw a diagonal pill shape. If flat on either end, the stroke is
149 // rendering wrong.
150 DlPathBuilder path_builder;
151 path_builder.MoveTo(DlPoint(250, 250));
152 path_builder.QuadraticCurveTo(DlPoint(100, 100), DlPoint(250, 250));
153
154 builder.DrawPath(path_builder.TakePath(), paint);
155
156 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
157 }
158
159 TEST_P(AiksTest, CanRenderFilledConicPaths) {
160 DisplayListBuilder builder;
161 builder.Scale(GetContentScale().x, GetContentScale().y);
162
163 DlPaint paint;
164 paint.setColor(DlColor::kRed());
165 paint.setDrawStyle(DlDrawStyle::kFill);
166
167 DlPaint reference_paint;
168 reference_paint.setColor(DlColor::kGreen());
169 reference_paint.setDrawStyle(DlDrawStyle::kFill);
170
171 DlPathBuilder path_builder;
172 DlPathBuilder reference_builder;
173
174 // weight of 1.0 is just a quadratic bezier
175 path_builder.MoveTo(DlPoint(100, 100));
176 path_builder.ConicCurveTo(DlPoint(150, 150), DlPoint(200, 100), 1.0f);
177 reference_builder.MoveTo(DlPoint(300, 100));
178 reference_builder.QuadraticCurveTo(DlPoint(350, 150), DlPoint(400, 100));
179
180 // weight of sqrt(2)/2 is a circular section
181 path_builder.MoveTo(DlPoint(100, 200));
182 path_builder.ConicCurveTo(DlPoint(150, 250), DlPoint(200, 200), kSqrt2Over2);
183 reference_builder.MoveTo(DlPoint(300, 200));
184 auto magic = DlPathBuilder::kArcApproximationMagic;
185 reference_builder.CubicCurveTo(DlPoint(300, 200) + DlPoint(50, 50) * magic,
186 DlPoint(400, 200) + DlPoint(-50, 50) * magic,
187 DlPoint(400, 200));
188
189 // weight of .01 is nearly a straight line
190 path_builder.MoveTo(DlPoint(100, 300));
191 path_builder.ConicCurveTo(DlPoint(150, 350), DlPoint(200, 300), 0.01f);
192 reference_builder.MoveTo(DlPoint(300, 300));
193 reference_builder.LineTo(DlPoint(350, 300.5));
194 reference_builder.LineTo(DlPoint(400, 300));
195
196 // weight of 100.0 is nearly a triangle
197 path_builder.MoveTo(DlPoint(100, 400));
198 path_builder.ConicCurveTo(DlPoint(150, 450), DlPoint(200, 400), 100.0f);
199 reference_builder.MoveTo(DlPoint(300, 400));
200 reference_builder.LineTo(DlPoint(350, 450));
201 reference_builder.LineTo(DlPoint(400, 400));
202
203 builder.DrawPath(path_builder.TakePath(), paint);
204 builder.DrawPath(reference_builder.TakePath(), reference_paint);
205
206 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
207 }
208
209 TEST_P(AiksTest, CanRenderStrokedConicPaths) {
210 DisplayListBuilder builder;
211 builder.Scale(GetContentScale().x, GetContentScale().y);
212
213 DlPaint paint;
214 paint.setColor(DlColor::kRed());
215 paint.setStrokeWidth(10);
216 paint.setDrawStyle(DlDrawStyle::kStroke);
217 paint.setStrokeCap(DlStrokeCap::kRound);
218 paint.setStrokeJoin(DlStrokeJoin::kRound);
219
220 DlPaint reference_paint;
221 reference_paint.setColor(DlColor::kGreen());
222 reference_paint.setStrokeWidth(10);
223 reference_paint.setDrawStyle(DlDrawStyle::kStroke);
224 reference_paint.setStrokeCap(DlStrokeCap::kRound);
225 reference_paint.setStrokeJoin(DlStrokeJoin::kRound);
226
227 DlPathBuilder path_builder;
228 DlPathBuilder reference_builder;
229
230 // weight of 1.0 is just a quadratic bezier
231 path_builder.MoveTo(DlPoint(100, 100));
232 path_builder.ConicCurveTo(DlPoint(150, 150), DlPoint(200, 100), 1.0f);
233 reference_builder.MoveTo(DlPoint(300, 100));
234 reference_builder.QuadraticCurveTo(DlPoint(350, 150), DlPoint(400, 100));
235
236 // weight of sqrt(2)/2 is a circular section
237 path_builder.MoveTo(DlPoint(100, 200));
238 path_builder.ConicCurveTo(DlPoint(150, 250), DlPoint(200, 200), kSqrt2Over2);
239 reference_builder.MoveTo(DlPoint(300, 200));
240 auto magic = DlPathBuilder::kArcApproximationMagic;
241 reference_builder.CubicCurveTo(DlPoint(300, 200) + DlPoint(50, 50) * magic,
242 DlPoint(400, 200) + DlPoint(-50, 50) * magic,
243 DlPoint(400, 200));
244
245 // weight of .0 is a straight line
246 path_builder.MoveTo(DlPoint(100, 300));
247 path_builder.ConicCurveTo(DlPoint(150, 350), DlPoint(200, 300), 0.0f);
248 reference_builder.MoveTo(DlPoint(300, 300));
249 reference_builder.LineTo(DlPoint(400, 300));
250
251 // weight of 100.0 is nearly a triangle
252 path_builder.MoveTo(DlPoint(100, 400));
253 path_builder.ConicCurveTo(DlPoint(150, 450), DlPoint(200, 400), 100.0f);
254 reference_builder.MoveTo(DlPoint(300, 400));
255 reference_builder.LineTo(DlPoint(350, 450));
256 reference_builder.LineTo(DlPoint(400, 400));
257
258 builder.DrawPath(path_builder.TakePath(), paint);
259 builder.DrawPath(reference_builder.TakePath(), reference_paint);
260
261 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
262 }
263
264 TEST_P(AiksTest, HairlinePath) {
265 Scalar scale = 1.f;
266 Scalar rotation = 0.f;
267 Scalar offset = 0.f;
268 auto callback = [&]() -> sk_sp<DisplayList> {
269 if (AiksTest::ImGuiBegin("Controls", nullptr,
270 ImGuiWindowFlags_AlwaysAutoResize)) {
271 ImGui::SliderFloat("Scale", &scale, 0, 6);
272 ImGui::SliderFloat("Rotate", &rotation, 0, 90);
273 ImGui::SliderFloat("Offset", &offset, 0, 2);
274 ImGui::End();
275 }
276
277 DisplayListBuilder builder;
278 builder.Scale(GetContentScale().x, GetContentScale().y);
279 builder.DrawPaint(DlPaint(DlColor(0xff111111)));
280
281 DlPaint paint;
282 paint.setStrokeWidth(0.f);
283 paint.setColor(DlColor::kWhite());
284 paint.setStrokeCap(DlStrokeCap::kRound);
285 paint.setStrokeJoin(DlStrokeJoin::kRound);
286 paint.setDrawStyle(DlDrawStyle::kStroke);
287
288 builder.Translate(512, 384);
289 builder.Scale(scale, scale);
290 builder.Rotate(rotation);
291 builder.Translate(-512, -384 + offset);
292
293 for (int i = 0; i < 5; ++i) {
294 Scalar yoffset = i * 25.25f + 300.f;
295 DlPathBuilder path_builder;
296
297 path_builder.MoveTo(DlPoint(100, yoffset));
298 path_builder.LineTo(DlPoint(924, yoffset));
299 builder.DrawPath(path_builder.TakePath(), paint);
300 }
301
302 return builder.Build();
303 };
304
305 ASSERT_TRUE(OpenPlaygroundHere(callback));
306 }
307
308 TEST_P(AiksTest, HairlineDrawLine) {
309 Scalar scale = 1.f;
310 Scalar rotation = 0.f;
311 Scalar offset = 0.f;
312 auto callback = [&]() -> sk_sp<DisplayList> {
313 if (AiksTest::ImGuiBegin("Controls", nullptr,
314 ImGuiWindowFlags_AlwaysAutoResize)) {
315 ImGui::SliderFloat("Scale", &scale, 0, 6);
316 ImGui::SliderFloat("Rotate", &rotation, 0, 90);
317 ImGui::SliderFloat("Offset", &offset, 0, 2);
318 ImGui::End();
319 }
320
321 DisplayListBuilder builder;
322 builder.Scale(GetContentScale().x, GetContentScale().y);
323 builder.DrawPaint(DlPaint(DlColor(0xff111111)));
324
325 DlPaint paint;
326 paint.setStrokeWidth(0.f);
327 paint.setColor(DlColor::kWhite());
328
329 builder.Translate(512, 384);
330 builder.Scale(scale, scale);
331 builder.Rotate(rotation);
332 builder.Translate(-512, -384 + offset);
333
334 for (int i = 0; i < 5; ++i) {
335 Scalar yoffset = i * 25.25f + 300.f;
336
337 builder.DrawLine(DlPoint(100, yoffset), DlPoint(924, yoffset), paint);
338 }
339
340 return builder.Build();
341 };
342
343 ASSERT_TRUE(OpenPlaygroundHere(callback));
344 }
345
346 TEST_P(AiksTest, CanRenderTightConicPath) {
347 DisplayListBuilder builder;
348 builder.Scale(GetContentScale().x, GetContentScale().y);
349
350 DlPaint paint;
351 paint.setColor(DlColor::kRed());
352 paint.setDrawStyle(DlDrawStyle::kFill);
353
354 DlPaint reference_paint;
355 reference_paint.setColor(DlColor::kGreen());
356 reference_paint.setDrawStyle(DlDrawStyle::kFill);
357
358 DlPathBuilder path_builder;
359
360 path_builder.MoveTo(DlPoint(100, 100));
361 path_builder.ConicCurveTo(DlPoint(150, 450), DlPoint(200, 100), 5.0f);
362
363 DlPathBuilder reference_builder;
364 PathTessellator::Conic component{DlPoint(300, 100), //
365 DlPoint(350, 450), //
366 DlPoint(400, 100), //
367 5.0f};
368 reference_builder.MoveTo(component.p1);
369 constexpr int N = 100;
370 for (int i = 1; i < N; i++) {
371 reference_builder.LineTo(component.Solve(static_cast<Scalar>(i) / N));
372 }
373 reference_builder.LineTo(component.p2);
374
375 DlPaint line_paint;
376 line_paint.setColor(DlColor::kYellow());
377 line_paint.setDrawStyle(DlDrawStyle::kStroke);
378 line_paint.setStrokeWidth(1.0f);
379
380 // Draw some lines to provide a spacial reference for the curvature of
381 // the tips of the direct rendering and the manually tessellated versions.
382 builder.DrawLine(DlPoint(145, 100), DlPoint(145, 450), line_paint);
383 builder.DrawLine(DlPoint(155, 100), DlPoint(155, 450), line_paint);
384 builder.DrawLine(DlPoint(345, 100), DlPoint(345, 450), line_paint);
385 builder.DrawLine(DlPoint(355, 100), DlPoint(355, 450), line_paint);
386 builder.DrawLine(DlPoint(100, 392.5f), DlPoint(400, 392.5f), line_paint);
387
388 // Draw the two paths (direct and manually tessellated) on top of the lines.
389 builder.DrawPath(path_builder.TakePath(), paint);
390 builder.DrawPath(reference_builder.TakePath(), reference_paint);
391
392 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
393 }
394
395 TEST_P(AiksTest, CanRenderDifferencePaths) {
396 DisplayListBuilder builder;
397
398 DlPaint paint;
399 paint.setColor(DlColor::kRed());
400
401 RoundingRadii radii = {
402 .top_left = {50, 25},
403 .top_right = {25, 50},
404 .bottom_left = {25, 50},
405 .bottom_right = {50, 25},
406 };
407 DlPathBuilder path_builder;
408 DlRoundRect rrect =
409 DlRoundRect::MakeRectRadii(DlRect::MakeXYWH(100, 100, 200, 200), radii);
410 // We use the factory method to convert the rrect and circle to a path so
411 // that they use the legacy conics for legacy golden output.
412 path_builder.AddPath(DlPath::MakeRoundRect(rrect));
413 path_builder.AddPath(DlPath::MakeCircle(DlPoint(200, 200), 50));
414 path_builder.SetFillType(DlPathFillType::kOdd);
415 DlPath path = path_builder.TakePath();
416
417 builder.DrawImage(
418 DlImageImpeller::Make(CreateTextureForFixture("boston.jpg")),
419 DlPoint{10, 10}, {});
420 builder.DrawPath(path, paint);
421
422 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
423 }
424
425 // Regression test for https://github.com/flutter/flutter/issues/134816.
426 //
427 // It should be possible to draw 3 lines, and not have an implicit close path.
428 TEST_P(AiksTest, CanDrawAnOpenPath) {
429 DisplayListBuilder builder;
430
431 // Starting at (50, 50), draw lines from:
432 // 1. (50, height)
433 // 2. (width, height)
434 // 3. (width, 50)
435 DlPathBuilder path_builder;
436 path_builder.MoveTo(DlPoint(50, 50));
437 path_builder.LineTo(DlPoint(50, 100));
438 path_builder.LineTo(DlPoint(100, 100));
439 path_builder.LineTo(DlPoint(100, 50));
440
441 DlPaint paint;
442 paint.setColor(DlColor::kRed());
443 paint.setDrawStyle(DlDrawStyle::kStroke);
444 paint.setStrokeWidth(10);
445
446 builder.DrawPath(path_builder.TakePath(), paint);
447
448 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
449 }
450
451 TEST_P(AiksTest, CanDrawAnOpenPathThatIsntARect) {
452 DisplayListBuilder builder;
453
454 // Draw a stroked path that is explicitly closed to verify
455 // It doesn't become a rectangle.
456 DlPathBuilder path_builder;
457 path_builder.MoveTo(DlPoint(50, 50));
458 path_builder.LineTo(DlPoint(520, 120));
459 path_builder.LineTo(DlPoint(300, 310));
460 path_builder.LineTo(DlPoint(100, 50));
461 path_builder.Close();
462
463 DlPaint paint;
464 paint.setColor(DlColor::kRed());
465 paint.setDrawStyle(DlDrawStyle::kStroke);
466 paint.setStrokeWidth(10);
467
468 builder.DrawPath(path_builder.TakePath(), paint);
469
470 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
471 }
472
473 TEST_P(AiksTest, SolidStrokesRenderCorrectly) {
474 // Compare with https://fiddle.skia.org/c/027392122bec8ac2b5d5de00a4b9bbe2
475 auto callback = [&]() -> sk_sp<DisplayList> {
476 static Color color = Color::Black().WithAlpha(0.5);
477 static float scale = 3;
478 static bool add_circle_clip = true;
479
480 if (AiksTest::ImGuiBegin("Controls", nullptr,
481 ImGuiWindowFlags_AlwaysAutoResize)) {
482 ImGui::ColorEdit4("Color", reinterpret_cast<float*>(&color));
483 ImGui::SliderFloat("Scale", &scale, 0, 6);
484 ImGui::Checkbox("Circle clip", &add_circle_clip);
485 ImGui::End();
486 }
487
488 DisplayListBuilder builder;
489 builder.Scale(GetContentScale().x, GetContentScale().y);
490 DlPaint paint;
491
492 paint.setColor(DlColor::kWhite());
493 builder.DrawPaint(paint);
494
495 paint.setColor(
496 DlColor::ARGB(color.alpha, color.red, color.green, color.blue));
497 paint.setDrawStyle(DlDrawStyle::kStroke);
498 paint.setStrokeWidth(10);
499
500 DlPathBuilder path_builder;
501 path_builder.MoveTo(DlPoint(20, 20));
502 path_builder.QuadraticCurveTo(DlPoint(60, 20), DlPoint(60, 60));
503 path_builder.Close();
504 path_builder.MoveTo(DlPoint(60, 20));
505 path_builder.QuadraticCurveTo(DlPoint(60, 60), DlPoint(20, 60));
506 DlPath path = path_builder.TakePath();
507
508 builder.Scale(scale, scale);
509
510 if (add_circle_clip) {
511 static PlaygroundPoint circle_clip_point_a(Point(60, 300), 20,
512 Color::Red());
513 static PlaygroundPoint circle_clip_point_b(Point(600, 300), 20,
514 Color::Red());
515 auto [handle_a, handle_b] =
516 DrawPlaygroundLine(circle_clip_point_a, circle_clip_point_b);
517
518 Matrix screen_to_canvas = builder.GetMatrix();
519 if (!screen_to_canvas.IsInvertible()) {
520 return nullptr;
521 }
522 screen_to_canvas = screen_to_canvas.Invert();
523
524 Point point_a = screen_to_canvas * handle_a;
525 Point point_b = screen_to_canvas * handle_b;
526
527 Point middle = point_a + point_b;
528 middle *= GetContentScale().x / 2;
529
530 auto radius = point_a.GetDistance(middle);
531
532 builder.ClipPath(DlPath::MakeCircle(middle, radius));
533 }
534
535 for (auto join :
536 {DlStrokeJoin::kBevel, DlStrokeJoin::kRound, DlStrokeJoin::kMiter}) {
537 paint.setStrokeJoin(join);
538 for (auto cap :
539 {DlStrokeCap::kButt, DlStrokeCap::kSquare, DlStrokeCap::kRound}) {
540 paint.setStrokeCap(cap);
541 builder.DrawPath(path, paint);
542 builder.Translate(80, 0);
543 }
544 builder.Translate(-240, 60);
545 }
546
547 return builder.Build();
548 };
549
550 ASSERT_TRUE(OpenPlaygroundHere(callback));
551 }
552
553 TEST_P(AiksTest, DrawLinesRenderCorrectly) {
554 DisplayListBuilder builder;
555 builder.Scale(GetContentScale().x, GetContentScale().y);
556
557 DlPaint paint;
558 paint.setColor(DlColor::kBlue());
559 paint.setStrokeWidth(10);
560
561 auto draw = [&builder](DlPaint& paint) {
562 for (auto cap :
563 {DlStrokeCap::kButt, DlStrokeCap::kSquare, DlStrokeCap::kRound}) {
564 paint.setStrokeCap(cap);
565 DlPoint origin = {100, 100};
566 builder.DrawLine(DlPoint(150, 100), DlPoint(250, 100), paint);
567 for (int d = 15; d < 90; d += 15) {
568 Matrix m = Matrix::MakeRotationZ(Degrees(d));
569 Point origin = {100, 100};
570 Point p0 = {50, 0};
571 Point p1 = {150, 0};
572 auto a = origin + m * p0;
573 auto b = origin + m * p1;
574
575 builder.DrawLine(a, b, paint);
576 }
577 builder.DrawLine(DlPoint(100, 150), DlPoint(100, 250), paint);
578 builder.DrawCircle(origin, 35, paint);
579
580 builder.DrawLine(DlPoint(250, 250), DlPoint(250, 250), paint);
581
582 builder.Translate(250, 0);
583 }
584 builder.Translate(-750, 250);
585 };
586
587 std::vector<DlColor> colors = {
588 DlColor::ARGB(1, 0x1f / 255.0, 0.0, 0x5c / 255.0),
589 DlColor::ARGB(1, 0x5b / 255.0, 0.0, 0x60 / 255.0),
590 DlColor::ARGB(1, 0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0),
591 DlColor::ARGB(1, 0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0),
592 DlColor::ARGB(1, 0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0),
593 DlColor::ARGB(1, 0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0),
594 DlColor::ARGB(1, 0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0)};
595 std::vector<Scalar> stops = {
596 0.0,
597 (1.0 / 6.0) * 1,
598 (1.0 / 6.0) * 2,
599 (1.0 / 6.0) * 3,
600 (1.0 / 6.0) * 4,
601 (1.0 / 6.0) * 5,
602 1.0,
603 };
604
605 auto texture = DlImageImpeller::Make(
606 CreateTextureForFixture("airplane.jpg",
607 /*enable_mipmapping=*/true));
608
609 draw(paint);
610
611 paint.setColorSource(DlColorSource::MakeRadial({100, 100}, 200, stops.size(),
612 colors.data(), stops.data(),
613 DlTileMode::kMirror));
614 draw(paint);
615
616 DlMatrix matrix = DlMatrix::MakeTranslation({-150, 75});
617 paint.setColorSource(DlColorSource::MakeImage(
618 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
619 DlImageSampling::kMipmapLinear, &matrix));
620 draw(paint);
621
622 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
623 }
624
625 // The goal of this test is to show that scaling the lines doesn't also scale
626 // the antialiasing. The amount of blurring should be the same for both
627 // horizontal lines.
628 TEST_P(AiksTest, ScaleExperimentAntialiasLines) {
629 Scalar scale = 5.0;
630 Scalar line_width = 10.f;
631 auto callback = [&]() -> sk_sp<DisplayList> {
632 if (AiksTest::ImGuiBegin("Controls", nullptr,
633 ImGuiWindowFlags_AlwaysAutoResize)) {
634 ImGui::SliderFloat("Scale", &scale, 0.001, 5);
635 ImGui::SliderFloat("Width", &line_width, 1, 20);
636
637 ImGui::End();
638 }
639 DisplayListBuilder builder;
640 builder.Scale(GetContentScale().x, GetContentScale().y);
641
642 builder.DrawPaint(DlPaint(DlColor(0xff111111)));
643
644 {
645 DlPaint paint;
646 paint.setColor(DlColor::kGreenYellow());
647 paint.setStrokeWidth(line_width);
648
649 builder.DrawLine(DlPoint(100, 100), DlPoint(350, 100), paint);
650 builder.DrawLine(DlPoint(100, 100), DlPoint(350, 150), paint);
651
652 builder.Save();
653 builder.Translate(100, 300);
654 builder.Scale(scale, scale);
655 builder.Translate(-100, -300);
656 builder.DrawLine(DlPoint(100, 300), DlPoint(350, 300), paint);
657 builder.DrawLine(DlPoint(100, 300), DlPoint(350, 450), paint);
658 builder.Restore();
659 }
660
661 {
662 DlPaint paint;
663 paint.setColor(DlColor::kGreenYellow());
664 paint.setStrokeWidth(2.0);
665
666 builder.Save();
667 builder.Translate(100, 500);
668 builder.Scale(0.2, 0.2);
669 builder.Translate(-100, -500);
670 builder.DrawLine(DlPoint(100, 500), DlPoint(350, 500), paint);
671 builder.DrawLine(DlPoint(100, 500), DlPoint(350, 650), paint);
672 builder.Restore();
673 }
674
675 return builder.Build();
676 };
677 ASSERT_TRUE(OpenPlaygroundHere(callback));
678 }
679
680 TEST_P(AiksTest, HexagonExperimentAntialiasLines) {
681 float scale = 5.0f;
682 float line_width = 10.f;
683 float rotation = 0.f;
684
685 auto callback = [&]() -> sk_sp<DisplayList> {
686 if (AiksTest::ImGuiBegin("Controls", nullptr,
687 ImGuiWindowFlags_AlwaysAutoResize)) {
688 // Use ImGui::SliderFloat for consistency
689 ImGui::SliderFloat("Scale", &scale, 0.001f, 5.0f);
690 ImGui::SliderFloat("Width", &line_width, 1.0f, 20.0f);
691 ImGui::SliderFloat("Rotation", &rotation, 0.0f, 180.0f);
692
693 ImGui::End();
694 }
695 DisplayListBuilder builder;
696 builder.Scale(static_cast<float>(GetContentScale().x),
697 static_cast<float>(GetContentScale().y));
698
699 builder.DrawPaint(DlPaint(DlColor(0xff111111))); // Background
700
701 {
702 DlPaint hex_paint;
703 hex_paint.setColor(
704 DlColor::kGreen()); // Changed color to Red for visibility
705 hex_paint.setStrokeWidth(line_width); // Use the interactive width
706
707 float cx = 512.0f; // Center X
708 float cy = 384.0f; // Center Y
709 float r = 80.0f; // Radius (distance from center to vertex)
710
711 float r_sin60 = r * std::sqrt(3.0f) / 2.0f;
712 float r_cos60 = r / 2.0f;
713
714 DlPoint v0 = DlPoint(cx + r, cy); // Right vertex
715 DlPoint v1 = DlPoint(cx + r_cos60, cy - r_sin60); // Top-right vertex
716 DlPoint v2 = DlPoint(
717 cx - r_cos60,
718 cy - r_sin60); // Top-left vertex (v1-v2 is top horizontal side)
719 DlPoint v3 = DlPoint(cx - r, cy); // Left vertex
720 DlPoint v4 = DlPoint(cx - r_cos60, cy + r_sin60); // Bottom-left vertex
721 DlPoint v5 =
722 DlPoint(cx + r_cos60, cy + r_sin60); // Bottom-right vertex (v4-v5 is
723 // bottom horizontal side)
724
725 builder.Translate(cx, cy);
726 builder.Scale(scale, scale);
727 builder.Rotate(rotation);
728 builder.Translate(-cx, -cy);
729
730 builder.DrawLine(v0, v1, hex_paint);
731 builder.DrawLine(v1, v2, hex_paint); // Top side
732 builder.DrawLine(v2, v3, hex_paint);
733 builder.DrawLine(v3, v4, hex_paint);
734 builder.DrawLine(v4, v5, hex_paint); // Bottom side
735 builder.DrawLine(v5, v0, hex_paint); // Close the hexagon
736 }
737
738 return builder.Build();
739 };
740 ASSERT_TRUE(OpenPlaygroundHere(callback));
741 }
742
743 TEST_P(AiksTest, SimpleExperimentAntialiasLines) {
744 DisplayListBuilder builder;
745 builder.Scale(GetContentScale().x, GetContentScale().y);
746
747 builder.DrawPaint(DlPaint(DlColor(0xff111111)));
748
749 DlPaint paint;
750 paint.setColor(DlColor::kGreenYellow());
751 paint.setStrokeWidth(10);
752
753 auto draw = [&builder](DlPaint& paint) {
754 for (auto cap :
755 {DlStrokeCap::kButt, DlStrokeCap::kSquare, DlStrokeCap::kRound}) {
756 paint.setStrokeCap(cap);
757 DlPoint origin = {100, 100};
758 builder.DrawLine(DlPoint(150, 100), DlPoint(250, 100), paint);
759 for (int d = 15; d < 90; d += 15) {
760 Matrix m = Matrix::MakeRotationZ(Degrees(d));
761 Point origin = {100, 100};
762 Point p0 = {50, 0};
763 Point p1 = {150, 0};
764 auto a = origin + m * p0;
765 auto b = origin + m * p1;
766
767 builder.DrawLine(a, b, paint);
768 }
769 builder.DrawLine(DlPoint(100, 150), DlPoint(100, 250), paint);
770 builder.DrawCircle(origin, 35, paint);
771
772 builder.DrawLine(DlPoint(250, 250), DlPoint(250, 250), paint);
773
774 builder.Translate(250, 0);
775 }
776 builder.Translate(-750, 250);
777 };
778
779 draw(paint);
780
781 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
782 }
783
784 TEST_P(AiksTest, DrawRectStrokesRenderCorrectly) {
785 DisplayListBuilder builder;
786 DlPaint paint;
787 paint.setColor(DlColor::kRed());
788 paint.setDrawStyle(DlDrawStyle::kStroke);
789 paint.setStrokeWidth(10);
790
791 builder.Translate(100, 100);
792 builder.DrawPath(DlPath::MakeRect(DlRect::MakeSize(DlSize(100, 100))), paint);
793
794 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
795 }
796
797 TEST_P(AiksTest, DrawRectStrokesWithBevelJoinRenderCorrectly) {
798 DisplayListBuilder builder;
799 DlPaint paint;
800 paint.setColor(DlColor::kRed());
801 paint.setDrawStyle(DlDrawStyle::kStroke);
802 paint.setStrokeWidth(10);
803 paint.setStrokeJoin(DlStrokeJoin::kBevel);
804
805 builder.Translate(100, 100);
806 builder.DrawPath(DlPath::MakeRect(DlRect::MakeSize(DlSize(100, 100))), paint);
807
808 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
809 }
810
811 TEST_P(AiksTest, CanDrawMultiContourConvexPath) {
812 DlPathBuilder path_builder;
813 for (auto i = 0; i < 10; i++) {
814 if (i % 2 == 0) {
815 // We use the factory method to convert the circle to a path so that it
816 // uses the legacy conics for legacy golden output.
817 DlPath circle =
818 DlPath::MakeCircle(DlPoint(100 + 50 * i, 100 + 50 * i), 100);
819 path_builder.AddPath(circle);
820 path_builder.Close();
821 } else {
822 path_builder.MoveTo(DlPoint(100.f + 50.f * i - 100, 100.f + 50.f * i));
823 path_builder.LineTo(DlPoint(100.f + 50.f * i, 100.f + 50.f * i - 100));
824 path_builder.LineTo(DlPoint(100.f + 50.f * i - 100, //
825 100.f + 50.f * i - 100));
826 path_builder.Close();
827 }
828 }
829 DlPath path = path_builder.TakePath();
830
831 DisplayListBuilder builder;
832 DlPaint paint;
833 paint.setColor(DlColor::kRed().withAlpha(102));
834 builder.DrawPath(path, paint);
835
836 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
837 }
838
839 TEST_P(AiksTest, ArcWithZeroSweepAndBlur) {
840 DisplayListBuilder builder;
841 builder.Scale(GetContentScale().x, GetContentScale().y);
842
843 DlPaint paint;
844 paint.setColor(DlColor::kRed());
845
846 std::vector<DlColor> colors = {DlColor::RGBA(1.0, 0.0, 0.0, 1.0),
847 DlColor::RGBA(0.0, 0.0, 0.0, 1.0)};
848 std::vector<Scalar> stops = {0.0, 1.0};
849
850 paint.setColorSource(
851 DlColorSource::MakeSweep({100, 100}, 45, 135, stops.size(), colors.data(),
852 stops.data(), DlTileMode::kMirror));
853 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 20));
854
855 DlPathBuilder path_builder;
856 path_builder.AddArc(DlRect::MakeXYWH(10, 10, 100, 100), //
857 DlDegrees(0), DlDegrees(0));
858 builder.DrawPath(path_builder.TakePath(), paint);
859
860 // Check that this empty picture can be created without crashing.
861 builder.Build();
862 }
863
864 TEST_P(AiksTest, CanRenderClips) {
865 DisplayListBuilder builder;
866 DlPaint paint;
867 paint.setColor(DlColor::kFuchsia());
868
869 builder.ClipPath(DlPath::MakeRect(DlRect::MakeXYWH(0, 0, 500, 500)));
870 builder.DrawPath(DlPath::MakeCircle(DlPoint(500, 500), 250), paint);
871
872 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
873 }
874
875 TEST_P(AiksTest, FatStrokeArc) {
876 DlScalar stroke_width = 300;
877 DlScalar aspect = 1.0;
878 DlScalar start_angle = 0;
879 DlScalar end_angle = 90;
880 auto callback = [&]() -> sk_sp<DisplayList> {
881 if (AiksTest::ImGuiBegin("Controls", nullptr,
882 ImGuiWindowFlags_AlwaysAutoResize)) {
883 ImGui::SliderFloat("Stroke Width", &stroke_width, 1, 300);
884 ImGui::SliderFloat("Aspect", &aspect, 0.5, 2.0);
885 ImGui::SliderFloat("Start Angle", &start_angle, 0, 360);
886 ImGui::SliderFloat("End Angle", &end_angle, 0, 360);
887 ImGui::End();
888 }
889
890 DisplayListBuilder builder;
891 DlPaint grey_paint;
892 grey_paint.setColor(DlColor(0xff111111));
893 builder.DrawPaint(grey_paint);
894
895 DlPaint white_paint;
896 white_paint.setColor(DlColor::kWhite());
897 white_paint.setStrokeWidth(stroke_width);
898 white_paint.setDrawStyle(DlDrawStyle::kStroke);
899 DlPaint red_paint;
900 red_paint.setColor(DlColor::kRed());
901
902 Rect rect = Rect::MakeXYWH(100, 100, 100, aspect * 100);
903 builder.DrawRect(rect, red_paint);
904 builder.DrawArc(rect, start_angle, end_angle,
905 /*useCenter=*/false, white_paint);
906 DlScalar frontier = rect.GetRight() + stroke_width / 2.0;
907 builder.DrawLine(Point(frontier, 0), Point(frontier, 150), red_paint);
908
909 return builder.Build();
910 };
911 ASSERT_TRUE(OpenPlaygroundHere(callback));
912 }
913
914 TEST_P(AiksTest, CanRenderOverlappingMultiContourPath) {
915 DisplayListBuilder builder;
916
917 DlPaint paint;
918 paint.setColor(DlColor::kRed());
919
920 RoundingRadii radii = {
921 .top_left = DlSize(50, 50),
922 .top_right = DlSize(50, 50),
923 .bottom_left = DlSize(50, 50),
924 .bottom_right = DlSize(50, 50),
925 };
926
927 const Scalar kTriangleHeight = 100;
928 DlRoundRect rrect = DlRoundRect::MakeRectRadii(
929 DlRect::MakeXYWH(-kTriangleHeight / 2.0f, -kTriangleHeight / 2.0f,
930 kTriangleHeight, kTriangleHeight),
931 radii //
932 );
933 // We use the factory method to convert the rrect to a path so that it
934 // uses the legacy conics for legacy golden output.
935 DlPath rrect_path = DlPath::MakeRoundRect(rrect);
936
937 builder.Translate(200, 200);
938 // Form a path similar to the Material drop slider value indicator. Both
939 // shapes should render identically side-by-side.
940 {
941 DlPathBuilder path_builder;
942 path_builder.MoveTo(DlPoint(0, kTriangleHeight));
943 path_builder.LineTo(DlPoint(-kTriangleHeight / 2.0f, 0));
944 path_builder.LineTo(DlPoint(kTriangleHeight / 2.0f, 0));
945 path_builder.Close();
946 path_builder.AddPath(rrect_path);
947
948 builder.DrawPath(path_builder.TakePath(), paint);
949 }
950 builder.Translate(100, 0);
951
952 {
953 DlPathBuilder path_builder;
954 path_builder.MoveTo(DlPoint(0, kTriangleHeight));
955 path_builder.LineTo(DlPoint(-kTriangleHeight / 2.0f, 0));
956 path_builder.LineTo(DlPoint(0, -10));
957 path_builder.LineTo(DlPoint(kTriangleHeight / 2.0f, 0));
958 path_builder.Close();
959 path_builder.AddPath(rrect_path);
960
961 builder.DrawPath(path_builder.TakePath(), paint);
962 }
963
964 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
965 }
966
967 TEST_P(AiksTest, TwoContourPathWithSinglePointContour) {
968 DisplayListBuilder builder;
969
970 DlPaint paint;
971 paint.setColor(DlColor::kRed());
972 paint.setDrawStyle(DlDrawStyle::kStroke);
973 paint.setStrokeWidth(15.0);
974 paint.setStrokeCap(DlStrokeCap::kRound);
975
976 DlPathBuilder path_builder;
977 path_builder.MoveTo(DlPoint(100, 100));
978 path_builder.LineTo(DlPoint(150, 150));
979 path_builder.MoveTo(DlPoint(200, 200));
980 path_builder.LineTo(DlPoint(200, 200));
981
982 builder.DrawPath(path_builder.TakePath(), paint);
983
984 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
985 }
986
987 TEST_P(AiksTest, StrokeCapsAndJoins) {
988 DisplayListBuilder builder;
989 builder.Scale(GetContentScale().x, GetContentScale().y);
990
991 builder.Translate(100, 0);
992
993 builder.Save();
994 for (auto cap : std::vector<DlStrokeCap>{
995 DlStrokeCap::kButt, DlStrokeCap::kRound, DlStrokeCap::kSquare}) {
996 DlPathBuilder path_builder;
997 path_builder.MoveTo({20, 50});
998 path_builder.LineTo({50, 50});
999 path_builder.MoveTo({120, 50});
1000 path_builder.LineTo({120, 80});
1001 path_builder.MoveTo({180, 50});
1002 path_builder.LineTo({180, 50});
1003 DlPath path = path_builder.TakePath();
1004
1005 DlPaint paint;
1006 paint.setColor(DlColor::kRed());
1007 paint.setDrawStyle(DlDrawStyle::kStroke);
1008 paint.setStrokeWidth(20.0f);
1009 paint.setStrokeCap(cap);
1010 paint.setStrokeJoin(DlStrokeJoin::kBevel);
1011
1012 builder.DrawPath(path, paint);
1013
1014 paint.setColor(DlColor::kYellow());
1015 paint.setStrokeWidth(1.0f);
1016 paint.setStrokeCap(DlStrokeCap::kButt);
1017
1018 builder.DrawPath(path, paint);
1019
1020 builder.Translate(250, 0);
1021 }
1022 builder.Restore();
1023
1024 builder.Translate(0, 100);
1025
1026 builder.Save();
1027 for (auto join : std::vector<DlStrokeJoin>{
1028 DlStrokeJoin::kBevel, DlStrokeJoin::kRound, DlStrokeJoin::kMiter}) {
1029 DlPathBuilder path_builder;
1030 path_builder.MoveTo({20, 50}); // 0 degree right turn
1031 path_builder.LineTo({50, 50});
1032 path_builder.LineTo({80, 50});
1033 path_builder.MoveTo({20, 150}); // 90 degree right turn
1034 path_builder.LineTo({50, 150});
1035 path_builder.LineTo({50, 180});
1036 path_builder.MoveTo({20, 250}); // 45 degree right turn
1037 path_builder.LineTo({50, 250});
1038 path_builder.LineTo({70, 270});
1039 path_builder.MoveTo({20, 350}); // 135 degree right turn
1040 path_builder.LineTo({50, 350});
1041 path_builder.LineTo({30, 370});
1042 path_builder.MoveTo({20, 450}); // 180 degree right turn
1043 path_builder.LineTo({50, 450});
1044 path_builder.LineTo({20, 450});
1045 path_builder.MoveTo({120, 80}); // 0 degree left turn
1046 path_builder.LineTo({150, 80});
1047 path_builder.LineTo({180, 80});
1048 path_builder.MoveTo({120, 180}); // 90 degree left turn
1049 path_builder.LineTo({150, 180});
1050 path_builder.LineTo({150, 150});
1051 path_builder.MoveTo({120, 280}); // 45 degree left turn
1052 path_builder.LineTo({150, 280});
1053 path_builder.LineTo({170, 260});
1054 path_builder.MoveTo({120, 380}); // 135 degree left turn
1055 path_builder.LineTo({150, 380});
1056 path_builder.LineTo({130, 360});
1057 path_builder.MoveTo({120, 480}); // 180 degree left turn
1058 path_builder.LineTo({150, 480});
1059 path_builder.LineTo({120, 480});
1060 DlPath path = path_builder.TakePath();
1061
1062 DlPaint paint;
1063
1064 paint.setColor(DlColor::kRed());
1065 paint.setDrawStyle(DlDrawStyle::kStroke);
1066 paint.setStrokeWidth(20.0f);
1067 paint.setStrokeCap(DlStrokeCap::kSquare);
1068 paint.setStrokeJoin(join);
1069 builder.DrawPath(path, paint);
1070
1071 paint.setColor(DlColor::kYellow());
1072 paint.setStrokeWidth(1.0f);
1073 paint.setStrokeCap(DlStrokeCap::kButt);
1074 builder.DrawPath(path, paint);
1075
1076 builder.Translate(250, 0);
1077 }
1078 builder.Restore();
1079
1080 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1081 }
1082
1083 TEST_P(AiksTest, BlurredCircleWithStrokeWidth) {
1084 DisplayListBuilder builder;
1085 DlPaint paint;
1086 paint.setColor(DlColor::kGreen());
1087 paint.setDrawStyle(DlDrawStyle::kStroke);
1088 paint.setStrokeWidth(30);
1089 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 5));
1090
1091 builder.DrawCircle(DlPoint(200, 200), 100, paint);
1092
1093 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1094 }
1095
1096 } // namespace testing
1097 } // namespace impeller
aiks_unittests.h
impeller::AiksPlayground
Definition: aiks_playground.h:16
impeller::AiksPlayground::ImGuiBegin
static bool ImGuiBegin(const char *name, bool *p_open, ImGuiWindowFlags flags)
Definition: aiks_playground.cc:30
impeller::DlImageImpeller::Make
static sk_sp< DlImageImpeller > Make(std::shared_ptr< Texture > texture, OwningContext owning_context=OwningContext::kIO)
Definition: dl_image_impeller.cc:23
x
int32_t x
Definition: dl_golden_unittests.cc:458
dl_image_impeller.h
flutter
Definition: dl_golden_blur_unittests.cc:16
impeller::saturated::b
SI b
Definition: saturated_math.h:87
impeller::testing::TEST_P
TEST_P(AiksTest, DrawAtlasNoColor)
Definition: aiks_dl_atlas_unittests.cc:59
impeller
Definition: allocation.cc:12
impeller::Scalar
float Scalar
Definition: scalar.h:19
impeller::DrawPlaygroundLine
std::tuple< Point, Point > DrawPlaygroundLine(PlaygroundPoint &point_a, PlaygroundPoint &point_b)
Definition: widgets.cc:51
impeller::kSqrt2Over2
constexpr float kSqrt2Over2
Definition: constants.h:51
impeller::DlRoundRect
flutter::DlRoundRect DlRoundRect
Definition: dl_dispatcher.h:27
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
path_tessellator.h
impeller::Color
Definition: color.h:124
impeller::Color::blue
Scalar blue
Definition: color.h:138
impeller::Color::alpha
Scalar alpha
Definition: color.h:143
impeller::Color::Black
static constexpr Color Black()
Definition: color.h:266
impeller::Color::WithAlpha
constexpr Color WithAlpha(Scalar new_alpha) const
Definition: color.h:278
impeller::Color::red
Scalar red
Definition: color.h:128
impeller::Color::Red
static constexpr Color Red()
Definition: color.h:272
impeller::Color::green
Scalar green
Definition: color.h:133
impeller::Degrees
Definition: scalar.h:76
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::Matrix::IsInvertible
bool IsInvertible() const
Definition: matrix.h:321
impeller::Matrix::Invert
Matrix Invert() const
Definition: matrix.cc:99
impeller::Matrix::MakeRotationZ
static Matrix MakeRotationZ(Radians r)
Definition: matrix.h:223
impeller::PathTessellator::Conic
Definition: path_tessellator.h:98
impeller::PlaygroundPoint
Definition: widgets.h:21
impeller::RoundingRadii
Definition: rounding_radii.h:14
impeller::RoundingRadii::top_left
Size top_left
Definition: rounding_radii.h:15
impeller::TPoint< Scalar >
impeller::TPoint::GetDistance
constexpr Type GetDistance(const TPoint &p) const
Definition: point.h:200
impeller::TPoint::x
Type x
Definition: point.h:30
impeller::TRect< Scalar >
impeller::TRect::GetRight
constexpr auto GetRight() const
Definition: rect.h:359
impeller::TRect< Scalar >::MakeXYWH
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:136
widgets.h