| Flutter Impeller |

aiks_dl_gradient_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/display_list.h"
6 #include "display_list/dl_blend_mode.h"
7 #include "display_list/dl_tile_mode.h"
8 #include "display_list/effects/dl_color_filter.h"
9 #include "display_list/effects/dl_color_source.h"
10 #include "display_list/effects/dl_mask_filter.h"
11 #include "display_list/geometry/dl_path_builder.h"
12 #include "flutter/impeller/display_list/aiks_unittests.h"
13
14 #include "flutter/display_list/dl_builder.h"
15 #include "flutter/display_list/dl_color.h"
16 #include "flutter/display_list/dl_paint.h"
17 #include "flutter/testing/testing.h"
18 #include "impeller/playground/widgets.h"
19
20 using namespace flutter;
21 ////////////////////////////////////////////////////////////////////////////////
22 // This is for tests of Canvas that are interested the results of rendering
23 // gradients.
24 ////////////////////////////////////////////////////////////////////////////////
25
26 namespace impeller {
27 namespace testing {
28
29 namespace {
30
31 /// Test body for linear gradient tile mode tests (ex.
32 /// CanRenderLinearGradientClamp).
33 void CanRenderLinearGradient(AiksTest* aiks_test, DlTileMode tile_mode) {
34 DisplayListBuilder builder;
35 Point scale = aiks_test->GetContentScale();
36 builder.Scale(scale.x, scale.y);
37 DlPaint paint;
38 builder.Translate(100.0f, 0);
39
40 std::vector<DlColor> colors = {
41 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
42 DlColor(Color{0.1294, 0.5882, 0.9529, 0.0}.ToARGB())};
43 std::vector<Scalar> stops = {0.0, 1.0};
44
45 auto gradient = DlColorSource::MakeLinear(
46 {0, 0}, {200, 200}, 2, colors.data(), stops.data(), tile_mode);
47 paint.setColorSource(gradient);
48 paint.setColor(DlColor::kWhite());
49 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
50 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
51 }
52
53 } // namespace
54
55 TEST_P(AiksTest, CanRenderLinearGradientClamp) {
56 CanRenderLinearGradient(this, DlTileMode::kClamp);
57 }
58 TEST_P(AiksTest, CanRenderLinearGradientRepeat) {
59 CanRenderLinearGradient(this, DlTileMode::kRepeat);
60 }
61 TEST_P(AiksTest, CanRenderLinearGradientMirror) {
62 CanRenderLinearGradient(this, DlTileMode::kMirror);
63 }
64 TEST_P(AiksTest, CanRenderLinearGradientDecal) {
65 CanRenderLinearGradient(this, DlTileMode::kDecal);
66 }
67
68 TEST_P(AiksTest, CanRenderLinearGradientDecalWithColorFilter) {
69 DisplayListBuilder builder;
70 Point scale = GetContentScale();
71 builder.Scale(scale.x, scale.y);
72 DlPaint paint;
73 builder.Translate(100.0f, 0);
74
75 std::vector<DlColor> colors = {
76 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
77 DlColor(Color{0.1294, 0.5882, 0.9529, 0.0}.ToARGB())};
78 std::vector<Scalar> stops = {0.0, 1.0};
79
80 paint.setColorSource(DlColorSource::MakeLinear(
81 {0, 0}, {200, 200}, 2, colors.data(), stops.data(), DlTileMode::kDecal));
82 // Overlay the gradient with 25% green. This should appear as the entire
83 // rectangle being drawn with 25% green, including the border area outside the
84 // decal gradient.
85 paint.setColorFilter(DlColorFilter::MakeBlend(DlColor::kGreen().withAlpha(64),
86 DlBlendMode::kSrcOver));
87 paint.setColor(DlColor::kWhite());
88 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
89 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
90 }
91
92 static void CanRenderLinearGradientWithDithering(AiksTest* aiks_test) {
93 DisplayListBuilder builder;
94 DlPaint paint;
95 builder.Translate(100.0, 100.0);
96
97 // 0xffcccccc --> 0xff333333, taken from
98 // https://github.com/flutter/flutter/issues/118073#issue-1521699748
99 std::vector<DlColor> colors = {DlColor(0xFFCCCCCC), DlColor(0xFF333333)};
100 std::vector<Scalar> stops = {0.0, 1.0};
101
102 paint.setColorSource(DlColorSource::MakeLinear(
103 {0, 0}, {800, 500}, 2, colors.data(), stops.data(), DlTileMode::kClamp));
104 builder.DrawRect(DlRect::MakeXYWH(0, 0, 800, 500), paint);
105 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
106 }
107
108 TEST_P(AiksTest, CanRenderLinearGradientWithDitheringEnabled) {
109 CanRenderLinearGradientWithDithering(this);
110 }
111
112 static void CanRenderRadialGradientWithDithering(AiksTest* aiks_test) {
113 DisplayListBuilder builder;
114 DlPaint paint;
115 builder.Translate(100.0, 100.0);
116
117 // #FFF -> #000
118 std::vector<DlColor> colors = {DlColor(Color{1.0, 1.0, 1.0, 1.0}.ToARGB()),
119 DlColor(Color{0.0, 0.0, 0.0, 1.0}.ToARGB())};
120 std::vector<Scalar> stops = {0.0, 1.0};
121
122 paint.setColorSource(DlColorSource::MakeRadial(
123 {600, 600}, 600, 2, colors.data(), stops.data(), DlTileMode::kClamp));
124 builder.DrawRect(DlRect::MakeXYWH(0, 0, 1200, 1200), paint);
125 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
126 }
127
128 TEST_P(AiksTest, CanRenderRadialGradientWithDitheringEnabled) {
129 CanRenderRadialGradientWithDithering(this);
130 }
131
132 static void CanRenderSweepGradientWithDithering(AiksTest* aiks_test) {
133 DisplayListBuilder builder;
134 builder.Scale(aiks_test->GetContentScale().x, aiks_test->GetContentScale().y);
135 DlPaint paint;
136 builder.Translate(100.0, 100.0);
137
138 // #FFF -> #000
139 std::vector<DlColor> colors = {DlColor(Color{1.0, 1.0, 1.0, 1.0}.ToARGB()),
140 DlColor(Color{0.0, 0.0, 0.0, 1.0}.ToARGB())};
141 std::vector<Scalar> stops = {0.0, 1.0};
142
143 paint.setColorSource(DlColorSource::MakeSweep(
144 {100, 100}, /*start=*/45, /*end=*/135, 2, colors.data(), stops.data(),
145 DlTileMode::kMirror));
146
147 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
148 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
149 }
150
151 TEST_P(AiksTest, CanRenderSweepGradientWithDitheringEnabled) {
152 CanRenderSweepGradientWithDithering(this);
153 }
154
155 static void CanRenderConicalGradientWithDithering(AiksTest* aiks_test) {
156 DisplayListBuilder builder;
157 builder.Scale(aiks_test->GetContentScale().x, aiks_test->GetContentScale().y);
158 DlPaint paint;
159 builder.Translate(100.0, 100.0);
160
161 // #FFF -> #000
162 std::vector<DlColor> colors = {DlColor(Color{1.0, 1.0, 1.0, 1.0}.ToARGB()),
163 DlColor(Color{0.0, 0.0, 0.0, 1.0}.ToARGB())};
164 std::vector<Scalar> stops = {0.0, 1.0};
165
166 paint.setColorSource(DlColorSource::MakeConical({0, 1}, 0, {100, 100}, 100, 2,
167 colors.data(), stops.data(),
168 DlTileMode::kMirror));
169
170 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
171 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
172 }
173
174 TEST_P(AiksTest, CanRenderConicalGradientWithDitheringEnabled) {
175 CanRenderConicalGradientWithDithering(this);
176 }
177
178 namespace {
179 void CanRenderLinearGradientWithOverlappingStops(AiksTest* aiks_test,
180 DlTileMode tile_mode) {
181 DisplayListBuilder builder;
182 DlPaint paint;
183 builder.Translate(100.0, 100.0);
184
185 std::vector<DlColor> colors = {
186 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
187 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
188 DlColor(Color{0.1294, 0.5882, 0.9529, 1.0}.ToARGB()),
189 DlColor(Color{0.1294, 0.5882, 0.9529, 1.0}.ToARGB())};
190 std::vector<Scalar> stops = {0.0, 0.5, 0.5, 1.0};
191
192 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {500, 500},
193 stops.size(), colors.data(),
194 stops.data(), tile_mode));
195
196 paint.setColor(DlColor::kWhite());
197 builder.DrawRect(DlRect::MakeXYWH(0, 0, 500, 500), paint);
198 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
199 }
200 } // namespace
201
202 // Only clamp is necessary. All tile modes are the same output.
203 TEST_P(AiksTest, CanRenderLinearGradientWithOverlappingStopsClamp) {
204 CanRenderLinearGradientWithOverlappingStops(this, DlTileMode::kClamp);
205 }
206
207 namespace {
208 void CanRenderGradientWithIncompleteStops(AiksTest* aiks_test,
209 DlColorSourceType type) {
210 const DlTileMode tile_modes[4] = {
211 DlTileMode::kClamp,
212 DlTileMode::kRepeat,
213 DlTileMode::kMirror,
214 DlTileMode::kDecal,
215 };
216 const DlScalar test_size = 250;
217 const DlScalar test_border = 25;
218 const DlScalar gradient_size = 50;
219 const DlScalar quadrant_size = test_size + test_border * 2;
220
221 DisplayListBuilder builder;
222 builder.DrawRect(DlRect::MakeWH(quadrant_size * 2, quadrant_size * 2),
223 DlPaint().setColor(DlColor::kDarkGrey()));
224
225 for (int quadrant = 0; quadrant < 4; quadrant++) {
226 builder.Save();
227 builder.Translate((quadrant & 1) * quadrant_size + test_border,
228 (quadrant >> 1) * quadrant_size + test_border);
229
230 if (type == DlColorSourceType::kLinearGradient) {
231 // Alignment lines for the gradient edges/repeats/mirrors/etc.
232 // (rendered under the gradient so as not to obscure it)
233 DlPoint center = DlPoint(test_size, test_size) * 0.5;
234 DlScalar ten_percent = gradient_size * 0.1;
235 for (int i = gradient_size / 2; i <= test_size / 2; i += gradient_size) {
236 auto draw_at = [=](DlCanvas& canvas, DlScalar offset, DlColor color) {
237 DlPaint line_paint;
238 line_paint.setColor(color);
239 // strokewidth of 2 straddles the dividing line
240 line_paint.setStrokeWidth(2.0f);
241 line_paint.setDrawStyle(DlDrawStyle::kStroke);
242
243 DlPoint along(offset, offset);
244 DlScalar across_distance = test_size / 2 + 10 - offset;
245 DlPoint across(across_distance, -across_distance);
246
247 canvas.DrawLine(center - along - across, //
248 center - along + across, //
249 line_paint);
250 canvas.DrawLine(center + along - across, //
251 center + along + across, //
252 line_paint);
253 };
254 // White line is at the edge of the gradient
255 // Grey lines are where the 0.1 and 0.9 color stops land
256 draw_at(builder, i - ten_percent, DlColor::kMidGrey());
257 draw_at(builder, i, DlColor::kWhite());
258 draw_at(builder, i + ten_percent, DlColor::kMidGrey());
259 }
260 }
261
262 std::vector<DlColor> colors = {
263 DlColor::kGreen(),
264 DlColor::kPurple(),
265 DlColor::kOrange(),
266 DlColor::kBlue(),
267 };
268 std::vector<Scalar> stops = {0.1, 0.3, 0.7, 0.9};
269
270 DlPaint paint;
271 switch (type) {
272 case DlColorSourceType::kLinearGradient:
273 paint.setColorSource(DlColorSource::MakeLinear(
274 {test_size / 2 - gradient_size / 2,
275 test_size / 2 - gradient_size / 2},
276 {test_size / 2 + gradient_size / 2,
277 test_size / 2 + gradient_size / 2},
278 stops.size(), colors.data(), stops.data(), tile_modes[quadrant]));
279 break;
280 case DlColorSourceType::kRadialGradient:
281 paint.setColorSource(DlColorSource::MakeRadial(
282 {test_size / 2, test_size / 2}, gradient_size, //
283 stops.size(), colors.data(), stops.data(), tile_modes[quadrant]));
284 break;
285 case DlColorSourceType::kConicalGradient:
286 paint.setColorSource(DlColorSource::MakeConical(
287 {test_size / 2, test_size / 2}, 0,
288 {test_size / 2 + 20, test_size / 2 - 10}, gradient_size,
289 stops.size(), colors.data(), stops.data(), tile_modes[quadrant]));
290 break;
291 case DlColorSourceType::kSweepGradient:
292 paint.setColorSource(DlColorSource::MakeSweep(
293 {test_size / 2, test_size / 2}, 0, 45, //
294 stops.size(), colors.data(), stops.data(), tile_modes[quadrant]));
295 break;
296 default:
297 FML_UNREACHABLE();
298 }
299
300 builder.DrawRect(DlRect::MakeXYWH(0, 0, test_size, test_size), paint);
301 builder.Restore();
302 }
303
304 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
305 }
306 } // namespace
307
308 TEST_P(AiksTest, CanRenderLinearGradientWithIncompleteStops) {
309 CanRenderGradientWithIncompleteStops(this,
310 DlColorSourceType::kLinearGradient);
311 }
312 TEST_P(AiksTest, CanRenderRadialGradientWithIncompleteStops) {
313 CanRenderGradientWithIncompleteStops(this,
314 DlColorSourceType::kRadialGradient);
315 }
316 TEST_P(AiksTest, CanRenderConicalGradientWithIncompleteStops) {
317 CanRenderGradientWithIncompleteStops(this,
318 DlColorSourceType::kConicalGradient);
319 }
320 TEST_P(AiksTest, CanRenderSweepGradientWithIncompleteStops) {
321 CanRenderGradientWithIncompleteStops(this, DlColorSourceType::kSweepGradient);
322 }
323
324 namespace {
325 void CanRenderLinearGradientManyColors(AiksTest* aiks_test,
326 DlTileMode tile_mode) {
327 DisplayListBuilder builder;
328 builder.Scale(aiks_test->GetContentScale().x, aiks_test->GetContentScale().y);
329 DlPaint paint;
330 builder.Translate(100, 100);
331
332 std::vector<DlColor> colors = {
333 DlColor(Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}.ToARGB()),
334 DlColor(Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}.ToARGB()),
335 DlColor(Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
336 DlColor(Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}.ToARGB()),
337 DlColor(Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}.ToARGB()),
338 DlColor(Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
339 DlColor(Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}.ToARGB())};
340 std::vector<Scalar> stops = {
341 0.0,
342 (1.0 / 6.0) * 1,
343 (1.0 / 6.0) * 2,
344 (1.0 / 6.0) * 3,
345 (1.0 / 6.0) * 4,
346 (1.0 / 6.0) * 5,
347 1.0,
348 };
349
350 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {200, 200},
351 stops.size(), colors.data(),
352 stops.data(), tile_mode));
353
354 paint.setColor(DlColor::kWhite());
355 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
356 builder.Restore();
357 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
358 }
359 } // namespace
360
361 TEST_P(AiksTest, CanRenderLinearGradientManyColorsClamp) {
362 CanRenderLinearGradientManyColors(this, DlTileMode::kClamp);
363 }
364 TEST_P(AiksTest, CanRenderLinearGradientManyColorsRepeat) {
365 CanRenderLinearGradientManyColors(this, DlTileMode::kRepeat);
366 }
367 TEST_P(AiksTest, CanRenderLinearGradientManyColorsMirror) {
368 CanRenderLinearGradientManyColors(this, DlTileMode::kMirror);
369 }
370 TEST_P(AiksTest, CanRenderLinearGradientManyColorsDecal) {
371 CanRenderLinearGradientManyColors(this, DlTileMode::kDecal);
372 }
373
374 namespace {
375 void CanRenderLinearGradientWayManyColors(AiksTest* aiks_test,
376 DlTileMode tile_mode) {
377 DisplayListBuilder builder;
378 DlPaint paint;
379 builder.Translate(100.0, 100.0);
380 auto color = DlColor(Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}.ToARGB());
381 std::vector<DlColor> colors;
382 std::vector<Scalar> stops;
383 auto current_stop = 0.0;
384 for (int i = 0; i < 2000; i++) {
385 colors.push_back(color);
386 stops.push_back(current_stop);
387 current_stop += 1 / 2000.0;
388 }
389 stops[2000 - 1] = 1.0;
390
391 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {200, 200},
392 stops.size(), colors.data(),
393 stops.data(), tile_mode));
394
395 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
396 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
397 }
398 } // namespace
399
400 // Only test clamp on purpose since they all look the same.
401 TEST_P(AiksTest, CanRenderLinearGradientWayManyColorsClamp) {
402 CanRenderLinearGradientWayManyColors(this, DlTileMode::kClamp);
403 }
404
405 TEST_P(AiksTest, CanRenderLinearGradientManyColorsUnevenStops) {
406 auto callback = [&]() -> sk_sp<DisplayList> {
407 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
408 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
409 DlTileMode::kMirror, DlTileMode::kDecal};
410
411 static int selected_tile_mode = 0;
412 static Matrix matrix;
413 if (AiksTest::ImGuiBegin("Controls", nullptr,
414 ImGuiWindowFlags_AlwaysAutoResize)) {
415 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
416 sizeof(tile_mode_names) / sizeof(char*));
417 std::string label = "##1";
418 for (int i = 0; i < 4; i++) {
419 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
420 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
421 label[2]++;
422 }
423 ImGui::End();
424 }
425
426 DisplayListBuilder builder;
427 DlPaint paint;
428 builder.Translate(100.0, 100.0);
429 auto tile_mode = tile_modes[selected_tile_mode];
430
431 std::vector<DlColor> colors = {
432 DlColor(Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}.ToARGB()),
433 DlColor(Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}.ToARGB()),
434 DlColor(Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
435 DlColor(Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}.ToARGB()),
436 DlColor(Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}.ToARGB()),
437 DlColor(Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
438 DlColor(Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}.ToARGB())};
439 std::vector<Scalar> stops = {
440 0.0, 2.0 / 62.0, 4.0 / 62.0, 8.0 / 62.0, 16.0 / 62.0, 32.0 / 62.0, 1.0,
441 };
442
443 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {200, 200},
444 stops.size(), colors.data(),
445 stops.data(), tile_mode));
446
447 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
448 return builder.Build();
449 };
450 ASSERT_TRUE(OpenPlaygroundHere(callback));
451 }
452
453 TEST_P(AiksTest, CanRenderLinearGradientMaskBlur) {
454 DisplayListBuilder builder;
455
456 std::vector<DlColor> colors = {
457 DlColor::kRed(), DlColor::kWhite(), DlColor::kRed(), DlColor::kWhite(),
458 DlColor::kRed(), DlColor::kWhite(), DlColor::kRed(), DlColor::kWhite(),
459 DlColor::kRed(), DlColor::kWhite(), DlColor::kRed()};
460 std::vector<Scalar> stops = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5,
461 0.6, 0.7, 0.8, 0.9, 1.0};
462
463 DlPaint paint;
464 paint.setColor(DlColor::kWhite());
465 paint.setColorSource(DlColorSource::MakeLinear(
466 {200, 200}, {400, 400}, stops.size(), colors.data(), stops.data(),
467 DlTileMode::kClamp));
468 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 20));
469
470 builder.DrawCircle(DlPoint(300, 300), 200, paint);
471 builder.DrawRect(DlRect::MakeLTRB(100, 300, 500, 600), paint);
472
473 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
474 }
475
476 TEST_P(AiksTest, CanRenderRadialGradient) {
477 auto callback = [&]() -> sk_sp<DisplayList> {
478 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
479 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
480 DlTileMode::kMirror, DlTileMode::kDecal};
481
482 static int selected_tile_mode = 0;
483 static Matrix matrix;
484 if (AiksTest::ImGuiBegin("Controls", nullptr,
485 ImGuiWindowFlags_AlwaysAutoResize)) {
486 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
487 sizeof(tile_mode_names) / sizeof(char*));
488 std::string label = "##1";
489 for (int i = 0; i < 4; i++) {
490 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
491 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
492 label[2]++;
493 }
494 ImGui::End();
495 }
496
497 DisplayListBuilder builder;
498 DlPaint paint;
499 builder.Translate(100.0, 100.0);
500 auto tile_mode = tile_modes[selected_tile_mode];
501
502 std::vector<DlColor> colors = {
503 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
504 DlColor(Color{0.1294, 0.5882, 0.9529, 1.0}.ToARGB())};
505 std::vector<Scalar> stops = {0.0, 1.0};
506
507 paint.setColorSource(DlColorSource::MakeRadial(
508 {100, 100}, 100, 2, colors.data(), stops.data(), tile_mode));
509
510 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
511 return builder.Build();
512 };
513 ASSERT_TRUE(OpenPlaygroundHere(callback));
514 }
515
516 TEST_P(AiksTest, CanRenderRadialGradientManyColors) {
517 auto callback = [&]() -> sk_sp<DisplayList> {
518 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
519 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
520 DlTileMode::kMirror, DlTileMode::kDecal};
521
522 static int selected_tile_mode = 0;
523 static Matrix matrix = {
524 1, 0, 0, 0, //
525 0, 1, 0, 0, //
526 0, 0, 1, 0, //
527 0, 0, 0, 1 //
528 };
529 if (AiksTest::ImGuiBegin("Controls", nullptr,
530 ImGuiWindowFlags_AlwaysAutoResize)) {
531 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
532 sizeof(tile_mode_names) / sizeof(char*));
533 std::string label = "##1";
534 for (int i = 0; i < 4; i++) {
535 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
536 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
537 label[2]++;
538 }
539 ImGui::End();
540 }
541
542 DisplayListBuilder builder;
543 DlPaint paint;
544 builder.Translate(100.0, 100.0);
545 auto tile_mode = tile_modes[selected_tile_mode];
546
547 std::vector<DlColor> colors = {
548 DlColor(Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}.ToARGB()),
549 DlColor(Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}.ToARGB()),
550 DlColor(Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
551 DlColor(Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}.ToARGB()),
552 DlColor(Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}.ToARGB()),
553 DlColor(Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
554 DlColor(Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}.ToARGB())};
555 std::vector<Scalar> stops = {
556 0.0,
557 (1.0 / 6.0) * 1,
558 (1.0 / 6.0) * 2,
559 (1.0 / 6.0) * 3,
560 (1.0 / 6.0) * 4,
561 (1.0 / 6.0) * 5,
562 1.0,
563 };
564
565 paint.setColorSource(DlColorSource::MakeRadial(
566 {100, 100}, 100, stops.size(), colors.data(), stops.data(), tile_mode));
567
568 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
569 return builder.Build();
570 };
571 ASSERT_TRUE(OpenPlaygroundHere(callback));
572 }
573
574 namespace {
575 void CanRenderSweepGradient(AiksTest* aiks_test, DlTileMode tile_mode) {
576 DisplayListBuilder builder;
577 builder.Scale(aiks_test->GetContentScale().x, aiks_test->GetContentScale().y);
578 DlPaint paint;
579 builder.Translate(100, 100);
580
581 std::vector<DlColor> colors = {
582 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
583 DlColor(Color{0.1294, 0.5882, 0.9529, 1.0}.ToARGB())};
584 std::vector<Scalar> stops = {0.0, 1.0};
585
586 paint.setColorSource(DlColorSource::MakeSweep(
587 {100, 100}, /*start=*/45, /*end=*/135, /*stop_count=*/2, colors.data(),
588 stops.data(), tile_mode));
589
590 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
591 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
592 }
593 } // namespace
594
595 TEST_P(AiksTest, CanRenderSweepGradientClamp) {
596 CanRenderSweepGradient(this, DlTileMode::kClamp);
597 }
598 TEST_P(AiksTest, CanRenderSweepGradientRepeat) {
599 CanRenderSweepGradient(this, DlTileMode::kRepeat);
600 }
601 TEST_P(AiksTest, CanRenderSweepGradientMirror) {
602 CanRenderSweepGradient(this, DlTileMode::kMirror);
603 }
604 TEST_P(AiksTest, CanRenderSweepGradientDecal) {
605 CanRenderSweepGradient(this, DlTileMode::kDecal);
606 }
607
608 namespace {
609 void CanRenderSweepGradientManyColors(AiksTest* aiks_test,
610 DlTileMode tile_mode) {
611 DisplayListBuilder builder;
612 DlPaint paint;
613 builder.Translate(100.0, 100.0);
614
615 std::vector<DlColor> colors = {
616 DlColor(Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}.ToARGB()),
617 DlColor(Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}.ToARGB()),
618 DlColor(Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
619 DlColor(Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}.ToARGB()),
620 DlColor(Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}.ToARGB()),
621 DlColor(Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
622 DlColor(Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}.ToARGB())};
623 std::vector<Scalar> stops = {
624 0.0,
625 (1.0 / 6.0) * 1,
626 (1.0 / 6.0) * 2,
627 (1.0 / 6.0) * 3,
628 (1.0 / 6.0) * 4,
629 (1.0 / 6.0) * 5,
630 1.0,
631 };
632
633 paint.setColorSource(DlColorSource::MakeSweep({100, 100}, 45, 135,
634 stops.size(), colors.data(),
635 stops.data(), tile_mode));
636
637 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600, 600), paint);
638 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
639 }
640 } // namespace
641
642 TEST_P(AiksTest, CanRenderSweepGradientManyColorsClamp) {
643 CanRenderSweepGradientManyColors(this, DlTileMode::kClamp);
644 }
645 TEST_P(AiksTest, CanRenderSweepGradientManyColorsRepeat) {
646 CanRenderSweepGradientManyColors(this, DlTileMode::kRepeat);
647 }
648 TEST_P(AiksTest, CanRenderSweepGradientManyColorsMirror) {
649 CanRenderSweepGradientManyColors(this, DlTileMode::kMirror);
650 }
651 TEST_P(AiksTest, CanRenderSweepGradientManyColorsDecal) {
652 CanRenderSweepGradientManyColors(this, DlTileMode::kDecal);
653 }
654
655 TEST_P(AiksTest, CanRenderConicalGradient) {
656 Scalar size = 256;
657 DisplayListBuilder builder;
658 DlPaint paint;
659 paint.setColor(DlColor::kWhite());
660 builder.DrawRect(DlRect::MakeXYWH(0, 0, size * 3, size * 3), paint);
661 std::vector<DlColor> colors = {
662 DlColor(Color::MakeRGBA8(0xF4, 0x43, 0x36, 0xFF).ToARGB()),
663 DlColor(Color::MakeRGBA8(0xFF, 0xEB, 0x3B, 0xFF).ToARGB()),
664 DlColor(Color::MakeRGBA8(0x4c, 0xAF, 0x50, 0xFF).ToARGB()),
665 DlColor(Color::MakeRGBA8(0x21, 0x96, 0xF3, 0xFF).ToARGB())};
666 std::vector<Scalar> stops = {0.0, 1.f / 3.f, 2.f / 3.f, 1.0};
667 std::array<std::tuple<DlPoint, float, DlPoint, float>, 8> array{
668 std::make_tuple(DlPoint(size / 2.f, size / 2.f), 0.f,
669 DlPoint(size / 2.f, size / 2.f), size / 2.f),
670 std::make_tuple(DlPoint(size / 2.f, size / 2.f), size / 4.f,
671 DlPoint(size / 2.f, size / 2.f), size / 2.f),
672 std::make_tuple(DlPoint(size / 4.f, size / 4.f), 0.f,
673 DlPoint(size / 2.f, size / 2.f), size / 2.f),
674 std::make_tuple(DlPoint(size / 4.f, size / 4.f), size / 2.f,
675 DlPoint(size / 2.f, size / 2.f), 0),
676 std::make_tuple(DlPoint(size / 4.f, size / 4.f), size / 4.f,
677 DlPoint(size / 2.f, size / 2.f), size / 2.f),
678 std::make_tuple(DlPoint(size / 4.f, size / 4.f), size / 16.f,
679 DlPoint(size / 2.f, size / 2.f), size / 8.f),
680 std::make_tuple(DlPoint(size / 4.f, size / 4.f), size / 8.f,
681 DlPoint(size / 2.f, size / 2.f), size / 16.f),
682 std::make_tuple(DlPoint(size / 8.f, size / 8.f), size / 8.f,
683 DlPoint(size / 2.f, size / 2.f), size / 8.f),
684 };
685 for (int i = 0; i < 8; i++) {
686 builder.Save();
687 builder.Translate((i % 3) * size, i / 3 * size);
688 paint.setColorSource(DlColorSource::MakeConical(
689 /*start_center=*/std::get<2>(array[i]),
690 /*start_radius=*/std::get<3>(array[i]),
691 /*end_center=*/std::get<0>(array[i]),
692 /*end_radius=*/std::get<1>(array[i]),
693 /*stop_count=*/stops.size(),
694 /*colors=*/colors.data(),
695 /*stops=*/stops.data(),
696 /*tile_mode=*/DlTileMode::kClamp));
697 builder.DrawRect(DlRect::MakeXYWH(0, 0, size, size), paint);
698 builder.Restore();
699 }
700 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
701 }
702
703 TEST_P(AiksTest, CanRenderGradientDecalWithBackground) {
704 std::vector<DlColor> colors = {
705 DlColor(Color::MakeRGBA8(0xF4, 0x43, 0x36, 0xFF).ToARGB()),
706 DlColor(Color::MakeRGBA8(0xFF, 0xEB, 0x3B, 0xFF).ToARGB()),
707 DlColor(Color::MakeRGBA8(0x4c, 0xAF, 0x50, 0xFF).ToARGB()),
708 DlColor(Color::MakeRGBA8(0x21, 0x96, 0xF3, 0xFF).ToARGB())};
709 std::vector<Scalar> stops = {0.0, 1.f / 3.f, 2.f / 3.f, 1.0};
710
711 std::array<std::shared_ptr<DlColorSource>, 3> color_sources = {
712 DlColorSource::MakeLinear({0, 0}, {100, 100}, stops.size(), colors.data(),
713 stops.data(), DlTileMode::kDecal),
714 DlColorSource::MakeRadial({100, 100}, 100, stops.size(), colors.data(),
715 stops.data(), DlTileMode::kDecal),
716 DlColorSource::MakeSweep({100, 100}, 45, 135, stops.size(), colors.data(),
717 stops.data(), DlTileMode::kDecal),
718 };
719
720 DisplayListBuilder builder;
721 DlPaint paint;
722 paint.setColor(DlColor::kWhite());
723 builder.DrawRect(DlRect::MakeLTRB(0, 0, 605, 205), paint);
724 for (int i = 0; i < 3; i++) {
725 builder.Save();
726 builder.Translate(i * 200.0f, 0);
727 paint.setColorSource(color_sources[i]);
728 builder.DrawRect(DlRect::MakeLTRB(0, 0, 200, 200), paint);
729 builder.Restore();
730 }
731 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
732 }
733
734 TEST_P(AiksTest, GradientStrokesRenderCorrectly) {
735 // Compare with https://fiddle.skia.org/c/027392122bec8ac2b5d5de00a4b9bbe2
736 auto callback = [&]() -> sk_sp<DisplayList> {
737 static float scale = 3;
738 static bool add_circle_clip = true;
739 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
740 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
741 DlTileMode::kMirror, DlTileMode::kDecal};
742 static int selected_tile_mode = 0;
743 static float alpha = 1;
744
745 if (AiksTest::ImGuiBegin("Controls", nullptr,
746 ImGuiWindowFlags_AlwaysAutoResize)) {
747 ImGui::SliderFloat("Scale", &scale, 0, 6);
748 ImGui::Checkbox("Circle clip", &add_circle_clip);
749 ImGui::SliderFloat("Alpha", &alpha, 0, 1);
750 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
751 sizeof(tile_mode_names) / sizeof(char*));
752 ImGui::End();
753 }
754
755 DisplayListBuilder builder;
756 builder.Scale(GetContentScale().x, GetContentScale().y);
757 DlPaint paint;
758 paint.setColor(DlColor::kWhite());
759 builder.DrawPaint(paint);
760
761 paint.setDrawStyle(DlDrawStyle::kStroke);
762 paint.setColor(DlColor::kWhite().withAlpha(alpha * 255));
763 paint.setStrokeWidth(10);
764 auto tile_mode = tile_modes[selected_tile_mode];
765
766 std::vector<DlColor> colors = {
767 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
768 DlColor(Color{0.1294, 0.5882, 0.9529, 1.0}.ToARGB())};
769 std::vector<Scalar> stops = {0.0, 1.0};
770
771 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {50, 50},
772 stops.size(), colors.data(),
773 stops.data(), tile_mode));
774
775 DlPathBuilder path_builder;
776 path_builder.MoveTo(DlPoint(20, 20));
777 path_builder.QuadraticCurveTo(DlPoint(60, 20), DlPoint(60, 60));
778 path_builder.Close();
779 path_builder.MoveTo(DlPoint(60, 20));
780 path_builder.QuadraticCurveTo(DlPoint(60, 60), DlPoint(20, 60));
781 DlPath path = path_builder.TakePath();
782
783 builder.Scale(scale, scale);
784
785 if (add_circle_clip) {
786 static PlaygroundPoint circle_clip_point_a(Point(60, 300), 20,
787 Color::Red());
788 static PlaygroundPoint circle_clip_point_b(Point(600, 300), 20,
789 Color::Red());
790 auto [handle_a, handle_b] =
791 DrawPlaygroundLine(circle_clip_point_a, circle_clip_point_b);
792
793 Matrix ip_matrix = builder.GetMatrix();
794 if (!ip_matrix.IsInvertible()) {
795 return nullptr;
796 }
797 ip_matrix = ip_matrix.Invert();
798 Point point_a = ip_matrix * handle_a * GetContentScale();
799 Point point_b = ip_matrix * handle_b * GetContentScale();
800
801 Point middle = (point_a + point_b) / 2;
802 auto radius = point_a.GetDistance(middle);
803 builder.ClipPath(DlPath::MakeCircle(middle, radius));
804 }
805
806 for (auto join :
807 {DlStrokeJoin::kBevel, DlStrokeJoin::kRound, DlStrokeJoin::kMiter}) {
808 paint.setStrokeJoin(join);
809 for (auto cap :
810 {DlStrokeCap::kButt, DlStrokeCap::kSquare, DlStrokeCap::kRound}) {
811 paint.setStrokeCap(cap);
812 builder.DrawPath(path, paint);
813 builder.Translate(80, 0);
814 }
815 builder.Translate(-240, 60);
816 }
817
818 return builder.Build();
819 };
820
821 ASSERT_TRUE(OpenPlaygroundHere(callback));
822 }
823
824 // Draws two gradients that should look identical (except that one is an RRECT).
825 TEST_P(AiksTest, FastGradientTestHorizontal) {
826 DisplayListBuilder builder;
827 DlPaint paint;
828 builder.Translate(100.0f, 0);
829
830 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
831 DlColor::kGreen()};
832 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
833
834 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {300, 0}, stops.size(),
835 colors.data(), stops.data(),
836 DlTileMode::kClamp));
837
838 paint.setColor(DlColor::kWhite());
839 builder.DrawRect(DlRect::MakeXYWH(0, 0, 300, 300), paint);
840 builder.Translate(400, 0);
841 builder.DrawRoundRect(
842 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(0, 0, 300, 300), 4, 4), paint);
843
844 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
845 }
846
847 // Draws two gradients that should look identical (except that one is an RRECT).
848 TEST_P(AiksTest, FastGradientTestVertical) {
849 DisplayListBuilder builder;
850 DlPaint paint;
851 builder.Translate(100.0f, 0);
852
853 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
854 DlColor::kGreen()};
855 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
856
857 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {0, 300}, stops.size(),
858 colors.data(), stops.data(),
859 DlTileMode::kClamp));
860
861 paint.setColor(DlColor::kWhite());
862 builder.DrawRect(DlRect::MakeXYWH(0, 0, 300, 300), paint);
863 builder.Translate(400, 0);
864 builder.DrawRoundRect(
865 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(0, 0, 300, 300), 4, 4), paint);
866
867 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
868 }
869
870 // Draws two gradients that should look identical (except that one is an RRECT).
871 TEST_P(AiksTest, FastGradientTestHorizontalReversed) {
872 DisplayListBuilder builder;
873 DlPaint paint;
874 builder.Translate(100.0f, 0);
875
876 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
877 DlColor::kGreen()};
878 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
879
880 paint.setColorSource(DlColorSource::MakeLinear({300, 0}, {0, 0}, stops.size(),
881 colors.data(), stops.data(),
882 DlTileMode::kClamp));
883
884 paint.setColor(DlColor::kWhite());
885 builder.DrawRect(DlRect::MakeXYWH(0, 0, 300, 300), paint);
886 builder.Translate(400, 0);
887 builder.DrawRoundRect(
888 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(0, 0, 300, 300), 4, 4), paint);
889
890 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
891 }
892
893 // Draws two gradients that should look identical (except that one is an RRECT).
894 TEST_P(AiksTest, FastGradientTestVerticalReversed) {
895 DisplayListBuilder builder;
896 DlPaint paint;
897 builder.Translate(100.0f, 0);
898
899 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
900 DlColor::kGreen()};
901 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
902
903 paint.setColorSource(DlColorSource::MakeLinear({0, 300}, {0, 0}, stops.size(),
904 colors.data(), stops.data(),
905 DlTileMode::kClamp));
906
907 paint.setColor(DlColor::kWhite());
908 builder.DrawRect(DlRect::MakeXYWH(0, 0, 300, 300), paint);
909 builder.Translate(400, 0);
910 builder.DrawRoundRect(
911 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(0, 0, 300, 300), 4, 4), paint);
912
913 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
914 }
915
916 TEST_P(AiksTest, VerifyNonOptimizedGradient) {
917 DisplayListBuilder builder;
918 DlPaint paint;
919 builder.Translate(100.0f, 0);
920
921 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
922 DlColor::kGreen()};
923 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
924
925 // Inset the start and end point to verify that we do not apply
926 // the fast gradient condition.
927 paint.setColorSource(
928 DlColorSource::MakeLinear({0, 150}, {0, 100}, stops.size(), colors.data(),
929 stops.data(), DlTileMode::kRepeat));
930
931 paint.setColor(DlColor::kWhite());
932 builder.DrawRect(DlRect::MakeXYWH(0, 0, 300, 300), paint);
933 builder.Translate(400, 0);
934 builder.DrawRoundRect(
935 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(0, 0, 300, 300), 4, 4), paint);
936
937 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
938 }
939
940 } // namespace testing
941 } // namespace impeller
aiks_unittests.h
type
GLenum type
Definition: blit_command_gles.cc:153
impeller::AiksPlayground
Definition: aiks_playground.h:16
impeller::AiksPlayground::OpenPlaygroundHere
bool OpenPlaygroundHere(const AiksDlPlaygroundCallback &callback)
Definition: aiks_playground.cc:42
impeller::Playground::GetContentScale
Point GetContentScale() const
Definition: playground.cc:189
x
int32_t x
Definition: dl_golden_unittests.cc:458
flutter
Definition: dl_golden_blur_unittests.cc:16
impeller::testing::AiksTest
AiksPlayground AiksTest
Definition: aiks_unittests.h:17
impeller::testing::CanRenderLinearGradientWithDithering
static void CanRenderLinearGradientWithDithering(AiksTest *aiks_test)
Definition: aiks_dl_gradient_unittests.cc:92
impeller::testing::CanRenderRadialGradientWithDithering
static void CanRenderRadialGradientWithDithering(AiksTest *aiks_test)
Definition: aiks_dl_gradient_unittests.cc:112
impeller::testing::CanRenderConicalGradientWithDithering
static void CanRenderConicalGradientWithDithering(AiksTest *aiks_test)
Definition: aiks_dl_gradient_unittests.cc:155
impeller::testing::CanRenderSweepGradientWithDithering
static void CanRenderSweepGradientWithDithering(AiksTest *aiks_test)
Definition: aiks_dl_gradient_unittests.cc:132
impeller::testing::TEST_P
TEST_P(AiksTest, VerifyNonOptimizedGradient)
Definition: aiks_dl_gradient_unittests.cc:916
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::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
impeller::Color
Definition: color.h:124
impeller::Color::ToARGB
uint32_t ToARGB() const
Convert to ARGB 32 bit color.
Definition: color.h:259
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::vec
Vector4 vec[4]
Definition: matrix.h:41
impeller::PlaygroundPoint
Definition: widgets.h:21
impeller::TPoint< Scalar >
impeller::TPoint::GetDistance
constexpr Type GetDistance(const TPoint &p) const
Definition: point.h:200
impeller::TPoint::y
Type y
Definition: point.h:31
impeller::TPoint::x
Type x
Definition: point.h:30
widgets.h