Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
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
10
21
22namespace impeller {
23namespace testing {
24
25using namespace flutter;
26
27TEST_P(AiksTest, RotateColorFilteredPath) {
28 DisplayListBuilder builder;
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);
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
58TEST_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
71TEST_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
83TEST_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
95TEST_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
107TEST_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
122TEST_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
139TEST_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
159TEST_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));
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
209TEST_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));
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
264namespace {
265using DrawLinesCallback = std::function<void(DisplayListBuilder& builder,
266 const DlPaint& paint,
267 const Point& p0,
268 const Point& p1,
269 Scalar width)>;
270
271static void DrawLinesTest(AiksTest* test, const DrawLinesCallback& draw_fn) {
272 Scalar scale = 1.f;
273 Scalar rotation = 0.f;
274 Scalar offset = 0.f;
275 Scalar width_adjustment = 0.f;
276 bool invert_colors = false;
277
278 auto callback = [=]() mutable -> sk_sp<DisplayList> {
279 if (test->IsPlaygroundEnabled()) {
280 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
281 ImGui::SliderFloat("Scale", &scale, 0, 6);
282 ImGui::SliderFloat("Rotate", &rotation, 0, 90);
283 ImGui::SliderFloat("Offset", &offset, 0, 2);
284 ImGui::SliderFloat("Width Adjustment", &width_adjustment, -1, 2);
285 ImGui::Checkbox("Invert colors", &invert_colors);
286 ImGui::End();
287 }
288
289 DisplayListBuilder builder;
290
291 // Most tests scale the builder with
292 // builder.Scale(GetContentScale().x, GetContentScale().y) in order to
293 // maintain the same visual size on different screens.
294 // These DrawLines tests explicitly don't invoke this scaling, because they
295 // are testing specific line widths relative to a device pixel size.
296
297 builder.DrawPaint(
298 DlPaint(invert_colors ? DlColor(0xffeeeeee) : DlColor(0xff111111)));
299
300 DlPaint paint;
301 paint.setColor(invert_colors ? DlColor::kBlack() : DlColor::kWhite());
302
303 std::vector<Scalar> widths = {0.0f, 0.3f, 1.0f};
304 std::vector<Scalar> angles = {0.0f, 3.0f, 45.0f, 87.0f, 90.0f};
305
306 const Scalar column_spacing = 1024.0f / widths.size();
307 const Scalar row_spacing = 768.0f / angles.size();
308
309 for (size_t col = 0; col < widths.size(); ++col) {
310 Scalar col_x = (col + 0.5f) * column_spacing;
311 Scalar width = std::max(0.0f, widths[col] + width_adjustment);
312 for (size_t row = 0; row < angles.size(); ++row) {
313 Scalar row_y = (row + 0.5f) * row_spacing;
314 builder.Save();
315 builder.Translate(col_x, row_y);
316 builder.Scale(scale, scale);
317 builder.Rotate(angles[row] + rotation);
318
319 // Draw 4 parallel lines centered around y = 0. Each line is spaced 8px
320 // apart (-12, -4, +4, +12), plus a 0.25px increment per line to test
321 // fractional subpixel alignment (0.0, 0.25, 0.5, 0.75).
322 for (int i = 0; i < 4; ++i) {
323 Scalar base_y = i * 8.0f - 12.0f;
324 Scalar subpixel_y = i * 0.25f;
325 Scalar line_y = base_y + subpixel_y + offset;
326 Point p0 = Point(-60.0f, line_y);
327 Point p1 = Point(60.0f, line_y);
328 draw_fn(builder, paint, p0, p1, width);
329 }
330
331 builder.Restore();
332 }
333 }
334
335 return builder.Build();
336 };
337
338 ASSERT_TRUE(test->OpenPlaygroundHere(callback));
339}
340} // namespace
341
342TEST_P(AiksTest, DrawLinesWithPath) {
343 DrawLinesTest(this, [](DisplayListBuilder& builder, const DlPaint& paint,
344 Point p0, Point p1, Scalar width) {
345 DlPaint stroke_paint = paint;
346 stroke_paint.setDrawStyle(DlDrawStyle::kStroke);
347 stroke_paint.setStrokeWidth(width);
348 DlPathBuilder path_builder;
349 path_builder.MoveTo(p0);
350 path_builder.LineTo(p1);
351 builder.DrawPath(path_builder.TakePath(), stroke_paint);
352 });
353}
354
355TEST_P(AiksTest, DrawLinesWithDrawLine) {
356 DrawLinesTest(this, [](DisplayListBuilder& builder, const DlPaint& paint,
357 Point p0, Point p1, Scalar width) {
358 DlPaint stroke_paint = paint;
359 stroke_paint.setDrawStyle(DlDrawStyle::kStroke);
360 stroke_paint.setStrokeWidth(width);
361 builder.DrawLine(p0, p1, stroke_paint);
362 });
363}
364
365TEST_P(AiksTest, DrawLinesWithFilledRects) {
366 DrawLinesTest(this, [](DisplayListBuilder& builder, const DlPaint& paint,
367 Point p0, Point p1, Scalar width) {
368 DlPaint fill_paint = paint;
369 fill_paint.setDrawStyle(DlDrawStyle::kFill);
370 Scalar length = p0.GetDistance(p1);
371 Point center = {(p0.x + p1.x) * 0.5f, (p0.y + p1.y) * 0.5f};
372 builder.DrawRect(
373 DlRect::MakeEllipseBounds(center, Size(length, width) * 0.5f),
374 fill_paint);
375 });
376}
377
378TEST_P(AiksTest, DrawLinesWithFilledRoundRects) {
379 DrawLinesTest(this, [](DisplayListBuilder& builder, const DlPaint& paint,
380 Point p0, Point p1, Scalar width) {
381 DlPaint fill_paint = paint;
382 fill_paint.setDrawStyle(DlDrawStyle::kFill);
383 Scalar length = p0.GetDistance(p1);
384 Point center = {(p0.x + p1.x) * 0.5f, (p0.y + p1.y) * 0.5f};
385 builder.DrawRoundRect(
387 DlRect::MakeEllipseBounds(center, Size(length, width) * 0.5f),
388 width * 0.5f),
389 fill_paint);
390 });
391}
392
393TEST_P(AiksTest, CanRenderTightConicPath) {
394 DisplayListBuilder builder;
395 builder.Scale(GetContentScale().x, GetContentScale().y);
396
397 DlPaint paint;
398 paint.setColor(DlColor::kRed());
399 paint.setDrawStyle(DlDrawStyle::kFill);
400
401 DlPaint reference_paint;
402 reference_paint.setColor(DlColor::kGreen());
403 reference_paint.setDrawStyle(DlDrawStyle::kFill);
404
405 DlPathBuilder path_builder;
406
407 path_builder.MoveTo(DlPoint(100, 100));
408 path_builder.ConicCurveTo(DlPoint(150, 450), DlPoint(200, 100), 5.0f);
409
410 DlPathBuilder reference_builder;
411 PathTessellator::Conic component{DlPoint(300, 100), //
412 DlPoint(350, 450), //
413 DlPoint(400, 100), //
414 5.0f};
415 reference_builder.MoveTo(component.p1);
416 constexpr int N = 100;
417 for (int i = 1; i < N; i++) {
418 reference_builder.LineTo(component.Solve(static_cast<Scalar>(i) / N));
419 }
420 reference_builder.LineTo(component.p2);
421
422 DlPaint line_paint;
423 line_paint.setColor(DlColor::kYellow());
424 line_paint.setDrawStyle(DlDrawStyle::kStroke);
425 line_paint.setStrokeWidth(1.0f);
426
427 // Draw some lines to provide a spacial reference for the curvature of
428 // the tips of the direct rendering and the manually tessellated versions.
429 builder.DrawLine(DlPoint(145, 100), DlPoint(145, 450), line_paint);
430 builder.DrawLine(DlPoint(155, 100), DlPoint(155, 450), line_paint);
431 builder.DrawLine(DlPoint(345, 100), DlPoint(345, 450), line_paint);
432 builder.DrawLine(DlPoint(355, 100), DlPoint(355, 450), line_paint);
433 builder.DrawLine(DlPoint(100, 392.5f), DlPoint(400, 392.5f), line_paint);
434
435 // Draw the two paths (direct and manually tessellated) on top of the lines.
436 builder.DrawPath(path_builder.TakePath(), paint);
437 builder.DrawPath(reference_builder.TakePath(), reference_paint);
438
439 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
440}
441
442TEST_P(AiksTest, CanRenderDifferencePaths) {
443 DisplayListBuilder builder;
444
445 DlPaint paint;
446 paint.setColor(DlColor::kRed());
447
448 RoundingRadii radii = {
449 .top_left = {50, 25},
450 .top_right = {25, 50},
451 .bottom_left = {25, 50},
452 .bottom_right = {50, 25},
453 };
454 DlPathBuilder path_builder;
455 DlRoundRect rrect =
456 DlRoundRect::MakeRectRadii(DlRect::MakeXYWH(100, 100, 200, 200), radii);
457 // We use the factory method to convert the rrect and circle to a path so
458 // that they use the legacy conics for legacy golden output.
459 path_builder.AddPath(DlPath::MakeRoundRect(rrect));
460 path_builder.AddPath(DlPath::MakeCircle(DlPoint(200, 200), 50));
461 path_builder.SetFillType(DlPathFillType::kOdd);
462 DlPath path = path_builder.TakePath();
463
464 builder.DrawImage(
465 DlImageImpeller::Make(CreateTextureForFixture("boston.jpg")),
466 DlPoint{10, 10}, {});
467 builder.DrawPath(path, paint);
468
469 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
470}
471
472// Regression test for https://github.com/flutter/flutter/issues/134816.
473//
474// It should be possible to draw 3 lines, and not have an implicit close path.
475TEST_P(AiksTest, CanDrawAnOpenPath) {
476 DisplayListBuilder builder;
477
478 // Starting at (50, 50), draw lines from:
479 // 1. (50, height)
480 // 2. (width, height)
481 // 3. (width, 50)
482 DlPathBuilder path_builder;
483 path_builder.MoveTo(DlPoint(50, 50));
484 path_builder.LineTo(DlPoint(50, 100));
485 path_builder.LineTo(DlPoint(100, 100));
486 path_builder.LineTo(DlPoint(100, 50));
487
488 DlPaint paint;
489 paint.setColor(DlColor::kRed());
490 paint.setDrawStyle(DlDrawStyle::kStroke);
491 paint.setStrokeWidth(10);
492
493 builder.DrawPath(path_builder.TakePath(), paint);
494
495 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
496}
497
498TEST_P(AiksTest, CanDrawAnOpenPathThatIsntARect) {
499 DisplayListBuilder builder;
500
501 // Draw a stroked path that is explicitly closed to verify
502 // It doesn't become a rectangle.
503 DlPathBuilder path_builder;
504 path_builder.MoveTo(DlPoint(50, 50));
505 path_builder.LineTo(DlPoint(520, 120));
506 path_builder.LineTo(DlPoint(300, 310));
507 path_builder.LineTo(DlPoint(100, 50));
508 path_builder.Close();
509
510 DlPaint paint;
511 paint.setColor(DlColor::kRed());
512 paint.setDrawStyle(DlDrawStyle::kStroke);
513 paint.setStrokeWidth(10);
514
515 builder.DrawPath(path_builder.TakePath(), paint);
516
517 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
518}
519
520TEST_P(AiksTest, SolidStrokesRenderCorrectly) {
521 // Compare with https://fiddle.skia.org/c/027392122bec8ac2b5d5de00a4b9bbe2
522 auto callback = [&]() -> sk_sp<DisplayList> {
523 static Color color = Color::Black().WithAlpha(0.5);
524 static float scale = 3;
525 static bool add_circle_clip = true;
526
527 if (IsPlaygroundEnabled()) {
528 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
529 ImGui::ColorEdit4("Color", reinterpret_cast<float*>(&color));
530 ImGui::SliderFloat("Scale", &scale, 0, 6);
531 ImGui::Checkbox("Circle clip", &add_circle_clip);
532 ImGui::End();
533 }
534
535 DisplayListBuilder builder;
536 builder.Scale(GetContentScale().x, GetContentScale().y);
537 DlPaint paint;
538
539 paint.setColor(DlColor::kWhite());
540 builder.DrawPaint(paint);
541
542 paint.setColor(
543 DlColor::ARGB(color.alpha, color.red, color.green, color.blue));
544 paint.setDrawStyle(DlDrawStyle::kStroke);
545 paint.setStrokeWidth(10);
546
547 DlPathBuilder path_builder;
548 path_builder.MoveTo(DlPoint(20, 20));
549 path_builder.QuadraticCurveTo(DlPoint(60, 20), DlPoint(60, 60));
550 path_builder.Close();
551 path_builder.MoveTo(DlPoint(60, 20));
552 path_builder.QuadraticCurveTo(DlPoint(60, 60), DlPoint(20, 60));
553 DlPath path = path_builder.TakePath();
554
555 builder.Scale(scale, scale);
556
557 if (add_circle_clip) {
558 static PlaygroundPoint circle_clip_point_a(Point(60, 300), 20,
559 Color::Red());
560 static PlaygroundPoint circle_clip_point_b(Point(600, 300), 20,
561 Color::Red());
562 auto [handle_a, handle_b] =
563 DrawPlaygroundLine(circle_clip_point_a, circle_clip_point_b);
564
565 Matrix screen_to_canvas = builder.GetMatrix();
566 if (!screen_to_canvas.IsInvertible()) {
567 return nullptr;
568 }
569 screen_to_canvas = screen_to_canvas.Invert();
570
571 Point point_a = screen_to_canvas * handle_a;
572 Point point_b = screen_to_canvas * handle_b;
573
574 Point middle = point_a + point_b;
575 middle *= GetContentScale().x / 2;
576
577 auto radius = point_a.GetDistance(middle);
578
579 builder.ClipPath(DlPath::MakeCircle(middle, radius));
580 }
581
582 for (auto join :
583 {DlStrokeJoin::kBevel, DlStrokeJoin::kRound, DlStrokeJoin::kMiter}) {
584 paint.setStrokeJoin(join);
585 for (auto cap :
586 {DlStrokeCap::kButt, DlStrokeCap::kSquare, DlStrokeCap::kRound}) {
587 paint.setStrokeCap(cap);
588 builder.DrawPath(path, paint);
589 builder.Translate(80, 0);
590 }
591 builder.Translate(-240, 60);
592 }
593
594 return builder.Build();
595 };
596
597 ASSERT_TRUE(OpenPlaygroundHere(callback));
598}
599
600TEST_P(AiksTest, DrawLinesRenderCorrectly) {
601 DisplayListBuilder builder;
602 builder.Scale(GetContentScale().x, GetContentScale().y);
603
604 DlPaint paint;
605 paint.setColor(DlColor::kBlue());
606 paint.setStrokeWidth(10);
607
608 auto draw = [&builder](DlPaint& paint) {
609 for (auto cap :
610 {DlStrokeCap::kButt, DlStrokeCap::kSquare, DlStrokeCap::kRound}) {
611 paint.setStrokeCap(cap);
612 DlPoint origin = {100, 100};
613 builder.DrawLine(DlPoint(150, 100), DlPoint(250, 100), paint);
614 for (int d = 15; d < 90; d += 15) {
616 Point origin = {100, 100};
617 Point p0 = {50, 0};
618 Point p1 = {150, 0};
619 auto a = origin + m * p0;
620 auto b = origin + m * p1;
621
622 builder.DrawLine(a, b, paint);
623 }
624 builder.DrawLine(DlPoint(100, 150), DlPoint(100, 250), paint);
625 builder.DrawCircle(origin, 35, paint);
626
627 builder.DrawLine(DlPoint(250, 250), DlPoint(250, 250), paint);
628
629 builder.Translate(250, 0);
630 }
631 builder.Translate(-750, 250);
632 };
633
634 std::vector<DlColor> colors = {
635 DlColor::ARGB(1, 0x1f / 255.0, 0.0, 0x5c / 255.0),
636 DlColor::ARGB(1, 0x5b / 255.0, 0.0, 0x60 / 255.0),
637 DlColor::ARGB(1, 0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0),
638 DlColor::ARGB(1, 0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0),
639 DlColor::ARGB(1, 0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0),
640 DlColor::ARGB(1, 0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0),
641 DlColor::ARGB(1, 0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0)};
642 std::vector<Scalar> stops = {
643 0.0,
644 (1.0 / 6.0) * 1,
645 (1.0 / 6.0) * 2,
646 (1.0 / 6.0) * 3,
647 (1.0 / 6.0) * 4,
648 (1.0 / 6.0) * 5,
649 1.0,
650 };
651
653 CreateTextureForFixture("airplane.jpg",
654 /*enable_mipmapping=*/true));
655
656 draw(paint);
657
658 paint.setColorSource(DlColorSource::MakeRadial({100, 100}, 200, stops.size(),
659 colors.data(), stops.data(),
660 DlTileMode::kMirror));
661 draw(paint);
662
663 DlMatrix matrix = DlMatrix::MakeTranslation({-150, 75});
665 texture, DlTileMode::kRepeat, DlTileMode::kRepeat,
666 DlImageSampling::kMipmapLinear, &matrix));
667 draw(paint);
668
669 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
670}
671
672TEST_P(AiksTest, DrawRectStrokesRenderCorrectly) {
673 DisplayListBuilder builder;
674 DlPaint paint;
675 paint.setColor(DlColor::kRed());
676 paint.setDrawStyle(DlDrawStyle::kStroke);
677 paint.setStrokeWidth(10);
678
679 builder.Translate(100, 100);
680 builder.DrawPath(DlPath::MakeRect(DlRect::MakeSize(DlSize(100, 100))), paint);
681
682 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
683}
684
685TEST_P(AiksTest, DrawRectStrokesWithBevelJoinRenderCorrectly) {
686 DisplayListBuilder builder;
687 DlPaint paint;
688 paint.setColor(DlColor::kRed());
689 paint.setDrawStyle(DlDrawStyle::kStroke);
690 paint.setStrokeWidth(10);
691 paint.setStrokeJoin(DlStrokeJoin::kBevel);
692
693 builder.Translate(100, 100);
694 builder.DrawPath(DlPath::MakeRect(DlRect::MakeSize(DlSize(100, 100))), paint);
695
696 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
697}
698
699TEST_P(AiksTest, CanDrawMultiContourConvexPath) {
700 DlPathBuilder path_builder;
701 for (auto i = 0; i < 10; i++) {
702 if (i % 2 == 0) {
703 // We use the factory method to convert the circle to a path so that it
704 // uses the legacy conics for legacy golden output.
705 DlPath circle =
706 DlPath::MakeCircle(DlPoint(100 + 50 * i, 100 + 50 * i), 100);
707 path_builder.AddPath(circle);
708 path_builder.Close();
709 } else {
710 path_builder.MoveTo(DlPoint(100.f + 50.f * i - 100, 100.f + 50.f * i));
711 path_builder.LineTo(DlPoint(100.f + 50.f * i, 100.f + 50.f * i - 100));
712 path_builder.LineTo(DlPoint(100.f + 50.f * i - 100, //
713 100.f + 50.f * i - 100));
714 path_builder.Close();
715 }
716 }
717 DlPath path = path_builder.TakePath();
718
719 DisplayListBuilder builder;
720 DlPaint paint;
721 paint.setColor(DlColor::kRed().withAlpha(102));
722 builder.DrawPath(path, paint);
723
724 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
725}
726
727TEST_P(AiksTest, ArcWithZeroSweepAndBlur) {
728 DisplayListBuilder builder;
729 builder.Scale(GetContentScale().x, GetContentScale().y);
730
731 DlPaint paint;
732 paint.setColor(DlColor::kRed());
733
734 std::vector<DlColor> colors = {DlColor::RGBA(1.0, 0.0, 0.0, 1.0),
735 DlColor::RGBA(0.0, 0.0, 0.0, 1.0)};
736 std::vector<Scalar> stops = {0.0, 1.0};
737
738 paint.setColorSource(
739 DlColorSource::MakeSweep({100, 100}, 45, 135, stops.size(), colors.data(),
740 stops.data(), DlTileMode::kMirror));
741 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 20));
742
743 DlPathBuilder path_builder;
744 path_builder.AddArc(DlRect::MakeXYWH(10, 10, 100, 100), //
745 DlDegrees(0), DlDegrees(0));
746 builder.DrawPath(path_builder.TakePath(), paint);
747
748 // Check that this empty picture can be created without crashing.
749 builder.Build();
750}
751
752TEST_P(AiksTest, CanRenderClips) {
753 DisplayListBuilder builder;
754 DlPaint paint;
756
757 builder.ClipPath(DlPath::MakeRect(DlRect::MakeXYWH(0, 0, 500, 500)));
758 builder.DrawPath(DlPath::MakeCircle(DlPoint(500, 500), 250), paint);
759
760 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
761}
762
763TEST_P(AiksTest, FatStrokeArc) {
764 DlScalar stroke_width = 300;
765 DlScalar aspect = 1.0;
766 DlScalar start_angle = 0;
767 DlScalar end_angle = 90;
768 auto callback = [&]() -> sk_sp<DisplayList> {
769 if (IsPlaygroundEnabled()) {
770 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
771 ImGui::SliderFloat("Stroke Width", &stroke_width, 1, 300);
772 ImGui::SliderFloat("Aspect", &aspect, 0.5, 2.0);
773 ImGui::SliderFloat("Start Angle", &start_angle, 0, 360);
774 ImGui::SliderFloat("End Angle", &end_angle, 0, 360);
775 ImGui::End();
776 }
777
778 DisplayListBuilder builder;
779 DlPaint grey_paint;
780 grey_paint.setColor(DlColor(0xff111111));
781 builder.DrawPaint(grey_paint);
782
783 DlPaint white_paint;
784 white_paint.setColor(DlColor::kWhite());
785 white_paint.setStrokeWidth(stroke_width);
786 white_paint.setDrawStyle(DlDrawStyle::kStroke);
787 DlPaint red_paint;
788 red_paint.setColor(DlColor::kRed());
789
790 Rect rect = Rect::MakeXYWH(100, 100, 100, aspect * 100);
791 builder.DrawRect(rect, red_paint);
792 builder.DrawArc(rect, start_angle, end_angle,
793 /*useCenter=*/false, white_paint);
794 DlScalar frontier = rect.GetRight() + stroke_width / 2.0;
795 builder.DrawLine(Point(frontier, 0), Point(frontier, 150), red_paint);
796
797 return builder.Build();
798 };
799 ASSERT_TRUE(OpenPlaygroundHere(callback));
800}
801
802TEST_P(AiksTest, CanRenderOverlappingMultiContourPath) {
803 DisplayListBuilder builder;
804
805 DlPaint paint;
806 paint.setColor(DlColor::kRed());
807
808 RoundingRadii radii = {
809 .top_left = DlSize(50, 50),
810 .top_right = DlSize(50, 50),
811 .bottom_left = DlSize(50, 50),
812 .bottom_right = DlSize(50, 50),
813 };
814
815 const Scalar kTriangleHeight = 100;
817 DlRect::MakeCircleBounds({0, 0}, kTriangleHeight * 0.5f), radii);
818 // We use the factory method to convert the rrect to a path so that it
819 // uses the legacy conics for legacy golden output.
820 DlPath rrect_path = DlPath::MakeRoundRect(rrect);
821
822 builder.Translate(200, 200);
823 // Form a path similar to the Material drop slider value indicator. Both
824 // shapes should render identically side-by-side.
825 {
826 DlPathBuilder path_builder;
827 path_builder.MoveTo(DlPoint(0, kTriangleHeight));
828 path_builder.LineTo(DlPoint(-kTriangleHeight / 2.0f, 0));
829 path_builder.LineTo(DlPoint(kTriangleHeight / 2.0f, 0));
830 path_builder.Close();
831 path_builder.AddPath(rrect_path);
832
833 builder.DrawPath(path_builder.TakePath(), paint);
834 }
835 builder.Translate(100, 0);
836
837 {
838 DlPathBuilder path_builder;
839 path_builder.MoveTo(DlPoint(0, kTriangleHeight));
840 path_builder.LineTo(DlPoint(-kTriangleHeight / 2.0f, 0));
841 path_builder.LineTo(DlPoint(0, -10));
842 path_builder.LineTo(DlPoint(kTriangleHeight / 2.0f, 0));
843 path_builder.Close();
844 path_builder.AddPath(rrect_path);
845
846 builder.DrawPath(path_builder.TakePath(), paint);
847 }
848
849 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
850}
851
852TEST_P(AiksTest, TwoContourPathWithSinglePointContour) {
853 DisplayListBuilder builder;
854
855 DlPaint paint;
856 paint.setColor(DlColor::kRed());
857 paint.setDrawStyle(DlDrawStyle::kStroke);
858 paint.setStrokeWidth(15.0);
859 paint.setStrokeCap(DlStrokeCap::kRound);
860
861 DlPathBuilder path_builder;
862 path_builder.MoveTo(DlPoint(100, 100));
863 path_builder.LineTo(DlPoint(150, 150));
864 path_builder.MoveTo(DlPoint(200, 200));
865 path_builder.LineTo(DlPoint(200, 200));
866
867 builder.DrawPath(path_builder.TakePath(), paint);
868
869 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
870}
871
872TEST_P(AiksTest, TwoContourPathWithConnectingLines) {
873 DisplayListBuilder builder;
874
875 DlPaint paint;
876 paint.setColor(DlColor::kRed());
877 paint.setDrawStyle(DlDrawStyle::kStroke);
878 paint.setStrokeWidth(15.0);
879
880 builder.Translate(100, 0);
881 for (auto join : std::vector<DlStrokeJoin>{
882 DlStrokeJoin::kMiter, DlStrokeJoin::kRound, DlStrokeJoin::kBevel}) {
883 builder.Translate(0, 100);
884 paint.setStrokeJoin(join);
885
886 DlPathBuilder path_builder;
887 path_builder.MoveTo(DlPoint(0, 0));
888 path_builder.LineTo(DlPoint(50, 50));
889 path_builder.MoveTo(DlPoint(50, 50));
890 path_builder.LineTo(DlPoint(100, 0));
891
892 builder.DrawPath(path_builder.TakePath(), paint);
893 }
894
895 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
896}
897
898TEST_P(AiksTest, StrokeCapsAndJoins) {
899 DisplayListBuilder builder;
900 builder.Scale(GetContentScale().x, GetContentScale().y);
901
902 builder.Translate(100, 0);
903
904 builder.Save();
905 for (auto cap : std::vector<DlStrokeCap>{
906 DlStrokeCap::kButt, DlStrokeCap::kRound, DlStrokeCap::kSquare}) {
907 DlPathBuilder path_builder;
908 path_builder.MoveTo({20, 50});
909 path_builder.LineTo({50, 50});
910 path_builder.MoveTo({120, 50});
911 path_builder.LineTo({120, 80});
912 path_builder.MoveTo({180, 50});
913 path_builder.LineTo({180, 50});
914 DlPath path = path_builder.TakePath();
915
916 DlPaint paint;
917 paint.setColor(DlColor::kRed());
918 paint.setDrawStyle(DlDrawStyle::kStroke);
919 paint.setStrokeWidth(20.0f);
920 paint.setStrokeCap(cap);
921 paint.setStrokeJoin(DlStrokeJoin::kBevel);
922
923 builder.DrawPath(path, paint);
924
925 paint.setColor(DlColor::kYellow());
926 paint.setStrokeWidth(1.0f);
927 paint.setStrokeCap(DlStrokeCap::kButt);
928
929 builder.DrawPath(path, paint);
930
931 builder.Translate(250, 0);
932 }
933 builder.Restore();
934
935 builder.Translate(0, 100);
936
937 builder.Save();
938 for (auto join : std::vector<DlStrokeJoin>{
939 DlStrokeJoin::kBevel, DlStrokeJoin::kRound, DlStrokeJoin::kMiter}) {
940 DlPathBuilder path_builder;
941 path_builder.MoveTo({20, 50}); // 0 degree right turn
942 path_builder.LineTo({50, 50});
943 path_builder.LineTo({80, 50});
944 path_builder.MoveTo({20, 150}); // 90 degree right turn
945 path_builder.LineTo({50, 150});
946 path_builder.LineTo({50, 180});
947 path_builder.MoveTo({20, 250}); // 45 degree right turn
948 path_builder.LineTo({50, 250});
949 path_builder.LineTo({70, 270});
950 path_builder.MoveTo({20, 350}); // 135 degree right turn
951 path_builder.LineTo({50, 350});
952 path_builder.LineTo({30, 370});
953 path_builder.MoveTo({20, 450}); // 180 degree right turn
954 path_builder.LineTo({50, 450});
955 path_builder.LineTo({20, 450});
956 path_builder.MoveTo({120, 80}); // 0 degree left turn
957 path_builder.LineTo({150, 80});
958 path_builder.LineTo({180, 80});
959 path_builder.MoveTo({120, 180}); // 90 degree left turn
960 path_builder.LineTo({150, 180});
961 path_builder.LineTo({150, 150});
962 path_builder.MoveTo({120, 280}); // 45 degree left turn
963 path_builder.LineTo({150, 280});
964 path_builder.LineTo({170, 260});
965 path_builder.MoveTo({120, 380}); // 135 degree left turn
966 path_builder.LineTo({150, 380});
967 path_builder.LineTo({130, 360});
968 path_builder.MoveTo({120, 480}); // 180 degree left turn
969 path_builder.LineTo({150, 480});
970 path_builder.LineTo({120, 480});
971 DlPath path = path_builder.TakePath();
972
973 DlPaint paint;
974
975 paint.setColor(DlColor::kRed());
976 paint.setDrawStyle(DlDrawStyle::kStroke);
977 paint.setStrokeWidth(20.0f);
978 paint.setStrokeCap(DlStrokeCap::kSquare);
979 paint.setStrokeJoin(join);
980 builder.DrawPath(path, paint);
981
982 paint.setColor(DlColor::kYellow());
983 paint.setStrokeWidth(1.0f);
984 paint.setStrokeCap(DlStrokeCap::kButt);
985 builder.DrawPath(path, paint);
986
987 builder.Translate(250, 0);
988 }
989 builder.Restore();
990
991 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
992}
993
994TEST_P(AiksTest, BlurredCircleWithStrokeWidth) {
995 DisplayListBuilder builder;
996 DlPaint paint;
997 paint.setColor(DlColor::kGreen());
998 paint.setDrawStyle(DlDrawStyle::kStroke);
999 paint.setStrokeWidth(30);
1000 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 5));
1001
1002 builder.DrawCircle(DlPoint(200, 200), 100, paint);
1003
1004 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1005}
1006
1007} // namespace testing
1008} // namespace impeller
void DrawRoundRect(const DlRoundRect &rrect, const DlPaint &paint) override
void DrawArc(const DlRect &bounds, DlScalar start, DlScalar sweep, bool useCenter, const DlPaint &paint) override
void DrawImage(const sk_sp< DlImage > &image, const DlPoint &point, DlImageSampling sampling, const DlPaint *paint=nullptr) override
DlMatrix GetMatrix() const override
Definition dl_builder.h:111
void DrawCircle(const DlPoint &center, DlScalar radius, const DlPaint &paint) override
void DrawLine(const DlPoint &p0, const DlPoint &p1, const DlPaint &paint) override
void Rotate(DlScalar degrees) override
void Scale(DlScalar sx, DlScalar sy) override
void Translate(DlScalar tx, DlScalar ty) override
void DrawPaint(const DlPaint &paint) override
sk_sp< DisplayList > Build()
void DrawPath(const DlPath &path, const DlPaint &paint) override
void ClipPath(const DlPath &path, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false) override
void Transform(const DlMatrix &matrix) override
void DrawRect(const DlRect &rect, const DlPaint &paint) override
static std::shared_ptr< DlMaskFilter > Make(DlBlurStyle style, SkScalar sigma, bool respect_ctm=true)
static std::shared_ptr< const DlColorFilter > MakeBlend(DlColor color, DlBlendMode mode)
static std::shared_ptr< DlColorSource > MakeSweep(DlPoint center, DlScalar start, DlScalar end, uint32_t stop_count, const DlColor *colors, const float *stops, DlTileMode tile_mode, const DlMatrix *matrix=nullptr)
static std::shared_ptr< DlColorSource > MakeImage(const sk_sp< const DlImage > &image, DlTileMode horizontal_tile_mode, DlTileMode vertical_tile_mode, DlImageSampling sampling=DlImageSampling::kLinear, const DlMatrix *matrix=nullptr)
static std::shared_ptr< DlColorSource > MakeRadial(DlPoint center, DlScalar radius, uint32_t stop_count, const DlColor *colors, const float *stops, DlTileMode tile_mode, const DlMatrix *matrix=nullptr)
DlPaint & setColor(DlColor color)
Definition dl_paint.h:70
DlPaint & setStrokeCap(DlStrokeCap cap)
Definition dl_paint.h:101
DlPaint & setStrokeWidth(float width)
Definition dl_paint.h:115
DlPaint & setMaskFilter(std::nullptr_t filter)
Definition dl_paint.h:185
DlPaint & setDrawStyle(DlDrawStyle style)
Definition dl_paint.h:93
DlPaint & setStrokeJoin(DlStrokeJoin join)
Definition dl_paint.h:109
DlPaint & setColorFilter(std::nullptr_t filter)
Definition dl_paint.h:149
DlPaint & setColorSource(std::nullptr_t source)
Definition dl_paint.h:131
DlPathBuilder & LineTo(DlPoint p2)
Draw a line from the current point to the indicated point p2.
DlPathBuilder & AddPath(const DlPath &path)
Append the provided path to this path as if the commands used to construct it were repeated on this p...
static constexpr const DlScalar kArcApproximationMagic
DlPathBuilder & MoveTo(DlPoint p2)
Start a new contour that will originate at the indicated point p2.
DlPathBuilder & SetFillType(DlPathFillType fill_type)
Set the fill type that should be used to determine the interior of this path to the indicated |fill_t...
const DlPath TakePath()
Returns the path constructed by this path builder and resets its internal state to the default state ...
DlPathBuilder & ConicCurveTo(DlPoint cp, DlPoint p2, DlScalar weight)
Draw a conic curve (a rational quadratic bezier curve) from the current point to the indicated point ...
DlPathBuilder & QuadraticCurveTo(DlPoint cp, DlPoint p2)
Draw a quadratic bezier curve from the current point to the indicated point p2, using the indicated p...
DlPathBuilder & Close()
The path is closed back to the location of the most recent MoveTo call. Contours that are filled are ...
DlPathBuilder & AddArc(const DlRect &bounds, DlDegrees start, DlDegrees sweep, bool use_center=false)
Append an arc contour to the path which:
DlPathBuilder & CubicCurveTo(DlPoint cp1, DlPoint cp2, DlPoint p2)
Draw a cubic bezier curve from the current point to the indicated point p2, using the indicated point...
static DlPath MakeLine(const DlPoint a, const DlPoint b)
Definition dl_path.cc:89
static DlPath MakeRoundRect(const DlRoundRect &rrect)
Definition dl_path.cc:72
static DlPath MakeCircle(const DlPoint center, DlScalar radius)
Definition dl_path.cc:68
static DlPath MakeArc(const DlRect &bounds, DlDegrees start, DlDegrees sweep, bool use_center)
Definition dl_path.cc:101
static DlPath MakeRect(const DlRect &rect)
Definition dl_path.cc:39
double x() const
Definition geometry.h:22
double y() const
Definition geometry.h:23
static sk_sp< DlImageImpeller > Make(std::shared_ptr< Texture > texture, OwningContext owning_context=OwningContext::kIO)
int32_t x
auto & d
Definition main.cc:28
FlutterDesktopBinaryReply callback
size_t length
FlTexture * texture
double y
impeller::Scalar DlScalar
impeller::Degrees DlDegrees
impeller::Size DlSize
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition switch_defs.h:52
impeller::Point DlPoint
TEST_P(AiksTest, DrawAtlasNoColor)
AiksPlaygroundWithGoldens AiksTest
float Scalar
Definition scalar.h:19
std::tuple< Point, Point > DrawPlaygroundLine(PlaygroundPoint &point_a, PlaygroundPoint &point_b)
Definition widgets.cc:51
constexpr float kSqrt2Over2
Definition constants.h:51
int32_t width
static constexpr DlColor kWhite()
Definition dl_color.h:70
static constexpr DlColor kBlue()
Definition dl_color.h:73
static constexpr DlColor RGBA(DlScalar r, DlScalar g, DlScalar b, DlScalar a)
Construct a 32 bit color from floating point R, G, B, and A color channels.
Definition dl_color.h:48
static constexpr DlColor kBlack()
Definition dl_color.h:69
static constexpr DlColor ARGB(DlScalar a, DlScalar r, DlScalar g, DlScalar b)
Construct a 32 bit color from floating point A, R, G, and B color channels.
Definition dl_color.h:57
static constexpr DlColor kYellow()
Definition dl_color.h:76
static constexpr DlColor kFuchsia()
Definition dl_color.h:81
static constexpr DlColor kAliceBlue()
Definition dl_color.h:80
static constexpr DlColor kRed()
Definition dl_color.h:71
static constexpr DlColor kGreen()
Definition dl_color.h:72
Scalar blue
Definition color.h:138
Scalar alpha
Definition color.h:143
static constexpr Color Black()
Definition color.h:271
constexpr Color WithAlpha(Scalar new_alpha) const
Definition color.h:283
Scalar red
Definition color.h:128
static constexpr Color Red()
Definition color.h:277
Scalar green
Definition color.h:133
A 4x4 matrix using column-major storage.
Definition matrix.h:37
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition matrix.h:95
bool IsInvertible() const
Definition matrix.h:321
Matrix Invert() const
Definition matrix.cc:99
static Matrix MakeRotationZ(Radians r)
Definition matrix.h:223
static RoundRect MakeRectRadius(const Rect &rect, Scalar radius)
Definition round_rect.h:27
static RoundRect MakeRectRadii(const Rect &rect, const RoundingRadii &radii)
Definition round_rect.cc:9
static constexpr TRect MakeEllipseBounds(const TPoint< Type > &center, const TSize< Type > &radii)
Definition rect.h:164
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition rect.h:136
static constexpr TRect MakeCircleBounds(const TPoint< Type > &center, Type radius)
Definition rect.h:156
static constexpr TRect MakeSize(const TSize< U > &size)
Definition rect.h:150