Flutter Engine
The Flutter Engine
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
11#include "flutter/impeller/aiks/aiks_unittests.h"
12
13#include "flutter/display_list/dl_builder.h"
14#include "flutter/display_list/dl_color.h"
15#include "flutter/display_list/dl_paint.h"
16#include "flutter/testing/testing.h"
18#include "include/core/SkPath.h"
20#include "include/core/SkRect.h"
21
22using namespace flutter;
23////////////////////////////////////////////////////////////////////////////////
24// This is for tests of Canvas that are interested the results of rendering
25// gradients.
26////////////////////////////////////////////////////////////////////////////////
27
28namespace impeller {
29namespace testing {
30
31namespace {
32
33/// Test body for linear gradient tile mode tests (ex.
34/// CanRenderLinearGradientClamp).
35void CanRenderLinearGradient(AiksTest* aiks_test, DlTileMode tile_mode) {
37 Point scale = aiks_test->GetContentScale();
38 builder.Scale(scale.x, scale.y);
40 builder.Translate(100.0f, 0);
41
42 std::vector<DlColor> colors = {
43 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
44 DlColor(Color{0.1294, 0.5882, 0.9529, 0.0}.ToARGB())};
45 std::vector<Scalar> stops = {0.0, 1.0};
46
47 auto gradient = DlColorSource::MakeLinear(
48 {0, 0}, {200, 200}, 2, colors.data(), stops.data(), tile_mode);
49 paint.setColorSource(gradient);
50 paint.setColor(DlColor::kWhite());
51 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600, 600), paint);
52 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
53}
54
55Matrix ToMatrix(const SkMatrix& m) {
56 return Matrix{
57 // clang-format off
58 m[0], m[3], 0, m[6],
59 m[1], m[4], 0, m[7],
60 0, 0, 1, 0,
61 m[2], m[5], 0, m[8],
62 // clang-format on
63 };
64}
65} // namespace
66
67TEST_P(AiksTest, CanRenderLinearGradientClamp) {
68 CanRenderLinearGradient(this, DlTileMode::kClamp);
69}
70TEST_P(AiksTest, CanRenderLinearGradientRepeat) {
71 CanRenderLinearGradient(this, DlTileMode::kRepeat);
72}
73TEST_P(AiksTest, CanRenderLinearGradientMirror) {
74 CanRenderLinearGradient(this, DlTileMode::kMirror);
75}
76TEST_P(AiksTest, CanRenderLinearGradientDecal) {
77 CanRenderLinearGradient(this, DlTileMode::kDecal);
78}
79
80TEST_P(AiksTest, CanRenderLinearGradientDecalWithColorFilter) {
82 Point scale = GetContentScale();
83 builder.Scale(scale.x, scale.y);
85 builder.Translate(100.0f, 0);
86
87 std::vector<DlColor> colors = {
88 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
89 DlColor(Color{0.1294, 0.5882, 0.9529, 0.0}.ToARGB())};
90 std::vector<Scalar> stops = {0.0, 1.0};
91
92 paint.setColorSource(DlColorSource::MakeLinear(
93 {0, 0}, {200, 200}, 2, colors.data(), stops.data(), DlTileMode::kDecal));
94 // Overlay the gradient with 25% green. This should appear as the entire
95 // rectangle being drawn with 25% green, including the border area outside the
96 // decal gradient.
97 paint.setColorFilter(DlBlendColorFilter::Make(DlColor::kGreen().withAlpha(64),
98 DlBlendMode::kSrcOver));
99 paint.setColor(DlColor::kWhite());
100 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600, 600), paint);
101 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
102}
103
107 builder.Translate(100.0, 100.0);
108
109 // 0xffcccccc --> 0xff333333, taken from
110 // https://github.com/flutter/flutter/issues/118073#issue-1521699748
111 std::vector<DlColor> colors = {DlColor(0xFFCCCCCC), DlColor(0xFF333333)};
112 std::vector<Scalar> stops = {0.0, 1.0};
113
114 paint.setColorSource(DlColorSource::MakeLinear(
115 {0, 0}, {800, 500}, 2, colors.data(), stops.data(), DlTileMode::kClamp));
116 builder.DrawRect(SkRect::MakeXYWH(0, 0, 800, 500), paint);
117 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
118}
119
120TEST_P(AiksTest, CanRenderLinearGradientWithDitheringEnabled) {
122}
123
127 builder.Translate(100.0, 100.0);
128
129 // #FFF -> #000
130 std::vector<DlColor> colors = {DlColor(Color{1.0, 1.0, 1.0, 1.0}.ToARGB()),
131 DlColor(Color{0.0, 0.0, 0.0, 1.0}.ToARGB())};
132 std::vector<Scalar> stops = {0.0, 1.0};
133
134 paint.setColorSource(DlColorSource::MakeRadial(
135 {600, 600}, 600, 2, colors.data(), stops.data(), DlTileMode::kClamp));
136 builder.DrawRect(SkRect::MakeXYWH(0, 0, 1200, 1200), paint);
137 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
138}
139
140TEST_P(AiksTest, CanRenderRadialGradientWithDitheringEnabled) {
142}
143
146 builder.Scale(aiks_test->GetContentScale().x, aiks_test->GetContentScale().y);
148 builder.Translate(100.0, 100.0);
149
150 // #FFF -> #000
151 std::vector<DlColor> colors = {DlColor(Color{1.0, 1.0, 1.0, 1.0}.ToARGB()),
152 DlColor(Color{0.0, 0.0, 0.0, 1.0}.ToARGB())};
153 std::vector<Scalar> stops = {0.0, 1.0};
154
155 paint.setColorSource(DlColorSource::MakeSweep(
156 {100, 100}, /*start=*/45, /*end=*/135, 2, colors.data(), stops.data(),
158
159 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600, 600), paint);
160 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
161}
162
163TEST_P(AiksTest, CanRenderSweepGradientWithDitheringEnabled) {
165}
166
169 builder.Scale(aiks_test->GetContentScale().x, aiks_test->GetContentScale().y);
171 builder.Translate(100.0, 100.0);
172
173 // #FFF -> #000
174 std::vector<DlColor> colors = {DlColor(Color{1.0, 1.0, 1.0, 1.0}.ToARGB()),
175 DlColor(Color{0.0, 0.0, 0.0, 1.0}.ToARGB())};
176 std::vector<Scalar> stops = {0.0, 1.0};
177
178 paint.setColorSource(DlColorSource::MakeConical({0, 1}, 0, {100, 100}, 100, 2,
179 colors.data(), stops.data(),
181
182 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600, 600), paint);
183 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
184}
185
186TEST_P(AiksTest, CanRenderConicalGradientWithDitheringEnabled) {
188}
189
190namespace {
191void CanRenderLinearGradientWithOverlappingStops(AiksTest* aiks_test,
192 DlTileMode tile_mode) {
195 builder.Translate(100.0, 100.0);
196
197 std::vector<DlColor> colors = {
198 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
199 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
200 DlColor(Color{0.1294, 0.5882, 0.9529, 1.0}.ToARGB()),
201 DlColor(Color{0.1294, 0.5882, 0.9529, 1.0}.ToARGB())};
202 std::vector<Scalar> stops = {0.0, 0.5, 0.5, 1.0};
203
204 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {500, 500},
205 stops.size(), colors.data(),
206 stops.data(), tile_mode));
207
208 paint.setColor(DlColor::kWhite());
209 builder.DrawRect(SkRect::MakeXYWH(0, 0, 500, 500), paint);
210 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
211}
212} // namespace
213
214// Only clamp is necessary. All tile modes are the same output.
215TEST_P(AiksTest, CanRenderLinearGradientWithOverlappingStopsClamp) {
216 CanRenderLinearGradientWithOverlappingStops(this, DlTileMode::kClamp);
217}
218
219namespace {
220void CanRenderLinearGradientManyColors(AiksTest* aiks_test,
221 DlTileMode tile_mode) {
223 builder.Scale(aiks_test->GetContentScale().x, aiks_test->GetContentScale().y);
225 builder.Translate(100, 100);
226
227 std::vector<DlColor> colors = {
228 DlColor(Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}.ToARGB()),
229 DlColor(Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}.ToARGB()),
230 DlColor(Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
231 DlColor(Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}.ToARGB()),
232 DlColor(Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}.ToARGB()),
233 DlColor(Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
234 DlColor(Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}.ToARGB())};
235 std::vector<Scalar> stops = {
236 0.0,
237 (1.0 / 6.0) * 1,
238 (1.0 / 6.0) * 2,
239 (1.0 / 6.0) * 3,
240 (1.0 / 6.0) * 4,
241 (1.0 / 6.0) * 5,
242 1.0,
243 };
244
245 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {200, 200},
246 stops.size(), colors.data(),
247 stops.data(), tile_mode));
248
249 paint.setColor(DlColor::kWhite());
250 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600, 600), paint);
251 builder.Restore();
252 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
253}
254} // namespace
255
256TEST_P(AiksTest, CanRenderLinearGradientManyColorsClamp) {
257 CanRenderLinearGradientManyColors(this, DlTileMode::kClamp);
258}
259TEST_P(AiksTest, CanRenderLinearGradientManyColorsRepeat) {
260 CanRenderLinearGradientManyColors(this, DlTileMode::kRepeat);
261}
262TEST_P(AiksTest, CanRenderLinearGradientManyColorsMirror) {
263 CanRenderLinearGradientManyColors(this, DlTileMode::kMirror);
264}
265TEST_P(AiksTest, CanRenderLinearGradientManyColorsDecal) {
266 CanRenderLinearGradientManyColors(this, DlTileMode::kDecal);
267}
268
269namespace {
270void CanRenderLinearGradientWayManyColors(AiksTest* aiks_test,
271 DlTileMode tile_mode) {
274 builder.Translate(100.0, 100.0);
275 auto color = DlColor(Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}.ToARGB());
276 std::vector<DlColor> colors;
277 std::vector<Scalar> stops;
278 auto current_stop = 0.0;
279 for (int i = 0; i < 2000; i++) {
280 colors.push_back(color);
281 stops.push_back(current_stop);
282 current_stop += 1 / 2000.0;
283 }
284 stops[2000 - 1] = 1.0;
285
286 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {200, 200},
287 stops.size(), colors.data(),
288 stops.data(), tile_mode));
289
290 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600, 600), paint);
291 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
292}
293} // namespace
294
295// Only test clamp on purpose since they all look the same.
296TEST_P(AiksTest, CanRenderLinearGradientWayManyColorsClamp) {
297 CanRenderLinearGradientWayManyColors(this, DlTileMode::kClamp);
298}
299
300TEST_P(AiksTest, CanRenderLinearGradientManyColorsUnevenStops) {
301 auto callback = [&]() -> sk_sp<DisplayList> {
302 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
305
306 static int selected_tile_mode = 0;
307 static Matrix matrix;
308 if (AiksTest::ImGuiBegin("Controls", nullptr,
309 ImGuiWindowFlags_AlwaysAutoResize)) {
310 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
311 sizeof(tile_mode_names) / sizeof(char*));
312 std::string label = "##1";
313 for (int i = 0; i < 4; i++) {
314 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
315 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
316 label[2]++;
317 }
318 ImGui::End();
319 }
320
323 builder.Translate(100.0, 100.0);
324 auto tile_mode = tile_modes[selected_tile_mode];
325
326 std::vector<DlColor> colors = {
327 DlColor(Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}.ToARGB()),
328 DlColor(Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}.ToARGB()),
329 DlColor(Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
330 DlColor(Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}.ToARGB()),
331 DlColor(Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}.ToARGB()),
332 DlColor(Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
333 DlColor(Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}.ToARGB())};
334 std::vector<Scalar> stops = {
335 0.0, 2.0 / 62.0, 4.0 / 62.0, 8.0 / 62.0, 16.0 / 62.0, 32.0 / 62.0, 1.0,
336 };
337
338 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {200, 200},
339 stops.size(), colors.data(),
340 stops.data(), tile_mode));
341
342 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600, 600), paint);
343 return builder.Build();
344 };
345 ASSERT_TRUE(OpenPlaygroundHere(callback));
346}
347
348TEST_P(AiksTest, CanRenderLinearGradientMaskBlur) {
350
351 std::vector<DlColor> colors = {
355 std::vector<Scalar> stops = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5,
356 0.6, 0.7, 0.8, 0.9, 1.0};
357
359 paint.setColor(DlColor::kWhite());
360 paint.setColorSource(DlColorSource::MakeLinear(
361 {200, 200}, {400, 400}, stops.size(), colors.data(), stops.data(),
364
365 builder.DrawCircle({300, 300}, 200, paint);
366 builder.DrawRect(SkRect::MakeLTRB(100, 300, 500, 600), paint);
367
368 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
369}
370
371TEST_P(AiksTest, CanRenderRadialGradient) {
372 auto callback = [&]() -> sk_sp<DisplayList> {
373 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
376
377 static int selected_tile_mode = 0;
378 static Matrix matrix;
379 if (AiksTest::ImGuiBegin("Controls", nullptr,
380 ImGuiWindowFlags_AlwaysAutoResize)) {
381 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
382 sizeof(tile_mode_names) / sizeof(char*));
383 std::string label = "##1";
384 for (int i = 0; i < 4; i++) {
385 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
386 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
387 label[2]++;
388 }
389 ImGui::End();
390 }
391
394 builder.Translate(100.0, 100.0);
395 auto tile_mode = tile_modes[selected_tile_mode];
396
397 std::vector<DlColor> colors = {
398 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
399 DlColor(Color{0.1294, 0.5882, 0.9529, 1.0}.ToARGB())};
400 std::vector<Scalar> stops = {0.0, 1.0};
401
402 paint.setColorSource(DlColorSource::MakeRadial(
403 {100, 100}, 100, 2, colors.data(), stops.data(), tile_mode));
404
405 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600, 600), paint);
406 return builder.Build();
407 };
408 ASSERT_TRUE(OpenPlaygroundHere(callback));
409}
410
411TEST_P(AiksTest, CanRenderRadialGradientManyColors) {
412 auto callback = [&]() -> sk_sp<DisplayList> {
413 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
416
417 static int selected_tile_mode = 0;
418 static Matrix matrix = {
419 1, 0, 0, 0, //
420 0, 1, 0, 0, //
421 0, 0, 1, 0, //
422 0, 0, 0, 1 //
423 };
424 if (AiksTest::ImGuiBegin("Controls", nullptr,
425 ImGuiWindowFlags_AlwaysAutoResize)) {
426 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
427 sizeof(tile_mode_names) / sizeof(char*));
428 std::string label = "##1";
429 for (int i = 0; i < 4; i++) {
430 ImGui::InputScalarN(label.c_str(), ImGuiDataType_Float,
431 &(matrix.vec[i]), 4, NULL, NULL, "%.2f", 0);
432 label[2]++;
433 }
434 ImGui::End();
435 }
436
439 builder.Translate(100.0, 100.0);
440 auto tile_mode = tile_modes[selected_tile_mode];
441
442 std::vector<DlColor> colors = {
443 DlColor(Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}.ToARGB()),
444 DlColor(Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}.ToARGB()),
445 DlColor(Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
446 DlColor(Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}.ToARGB()),
447 DlColor(Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}.ToARGB()),
448 DlColor(Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
449 DlColor(Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}.ToARGB())};
450 std::vector<Scalar> stops = {
451 0.0,
452 (1.0 / 6.0) * 1,
453 (1.0 / 6.0) * 2,
454 (1.0 / 6.0) * 3,
455 (1.0 / 6.0) * 4,
456 (1.0 / 6.0) * 5,
457 1.0,
458 };
459
460 paint.setColorSource(DlColorSource::MakeRadial(
461 {100, 100}, 100, stops.size(), colors.data(), stops.data(), tile_mode));
462
463 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600, 600), paint);
464 return builder.Build();
465 };
466 ASSERT_TRUE(OpenPlaygroundHere(callback));
467}
468
469namespace {
470void CanRenderSweepGradient(AiksTest* aiks_test, DlTileMode tile_mode) {
472 builder.Scale(aiks_test->GetContentScale().x, aiks_test->GetContentScale().y);
474 builder.Translate(100, 100);
475
476 std::vector<DlColor> colors = {
477 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
478 DlColor(Color{0.1294, 0.5882, 0.9529, 1.0}.ToARGB())};
479 std::vector<Scalar> stops = {0.0, 1.0};
480
481 paint.setColorSource(DlColorSource::MakeSweep(
482 {100, 100}, /*start=*/45, /*end=*/135, /*stop_count=*/2, colors.data(),
483 stops.data(), tile_mode));
484
485 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600, 600), paint);
486 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
487}
488} // namespace
489
490TEST_P(AiksTest, CanRenderSweepGradientClamp) {
491 CanRenderSweepGradient(this, DlTileMode::kClamp);
492}
493TEST_P(AiksTest, CanRenderSweepGradientRepeat) {
494 CanRenderSweepGradient(this, DlTileMode::kRepeat);
495}
496TEST_P(AiksTest, CanRenderSweepGradientMirror) {
497 CanRenderSweepGradient(this, DlTileMode::kMirror);
498}
499TEST_P(AiksTest, CanRenderSweepGradientDecal) {
500 CanRenderSweepGradient(this, DlTileMode::kDecal);
501}
502
503namespace {
504void CanRenderSweepGradientManyColors(AiksTest* aiks_test,
505 DlTileMode tile_mode) {
508 builder.Translate(100.0, 100.0);
509
510 std::vector<DlColor> colors = {
511 DlColor(Color{0x1f / 255.0, 0.0, 0x5c / 255.0, 1.0}.ToARGB()),
512 DlColor(Color{0x5b / 255.0, 0.0, 0x60 / 255.0, 1.0}.ToARGB()),
513 DlColor(Color{0x87 / 255.0, 0x01 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
514 DlColor(Color{0xac / 255.0, 0x25 / 255.0, 0x53 / 255.0, 1.0}.ToARGB()),
515 DlColor(Color{0xe1 / 255.0, 0x6b / 255.0, 0x5c / 255.0, 1.0}.ToARGB()),
516 DlColor(Color{0xf3 / 255.0, 0x90 / 255.0, 0x60 / 255.0, 1.0}.ToARGB()),
517 DlColor(Color{0xff / 255.0, 0xb5 / 255.0, 0x6b / 250.0, 1.0}.ToARGB())};
518 std::vector<Scalar> stops = {
519 0.0,
520 (1.0 / 6.0) * 1,
521 (1.0 / 6.0) * 2,
522 (1.0 / 6.0) * 3,
523 (1.0 / 6.0) * 4,
524 (1.0 / 6.0) * 5,
525 1.0,
526 };
527
528 paint.setColorSource(DlColorSource::MakeSweep({100, 100}, 45, 135,
529 stops.size(), colors.data(),
530 stops.data(), tile_mode));
531
532 builder.DrawRect(SkRect::MakeXYWH(0, 0, 600, 600), paint);
533 ASSERT_TRUE(aiks_test->OpenPlaygroundHere(builder.Build()));
534}
535} // namespace
536
537TEST_P(AiksTest, CanRenderSweepGradientManyColorsClamp) {
538 CanRenderSweepGradientManyColors(this, DlTileMode::kClamp);
539}
540TEST_P(AiksTest, CanRenderSweepGradientManyColorsRepeat) {
541 CanRenderSweepGradientManyColors(this, DlTileMode::kRepeat);
542}
543TEST_P(AiksTest, CanRenderSweepGradientManyColorsMirror) {
544 CanRenderSweepGradientManyColors(this, DlTileMode::kMirror);
545}
546TEST_P(AiksTest, CanRenderSweepGradientManyColorsDecal) {
547 CanRenderSweepGradientManyColors(this, DlTileMode::kDecal);
548}
549
550TEST_P(AiksTest, CanRenderConicalGradient) {
551 Scalar size = 256;
554 paint.setColor(DlColor::kWhite());
555 builder.DrawRect(SkRect::MakeXYWH(0, 0, size * 3, size * 3), paint);
556 std::vector<DlColor> colors = {
557 DlColor(Color::MakeRGBA8(0xF4, 0x43, 0x36, 0xFF).ToARGB()),
558 DlColor(Color::MakeRGBA8(0xFF, 0xEB, 0x3B, 0xFF).ToARGB()),
559 DlColor(Color::MakeRGBA8(0x4c, 0xAF, 0x50, 0xFF).ToARGB()),
560 DlColor(Color::MakeRGBA8(0x21, 0x96, 0xF3, 0xFF).ToARGB())};
561 std::vector<Scalar> stops = {0.0, 1.f / 3.f, 2.f / 3.f, 1.0};
562 std::array<std::tuple<SkPoint, float, SkPoint, float>, 8> array{
563 std::make_tuple(SkPoint::Make(size / 2.f, size / 2.f), 0.f,
564 SkPoint::Make(size / 2.f, size / 2.f), size / 2.f),
565 std::make_tuple(SkPoint::Make(size / 2.f, size / 2.f), size / 4.f,
566 SkPoint::Make(size / 2.f, size / 2.f), size / 2.f),
567 std::make_tuple(SkPoint::Make(size / 4.f, size / 4.f), 0.f,
568 SkPoint::Make(size / 2.f, size / 2.f), size / 2.f),
569 std::make_tuple(SkPoint::Make(size / 4.f, size / 4.f), size / 2.f,
570 SkPoint::Make(size / 2.f, size / 2.f), 0),
571 std::make_tuple(SkPoint::Make(size / 4.f, size / 4.f), size / 4.f,
572 SkPoint::Make(size / 2.f, size / 2.f), size / 2.f),
573 std::make_tuple(SkPoint::Make(size / 4.f, size / 4.f), size / 16.f,
574 SkPoint::Make(size / 2.f, size / 2.f), size / 8.f),
575 std::make_tuple(SkPoint::Make(size / 4.f, size / 4.f), size / 8.f,
576 SkPoint::Make(size / 2.f, size / 2.f), size / 16.f),
577 std::make_tuple(SkPoint::Make(size / 8.f, size / 8.f), size / 8.f,
578 SkPoint::Make(size / 2.f, size / 2.f), size / 8.f),
579 };
580 for (int i = 0; i < 8; i++) {
581 builder.Save();
582 builder.Translate((i % 3) * size, i / 3 * size);
583 paint.setColorSource(DlColorSource::MakeConical(
584 std::get<2>(array[i]), std::get<3>(array[i]), std::get<0>(array[i]),
585 std::get<1>(array[i]), stops.size(), colors.data(), stops.data(),
587 builder.DrawRect(SkRect::MakeXYWH(0, 0, size, size), paint);
588 builder.Restore();
589 }
590 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
591}
592
593TEST_P(AiksTest, CanRenderGradientDecalWithBackground) {
594 std::vector<DlColor> colors = {
595 DlColor(Color::MakeRGBA8(0xF4, 0x43, 0x36, 0xFF).ToARGB()),
596 DlColor(Color::MakeRGBA8(0xFF, 0xEB, 0x3B, 0xFF).ToARGB()),
597 DlColor(Color::MakeRGBA8(0x4c, 0xAF, 0x50, 0xFF).ToARGB()),
598 DlColor(Color::MakeRGBA8(0x21, 0x96, 0xF3, 0xFF).ToARGB())};
599 std::vector<Scalar> stops = {0.0, 1.f / 3.f, 2.f / 3.f, 1.0};
600
601 std::array<std::shared_ptr<DlColorSource>, 3> color_sources = {
602 DlColorSource::MakeLinear({0, 0}, {100, 100}, stops.size(), colors.data(),
603 stops.data(), DlTileMode::kDecal),
604 DlColorSource::MakeRadial({100, 100}, 100, stops.size(), colors.data(),
605 stops.data(), DlTileMode::kDecal),
606 DlColorSource::MakeSweep({100, 100}, 45, 135, stops.size(), colors.data(),
607 stops.data(), DlTileMode::kDecal),
608 };
609
612 paint.setColor(DlColor::kWhite());
613 builder.DrawRect(SkRect::MakeLTRB(0, 0, 605, 205), paint);
614 for (int i = 0; i < 3; i++) {
615 builder.Save();
616 builder.Translate(i * 200.0f, 0);
617 paint.setColorSource(color_sources[i]);
618 builder.DrawRect(SkRect::MakeLTRB(0, 0, 200, 200), paint);
619 builder.Restore();
620 }
621 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
622}
623
624TEST_P(AiksTest, GradientStrokesRenderCorrectly) {
625 // Compare with https://fiddle.skia.org/c/027392122bec8ac2b5d5de00a4b9bbe2
626 auto callback = [&]() -> sk_sp<DisplayList> {
627 static float scale = 3;
628 static bool add_circle_clip = true;
629 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
632 static int selected_tile_mode = 0;
633 static float alpha = 1;
634
635 if (AiksTest::ImGuiBegin("Controls", nullptr,
636 ImGuiWindowFlags_AlwaysAutoResize)) {
637 ImGui::SliderFloat("Scale", &scale, 0, 6);
638 ImGui::Checkbox("Circle clip", &add_circle_clip);
639 ImGui::SliderFloat("Alpha", &alpha, 0, 1);
640 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
641 sizeof(tile_mode_names) / sizeof(char*));
642 ImGui::End();
643 }
644
646 builder.Scale(GetContentScale().x, GetContentScale().y);
648 paint.setColor(DlColor::kWhite());
649 builder.DrawPaint(paint);
650
651 paint.setDrawStyle(DlDrawStyle::kStroke);
652 paint.setColor(DlColor::kWhite().withAlpha(alpha * 255));
653 paint.setStrokeWidth(10);
654 auto tile_mode = tile_modes[selected_tile_mode];
655
656 std::vector<DlColor> colors = {
657 DlColor(Color{0.9568, 0.2627, 0.2118, 1.0}.ToARGB()),
658 DlColor(Color{0.1294, 0.5882, 0.9529, 1.0}.ToARGB())};
659 std::vector<Scalar> stops = {0.0, 1.0};
660
661 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {50, 50},
662 stops.size(), colors.data(),
663 stops.data(), tile_mode));
664
665 SkPath path;
666 path.moveTo(20, 20);
667 path.quadTo({60, 20}, {60, 60});
668 path.close();
669 path.moveTo(60, 20);
670 path.quadTo({60, 60}, {20, 60});
671
672 builder.Scale(scale, scale);
673
674 if (add_circle_clip) {
675 static PlaygroundPoint circle_clip_point_a(Point(60, 300), 20,
676 Color::Red());
677 static PlaygroundPoint circle_clip_point_b(Point(600, 300), 20,
678 Color::Red());
679 auto [handle_a, handle_b] =
680 DrawPlaygroundLine(circle_clip_point_a, circle_clip_point_b);
681
682 SkMatrix screen_to_canvas;
683 if (!builder.GetTransform().invert(&screen_to_canvas)) {
684 return nullptr;
685 }
686 Matrix ip_matrix = ToMatrix(screen_to_canvas);
687 Point point_a = ip_matrix * handle_a * GetContentScale();
688 Point point_b = ip_matrix * handle_b * GetContentScale();
689
690 Point middle = (point_a + point_b) / 2;
691 auto radius = point_a.GetDistance(middle);
692 SkPath circle;
693 circle.addCircle(middle.x, middle.y, radius);
694 builder.ClipPath(circle);
695 }
696
697 for (auto join :
699 paint.setStrokeJoin(join);
700 for (auto cap :
701 {DlStrokeCap::kButt, DlStrokeCap::kSquare, DlStrokeCap::kRound}) {
702 paint.setStrokeCap(cap);
703 builder.DrawPath(path, paint);
704 builder.Translate(80, 0);
705 }
706 builder.Translate(-240, 60);
707 }
708
709 return builder.Build();
710 };
711
712 ASSERT_TRUE(OpenPlaygroundHere(callback));
713}
714
715// Draws two gradients that should look identical (except that one is an RRECT).
716TEST_P(AiksTest, FastGradientTestHorizontal) {
719 builder.Translate(100.0f, 0);
720
721 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
723 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
724
725 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {300, 0}, stops.size(),
726 colors.data(), stops.data(),
728
729 paint.setColor(DlColor::kWhite());
730 builder.DrawRect(SkRect::MakeXYWH(0, 0, 300, 300), paint);
731 builder.Translate(400, 0);
732 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(0, 0, 300, 300), 4, 4),
733 paint);
734
735 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
736}
737
738// Draws two gradients that should look identical (except that one is an RRECT).
739TEST_P(AiksTest, FastGradientTestVertical) {
742 builder.Translate(100.0f, 0);
743
744 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
746 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
747
748 paint.setColorSource(DlColorSource::MakeLinear({0, 0}, {0, 300}, stops.size(),
749 colors.data(), stops.data(),
751
752 paint.setColor(DlColor::kWhite());
753 builder.DrawRect(SkRect::MakeXYWH(0, 0, 300, 300), paint);
754 builder.Translate(400, 0);
755 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(0, 0, 300, 300), 4, 4),
756 paint);
757
758 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
759}
760
761// Draws two gradients that should look identical (except that one is an RRECT).
762TEST_P(AiksTest, FastGradientTestHorizontalReversed) {
765 builder.Translate(100.0f, 0);
766
767 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
769 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
770
771 paint.setColorSource(DlColorSource::MakeLinear({300, 0}, {0, 0}, stops.size(),
772 colors.data(), stops.data(),
774
775 paint.setColor(DlColor::kWhite());
776 builder.DrawRect(SkRect::MakeXYWH(0, 0, 300, 300), paint);
777 builder.Translate(400, 0);
778 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(0, 0, 300, 300), 4, 4),
779 paint);
780
781 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
782}
783
784// Draws two gradients that should look identical (except that one is an RRECT).
785TEST_P(AiksTest, FastGradientTestVerticalReversed) {
788 builder.Translate(100.0f, 0);
789
790 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
792 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
793
794 paint.setColorSource(DlColorSource::MakeLinear({0, 300}, {0, 0}, stops.size(),
795 colors.data(), stops.data(),
797
798 paint.setColor(DlColor::kWhite());
799 builder.DrawRect(SkRect::MakeXYWH(0, 0, 300, 300), paint);
800 builder.Translate(400, 0);
801 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(0, 0, 300, 300), 4, 4),
802 paint);
803
804 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
805}
806
807TEST_P(AiksTest, VerifyNonOptimizedGradient) {
810 builder.Translate(100.0f, 0);
811
812 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue(),
814 std::vector<Scalar> stops = {0.0, 0.1, 1.0};
815
816 // Inset the start and end point to verify that we do not apply
817 // the fast gradient condition.
818 paint.setColorSource(
819 DlColorSource::MakeLinear({0, 150}, {0, 100}, stops.size(), colors.data(),
820 stops.data(), DlTileMode::kRepeat));
821
822 paint.setColor(DlColor::kWhite());
823 builder.DrawRect(SkRect::MakeXYWH(0, 0, 300, 300), paint);
824 builder.Translate(400, 0);
825 builder.DrawRRect(SkRRect::MakeRectXY(SkRect::MakeXYWH(0, 0, 300, 300), 4, 4),
826 paint);
827
828 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
829}
830
831} // namespace testing
832} // namespace impeller
Definition: SkPath.h:59
SkPath & addCircle(SkScalar x, SkScalar y, SkScalar radius, SkPathDirection dir=SkPathDirection::kCW)
Definition: SkPath.cpp:1213
static SkRRect MakeRectXY(const SkRect &rect, SkScalar xRad, SkScalar yRad)
Definition: SkRRect.h:180
static std::shared_ptr< DlColorFilter > Make(DlColor color, DlBlendMode mode)
static std::shared_ptr< DlMaskFilter > Make(DlBlurStyle style, SkScalar sigma, bool respect_ctm=true)
static std::shared_ptr< DlConicalGradientColorSource > MakeConical(SkPoint start_center, SkScalar start_radius, SkPoint end_center, SkScalar end_radius, uint32_t stop_count, const DlColor *colors, const float *stops, DlTileMode tile_mode, const SkMatrix *matrix=nullptr)
static std::shared_ptr< DlLinearGradientColorSource > MakeLinear(const SkPoint start_point, const SkPoint end_point, uint32_t stop_count, const DlColor *colors, const float *stops, DlTileMode tile_mode, const SkMatrix *matrix=nullptr)
static std::shared_ptr< DlSweepGradientColorSource > MakeSweep(SkPoint center, SkScalar start, SkScalar end, uint32_t stop_count, const DlColor *colors, const float *stops, DlTileMode tile_mode, const SkMatrix *matrix=nullptr)
static std::shared_ptr< DlRadialGradientColorSource > MakeRadial(SkPoint center, SkScalar radius, uint32_t stop_count, const DlColor *colors, const float *stops, DlTileMode tile_mode, const SkMatrix *matrix=nullptr)
bool OpenPlaygroundHere(Picture picture)
static bool ImGuiBegin(const char *name, bool *p_open, ImGuiWindowFlags flags)
Point GetContentScale() const
Definition: playground.cc:192
const Paint & paint
Definition: color_source.cc:38
DlColor color
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
double y
double x
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
PODArray< SkColor > colors
Definition: SkRecords.h:276
SK_API sk_sp< SkShader > Color(SkColor)
@ kMiter
extends to miter limit
@ kBevel
connects outside edges
@ kRound
adds circle
@ kSquare
adds square
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: switches.h:57
@ kStroke
strokes boundary of shapes
@ kNormal
fuzzy inside and outside
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
AiksPlayground AiksTest
static void CanRenderLinearGradientWithDithering(AiksTest *aiks_test)
static void CanRenderRadialGradientWithDithering(AiksTest *aiks_test)
TEST_P(AiksTest, CanRenderAdvancedBlendColorFilterWithSaveLayer)
static void CanRenderConicalGradientWithDithering(AiksTest *aiks_test)
static void CanRenderSweepGradientWithDithering(AiksTest *aiks_test)
float Scalar
Definition: scalar.h:18
std::tuple< Point, Point > DrawPlaygroundLine(PlaygroundPoint &point_a, PlaygroundPoint &point_b)
Definition: widgets.cc:50
TPoint< Scalar > Point
Definition: point.h:322
static Matrix ToMatrix(const SkMatrix &m)
const myers::Point & get< 1 >(const myers::Segment &s)
Definition: Myers.h:81
const myers::Point & get< 0 >(const myers::Segment &s)
Definition: Myers.h:80
SK_API sk_sp< PrecompileColorFilter > Matrix()
flutter::DlColor DlColor
static SkString join(const CommandLineFlags::StringArray &)
Definition: skpbench.cpp:741
const Scalar scale
static constexpr SkPoint Make(float x, float y)
Definition: SkPoint_impl.h:173
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition: SkRect.h:659
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition: SkRect.h:646
static constexpr DlColor kWhite()
Definition: dl_color.h:23
static constexpr DlColor kBlue()
Definition: dl_color.h:26
static constexpr DlColor kRed()
Definition: dl_color.h:24
static constexpr DlColor kGreen()
Definition: dl_color.h:25
constexpr uint32_t ToARGB() const
Convert to ARGB 32 bit color.
Definition: color.h:261
static constexpr Color Red()
Definition: color.h:274
static constexpr Color MakeRGBA8(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
Definition: color.h:154
A 4x4 matrix using column-major storage.
Definition: matrix.h:37