| Flutter Impeller |

aiks_dl_blur_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 "flutter/display_list/display_list.h"
6 #include "flutter/display_list/dl_blend_mode.h"
7 #include "flutter/display_list/dl_builder.h"
8 #include "flutter/display_list/dl_color.h"
9 #include "flutter/display_list/dl_paint.h"
10 #include "flutter/display_list/dl_sampling_options.h"
11 #include "flutter/display_list/dl_tile_mode.h"
12 #include "flutter/display_list/effects/dl_color_filter.h"
13 #include "flutter/display_list/effects/dl_color_source.h"
14 #include "flutter/display_list/effects/dl_image_filter.h"
15 #include "flutter/display_list/effects/dl_mask_filter.h"
16 #include "flutter/display_list/effects/image_filters/dl_blur_image_filter.h"
17 #include "flutter/display_list/geometry/dl_path_builder.h"
18 #include "flutter/impeller/display_list/aiks_unittests.h"
19
20 #include "gmock/gmock.h"
21 #include "impeller/display_list/dl_dispatcher.h"
22 #include "impeller/display_list/dl_image_impeller.h"
23 #include "impeller/playground/widgets.h"
24 #include "impeller/renderer/testing/mocks.h"
25 #include "third_party/imgui/imgui.h"
26
27 ////////////////////////////////////////////////////////////////////////////////
28 // This is for tests of Canvas that are interested the results of rendering
29 // blurs.
30 ////////////////////////////////////////////////////////////////////////////////
31
32 namespace impeller {
33 namespace testing {
34
35 using namespace flutter;
36
37 // The shapes of these ovals should appear equal. They are demonstrating the
38 // difference between the fast pass and not.
39 TEST_P(AiksTest, SolidColorOvalsMaskBlurTinySigma) {
40 DisplayListBuilder builder;
41 builder.Scale(GetContentScale().x, GetContentScale().y);
42
43 std::vector<float> sigmas = {0.0, 0.01, 1.0};
44 std::vector<DlColor> colors = {DlColor::kGreen(), DlColor::kYellow(),
45 DlColor::kRed()};
46 for (uint32_t i = 0; i < sigmas.size(); ++i) {
47 DlPaint paint;
48 paint.setColor(colors[i]);
49 paint.setMaskFilter(
50 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigmas[i]));
51
52 builder.Save();
53 builder.Translate(100 + (i * 100), 100);
54 DlRoundRect rrect =
55 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(0, 0, 60.0f, 160.0f), 50, 100);
56 builder.DrawRoundRect(rrect, paint);
57 builder.Restore();
58 }
59
60 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
61 }
62
63 sk_sp<flutter::DisplayList> DoGradientOvalStrokeMaskBlur(Vector2 content_Scale,
64 Scalar sigma,
65 DlBlurStyle style) {
66 DisplayListBuilder builder;
67 builder.Scale(content_Scale.x, content_Scale.y);
68
69 DlPaint background_paint;
70 background_paint.setColor(DlColor(1, 0.1, 0.1, 0.1, DlColorSpace::kSRGB));
71 builder.DrawPaint(background_paint);
72
73 std::vector<DlColor> colors = {DlColor::kRed(), DlColor::kBlue()};
74 std::vector<Scalar> stops = {0.0, 1.0};
75
76 DlPaint paint;
77 paint.setMaskFilter(DlBlurMaskFilter::Make(style, sigma));
78 auto gradient = DlColorSource::MakeLinear(
79 {0, 0}, {200, 200}, 2, colors.data(), stops.data(), DlTileMode::kClamp);
80 paint.setColorSource(gradient);
81 paint.setColor(DlColor::kWhite());
82 paint.setDrawStyle(DlDrawStyle::kStroke);
83 paint.setStrokeWidth(20);
84
85 builder.Save();
86 builder.Translate(100, 100);
87
88 {
89 DlPaint line_paint;
90 line_paint.setColor(DlColor::kWhite());
91 builder.DrawLine(DlPoint(100, 0), DlPoint(100, 60), line_paint);
92 builder.DrawLine(DlPoint(0, 30), DlPoint(200, 30), line_paint);
93 }
94
95 DlRoundRect rrect =
96 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(0, 0, 200.0f, 60.0f), 50, 100);
97 builder.DrawRoundRect(rrect, paint);
98 builder.Restore();
99
100 return builder.Build();
101 }
102
103 // https://github.com/flutter/flutter/issues/155930
104 TEST_P(AiksTest, GradientOvalStrokeMaskBlur) {
105 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
106 GetContentScale(), /*sigma=*/10, DlBlurStyle::kNormal)));
107 }
108
109 TEST_P(AiksTest, GradientOvalStrokeMaskBlurSigmaZero) {
110 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
111 GetContentScale(), /*sigma=*/0, DlBlurStyle::kNormal)));
112 }
113
114 TEST_P(AiksTest, GradientOvalStrokeMaskBlurOuter) {
115 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
116 GetContentScale(), /*sigma=*/10, DlBlurStyle::kOuter)));
117 }
118
119 TEST_P(AiksTest, GradientOvalStrokeMaskBlurInner) {
120 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
121 GetContentScale(), /*sigma=*/10, DlBlurStyle::kInner)));
122 }
123
124 TEST_P(AiksTest, GradientOvalStrokeMaskBlurSolid) {
125 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
126 GetContentScale(), /*sigma=*/10, DlBlurStyle::kSolid)));
127 }
128
129 TEST_P(AiksTest, SolidColorCircleMaskBlurTinySigma) {
130 DisplayListBuilder builder;
131 builder.Scale(GetContentScale().x, GetContentScale().y);
132
133 std::vector<float> sigmas = {0.0, 0.01, 1.0};
134 std::vector<DlColor> colors = {DlColor::kGreen(), DlColor::kYellow(),
135 DlColor::kRed()};
136 for (uint32_t i = 0; i < sigmas.size(); ++i) {
137 DlPaint paint;
138 paint.setColor(colors[i]);
139 paint.setMaskFilter(
140 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigmas[i]));
141
142 builder.Save();
143 builder.Translate(100 + (i * 100), 100);
144 DlRoundRect rrect = DlRoundRect::MakeRectXY(
145 DlRect::MakeXYWH(0, 0, 100.0f, 100.0f), 100, 100);
146 builder.DrawRoundRect(rrect, paint);
147 builder.Restore();
148 }
149
150 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
151 }
152
153 TEST_P(AiksTest, CanRenderMaskBlurHugeSigma) {
154 DisplayListBuilder builder;
155
156 DlPaint paint;
157 paint.setColor(DlColor::kGreen());
158 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 99999));
159 builder.DrawCircle(DlPoint(400, 400), 300, paint);
160 builder.Restore();
161
162 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
163 }
164
165 TEST_P(AiksTest, CanRenderForegroundBlendWithMaskBlur) {
166 // This case triggers the ForegroundPorterDuffBlend path. The color filter
167 // should apply to the color only, and respect the alpha mask.
168 DisplayListBuilder builder;
169 builder.ClipRect(DlRect::MakeXYWH(100, 150, 400, 400));
170
171 DlPaint paint;
172 paint.setColor(DlColor::kWhite());
173
174 Sigma sigma = Radius(20);
175 paint.setMaskFilter(
176 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
177 paint.setColorFilter(
178 DlColorFilter::MakeBlend(DlColor::kGreen(), DlBlendMode::kSrc));
179 builder.DrawCircle(DlPoint(400, 400), 200, paint);
180
181 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
182 }
183
184 TEST_P(AiksTest, CanRenderForegroundAdvancedBlendWithMaskBlur) {
185 // This case triggers the ForegroundAdvancedBlend path. The color filter
186 // should apply to the color only, and respect the alpha mask.
187 DisplayListBuilder builder;
188 builder.ClipRect(DlRect::MakeXYWH(100, 150, 400, 400));
189
190 DlPaint paint;
191 paint.setColor(
192 DlColor::RGBA(128.0f / 255.0f, 128.0f / 255.0f, 128.0f / 255.0f, 1.0f));
193
194 Sigma sigma = Radius(20);
195 paint.setMaskFilter(
196 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
197 paint.setColorFilter(
198 DlColorFilter::MakeBlend(DlColor::kGreen(), DlBlendMode::kColor));
199 builder.DrawCircle(DlPoint(400, 400), 200, paint);
200 builder.Restore();
201
202 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
203 }
204
205 TEST_P(AiksTest, CanRenderBackdropBlurInteractive) {
206 auto callback = [&]() -> sk_sp<DisplayList> {
207 static PlaygroundPoint point_a(Point(50, 50), 30, Color::White());
208 static PlaygroundPoint point_b(Point(300, 200), 30, Color::White());
209 auto [a, b] = DrawPlaygroundLine(point_a, point_b);
210
211 DisplayListBuilder builder;
212 DlPaint paint;
213 paint.setColor(DlColor::kCornflowerBlue());
214 builder.DrawCircle(DlPoint(100, 100), 50, paint);
215
216 paint.setColor(DlColor::kGreenYellow());
217 builder.DrawCircle(DlPoint(300, 200), 100, paint);
218
219 paint.setColor(DlColor::kDarkMagenta());
220 builder.DrawCircle(DlPoint(140, 170), 75, paint);
221
222 paint.setColor(DlColor::kOrangeRed());
223 builder.DrawCircle(DlPoint(180, 120), 100, paint);
224
225 DlRoundRect rrect =
226 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(a.x, a.y, b.x, b.y), 20, 20);
227 builder.ClipRoundRect(rrect);
228
229 DlPaint save_paint;
230 save_paint.setBlendMode(DlBlendMode::kSrc);
231
232 auto backdrop_filter = DlImageFilter::MakeBlur(20, 20, DlTileMode::kClamp);
233 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get());
234 builder.Restore();
235
236 return builder.Build();
237 };
238
239 ASSERT_TRUE(OpenPlaygroundHere(callback));
240 }
241
242 TEST_P(AiksTest, CanRenderBackdropBlur) {
243 DisplayListBuilder builder;
244
245 DlPaint paint;
246 paint.setColor(DlColor::kCornflowerBlue());
247 builder.DrawCircle(DlPoint(100, 100), 50, paint);
248
249 paint.setColor(DlColor::kGreenYellow());
250 builder.DrawCircle(DlPoint(300, 200), 100, paint);
251
252 paint.setColor(DlColor::kDarkMagenta());
253 builder.DrawCircle(DlPoint(140, 170), 75, paint);
254
255 paint.setColor(DlColor::kOrangeRed());
256 builder.DrawCircle(DlPoint(180, 120), 100, paint);
257
258 DlRoundRect rrect =
259 DlRoundRect::MakeRectXY(DlRect::MakeLTRB(75, 50, 375, 275), 20, 20);
260 builder.ClipRoundRect(rrect);
261
262 DlPaint save_paint;
263 save_paint.setBlendMode(DlBlendMode::kSrc);
264 auto backdrop_filter = DlImageFilter::MakeBlur(30, 30, DlTileMode::kClamp);
265 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get());
266 builder.Restore();
267
268 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
269 }
270
271 TEST_P(AiksTest, CanRenderBackdropBlurWithSingleBackdropId) {
272 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
273
274 DisplayListBuilder builder;
275
276 DlPaint paint;
277 builder.DrawImage(image, DlPoint(50.0, 50.0),
278 DlImageSampling::kNearestNeighbor, &paint);
279
280 DlRoundRect rrect =
281 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(50, 250, 100, 100), 20, 20);
282 builder.Save();
283 builder.ClipRoundRect(rrect);
284
285 DlPaint save_paint;
286 save_paint.setBlendMode(DlBlendMode::kSrc);
287 auto backdrop_filter = DlImageFilter::MakeBlur(30, 30, DlTileMode::kClamp);
288 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get(),
289 /*backdrop_id=*/1);
290 builder.Restore();
291 builder.Restore();
292
293 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
294 }
295
296 TEST_P(AiksTest, CanRenderMultipleBackdropBlurWithSingleBackdropId) {
297 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
298
299 DisplayListBuilder builder;
300
301 DlPaint paint;
302 builder.DrawImage(image, DlPoint(50.0, 50.0),
303 DlImageSampling::kNearestNeighbor, &paint);
304
305 for (int i = 0; i < 6; i++) {
306 DlRoundRect rrect = DlRoundRect::MakeRectXY(
307 DlRect::MakeXYWH(50 + (i * 100), 250, 100, 100), 20, 20);
308 builder.Save();
309 builder.ClipRoundRect(rrect);
310
311 DlPaint save_paint;
312 save_paint.setBlendMode(DlBlendMode::kSrc);
313 auto backdrop_filter = DlImageFilter::MakeBlur(30, 30, DlTileMode::kClamp);
314 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get(),
315 /*backdrop_id=*/1);
316 builder.Restore();
317 builder.Restore();
318 }
319
320 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
321 }
322
323 TEST_P(AiksTest,
324 CanRenderMultipleBackdropBlurWithSingleBackdropIdAndDistinctFilters) {
325 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
326
327 DisplayListBuilder builder;
328
329 DlPaint paint;
330 builder.DrawImage(image, DlPoint(50.0, 50.0),
331 DlImageSampling::kNearestNeighbor, &paint);
332
333 for (int i = 0; i < 6; i++) {
334 DlRoundRect rrect = DlRoundRect::MakeRectXY(
335 DlRect::MakeXYWH(50 + (i * 100), 250, 100, 100), 20, 20);
336 builder.Save();
337 builder.ClipRoundRect(rrect);
338
339 DlPaint save_paint;
340 save_paint.setBlendMode(DlBlendMode::kSrc);
341 auto backdrop_filter =
342 DlImageFilter::MakeBlur(30 + i, 30, DlTileMode::kClamp);
343 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get(),
344 /*backdrop_id=*/1);
345 builder.Restore();
346 builder.Restore();
347 }
348
349 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
350 }
351
352 TEST_P(AiksTest, CanRenderBackdropBlurHugeSigma) {
353 DisplayListBuilder builder;
354
355 DlPaint paint;
356 paint.setColor(DlColor::kGreen());
357 builder.DrawCircle(DlPoint(400, 400), 300, paint);
358
359 DlPaint save_paint;
360 save_paint.setBlendMode(DlBlendMode::kSrc);
361
362 auto backdrop_filter =
363 DlImageFilter::MakeBlur(999999, 999999, DlTileMode::kClamp);
364 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get());
365 builder.Restore();
366
367 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
368 }
369
370 TEST_P(AiksTest, CanRenderBoundedBlur) {
371 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
372
373 DisplayListBuilder builder;
374
375 DlPaint paint;
376 builder.DrawImage(image, DlPoint(0.0, 0.0), DlImageSampling::kNearestNeighbor,
377 &paint);
378
379 DlPaint save_paint;
380 save_paint.setBlendMode(DlBlendMode::kSrcOver);
381 builder.Save();
382
383 // Subcase 1: The 1st branch of downsampling, where the coverage hint is
384 // non-null but was ignored during snapshotting.
385
386 builder.Scale(1.1, 1.2);
387 builder.Rotate(10);
388 DlRect rect1 = DlRect::MakeLTRB(70, 70, 313, 170);
389 builder.ClipRect(rect1);
390 auto backdrop_filter1 =
391 DlBlurImageFilter::Make(20, 20, DlTileMode::kDecal, /*bounds=*/rect1);
392 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter1.get());
393 builder.Restore();
394 builder.Restore();
395
396 // Subcase 2: The 2nd branch of downsampling, where the coverage hint is null
397 // or was already used during snapshotting.
398
399 builder.Scale(1.1, 1.2);
400 builder.Rotate(10);
401 DlRect rect2 = DlRect::MakeLTRB(55, 190, 298, 290);
402 builder.ClipRect(rect2);
403 auto backdrop_filter2 =
404 DlBlurImageFilter::Make(20, 20, DlTileMode::kDecal, /*bounds=*/rect2);
405 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter2.get());
406 builder.Restore();
407 builder.Restore();
408
409 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
410 }
411
412 TEST_P(AiksTest, CanRenderClippedBlur) {
413 DisplayListBuilder builder;
414 builder.ClipRect(DlRect::MakeXYWH(100, 150, 400, 400));
415
416 DlPaint paint;
417 paint.setColor(DlColor::kGreen());
418 paint.setImageFilter(DlImageFilter::MakeBlur(20, 20, DlTileMode::kDecal));
419 builder.DrawCircle(DlPoint(400, 400), 200, paint);
420 builder.Restore();
421
422 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
423 }
424
425 TEST_P(AiksTest, ComposePaintBlurOuter) {
426 DisplayListBuilder builder;
427
428 DlPaint background;
429 background.setColor(DlColor(1.0, 0.1, 0.1, 0.1, DlColorSpace::kSRGB));
430 builder.DrawPaint(background);
431
432 DlPaint paint;
433 paint.setColor(DlColor::kGreen());
434 float matrix[] = {
435 0, 1, 0, 0, 0, //
436 1, 0, 0, 0, 0, //
437 0, 0, 1, 0, 0, //
438 0, 0, 0, 1, 0 //
439 };
440 std::shared_ptr<DlImageFilter> color_filter =
441 DlImageFilter::MakeColorFilter(DlColorFilter::MakeMatrix(matrix));
442 std::shared_ptr<DlImageFilter> blur =
443 DlImageFilter::MakeBlur(20, 20, DlTileMode::kDecal);
444 paint.setImageFilter(DlImageFilter::MakeCompose(blur, color_filter));
445 builder.DrawCircle(DlPoint(400, 400), 200, paint);
446
447 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
448 }
449
450 TEST_P(AiksTest, ComposePaintBlurInner) {
451 DisplayListBuilder builder;
452
453 DlPaint background;
454 background.setColor(DlColor(1.0, 0.1, 0.1, 0.1, DlColorSpace::kSRGB));
455 builder.DrawPaint(background);
456
457 DlPaint paint;
458 paint.setColor(DlColor::kGreen());
459 float matrix[] = {
460 0, 1, 0, 0, 0, //
461 1, 0, 0, 0, 0, //
462 0, 0, 1, 0, 0, //
463 0, 0, 0, 1, 0 //
464 };
465 std::shared_ptr<DlImageFilter> color_filter =
466 DlImageFilter::MakeColorFilter(DlColorFilter::MakeMatrix(matrix));
467 std::shared_ptr<DlImageFilter> blur =
468 DlImageFilter::MakeBlur(20, 20, DlTileMode::kDecal);
469 paint.setImageFilter(DlImageFilter::MakeCompose(color_filter, blur));
470 builder.DrawCircle(DlPoint(400, 400), 200, paint);
471
472 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
473 }
474
475 TEST_P(AiksTest, ClippedBlurFilterRendersCorrectlyInteractive) {
476 auto callback = [&]() -> sk_sp<DisplayList> {
477 static PlaygroundPoint playground_point(Point(400, 400), 20,
478 Color::Green());
479 auto point = DrawPlaygroundPoint(playground_point);
480
481 DisplayListBuilder builder;
482 auto location = point - Point(400, 400);
483 builder.Translate(location.x, location.y);
484
485 DlPaint paint;
486 Sigma sigma = Radius{120 * 3};
487 paint.setMaskFilter(
488 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
489 paint.setColor(DlColor::kRed());
490
491 DlPath path = DlPath::MakeRect(DlRect::MakeLTRB(0, 0, 800, 800));
492 path = path + DlPath::MakeCircle(DlPoint(0, 0), 0.5);
493 builder.DrawPath(path, paint);
494 return builder.Build();
495 };
496 ASSERT_TRUE(OpenPlaygroundHere(callback));
497 }
498
499 TEST_P(AiksTest, ClippedBlurFilterRendersCorrectly) {
500 DisplayListBuilder builder;
501 builder.Translate(0, -400);
502 DlPaint paint;
503
504 Sigma sigma = Radius{120 * 3};
505 paint.setMaskFilter(
506 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma.sigma));
507 paint.setColor(DlColor::kRed());
508
509 DlPath path = DlPath::MakeRect(DlRect::MakeLTRB(0, 0, 800, 800));
510 path = path + DlPath::MakeCircle(DlPoint(0, 0), 0.5);
511 builder.DrawPath(path, paint);
512
513 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
514 }
515
516 TEST_P(AiksTest, ClearBlendWithBlur) {
517 DisplayListBuilder builder;
518 DlPaint paint;
519 paint.setColor(DlColor::kBlue());
520 builder.DrawRect(DlRect::MakeXYWH(0, 0, 600.0, 600.0), paint);
521
522 DlPaint clear;
523 clear.setBlendMode(DlBlendMode::kClear);
524 clear.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 20));
525
526 builder.DrawCircle(DlPoint(300.0, 300.0), 200.0, clear);
527
528 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
529 }
530
531 TEST_P(AiksTest, BlurHasNoEdge) {
532 Scalar sigma = 47.6;
533 auto callback = [&]() -> sk_sp<DisplayList> {
534 if (AiksTest::ImGuiBegin("Controls", nullptr,
535 ImGuiWindowFlags_AlwaysAutoResize)) {
536 ImGui::SliderFloat("Sigma", &sigma, 0, 50);
537 ImGui::End();
538 }
539 DisplayListBuilder builder;
540 builder.Scale(GetContentScale().x, GetContentScale().y);
541 builder.DrawPaint({});
542
543 DlPaint paint;
544 paint.setColor(DlColor::kGreen());
545 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
546
547 builder.DrawRect(DlRect::MakeXYWH(300, 300, 200, 200), paint);
548 return builder.Build();
549 };
550
551 ASSERT_TRUE(OpenPlaygroundHere(callback));
552 }
553
554 TEST_P(AiksTest, MaskBlurWithZeroSigmaIsSkipped) {
555 DisplayListBuilder builder;
556
557 DlPaint paint;
558 paint.setColor(DlColor::kBlue());
559 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 0));
560
561 builder.DrawCircle(DlPoint(300, 300), 200, paint);
562 builder.DrawRect(DlRect::MakeLTRB(100, 300, 500, 600), paint);
563
564 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
565 }
566
567 TEST_P(AiksTest, MaskBlurOnZeroDimensionIsSkippedWideGamut) {
568 // Making sure this test is run on a wide gamut enabled backend
569 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
570 PixelFormat::kB10G10R10A10XR);
571
572 DisplayListBuilder builder;
573 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
574
575 DlPaint paint;
576 paint.setColor(DlColor::kBlue());
577 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 10));
578
579 // Zero height above
580 builder.DrawRect(DlRect::MakeLTRB(100, 250, 500, 250), paint);
581 // Regular rect
582 builder.DrawRect(DlRect::MakeLTRB(100, 300, 500, 600), paint);
583 // Zero width to the right
584 builder.DrawRect(DlRect::MakeLTRB(550, 300, 550, 600), paint);
585
586 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
587 }
588
589 struct MaskBlurTestConfig {
590 DlBlurStyle style = DlBlurStyle::kNormal;
591 Scalar sigma = 1.0f;
592 Scalar alpha = 1.0f;
593 std::shared_ptr<DlImageFilter> image_filter;
594 bool invert_colors = false;
595 DlBlendMode blend_mode = DlBlendMode::kSrcOver;
596 };
597
598 static sk_sp<DisplayList> MaskBlurVariantTest(
599 const AiksTest& test_context,
600 const MaskBlurTestConfig& config) {
601 DisplayListBuilder builder;
602 builder.Scale(test_context.GetContentScale().x,
603 test_context.GetContentScale().y);
604 builder.Scale(0.8f, 0.8f);
605 builder.Translate(50.f, 50.f);
606
607 DlPaint draw_paint;
608 draw_paint.setColor(
609 DlColor::RGBA(Color::AntiqueWhite().red, Color::AntiqueWhite().green,
610 Color::AntiqueWhite().blue, Color::AntiqueWhite().alpha));
611 builder.DrawPaint(draw_paint);
612
613 DlPaint paint;
614 paint.setMaskFilter(DlBlurMaskFilter::Make(config.style, config.sigma));
615 paint.setInvertColors(config.invert_colors);
616 paint.setImageFilter(config.image_filter);
617 paint.setBlendMode(config.blend_mode);
618
619 const Scalar x = 50;
620 const Scalar radius = 20.0f;
621 const Scalar y_spacing = 100.0f;
622 Scalar alpha = config.alpha * 255;
623
624 Scalar y = 50;
625 paint.setColor(DlColor::kCrimson().withAlpha(alpha));
626 builder.DrawRect(DlRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
627 radius, 60.0f - radius),
628 paint);
629
630 y += y_spacing;
631 paint.setColor(DlColor::kBlue().withAlpha(alpha));
632 builder.DrawCircle(DlPoint{x + 25, y + 25}, radius, paint);
633
634 y += y_spacing;
635 paint.setColor(DlColor::kGreen().withAlpha(alpha));
636 builder.DrawOval(DlRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
637 radius, 60.0f - radius),
638 paint);
639
640 y += y_spacing;
641 paint.setColor(DlColor::kPurple().withAlpha(alpha));
642 DlRoundRect rrect = DlRoundRect::MakeRectXY(
643 DlRect::MakeXYWH(x, y, 60.0f, 60.0f), radius, radius);
644 builder.DrawRoundRect(rrect, paint);
645
646 y += y_spacing;
647 paint.setColor(DlColor::kOrange().withAlpha(alpha));
648
649 rrect = DlRoundRect::MakeRectXY(DlRect::MakeXYWH(x, y, 60.0f, 60.0f), //
650 radius, 5.0);
651 builder.DrawRoundRect(rrect, paint);
652
653 y += y_spacing;
654 paint.setColor(DlColor::kMaroon().withAlpha(alpha));
655
656 {
657 DlPathBuilder path_builder;
658 path_builder.MoveTo(DlPoint(x + 0, y + 60));
659 path_builder.LineTo(DlPoint(x + 30, y + 0));
660 path_builder.LineTo(DlPoint(x + 60, y + 60));
661 path_builder.Close();
662
663 builder.DrawPath(path_builder.TakePath(), paint);
664 }
665
666 y += y_spacing;
667 paint.setColor(DlColor::kMaroon().withAlpha(alpha));
668 {
669 DlPath path = DlPath::MakeArc(Rect::MakeXYWH(x + 5, y, 50, 50), //
670 Degrees(90), Degrees(180), false) +
671 DlPath::MakeArc(Rect::MakeXYWH(x + 25, y, 50, 50), //
672 Degrees(90), Degrees(180), false);
673 builder.DrawPath(path, paint);
674 }
675
676 return builder.Build();
677 }
678
679 static const std::map<std::string, MaskBlurTestConfig> kPaintVariations = {
680 // 1. Normal style, translucent, zero sigma.
681 {"NormalTranslucentZeroSigma",
682 {.style = DlBlurStyle::kNormal, .sigma = 0.0f, .alpha = 0.5f}},
683 // 2. Normal style, translucent.
684 {"NormalTranslucent",
685 {.style = DlBlurStyle::kNormal, .sigma = 8.0f, .alpha = 0.5f}},
686 // 3. Solid style, translucent.
687 {"SolidTranslucent",
688 {.style = DlBlurStyle::kSolid, .sigma = 8.0f, .alpha = 0.5f}},
689 // 4. Solid style, opaque.
690 {"SolidOpaque", {.style = DlBlurStyle::kSolid, .sigma = 8.0f}},
691 // 5. Solid style, translucent, color & image filtered.
692 {"SolidTranslucentWithFilters",
693 {.style = DlBlurStyle::kSolid,
694 .sigma = 8.0f,
695 .alpha = 0.5f,
696 .image_filter = DlImageFilter::MakeBlur(3, 3, DlTileMode::kClamp),
697 .invert_colors = true}},
698 // 6. Solid style, translucent, exclusion blended.
699 {"SolidTranslucentExclusionBlend",
700 {.style = DlBlurStyle::kSolid,
701 .sigma = 8.0f,
702 .alpha = 0.5f,
703 .blend_mode = DlBlendMode::kExclusion}},
704 // 7. Inner style, translucent.
705 {"InnerTranslucent",
706 {.style = DlBlurStyle::kInner, .sigma = 8.0f, .alpha = 0.5f}},
707 // 8. Inner style, translucent, blurred.
708 {"InnerTranslucentWithBlurImageFilter",
709 {.style = DlBlurStyle::kInner,
710 .sigma = 8.0f,
711 .alpha = 0.5f,
712 .image_filter = DlImageFilter::MakeBlur(3, 3, DlTileMode::kClamp)}},
713 // 9. Outer style, translucent.
714 {"OuterTranslucent",
715 {.style = DlBlurStyle::kOuter, .sigma = 8.0f, .alpha = 0.5f}},
716 // 10. Outer style, opaque, image filtered.
717 {"OuterOpaqueWithBlurImageFilter",
718 {.style = DlBlurStyle::kOuter,
719 .sigma = 8.0f,
720 .image_filter = DlImageFilter::MakeBlur(3, 3, DlTileMode::kClamp)}}};
721
722 #define MASK_BLUR_VARIANT_TEST(config) \
723 TEST_P(AiksTest, MaskBlurVariantTest##config) { \
724 ASSERT_TRUE(OpenPlaygroundHere( \
725 MaskBlurVariantTest(*this, kPaintVariations.at(#config)))); \
726 }
727
728 MASK_BLUR_VARIANT_TEST(NormalTranslucentZeroSigma)
729 MASK_BLUR_VARIANT_TEST(NormalTranslucent)
730 MASK_BLUR_VARIANT_TEST(SolidTranslucent)
731 MASK_BLUR_VARIANT_TEST(SolidOpaque)
732 MASK_BLUR_VARIANT_TEST(SolidTranslucentWithFilters)
733 MASK_BLUR_VARIANT_TEST(SolidTranslucentExclusionBlend)
734 MASK_BLUR_VARIANT_TEST(InnerTranslucent)
735 MASK_BLUR_VARIANT_TEST(InnerTranslucentWithBlurImageFilter)
736 MASK_BLUR_VARIANT_TEST(OuterTranslucent)
737 MASK_BLUR_VARIANT_TEST(OuterOpaqueWithBlurImageFilter)
738
739 #undef MASK_BLUR_VARIANT_TEST
740
741 TEST_P(AiksTest, GaussianBlurStyleInner) {
742 DisplayListBuilder builder;
743 builder.Scale(GetContentScale().x, GetContentScale().y);
744
745 DlPaint paint;
746 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1));
747 builder.DrawPaint(paint);
748
749 paint.setColor(DlColor::kGreen());
750 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kInner, 30));
751
752 DlPathBuilder path_builder;
753 path_builder.MoveTo(DlPoint(200, 200));
754 path_builder.LineTo(DlPoint(300, 400));
755 path_builder.LineTo(DlPoint(100, 400));
756 path_builder.Close();
757
758 builder.DrawPath(path_builder.TakePath(), paint);
759
760 // Draw another thing to make sure the clip area is reset.
761 DlPaint red;
762 red.setColor(DlColor::kRed());
763 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
764
765 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
766 }
767
768 TEST_P(AiksTest, GaussianBlurStyleOuter) {
769 DisplayListBuilder builder;
770 builder.Scale(GetContentScale().x, GetContentScale().y);
771
772 DlPaint paint;
773 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
774 builder.DrawPaint(paint);
775
776 paint.setColor(DlColor::kGreen());
777 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kOuter, 30));
778
779 DlPathBuilder path_builder;
780 path_builder.MoveTo(DlPoint(200, 200));
781 path_builder.LineTo(DlPoint(300, 400));
782 path_builder.LineTo(DlPoint(100, 400));
783 path_builder.Close();
784
785 builder.DrawPath(path_builder.TakePath(), paint);
786
787 // Draw another thing to make sure the clip area is reset.
788 DlPaint red;
789 red.setColor(DlColor::kRed());
790 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
791
792 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
793 }
794
795 TEST_P(AiksTest, GaussianBlurStyleSolid) {
796 DisplayListBuilder builder;
797 builder.Scale(GetContentScale().x, GetContentScale().y);
798
799 DlPaint paint;
800 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
801 builder.DrawPaint(paint);
802
803 paint.setColor(DlColor::kGreen());
804 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kSolid, 30));
805
806 DlPathBuilder path_builder;
807 path_builder.MoveTo(DlPoint(200, 200));
808 path_builder.LineTo(DlPoint(300, 400));
809 path_builder.LineTo(DlPoint(100, 400));
810 path_builder.Close();
811
812 builder.DrawPath(path_builder.TakePath(), paint);
813
814 // Draw another thing to make sure the clip area is reset.
815 DlPaint red;
816 red.setColor(DlColor::kRed());
817 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
818
819 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
820 }
821
822 TEST_P(AiksTest, MaskBlurTexture) {
823 Scalar sigma = 30;
824 auto callback = [&]() -> sk_sp<DisplayList> {
825 if (AiksTest::ImGuiBegin("Controls", nullptr,
826 ImGuiWindowFlags_AlwaysAutoResize)) {
827 ImGui::SliderFloat("Sigma", &sigma, 0, 500);
828 ImGui::End();
829 }
830
831 DisplayListBuilder builder;
832 builder.Scale(GetContentScale().x, GetContentScale().y);
833
834 DlPaint paint;
835 paint.setColor(DlColor::kGreen());
836 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
837
838 builder.DrawImage(
839 DlImageImpeller::Make(CreateTextureForFixture("boston.jpg")),
840 DlPoint(200, 200), DlImageSampling::kNearestNeighbor, &paint);
841
842 DlPaint red;
843 red.setColor(DlColor::kRed());
844 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
845
846 return builder.Build();
847 };
848 ASSERT_TRUE(OpenPlaygroundHere(callback));
849 }
850
851 TEST_P(AiksTest, MaskBlurDoesntStretchContents) {
852 Scalar sigma = 70;
853 auto callback = [&]() -> sk_sp<DisplayList> {
854 if (AiksTest::ImGuiBegin("Controls", nullptr,
855 ImGuiWindowFlags_AlwaysAutoResize)) {
856 ImGui::SliderFloat("Sigma", &sigma, 0, 500);
857 ImGui::End();
858 }
859
860 DisplayListBuilder builder;
861 builder.Scale(GetContentScale().x, GetContentScale().y);
862
863 DlPaint paint;
864 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
865 builder.DrawPaint(paint);
866
867 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
868
869 builder.Transform(Matrix::MakeTranslation({100, 100}) *
870 Matrix::MakeScale({0.5, 0.5, 1.0f}));
871
872 paint.setColorSource(DlColorSource::MakeImage(
873 DlImageImpeller::Make(boston), DlTileMode::kRepeat, DlTileMode::kRepeat,
874 DlImageSampling::kMipmapLinear));
875 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
876
877 builder.DrawRect(DlRect::MakeXYWH(0, 0, boston->GetSize().width,
878 boston->GetSize().height),
879 paint);
880
881 return builder.Build();
882 };
883 ASSERT_TRUE(OpenPlaygroundHere(callback));
884 }
885
886 TEST_P(AiksTest, GaussianBlurAtPeripheryVertical) {
887 DisplayListBuilder builder;
888
889 DlPaint paint;
890 builder.Scale(GetContentScale().x, GetContentScale().y);
891
892 paint.setColor(DlColor::kLimeGreen());
893 DlRoundRect rrect = DlRoundRect::MakeRectXY(
894 DlRect::MakeLTRB(0, 0, GetWindowSize().width, 100), 10, 10);
895 builder.DrawRoundRect(rrect, paint);
896
897 paint.setColor(DlColor::kMagenta());
898 rrect = DlRoundRect::MakeRectXY(
899 DlRect::MakeLTRB(0, 110, GetWindowSize().width, 210), 10, 10);
900 builder.DrawRoundRect(rrect, paint);
901 builder.ClipRect(DlRect::MakeLTRB(100, 0, 200, GetWindowSize().height));
902
903 DlPaint save_paint;
904 save_paint.setBlendMode(DlBlendMode::kSrc);
905
906 auto backdrop_filter = DlImageFilter::MakeBlur(20, 20, DlTileMode::kClamp);
907
908 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get());
909 builder.Restore();
910
911 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
912 }
913
914 TEST_P(AiksTest, GaussianBlurAtPeripheryHorizontal) {
915 DisplayListBuilder builder;
916
917 builder.Scale(GetContentScale().x, GetContentScale().y);
918 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
919 builder.DrawImageRect(
920 DlImageImpeller::Make(boston),
921 DlRect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height),
922 DlRect::MakeLTRB(0, 0, GetWindowSize().width, 100),
923 DlImageSampling::kNearestNeighbor);
924
925 DlPaint paint;
926 paint.setColor(DlColor::kMagenta());
927
928 DlRoundRect rrect = DlRoundRect::MakeRectXY(
929 DlRect::MakeLTRB(0, 110, GetWindowSize().width, 210), 10, 10);
930 builder.DrawRoundRect(rrect, paint);
931 builder.ClipRect(DlRect::MakeLTRB(0, 50, GetWindowSize().width, 150));
932
933 DlPaint save_paint;
934 save_paint.setBlendMode(DlBlendMode::kSrc);
935
936 auto backdrop_filter = DlImageFilter::MakeBlur(20, 20, DlTileMode::kClamp);
937 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get());
938
939 builder.Restore();
940 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
941 }
942
943 TEST_P(AiksTest, GaussianBlurAnimatedBackdrop) {
944 // This test is for checking out how stable rendering is when content is
945 // translated underneath a blur. Animating under a blur can cause
946 // *shimmering* to happen as a result of pixel alignment.
947 // See also: https://github.com/flutter/flutter/issues/140193
948 auto boston =
949 CreateTextureForFixture("boston.jpg", /*enable_mipmapping=*/true);
950 ASSERT_TRUE(boston);
951 int64_t count = 0;
952 Scalar sigma = 20.0;
953 Scalar freq = 0.1;
954 Scalar amp = 50.0;
955 auto callback = [&]() -> sk_sp<DisplayList> {
956 if (AiksTest::ImGuiBegin("Controls", nullptr,
957 ImGuiWindowFlags_AlwaysAutoResize)) {
958 ImGui::SliderFloat("Sigma", &sigma, 0, 200);
959 ImGui::SliderFloat("Frequency", &freq, 0.01, 2.0);
960 ImGui::SliderFloat("Amplitude", &amp, 1, 100);
961 ImGui::End();
962 }
963
964 DisplayListBuilder builder;
965 builder.Scale(GetContentScale().x, GetContentScale().y);
966 Scalar y = amp * sin(freq * 2.0 * M_PI * count / 60);
967 builder.DrawImage(DlImageImpeller::Make(boston),
968 DlPoint(1024 / 2 - boston->GetSize().width / 2,
969 (768 / 2 - boston->GetSize().height / 2) + y),
970 DlImageSampling::kMipmapLinear);
971 static PlaygroundPoint point_a(Point(100, 100), 20, Color::Red());
972 static PlaygroundPoint point_b(Point(900, 700), 20, Color::Red());
973 auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
974
975 builder.ClipRect(
976 DlRect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
977 builder.ClipRect(DlRect::MakeLTRB(100, 100, 900, 700));
978
979 DlPaint paint;
980 paint.setBlendMode(DlBlendMode::kSrc);
981
982 auto backdrop_filter =
983 DlImageFilter::MakeBlur(sigma, sigma, DlTileMode::kClamp);
984 builder.SaveLayer(std::nullopt, &paint, backdrop_filter.get());
985 count += 1;
986 return builder.Build();
987 };
988 ASSERT_TRUE(OpenPlaygroundHere(callback));
989 }
990
991 TEST_P(AiksTest, GaussianBlurStyleInnerGradient) {
992 DisplayListBuilder builder;
993
994 builder.Scale(GetContentScale().x, GetContentScale().y);
995
996 DlPaint paint;
997 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
998 builder.DrawPaint(paint);
999
1000 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
1001 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
1002 std::vector<Scalar> stops = {0.0, 1.0};
1003
1004 paint = DlPaint{};
1005 paint.setColorSource(DlColorSource::MakeLinear(
1006 /*start_point=*/{0, 0},
1007 /*end_point=*/{200, 200},
1008 /*stop_count=*/colors.size(),
1009 /*colors=*/colors.data(),
1010 /*stops=*/stops.data(),
1011 /*tile_mode=*/DlTileMode::kMirror));
1012 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kInner, 30));
1013
1014 DlPathBuilder path_builder;
1015 path_builder.MoveTo(DlPoint(200, 200));
1016 path_builder.LineTo(DlPoint(300, 400));
1017 path_builder.LineTo(DlPoint(100, 400));
1018 path_builder.Close();
1019 builder.DrawPath(path_builder.TakePath(), paint);
1020
1021 // Draw another thing to make sure the clip area is reset.
1022 DlPaint red;
1023 red.setColor(DlColor::kRed());
1024 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
1025
1026 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1027 }
1028
1029 TEST_P(AiksTest, GaussianBlurStyleSolidGradient) {
1030 DisplayListBuilder builder;
1031 builder.Scale(GetContentScale().x, GetContentScale().y);
1032
1033 DlPaint paint;
1034 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
1035 builder.DrawPaint(paint);
1036
1037 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
1038 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
1039 std::vector<Scalar> stops = {0.0, 1.0};
1040
1041 paint = DlPaint{};
1042 paint.setColorSource(DlColorSource::MakeLinear(
1043 /*start_point=*/{0, 0},
1044 /*end_point=*/{200, 200},
1045 /*stop_count=*/colors.size(),
1046 /*colors=*/colors.data(),
1047 /*stops=*/stops.data(),
1048 /*tile_mode=*/DlTileMode::kMirror));
1049 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kSolid, 30));
1050
1051 DlPathBuilder path_builder;
1052 path_builder.MoveTo(DlPoint(200, 200));
1053 path_builder.LineTo(DlPoint(300, 400));
1054 path_builder.LineTo(DlPoint(100, 400));
1055 path_builder.Close();
1056 builder.DrawPath(path_builder.TakePath(), paint);
1057
1058 // Draw another thing to make sure the clip area is reset.
1059 DlPaint red;
1060 red.setColor(DlColor::kRed());
1061 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
1062 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1063 }
1064
1065 TEST_P(AiksTest, GaussianBlurStyleOuterGradient) {
1066 DisplayListBuilder builder;
1067 builder.Scale(GetContentScale().x, GetContentScale().y);
1068
1069 DlPaint paint;
1070 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
1071 builder.DrawPaint(paint);
1072
1073 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
1074 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
1075 std::vector<Scalar> stops = {0.0, 1.0};
1076
1077 paint = DlPaint{};
1078 paint.setColorSource(DlColorSource::MakeLinear(
1079 /*start_point=*/{0, 0},
1080 /*end_point=*/{200, 200},
1081 /*stop_count=*/colors.size(),
1082 /*colors=*/colors.data(),
1083 /*stops=*/stops.data(),
1084 /*tile_mode=*/DlTileMode::kMirror));
1085 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kOuter, 30));
1086
1087 DlPathBuilder path_builder;
1088 path_builder.MoveTo(DlPoint(200, 200));
1089 path_builder.LineTo(DlPoint(300, 400));
1090 path_builder.LineTo(DlPoint(100, 400));
1091 path_builder.Close();
1092 builder.DrawPath(path_builder.TakePath(), paint);
1093
1094 // Draw another thing to make sure the clip area is reset.
1095 DlPaint red;
1096 red.setColor(DlColor::kRed());
1097 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
1098 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1099 }
1100
1101 TEST_P(AiksTest, GaussianBlurScaledAndClipped) {
1102 DisplayListBuilder builder;
1103 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1104 Rect bounds =
1105 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
1106 Vector2 image_center = Vector2(bounds.GetSize() / 2);
1107
1108 DlPaint paint;
1109 paint.setImageFilter(DlImageFilter::MakeBlur(20, 20, DlTileMode::kDecal));
1110
1111 Vector2 clip_size = {150, 75};
1112 Vector2 center = Vector2(1024, 768) / 2;
1113 builder.Scale(GetContentScale().x, GetContentScale().y);
1114
1115 auto rect =
1116 Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size);
1117 builder.ClipRect(DlRect::MakeLTRB(rect.GetLeft(), rect.GetTop(),
1118 rect.GetRight(), rect.GetBottom()));
1119 builder.Translate(center.x, center.y);
1120 builder.Scale(0.6, 0.6);
1121
1122 DlRect sk_bounds = DlRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(),
1123 bounds.GetRight(), bounds.GetBottom());
1124 Rect dest = bounds.Shift(-image_center);
1125 DlRect sk_dst = DlRect::MakeLTRB(dest.GetLeft(), dest.GetTop(),
1126 dest.GetRight(), dest.GetBottom());
1127 builder.DrawImageRect(DlImageImpeller::Make(boston), /*src=*/sk_bounds,
1128 /*dst=*/sk_dst, DlImageSampling::kNearestNeighbor,
1129 &paint);
1130
1131 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1132 }
1133
1134 TEST_P(AiksTest, GaussianBlurRotatedAndClippedInteractive) {
1135 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1136
1137 auto callback = [&]() -> sk_sp<DisplayList> {
1138 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
1139 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
1140 DlTileMode::kMirror, DlTileMode::kDecal};
1141
1142 static float rotation = 0;
1143 static float scale = 0.6;
1144 static int selected_tile_mode = 3;
1145
1146 if (AiksTest::ImGuiBegin("Controls", nullptr,
1147 ImGuiWindowFlags_AlwaysAutoResize)) {
1148 ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
1149 ImGui::SliderFloat("Scale", &scale, 0, 2.0);
1150 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1151 sizeof(tile_mode_names) / sizeof(char*));
1152 ImGui::End();
1153 }
1154
1155 DisplayListBuilder builder;
1156 Rect bounds =
1157 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
1158 Vector2 image_center = Vector2(bounds.GetSize() / 2);
1159 DlPaint paint;
1160 paint.setImageFilter(
1161 DlImageFilter::MakeBlur(20, 20, tile_modes[selected_tile_mode]));
1162
1163 static PlaygroundPoint point_a(Point(362, 309), 20, Color::Red());
1164 static PlaygroundPoint point_b(Point(662, 459), 20, Color::Red());
1165 auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
1166 Vector2 center = Vector2(1024, 768) / 2;
1167
1168 builder.Scale(GetContentScale().x, GetContentScale().y);
1169 builder.ClipRect(
1170 DlRect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
1171 builder.Translate(center.x, center.y);
1172 builder.Scale(scale, scale);
1173 builder.Rotate(rotation);
1174
1175 DlRect sk_bounds = DlRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(),
1176 bounds.GetRight(), bounds.GetBottom());
1177 Rect dest = bounds.Shift(-image_center);
1178 DlRect sk_dst = DlRect::MakeLTRB(dest.GetLeft(), dest.GetTop(),
1179 dest.GetRight(), dest.GetBottom());
1180 builder.DrawImageRect(DlImageImpeller::Make(boston), /*src=*/sk_bounds,
1181 /*dst=*/sk_dst, DlImageSampling::kNearestNeighbor,
1182 &paint);
1183 return builder.Build();
1184 };
1185
1186 ASSERT_TRUE(OpenPlaygroundHere(callback));
1187 }
1188
1189 TEST_P(AiksTest, GaussianBlurOneDimension) {
1190 DisplayListBuilder builder;
1191
1192 builder.Scale(GetContentScale().x, GetContentScale().y);
1193 builder.Scale(0.5, 0.5);
1194
1195 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1196 builder.DrawImage(DlImageImpeller::Make(boston), DlPoint(100, 100), {});
1197
1198 DlPaint paint;
1199 paint.setBlendMode(DlBlendMode::kSrc);
1200
1201 auto backdrop_filter = DlImageFilter::MakeBlur(50, 0, DlTileMode::kClamp);
1202 builder.SaveLayer(std::nullopt, &paint, backdrop_filter.get());
1203 builder.Restore();
1204 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1205 }
1206
1207 // Smoketest to catch issues with the coverage hint.
1208 // Draws a rotated blurred image within a rectangle clip. The center of the clip
1209 // rectangle is the center of the rotated image. The entire area of the clip
1210 // rectangle should be filled with opaque colors output by the blur.
1211 TEST_P(AiksTest, GaussianBlurRotatedAndClipped) {
1212 DisplayListBuilder builder;
1213
1214 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1215 Rect bounds =
1216 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
1217
1218 DlPaint paint;
1219 paint.setImageFilter(DlImageFilter::MakeBlur(20, 20, DlTileMode::kDecal));
1220
1221 Vector2 image_center = Vector2(bounds.GetSize() / 2);
1222 Vector2 clip_size = {150, 75};
1223 Vector2 center = Vector2(1024, 768) / 2;
1224 builder.Scale(GetContentScale().x, GetContentScale().y);
1225
1226 auto clip_bounds =
1227 Rect::MakeLTRB(center.x, center.y, center.x, center.y).Expand(clip_size);
1228 builder.ClipRect(DlRect::MakeLTRB(clip_bounds.GetLeft(), clip_bounds.GetTop(),
1229 clip_bounds.GetRight(),
1230 clip_bounds.GetBottom()));
1231 builder.Translate(center.x, center.y);
1232 builder.Scale(0.6, 0.6);
1233 builder.Rotate(25);
1234
1235 auto dst_rect = bounds.Shift(-image_center);
1236 builder.DrawImageRect(
1237 DlImageImpeller::Make(boston), /*src=*/
1238 DlRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(), bounds.GetRight(),
1239 bounds.GetBottom()),
1240 /*dst=*/
1241 DlRect::MakeLTRB(dst_rect.GetLeft(), dst_rect.GetTop(),
1242 dst_rect.GetRight(), dst_rect.GetBottom()),
1243 DlImageSampling::kMipmapLinear, &paint);
1244
1245 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1246 }
1247
1248 TEST_P(AiksTest, GaussianBlurRotatedNonUniform) {
1249 auto callback = [&]() -> sk_sp<DisplayList> {
1250 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
1251 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
1252 DlTileMode::kMirror, DlTileMode::kDecal};
1253
1254 static float rotation = 45;
1255 static float scale = 0.6;
1256 static int selected_tile_mode = 3;
1257
1258 if (AiksTest::ImGuiBegin("Controls", nullptr,
1259 ImGuiWindowFlags_AlwaysAutoResize)) {
1260 ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
1261 ImGui::SliderFloat("Scale", &scale, 0, 2.0);
1262 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1263 sizeof(tile_mode_names) / sizeof(char*));
1264 ImGui::End();
1265 }
1266
1267 DisplayListBuilder builder;
1268
1269 DlPaint paint;
1270 paint.setColor(DlColor::kGreen());
1271 paint.setImageFilter(
1272 DlImageFilter::MakeBlur(50, 0, tile_modes[selected_tile_mode]));
1273
1274 Vector2 center = Vector2(1024, 768) / 2;
1275 builder.Scale(GetContentScale().x, GetContentScale().y);
1276 builder.Translate(center.x, center.y);
1277 builder.Scale(scale, scale);
1278 builder.Rotate(rotation);
1279
1280 DlRoundRect rrect =
1281 DlRoundRect::MakeRectXY(DlRect::MakeXYWH(-100, -100, 200, 200), 10, 10);
1282 builder.DrawRoundRect(rrect, paint);
1283 return builder.Build();
1284 };
1285
1286 ASSERT_TRUE(OpenPlaygroundHere(callback));
1287 }
1288
1289 TEST_P(AiksTest, BlurredRectangleWithShader) {
1290 DisplayListBuilder builder;
1291 builder.Scale(GetContentScale().x, GetContentScale().y);
1292
1293 auto paint_lines = [&builder](Scalar dx, Scalar dy, DlPaint paint) {
1294 auto draw_line = [&builder, &paint](DlPoint a, DlPoint b) {
1295 DlPath line = DlPath::MakeLine(a, b);
1296 builder.DrawPath(line, paint);
1297 };
1298 paint.setStrokeWidth(5);
1299 paint.setDrawStyle(DlDrawStyle::kStroke);
1300 draw_line(DlPoint(dx + 100, dy + 100), DlPoint(dx + 200, dy + 200));
1301 draw_line(DlPoint(dx + 100, dy + 200), DlPoint(dx + 200, dy + 100));
1302 draw_line(DlPoint(dx + 150, dy + 100), DlPoint(dx + 200, dy + 150));
1303 draw_line(DlPoint(dx + 100, dy + 150), DlPoint(dx + 150, dy + 200));
1304 };
1305
1306 AiksContext renderer(GetContext(), nullptr);
1307 DisplayListBuilder recorder_builder;
1308 for (int x = 0; x < 5; ++x) {
1309 for (int y = 0; y < 5; ++y) {
1310 DlRect rect = DlRect::MakeXYWH(x * 20, y * 20, 20, 20);
1311 DlPaint paint;
1312 paint.setColor(((x + y) & 1) == 0 ? DlColor::kYellow()
1313 : DlColor::kBlue());
1314
1315 recorder_builder.DrawRect(rect, paint);
1316 }
1317 }
1318 auto texture =
1319 DisplayListToTexture(recorder_builder.Build(), {100, 100}, renderer);
1320
1321 auto image_source = DlColorSource::MakeImage(
1322 DlImageImpeller::Make(texture), DlTileMode::kRepeat, DlTileMode::kRepeat);
1323 auto blur_filter = DlImageFilter::MakeBlur(5, 5, DlTileMode::kDecal);
1324
1325 DlPaint paint;
1326 paint.setColor(DlColor::kDarkGreen());
1327 builder.DrawRect(DlRect::MakeLTRB(0, 0, 300, 600), paint);
1328
1329 paint.setColorSource(image_source);
1330 builder.DrawRect(DlRect::MakeLTRB(100, 100, 200, 200), paint);
1331
1332 paint.setColorSource(nullptr);
1333 paint.setColor(DlColor::kRed());
1334 builder.DrawRect(DlRect::MakeLTRB(300, 0, 600, 600), paint);
1335
1336 paint.setColorSource(image_source);
1337 paint.setImageFilter(blur_filter);
1338 builder.DrawRect(DlRect::MakeLTRB(400, 100, 500, 200), paint);
1339
1340 paint.setImageFilter(nullptr);
1341 paint_lines(0, 300, paint);
1342
1343 paint.setImageFilter(blur_filter);
1344 paint_lines(300, 300, paint);
1345
1346 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1347 }
1348
1349 // This addresses a bug where tiny blurs could result in mip maps that beyond
1350 // the limits for the textures used for blurring.
1351 // See also: b/323402168
1352 TEST_P(AiksTest, GaussianBlurSolidColorTinyMipMap) {
1353 AiksContext renderer(GetContext(), nullptr);
1354
1355 for (int32_t i = 1; i < 5; ++i) {
1356 DisplayListBuilder builder;
1357 Scalar fi = i;
1358 DlPathBuilder path_builder;
1359 path_builder.MoveTo(DlPoint(100, 100));
1360 path_builder.LineTo(DlPoint(100 + fi, 100 + fi));
1361
1362 DlPaint paint;
1363 paint.setColor(DlColor::kChartreuse());
1364 auto blur_filter = DlImageFilter::MakeBlur(0.1, 0.1, DlTileMode::kClamp);
1365 paint.setImageFilter(blur_filter);
1366
1367 builder.DrawPath(path_builder.TakePath(), paint);
1368
1369 auto image = DisplayListToTexture(builder.Build(), {1024, 768}, renderer);
1370 EXPECT_TRUE(image) << " length " << i;
1371 }
1372 }
1373
1374 // This addresses a bug where tiny blurs could result in mip maps that beyond
1375 // the limits for the textures used for blurring.
1376 // See also: b/323402168
1377 TEST_P(AiksTest, GaussianBlurBackdropTinyMipMap) {
1378 AiksContext renderer(GetContext(), nullptr);
1379 for (int32_t i = 1; i < 5; ++i) {
1380 DisplayListBuilder builder;
1381
1382 ISize clip_size = ISize(i, i);
1383 builder.Save();
1384 builder.ClipRect(
1385 DlRect::MakeXYWH(400, 400, clip_size.width, clip_size.height));
1386
1387 DlPaint paint;
1388 paint.setColor(DlColor::kGreen());
1389 auto blur_filter = DlImageFilter::MakeBlur(0.1, 0.1, DlTileMode::kDecal);
1390 paint.setImageFilter(blur_filter);
1391
1392 builder.DrawCircle(DlPoint(400, 400), 200, paint);
1393 builder.Restore();
1394
1395 auto image = DisplayListToTexture(builder.Build(), {1024, 768}, renderer);
1396 EXPECT_TRUE(image) << " length " << i;
1397 }
1398 }
1399
1400 TEST_P(AiksTest,
1401 CanRenderMultipleBackdropBlurWithSingleBackdropIdDifferentLayers) {
1402 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
1403
1404 DisplayListBuilder builder;
1405
1406 DlPaint paint;
1407 builder.DrawImage(image, DlPoint(50.0, 50.0),
1408 DlImageSampling::kNearestNeighbor, &paint);
1409
1410 for (int i = 0; i < 6; i++) {
1411 if (i != 0) {
1412 DlPaint paint;
1413 paint.setColor(DlColor::kWhite().withAlphaF(0.95));
1414 builder.SaveLayer(std::nullopt, &paint);
1415 }
1416 DlRoundRect rrect = DlRoundRect::MakeRectXY(
1417 DlRect::MakeXYWH(50 + (i * 100), 250, 100, 100), 20, 20);
1418 builder.Save();
1419 builder.ClipRoundRect(rrect);
1420
1421 DlPaint save_paint;
1422 save_paint.setBlendMode(DlBlendMode::kSrc);
1423 auto backdrop_filter = DlImageFilter::MakeBlur(30, 30, DlTileMode::kClamp);
1424 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get(),
1425 /*backdrop_id=*/1);
1426 builder.Restore();
1427 builder.Restore();
1428 if (i != 0) {
1429 builder.Restore();
1430 }
1431 }
1432
1433 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1434 }
1435
1436 TEST_P(AiksTest, BlurGradientWithOpacity) {
1437 DisplayListBuilder builder;
1438 builder.Scale(GetContentScale().x, GetContentScale().y);
1439
1440 std::vector<DlColor> colors = {DlColor(0xFFFF0000), DlColor(0xFF00FF00)};
1441 std::vector<Scalar> stops = {0.0, 1.0};
1442
1443 auto gradient = DlColorSource::MakeLinear(
1444 {0, 0}, {400, 400}, 2, colors.data(), stops.data(), DlTileMode::kClamp);
1445
1446 DlPaint save_paint;
1447 save_paint.setOpacity(0.5);
1448 builder.SaveLayer(std::nullopt, &save_paint);
1449
1450 DlPaint paint;
1451 paint.setColorSource(gradient);
1452 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 1));
1453 builder.DrawRect(DlRect::MakeXYWH(100, 100, 200, 200), paint);
1454
1455 builder.Restore();
1456
1457 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1458 }
1459
1460 // The artifacts this test attempts to reproduce don't reproduce on playgrounds.
1461 // The test is animated as an attempt to catch any ghosting that may happen
1462 // when DontCare is used instead of Clear.
1463 // https://github.com/flutter/flutter/issues/171772
1464 TEST_P(AiksTest, CanRenderNestedBackdropBlur) {
1465 int64_t count = 0;
1466 auto callback = [&]() -> sk_sp<DisplayList> {
1467 DisplayListBuilder builder;
1468
1469 Scalar freq = 1.0;
1470 Scalar amp = 50.0;
1471 Scalar offset = amp * sin(freq * 2.0 * M_PI * count / 60.0);
1472
1473 // Draw some background content to be blurred.
1474 DlPaint paint;
1475 paint.setColor(DlColor::kCornflowerBlue());
1476 builder.DrawCircle(DlPoint(100 + offset, 100), 50, paint);
1477 paint.setColor(DlColor::kGreenYellow());
1478 builder.DrawCircle(DlPoint(300, 200 + offset), 100, paint);
1479 paint.setColor(DlColor::kDarkMagenta());
1480 builder.DrawCircle(DlPoint(140, 170), 75, paint);
1481 paint.setColor(DlColor::kOrangeRed());
1482 builder.DrawCircle(DlPoint(180 + offset, 120 + offset), 100, paint);
1483
1484 // This is the first backdrop blur, simulating the navigation transition.
1485 auto backdrop_filter1 = DlImageFilter::MakeBlur(15, 15, DlTileMode::kClamp);
1486 builder.SaveLayer(std::nullopt, nullptr, backdrop_filter1.get());
1487
1488 // Draw the semi-transparent container from the second screen.
1489 DlPaint transparent_paint;
1490 transparent_paint.setColor(DlColor::kWhite().withAlpha(0.1 * 255));
1491 builder.DrawPaint(transparent_paint);
1492
1493 {
1494 // This is the second, nested backdrop blur.
1495 auto backdrop_filter2 =
1496 DlImageFilter::MakeBlur(10, 10, DlTileMode::kClamp);
1497 builder.Save();
1498 builder.ClipRect(DlRect::MakeXYWH(150, 150, 300, 300));
1499 builder.SaveLayer(std::nullopt, nullptr, backdrop_filter2.get());
1500 builder.Restore(); // Restore from SaveLayer
1501 builder.Restore(); // Restore from ClipRect
1502 }
1503
1504 builder.Restore(); // Restore from the first SaveLayer
1505
1506 count++;
1507 return builder.Build();
1508 };
1509 ASSERT_TRUE(OpenPlaygroundHere(callback));
1510 }
1511
1512 } // namespace testing
1513 } // namespace impeller
MASK_BLUR_VARIANT_TEST
#define MASK_BLUR_VARIANT_TEST(config)
Definition: aiks_dl_blur_unittests.cc:722
aiks_unittests.h
impeller::AiksContext
Definition: aiks_context.h:20
impeller::AiksPlayground
Definition: aiks_playground.h:16
impeller::AiksPlayground::ImGuiBegin
static bool ImGuiBegin(const char *name, bool *p_open, ImGuiWindowFlags flags)
Definition: aiks_playground.cc:30
impeller::DlImageImpeller::Make
static sk_sp< DlImageImpeller > Make(std::shared_ptr< Texture > texture, OwningContext owning_context=OwningContext::kIO)
Definition: dl_image_impeller.cc:23
impeller::Playground::GetContentScale
Point GetContentScale() const
Definition: playground.cc:189
location
uint32_t location
Definition: compiler_unittests.cc:129
dl_dispatcher.h
x
int32_t x
Definition: dl_golden_unittests.cc:458
dl_image_impeller.h
flutter
Definition: dl_golden_blur_unittests.cc:16
impeller::saturated::b
SI b
Definition: saturated_math.h:87
impeller::testing::DoGradientOvalStrokeMaskBlur
sk_sp< flutter::DisplayList > DoGradientOvalStrokeMaskBlur(Vector2 content_Scale, Scalar sigma, DlBlurStyle style)
Definition: aiks_dl_blur_unittests.cc:63
impeller::testing::MaskBlurVariantTest
static sk_sp< DisplayList > MaskBlurVariantTest(const AiksTest &test_context, const MaskBlurTestConfig &config)
Definition: aiks_dl_blur_unittests.cc:598
impeller::testing::TEST_P
TEST_P(AiksTest, DrawAtlasNoColor)
Definition: aiks_dl_atlas_unittests.cc:59
impeller::testing::kPaintVariations
static const std::map< std::string, MaskBlurTestConfig > kPaintVariations
Definition: aiks_dl_blur_unittests.cc:679
impeller
Definition: allocation.cc:12
impeller::Vector2
Point Vector2
Definition: point.h:429
impeller::DlRect
flutter::DlRect DlRect
Definition: dl_dispatcher.h:25
impeller::Scalar
float Scalar
Definition: scalar.h:19
impeller::DrawPlaygroundPoint
Point DrawPlaygroundPoint(PlaygroundPoint &point)
Definition: widgets.cc:11
impeller::DrawPlaygroundLine
std::tuple< Point, Point > DrawPlaygroundLine(PlaygroundPoint &point_a, PlaygroundPoint &point_b)
Definition: widgets.cc:51
impeller::DisplayListToTexture
std::shared_ptr< Texture > DisplayListToTexture(const sk_sp< flutter::DisplayList > &display_list, ISize size, AiksContext &context, bool reset_host_buffer, bool generate_mips, std::optional< PixelFormat > target_pixel_format)
Render the provided display list to a texture with the given size.
Definition: dl_dispatcher.cc:1220
impeller::DlRoundRect
flutter::DlRoundRect DlRoundRect
Definition: dl_dispatcher.h:27
impeller::Point
TPoint< Scalar > Point
Definition: point.h:425
impeller::PixelFormat::kB10G10R10A10XR
@ kB10G10R10A10XR
impeller::DlPoint
flutter::DlPoint DlPoint
Definition: dl_dispatcher.h:24
impeller::DlPath
flutter::DlPath DlPath
Definition: dl_dispatcher.h:29
impeller::ISize
ISize64 ISize
Definition: size.h:162
impeller::Color::White
static constexpr Color White()
Definition: color.h:264
impeller::Color::Red
static constexpr Color Red()
Definition: color.h:272
impeller::Color::AntiqueWhite
static constexpr Color AntiqueWhite()
Definition: color.h:286
impeller::Color::Green
static constexpr Color Green()
Definition: color.h:274
impeller::Degrees
Definition: scalar.h:66
impeller::Matrix::MakeTranslation
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition: matrix.h:95
impeller::Matrix::MakeScale
static constexpr Matrix MakeScale(const Vector3 &s)
Definition: matrix.h:104
impeller::PlaygroundPoint
Definition: widgets.h:21
impeller::Radius
For convolution filters, the "radius" is the size of the convolution kernel to use on the local space...
Definition: sigma.h:48
impeller::Sigma
In filters that use Gaussian distributions, "sigma" is a size of one standard deviation in terms of t...
Definition: sigma.h:32
impeller::Sigma::sigma
Scalar sigma
Definition: sigma.h:33
impeller::TPoint< Scalar >
impeller::TPoint::Rotate
constexpr TPoint Rotate(const Radians &angle) const
Definition: point.h:314
impeller::TPoint::y
Type y
Definition: point.h:32
impeller::TPoint::x
Type x
Definition: point.h:31
impeller::TRect< Scalar >
impeller::TRect::Expand
constexpr TRect< T > Expand(T left, T top, T right, T bottom) const
Returns a rectangle with expanded edges. Negative expansion results in shrinking.
Definition: rect.h:618
impeller::TRect::GetBottom
constexpr auto GetBottom() const
Definition: rect.h:357
impeller::TRect::GetTop
constexpr auto GetTop() const
Definition: rect.h:353
impeller::TRect::GetLeft
constexpr auto GetLeft() const
Definition: rect.h:351
impeller::TRect::GetSize
constexpr TSize< Type > GetSize() const
Returns the size of the rectangle which may be negative in either width or height and may have been c...
Definition: rect.h:327
impeller::TRect::GetRight
constexpr auto GetRight() const
Definition: rect.h:355
impeller::TRect< Scalar >::MakeXYWH
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:136
impeller::TRect::Shift
constexpr TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
Definition: rect.h:602
impeller::TRect< Scalar >::MakeLTRB
constexpr static TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition: rect.h:129
impeller::TSize
Definition: size.h:25
impeller::TSize::height
Type height
Definition: size.h:29
impeller::TSize::width
Type width
Definition: size.h:28
impeller::testing::MaskBlurTestConfig
Definition: aiks_dl_blur_unittests.cc:589
impeller::testing::MaskBlurTestConfig::blend_mode
DlBlendMode blend_mode
Definition: aiks_dl_blur_unittests.cc:595
impeller::testing::MaskBlurTestConfig::invert_colors
bool invert_colors
Definition: aiks_dl_blur_unittests.cc:594
impeller::testing::MaskBlurTestConfig::alpha
Scalar alpha
Definition: aiks_dl_blur_unittests.cc:592
impeller::testing::MaskBlurTestConfig::style
DlBlurStyle style
Definition: aiks_dl_blur_unittests.cc:590
impeller::testing::MaskBlurTestConfig::image_filter
std::shared_ptr< DlImageFilter > image_filter
Definition: aiks_dl_blur_unittests.cc:593
impeller::testing::MaskBlurTestConfig::sigma
Scalar sigma
Definition: aiks_dl_blur_unittests.cc:591
widgets.h