Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
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
19
20#include "gmock/gmock.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
32namespace impeller {
33namespace testing {
34
35using namespace flutter;
36
37// The shapes of these ovals should appear equal. They are demonstrating the
38// difference between the fast pass and not.
39TEST_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(),
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
63sk_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);
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
104TEST_P(AiksTest, GradientOvalStrokeMaskBlur) {
105 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
106 GetContentScale(), /*sigma=*/10, DlBlurStyle::kNormal)));
107}
108
109TEST_P(AiksTest, GradientOvalStrokeMaskBlurSigmaZero) {
110 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
111 GetContentScale(), /*sigma=*/0, DlBlurStyle::kNormal)));
112}
113
114TEST_P(AiksTest, GradientOvalStrokeMaskBlurOuter) {
115 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
116 GetContentScale(), /*sigma=*/10, DlBlurStyle::kOuter)));
117}
118
119TEST_P(AiksTest, GradientOvalStrokeMaskBlurInner) {
120 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
121 GetContentScale(), /*sigma=*/10, DlBlurStyle::kInner)));
122}
123
124TEST_P(AiksTest, GradientOvalStrokeMaskBlurSolid) {
125 ASSERT_TRUE(OpenPlaygroundHere(DoGradientOvalStrokeMaskBlur(
126 GetContentScale(), /*sigma=*/10, DlBlurStyle::kSolid)));
127}
128
129TEST_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);
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
153TEST_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
165TEST_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
184TEST_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
205TEST_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;
214 builder.DrawCircle(DlPoint(100, 100), 50, paint);
215
217 builder.DrawCircle(DlPoint(300, 200), 100, paint);
218
220 builder.DrawCircle(DlPoint(140, 170), 75, paint);
221
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
242TEST_P(AiksTest, CanRenderBackdropBlur) {
243 DisplayListBuilder builder;
244
245 DlPaint paint;
247 builder.DrawCircle(DlPoint(100, 100), 50, paint);
248
250 builder.DrawCircle(DlPoint(300, 200), 100, paint);
251
253 builder.DrawCircle(DlPoint(140, 170), 75, paint);
254
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
271TEST_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
296TEST_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++) {
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
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++) {
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
352TEST_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
370TEST_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
412TEST_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
425TEST_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 =
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
450TEST_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 =
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
475TEST_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
499TEST_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
516TEST_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
531TEST_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
554TEST_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
567TEST_P(AiksTest, MaskBlurOnZeroDimensionIsSkippedWideGamut) {
568 // Must be called before any methods that use the context to ensure that
569 // this test is always run with wide gamut support.
570 if (!EnsureContextSupportsWideGamut()) {
571 GTEST_SKIP() << "This backend doesn't yet support wide gamut.";
572 }
573
574 // Making sure this test is run on a wide gamut enabled backend
575 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
577
578 DisplayListBuilder builder;
579 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
580
581 DlPaint paint;
582 paint.setColor(DlColor::kBlue());
583 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 10));
584
585 // Zero height above
586 builder.DrawRect(DlRect::MakeLTRB(100, 250, 500, 250), paint);
587 // Regular rect
588 builder.DrawRect(DlRect::MakeLTRB(100, 300, 500, 600), paint);
589 // Zero width to the right
590 builder.DrawRect(DlRect::MakeLTRB(550, 300, 550, 600), paint);
591
592 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
593}
594
596 DlBlurStyle style = DlBlurStyle::kNormal;
597 Scalar sigma = 1.0f;
598 Scalar alpha = 1.0f;
599 std::shared_ptr<DlImageFilter> image_filter;
600 bool invert_colors = false;
601 DlBlendMode blend_mode = DlBlendMode::kSrcOver;
602};
603
604static sk_sp<DisplayList> MaskBlurVariantTest(
605 const AiksTest& test_context,
606 const MaskBlurTestConfig& config) {
607 DisplayListBuilder builder;
608 builder.Scale(test_context.GetContentScale().x,
609 test_context.GetContentScale().y);
610 builder.Scale(0.8f, 0.8f);
611 builder.Translate(50.f, 50.f);
612
613 DlPaint draw_paint;
614 draw_paint.setColor(
617 builder.DrawPaint(draw_paint);
618
619 DlPaint paint;
620 paint.setMaskFilter(DlBlurMaskFilter::Make(config.style, config.sigma));
621 paint.setInvertColors(config.invert_colors);
622 paint.setImageFilter(config.image_filter);
623 paint.setBlendMode(config.blend_mode);
624
625 const Scalar x = 50;
626 const Scalar radius = 20.0f;
627 const Scalar y_spacing = 100.0f;
628 Scalar alpha = config.alpha * 255;
629
630 Scalar y = 50;
631 paint.setColor(DlColor::kCrimson().withAlpha(alpha));
632 builder.DrawRect(DlRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
633 radius, 60.0f - radius),
634 paint);
635
636 y += y_spacing;
637 paint.setColor(DlColor::kBlue().withAlpha(alpha));
638 builder.DrawCircle(DlPoint{x + 25, y + 25}, radius, paint);
639
640 y += y_spacing;
641 paint.setColor(DlColor::kGreen().withAlpha(alpha));
642 builder.DrawOval(DlRect::MakeXYWH(x + 25 - radius / 2, y + radius / 2, //
643 radius, 60.0f - radius),
644 paint);
645
646 y += y_spacing;
647 paint.setColor(DlColor::kPurple().withAlpha(alpha));
649 DlRect::MakeXYWH(x, y, 60.0f, 60.0f), radius, radius);
650 builder.DrawRoundRect(rrect, paint);
651
652 y += y_spacing;
653 paint.setColor(DlColor::kOrange().withAlpha(alpha));
654
655 rrect = DlRoundRect::MakeRectXY(DlRect::MakeXYWH(x, y, 60.0f, 60.0f), //
656 radius, 5.0);
657 builder.DrawRoundRect(rrect, paint);
658
659 y += y_spacing;
660 paint.setColor(DlColor::kMaroon().withAlpha(alpha));
661
662 {
663 DlPathBuilder path_builder;
664 path_builder.MoveTo(DlPoint(x + 0, y + 60));
665 path_builder.LineTo(DlPoint(x + 30, y + 0));
666 path_builder.LineTo(DlPoint(x + 60, y + 60));
667 path_builder.Close();
668
669 builder.DrawPath(path_builder.TakePath(), paint);
670 }
671
672 y += y_spacing;
673 paint.setColor(DlColor::kMaroon().withAlpha(alpha));
674 {
675 DlPath path = DlPath::MakeArc(Rect::MakeXYWH(x + 5, y, 50, 50), //
676 Degrees(90), Degrees(180), false) +
677 DlPath::MakeArc(Rect::MakeXYWH(x + 25, y, 50, 50), //
678 Degrees(90), Degrees(180), false);
679 builder.DrawPath(path, paint);
680 }
681
682 return builder.Build();
683}
684
685static const std::map<std::string, MaskBlurTestConfig> kPaintVariations = {
686 // 1. Normal style, translucent, zero sigma.
687 {"NormalTranslucentZeroSigma",
688 {.style = DlBlurStyle::kNormal, .sigma = 0.0f, .alpha = 0.5f}},
689 // 2. Normal style, translucent.
690 {"NormalTranslucent",
691 {.style = DlBlurStyle::kNormal, .sigma = 8.0f, .alpha = 0.5f}},
692 // 3. Solid style, translucent.
693 {"SolidTranslucent",
694 {.style = DlBlurStyle::kSolid, .sigma = 8.0f, .alpha = 0.5f}},
695 // 4. Solid style, opaque.
696 {"SolidOpaque", {.style = DlBlurStyle::kSolid, .sigma = 8.0f}},
697 // 5. Solid style, translucent, color & image filtered.
698 {"SolidTranslucentWithFilters",
699 {.style = DlBlurStyle::kSolid,
700 .sigma = 8.0f,
701 .alpha = 0.5f,
702 .image_filter = DlImageFilter::MakeBlur(3, 3, DlTileMode::kClamp),
703 .invert_colors = true}},
704 // 6. Solid style, translucent, exclusion blended.
705 {"SolidTranslucentExclusionBlend",
706 {.style = DlBlurStyle::kSolid,
707 .sigma = 8.0f,
708 .alpha = 0.5f,
709 .blend_mode = DlBlendMode::kExclusion}},
710 // 7. Inner style, translucent.
711 {"InnerTranslucent",
712 {.style = DlBlurStyle::kInner, .sigma = 8.0f, .alpha = 0.5f}},
713 // 8. Inner style, translucent, blurred.
714 {"InnerTranslucentWithBlurImageFilter",
715 {.style = DlBlurStyle::kInner,
716 .sigma = 8.0f,
717 .alpha = 0.5f,
718 .image_filter = DlImageFilter::MakeBlur(3, 3, DlTileMode::kClamp)}},
719 // 9. Outer style, translucent.
720 {"OuterTranslucent",
721 {.style = DlBlurStyle::kOuter, .sigma = 8.0f, .alpha = 0.5f}},
722 // 10. Outer style, opaque, image filtered.
723 {"OuterOpaqueWithBlurImageFilter",
724 {.style = DlBlurStyle::kOuter,
725 .sigma = 8.0f,
726 .image_filter = DlImageFilter::MakeBlur(3, 3, DlTileMode::kClamp)}}};
727
728#define MASK_BLUR_VARIANT_TEST(config) \
729 TEST_P(AiksTest, MaskBlurVariantTest##config) { \
730 ASSERT_TRUE(OpenPlaygroundHere( \
731 MaskBlurVariantTest(*this, kPaintVariations.at(#config)))); \
732 }
733
734MASK_BLUR_VARIANT_TEST(NormalTranslucentZeroSigma)
735MASK_BLUR_VARIANT_TEST(NormalTranslucent)
736MASK_BLUR_VARIANT_TEST(SolidTranslucent)
737MASK_BLUR_VARIANT_TEST(SolidOpaque)
738MASK_BLUR_VARIANT_TEST(SolidTranslucentWithFilters)
739MASK_BLUR_VARIANT_TEST(SolidTranslucentExclusionBlend)
740MASK_BLUR_VARIANT_TEST(InnerTranslucent)
741MASK_BLUR_VARIANT_TEST(InnerTranslucentWithBlurImageFilter)
742MASK_BLUR_VARIANT_TEST(OuterTranslucent)
743MASK_BLUR_VARIANT_TEST(OuterOpaqueWithBlurImageFilter)
744
745#undef MASK_BLUR_VARIANT_TEST
746
747TEST_P(AiksTest, GaussianBlurStyleInner) {
748 DisplayListBuilder builder;
749 builder.Scale(GetContentScale().x, GetContentScale().y);
750
751 DlPaint paint;
752 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1));
753 builder.DrawPaint(paint);
754
755 paint.setColor(DlColor::kGreen());
756 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kInner, 30));
757
758 DlPathBuilder path_builder;
759 path_builder.MoveTo(DlPoint(200, 200));
760 path_builder.LineTo(DlPoint(300, 400));
761 path_builder.LineTo(DlPoint(100, 400));
762 path_builder.Close();
763
764 builder.DrawPath(path_builder.TakePath(), paint);
765
766 // Draw another thing to make sure the clip area is reset.
767 DlPaint red;
768 red.setColor(DlColor::kRed());
769 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
770
771 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
772}
773
774TEST_P(AiksTest, GaussianBlurStyleOuter) {
775 DisplayListBuilder builder;
776 builder.Scale(GetContentScale().x, GetContentScale().y);
777
778 DlPaint paint;
779 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
780 builder.DrawPaint(paint);
781
782 paint.setColor(DlColor::kGreen());
783 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kOuter, 30));
784
785 DlPathBuilder path_builder;
786 path_builder.MoveTo(DlPoint(200, 200));
787 path_builder.LineTo(DlPoint(300, 400));
788 path_builder.LineTo(DlPoint(100, 400));
789 path_builder.Close();
790
791 builder.DrawPath(path_builder.TakePath(), paint);
792
793 // Draw another thing to make sure the clip area is reset.
794 DlPaint red;
795 red.setColor(DlColor::kRed());
796 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
797
798 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
799}
800
801TEST_P(AiksTest, GaussianBlurStyleSolid) {
802 DisplayListBuilder builder;
803 builder.Scale(GetContentScale().x, GetContentScale().y);
804
805 DlPaint paint;
806 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
807 builder.DrawPaint(paint);
808
809 paint.setColor(DlColor::kGreen());
810 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kSolid, 30));
811
812 DlPathBuilder path_builder;
813 path_builder.MoveTo(DlPoint(200, 200));
814 path_builder.LineTo(DlPoint(300, 400));
815 path_builder.LineTo(DlPoint(100, 400));
816 path_builder.Close();
817
818 builder.DrawPath(path_builder.TakePath(), paint);
819
820 // Draw another thing to make sure the clip area is reset.
821 DlPaint red;
822 red.setColor(DlColor::kRed());
823 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
824
825 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
826}
827
828TEST_P(AiksTest, MaskBlurTexture) {
829 Scalar sigma = 30;
830 auto callback = [&]() -> sk_sp<DisplayList> {
831 if (AiksTest::ImGuiBegin("Controls", nullptr,
832 ImGuiWindowFlags_AlwaysAutoResize)) {
833 ImGui::SliderFloat("Sigma", &sigma, 0, 500);
834 ImGui::End();
835 }
836
837 DisplayListBuilder builder;
838 builder.Scale(GetContentScale().x, GetContentScale().y);
839
840 DlPaint paint;
841 paint.setColor(DlColor::kGreen());
842 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
843
844 builder.DrawImage(
845 DlImageImpeller::Make(CreateTextureForFixture("boston.jpg")),
846 DlPoint(200, 200), DlImageSampling::kNearestNeighbor, &paint);
847
848 DlPaint red;
849 red.setColor(DlColor::kRed());
850 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
851
852 return builder.Build();
853 };
854 ASSERT_TRUE(OpenPlaygroundHere(callback));
855}
856
857TEST_P(AiksTest, MaskBlurDoesntStretchContents) {
858 Scalar sigma = 70;
859 auto callback = [&]() -> sk_sp<DisplayList> {
860 if (AiksTest::ImGuiBegin("Controls", nullptr,
861 ImGuiWindowFlags_AlwaysAutoResize)) {
862 ImGui::SliderFloat("Sigma", &sigma, 0, 500);
863 ImGui::End();
864 }
865
866 DisplayListBuilder builder;
867 builder.Scale(GetContentScale().x, GetContentScale().y);
868
869 DlPaint paint;
870 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
871 builder.DrawPaint(paint);
872
873 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
874
875 builder.Transform(Matrix::MakeTranslation({100, 100}) *
876 Matrix::MakeScale({0.5, 0.5, 1.0f}));
877
879 DlImageImpeller::Make(boston), DlTileMode::kRepeat, DlTileMode::kRepeat,
880 DlImageSampling::kMipmapLinear));
881 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, sigma));
882
883 builder.DrawRect(DlRect::MakeXYWH(0, 0, boston->GetSize().width,
884 boston->GetSize().height),
885 paint);
886
887 return builder.Build();
888 };
889 ASSERT_TRUE(OpenPlaygroundHere(callback));
890}
891
892TEST_P(AiksTest, GaussianBlurAtPeripheryVertical) {
893 DisplayListBuilder builder;
894
895 DlPaint paint;
896 builder.Scale(GetContentScale().x, GetContentScale().y);
897
900 DlRect::MakeLTRB(0, 0, GetWindowSize().width, 100), 10, 10);
901 builder.DrawRoundRect(rrect, paint);
902
905 DlRect::MakeLTRB(0, 110, GetWindowSize().width, 210), 10, 10);
906 builder.DrawRoundRect(rrect, paint);
907 builder.ClipRect(DlRect::MakeLTRB(100, 0, 200, GetWindowSize().height));
908
909 DlPaint save_paint;
910 save_paint.setBlendMode(DlBlendMode::kSrc);
911
912 auto backdrop_filter = DlImageFilter::MakeBlur(20, 20, DlTileMode::kClamp);
913
914 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get());
915 builder.Restore();
916
917 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
918}
919
920TEST_P(AiksTest, GaussianBlurAtPeripheryHorizontal) {
921 DisplayListBuilder builder;
922
923 builder.Scale(GetContentScale().x, GetContentScale().y);
924 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
925 builder.DrawImageRect(
926 DlImageImpeller::Make(boston),
927 DlRect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height),
928 DlRect::MakeLTRB(0, 0, GetWindowSize().width, 100),
929 DlImageSampling::kNearestNeighbor);
930
931 DlPaint paint;
933
935 DlRect::MakeLTRB(0, 110, GetWindowSize().width, 210), 10, 10);
936 builder.DrawRoundRect(rrect, paint);
937 builder.ClipRect(DlRect::MakeLTRB(0, 50, GetWindowSize().width, 150));
938
939 DlPaint save_paint;
940 save_paint.setBlendMode(DlBlendMode::kSrc);
941
942 auto backdrop_filter = DlImageFilter::MakeBlur(20, 20, DlTileMode::kClamp);
943 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get());
944
945 builder.Restore();
946 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
947}
948
949TEST_P(AiksTest, GaussianBlurAnimatedBackdrop) {
950 // This test is for checking out how stable rendering is when content is
951 // translated underneath a blur. Animating under a blur can cause
952 // *shimmering* to happen as a result of pixel alignment.
953 // See also: https://github.com/flutter/flutter/issues/140193
954 auto boston =
955 CreateTextureForFixture("boston.jpg", /*enable_mipmapping=*/true);
956 ASSERT_TRUE(boston);
957 int64_t count = 0;
958 Scalar sigma = 20.0;
959 Scalar freq = 0.1;
960 Scalar amp = 50.0;
961 auto callback = [&]() -> sk_sp<DisplayList> {
962 if (AiksTest::ImGuiBegin("Controls", nullptr,
963 ImGuiWindowFlags_AlwaysAutoResize)) {
964 ImGui::SliderFloat("Sigma", &sigma, 0, 200);
965 ImGui::SliderFloat("Frequency", &freq, 0.01, 2.0);
966 ImGui::SliderFloat("Amplitude", &amp, 1, 100);
967 ImGui::End();
968 }
969
970 DisplayListBuilder builder;
971 builder.Scale(GetContentScale().x, GetContentScale().y);
972 Scalar y = amp * sin(freq * 2.0 * M_PI * count / 60);
973 builder.DrawImage(DlImageImpeller::Make(boston),
974 DlPoint(1024 / 2 - boston->GetSize().width / 2,
975 (768 / 2 - boston->GetSize().height / 2) + y),
976 DlImageSampling::kMipmapLinear);
977 static PlaygroundPoint point_a(Point(100, 100), 20, Color::Red());
978 static PlaygroundPoint point_b(Point(900, 700), 20, Color::Red());
979 auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
980
981 builder.ClipRect(
982 DlRect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
983 builder.ClipRect(DlRect::MakeLTRB(100, 100, 900, 700));
984
985 DlPaint paint;
986 paint.setBlendMode(DlBlendMode::kSrc);
987
988 auto backdrop_filter =
989 DlImageFilter::MakeBlur(sigma, sigma, DlTileMode::kClamp);
990 builder.SaveLayer(std::nullopt, &paint, backdrop_filter.get());
991 count += 1;
992 return builder.Build();
993 };
994 ASSERT_TRUE(OpenPlaygroundHere(callback));
995}
996
997TEST_P(AiksTest, GaussianBlurStyleInnerGradient) {
998 DisplayListBuilder builder;
999
1000 builder.Scale(GetContentScale().x, GetContentScale().y);
1001
1002 DlPaint paint;
1003 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
1004 builder.DrawPaint(paint);
1005
1006 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
1007 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
1008 std::vector<Scalar> stops = {0.0, 1.0};
1009
1010 paint = DlPaint{};
1012 /*start_point=*/{0, 0},
1013 /*end_point=*/{200, 200},
1014 /*stop_count=*/colors.size(),
1015 /*colors=*/colors.data(),
1016 /*stops=*/stops.data(),
1017 /*tile_mode=*/DlTileMode::kMirror));
1018 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kInner, 30));
1019
1020 DlPathBuilder path_builder;
1021 path_builder.MoveTo(DlPoint(200, 200));
1022 path_builder.LineTo(DlPoint(300, 400));
1023 path_builder.LineTo(DlPoint(100, 400));
1024 path_builder.Close();
1025 builder.DrawPath(path_builder.TakePath(), paint);
1026
1027 // Draw another thing to make sure the clip area is reset.
1028 DlPaint red;
1029 red.setColor(DlColor::kRed());
1030 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
1031
1032 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1033}
1034
1035TEST_P(AiksTest, GaussianBlurStyleSolidGradient) {
1036 DisplayListBuilder builder;
1037 builder.Scale(GetContentScale().x, GetContentScale().y);
1038
1039 DlPaint paint;
1040 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
1041 builder.DrawPaint(paint);
1042
1043 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
1044 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
1045 std::vector<Scalar> stops = {0.0, 1.0};
1046
1047 paint = DlPaint{};
1049 /*start_point=*/{0, 0},
1050 /*end_point=*/{200, 200},
1051 /*stop_count=*/colors.size(),
1052 /*colors=*/colors.data(),
1053 /*stops=*/stops.data(),
1054 /*tile_mode=*/DlTileMode::kMirror));
1055 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kSolid, 30));
1056
1057 DlPathBuilder path_builder;
1058 path_builder.MoveTo(DlPoint(200, 200));
1059 path_builder.LineTo(DlPoint(300, 400));
1060 path_builder.LineTo(DlPoint(100, 400));
1061 path_builder.Close();
1062 builder.DrawPath(path_builder.TakePath(), paint);
1063
1064 // Draw another thing to make sure the clip area is reset.
1065 DlPaint red;
1066 red.setColor(DlColor::kRed());
1067 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
1068 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1069}
1070
1071TEST_P(AiksTest, GaussianBlurStyleOuterGradient) {
1072 DisplayListBuilder builder;
1073 builder.Scale(GetContentScale().x, GetContentScale().y);
1074
1075 DlPaint paint;
1076 paint.setColor(DlColor::RGBA(0.1, 0.1, 0.1, 1.0));
1077 builder.DrawPaint(paint);
1078
1079 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
1080 DlColor::RGBA(0.7568, 0.2627, 0.2118, 1.0)};
1081 std::vector<Scalar> stops = {0.0, 1.0};
1082
1083 paint = DlPaint{};
1085 /*start_point=*/{0, 0},
1086 /*end_point=*/{200, 200},
1087 /*stop_count=*/colors.size(),
1088 /*colors=*/colors.data(),
1089 /*stops=*/stops.data(),
1090 /*tile_mode=*/DlTileMode::kMirror));
1091 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kOuter, 30));
1092
1093 DlPathBuilder path_builder;
1094 path_builder.MoveTo(DlPoint(200, 200));
1095 path_builder.LineTo(DlPoint(300, 400));
1096 path_builder.LineTo(DlPoint(100, 400));
1097 path_builder.Close();
1098 builder.DrawPath(path_builder.TakePath(), paint);
1099
1100 // Draw another thing to make sure the clip area is reset.
1101 DlPaint red;
1102 red.setColor(DlColor::kRed());
1103 builder.DrawRect(DlRect::MakeXYWH(0, 0, 200, 200), red);
1104 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1105}
1106
1107TEST_P(AiksTest, GaussianBlurScaledAndClipped) {
1108 DisplayListBuilder builder;
1109 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1110 Rect bounds =
1111 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
1112 Vector2 image_center = Vector2(bounds.GetSize() / 2);
1113
1114 DlPaint paint;
1115 paint.setImageFilter(DlImageFilter::MakeBlur(20, 20, DlTileMode::kDecal));
1116
1117 Vector2 clip_size = {150, 75};
1118 Vector2 center = Vector2(1024, 768) / 2;
1119 builder.Scale(GetContentScale().x, GetContentScale().y);
1120
1121 auto rect = Rect::MakeEllipseBounds(center, clip_size);
1122 builder.ClipRect(DlRect::MakeLTRB(rect.GetLeft(), rect.GetTop(),
1123 rect.GetRight(), rect.GetBottom()));
1124 builder.Translate(center.x, center.y);
1125 builder.Scale(0.6, 0.6);
1126
1127 DlRect sk_bounds = DlRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(),
1128 bounds.GetRight(), bounds.GetBottom());
1129 Rect dest = bounds.Shift(-image_center);
1130 DlRect sk_dst = DlRect::MakeLTRB(dest.GetLeft(), dest.GetTop(),
1131 dest.GetRight(), dest.GetBottom());
1132 builder.DrawImageRect(DlImageImpeller::Make(boston), /*src=*/sk_bounds,
1133 /*dst=*/sk_dst, DlImageSampling::kNearestNeighbor,
1134 &paint);
1135
1136 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1137}
1138
1139TEST_P(AiksTest, GaussianBlurRotatedAndClippedInteractive) {
1140 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1141
1142 auto callback = [&]() -> sk_sp<DisplayList> {
1143 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
1144 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
1145 DlTileMode::kMirror, DlTileMode::kDecal};
1146
1147 static float rotation = 0;
1148 static float scale = 0.6;
1149 static int selected_tile_mode = 3;
1150
1151 if (AiksTest::ImGuiBegin("Controls", nullptr,
1152 ImGuiWindowFlags_AlwaysAutoResize)) {
1153 ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
1154 ImGui::SliderFloat("Scale", &scale, 0, 2.0);
1155 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1156 sizeof(tile_mode_names) / sizeof(char*));
1157 ImGui::End();
1158 }
1159
1160 DisplayListBuilder builder;
1161 Rect bounds =
1162 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
1163 Vector2 image_center = Vector2(bounds.GetSize() / 2);
1164 DlPaint paint;
1165 paint.setImageFilter(
1166 DlImageFilter::MakeBlur(20, 20, tile_modes[selected_tile_mode]));
1167
1168 static PlaygroundPoint point_a(Point(362, 309), 20, Color::Red());
1169 static PlaygroundPoint point_b(Point(662, 459), 20, Color::Red());
1170 auto [handle_a, handle_b] = DrawPlaygroundLine(point_a, point_b);
1171 Vector2 center = Vector2(1024, 768) / 2;
1172
1173 builder.Scale(GetContentScale().x, GetContentScale().y);
1174 builder.ClipRect(
1175 DlRect::MakeLTRB(handle_a.x, handle_a.y, handle_b.x, handle_b.y));
1176 builder.Translate(center.x, center.y);
1177 builder.Scale(scale, scale);
1178 builder.Rotate(rotation);
1179
1180 DlRect sk_bounds = DlRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(),
1181 bounds.GetRight(), bounds.GetBottom());
1182 Rect dest = bounds.Shift(-image_center);
1183 DlRect sk_dst = DlRect::MakeLTRB(dest.GetLeft(), dest.GetTop(),
1184 dest.GetRight(), dest.GetBottom());
1185 builder.DrawImageRect(DlImageImpeller::Make(boston), /*src=*/sk_bounds,
1186 /*dst=*/sk_dst, DlImageSampling::kNearestNeighbor,
1187 &paint);
1188 return builder.Build();
1189 };
1190
1191 ASSERT_TRUE(OpenPlaygroundHere(callback));
1192}
1193
1194TEST_P(AiksTest, GaussianBlurOneDimension) {
1195 DisplayListBuilder builder;
1196
1197 builder.Scale(GetContentScale().x, GetContentScale().y);
1198 builder.Scale(0.5, 0.5);
1199
1200 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1201 builder.DrawImage(DlImageImpeller::Make(boston), DlPoint(100, 100), {});
1202
1203 DlPaint paint;
1204 paint.setBlendMode(DlBlendMode::kSrc);
1205
1206 auto backdrop_filter = DlImageFilter::MakeBlur(50, 0, DlTileMode::kClamp);
1207 builder.SaveLayer(std::nullopt, &paint, backdrop_filter.get());
1208 builder.Restore();
1209 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1210}
1211
1212// Smoketest to catch issues with the coverage hint.
1213// Draws a rotated blurred image within a rectangle clip. The center of the clip
1214// rectangle is the center of the rotated image. The entire area of the clip
1215// rectangle should be filled with opaque colors output by the blur.
1216TEST_P(AiksTest, GaussianBlurRotatedAndClipped) {
1217 DisplayListBuilder builder;
1218
1219 std::shared_ptr<Texture> boston = CreateTextureForFixture("boston.jpg");
1220 Rect bounds =
1221 Rect::MakeXYWH(0, 0, boston->GetSize().width, boston->GetSize().height);
1222
1223 DlPaint paint;
1224 paint.setImageFilter(DlImageFilter::MakeBlur(20, 20, DlTileMode::kDecal));
1225
1226 Vector2 image_center = Vector2(bounds.GetSize() / 2);
1227 Vector2 clip_size = {150, 75};
1228 Vector2 center = Vector2(1024, 768) / 2;
1229 builder.Scale(GetContentScale().x, GetContentScale().y);
1230
1231 auto clip_bounds = Rect::MakeEllipseBounds(center, clip_size);
1232 builder.ClipRect(DlRect::MakeLTRB(clip_bounds.GetLeft(), clip_bounds.GetTop(),
1233 clip_bounds.GetRight(),
1234 clip_bounds.GetBottom()));
1235 builder.Translate(center.x, center.y);
1236 builder.Scale(0.6, 0.6);
1237 builder.Rotate(25);
1238
1239 auto dst_rect = bounds.Shift(-image_center);
1240 builder.DrawImageRect(
1241 DlImageImpeller::Make(boston), /*src=*/
1242 DlRect::MakeLTRB(bounds.GetLeft(), bounds.GetTop(), bounds.GetRight(),
1243 bounds.GetBottom()),
1244 /*dst=*/
1245 DlRect::MakeLTRB(dst_rect.GetLeft(), dst_rect.GetTop(),
1246 dst_rect.GetRight(), dst_rect.GetBottom()),
1247 DlImageSampling::kMipmapLinear, &paint);
1248
1249 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1250}
1251
1252TEST_P(AiksTest, GaussianBlurRotatedNonUniform) {
1253 auto callback = [&]() -> sk_sp<DisplayList> {
1254 const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"};
1255 const DlTileMode tile_modes[] = {DlTileMode::kClamp, DlTileMode::kRepeat,
1256 DlTileMode::kMirror, DlTileMode::kDecal};
1257
1258 static float rotation = 45;
1259 static float scale = 0.6;
1260 static int selected_tile_mode = 3;
1261
1262 if (AiksTest::ImGuiBegin("Controls", nullptr,
1263 ImGuiWindowFlags_AlwaysAutoResize)) {
1264 ImGui::SliderFloat("Rotation (degrees)", &rotation, -180, 180);
1265 ImGui::SliderFloat("Scale", &scale, 0, 2.0);
1266 ImGui::Combo("Tile mode", &selected_tile_mode, tile_mode_names,
1267 sizeof(tile_mode_names) / sizeof(char*));
1268 ImGui::End();
1269 }
1270
1271 DisplayListBuilder builder;
1272
1273 DlPaint paint;
1274 paint.setColor(DlColor::kGreen());
1275 paint.setImageFilter(
1276 DlImageFilter::MakeBlur(50, 0, tile_modes[selected_tile_mode]));
1277
1278 Vector2 center = Vector2(1024, 768) / 2;
1279 builder.Scale(GetContentScale().x, GetContentScale().y);
1280 builder.Translate(center.x, center.y);
1281 builder.Scale(scale, scale);
1282 builder.Rotate(rotation);
1283
1284 DlRoundRect rrect =
1286 builder.DrawRoundRect(rrect, paint);
1287 return builder.Build();
1288 };
1289
1290 ASSERT_TRUE(OpenPlaygroundHere(callback));
1291}
1292
1293TEST_P(AiksTest, BlurredRectangleWithShader) {
1294 DisplayListBuilder builder;
1295 builder.Scale(GetContentScale().x, GetContentScale().y);
1296
1297 auto paint_lines = [&builder](Scalar dx, Scalar dy, DlPaint paint) {
1298 auto draw_line = [&builder, &paint](DlPoint a, DlPoint b) {
1299 DlPath line = DlPath::MakeLine(a, b);
1300 builder.DrawPath(line, paint);
1301 };
1302 paint.setStrokeWidth(5);
1303 paint.setDrawStyle(DlDrawStyle::kStroke);
1304 draw_line(DlPoint(dx + 100, dy + 100), DlPoint(dx + 200, dy + 200));
1305 draw_line(DlPoint(dx + 100, dy + 200), DlPoint(dx + 200, dy + 100));
1306 draw_line(DlPoint(dx + 150, dy + 100), DlPoint(dx + 200, dy + 150));
1307 draw_line(DlPoint(dx + 100, dy + 150), DlPoint(dx + 150, dy + 200));
1308 };
1309
1310 AiksContext renderer(GetContext(), nullptr);
1311 DisplayListBuilder recorder_builder;
1312 for (int x = 0; x < 5; ++x) {
1313 for (int y = 0; y < 5; ++y) {
1314 DlRect rect = DlRect::MakeXYWH(x * 20, y * 20, 20, 20);
1315 DlPaint paint;
1316 paint.setColor(((x + y) & 1) == 0 ? DlColor::kYellow()
1317 : DlColor::kBlue());
1318
1319 recorder_builder.DrawRect(rect, paint);
1320 }
1321 }
1322 auto texture =
1323 DisplayListToTexture(recorder_builder.Build(), {100, 100}, renderer);
1324
1325 auto image_source = DlColorSource::MakeImage(
1326 DlImageImpeller::Make(texture), DlTileMode::kRepeat, DlTileMode::kRepeat);
1327 auto blur_filter = DlImageFilter::MakeBlur(5, 5, DlTileMode::kDecal);
1328
1329 DlPaint paint;
1331 builder.DrawRect(DlRect::MakeLTRB(0, 0, 300, 600), paint);
1332
1333 paint.setColorSource(image_source);
1334 builder.DrawRect(DlRect::MakeLTRB(100, 100, 200, 200), paint);
1335
1336 paint.setColorSource(nullptr);
1337 paint.setColor(DlColor::kRed());
1338 builder.DrawRect(DlRect::MakeLTRB(300, 0, 600, 600), paint);
1339
1340 paint.setColorSource(image_source);
1341 paint.setImageFilter(blur_filter);
1342 builder.DrawRect(DlRect::MakeLTRB(400, 100, 500, 200), paint);
1343
1344 paint.setImageFilter(nullptr);
1345 paint_lines(0, 300, paint);
1346
1347 paint.setImageFilter(blur_filter);
1348 paint_lines(300, 300, paint);
1349
1350 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1351}
1352
1353// This addresses a bug where tiny blurs could result in mip maps that beyond
1354// the limits for the textures used for blurring.
1355// See also: b/323402168
1356TEST_P(AiksTest, GaussianBlurSolidColorTinyMipMap) {
1357 AiksContext renderer(GetContext(), nullptr);
1358
1359 for (int32_t i = 1; i < 5; ++i) {
1360 DisplayListBuilder builder;
1361 Scalar fi = i;
1362 DlPathBuilder path_builder;
1363 path_builder.MoveTo(DlPoint(100, 100));
1364 path_builder.LineTo(DlPoint(100 + fi, 100 + fi));
1365
1366 DlPaint paint;
1368 auto blur_filter = DlImageFilter::MakeBlur(0.1, 0.1, DlTileMode::kClamp);
1369 paint.setImageFilter(blur_filter);
1370
1371 builder.DrawPath(path_builder.TakePath(), paint);
1372
1373 auto image = DisplayListToTexture(builder.Build(), {1024, 768}, renderer);
1374 EXPECT_TRUE(image) << " length " << i;
1375 }
1376}
1377
1378// This addresses a bug where tiny blurs could result in mip maps that beyond
1379// the limits for the textures used for blurring.
1380// See also: b/323402168
1381TEST_P(AiksTest, GaussianBlurBackdropTinyMipMap) {
1382 AiksContext renderer(GetContext(), nullptr);
1383 for (int32_t i = 1; i < 5; ++i) {
1384 DisplayListBuilder builder;
1385
1386 ISize clip_size = ISize(i, i);
1387 builder.Save();
1388 builder.ClipRect(
1389 DlRect::MakeXYWH(400, 400, clip_size.width, clip_size.height));
1390
1391 DlPaint paint;
1392 paint.setColor(DlColor::kGreen());
1393 auto blur_filter = DlImageFilter::MakeBlur(0.1, 0.1, DlTileMode::kDecal);
1394 paint.setImageFilter(blur_filter);
1395
1396 builder.DrawCircle(DlPoint(400, 400), 200, paint);
1397 builder.Restore();
1398
1399 auto image = DisplayListToTexture(builder.Build(), {1024, 768}, renderer);
1400 EXPECT_TRUE(image) << " length " << i;
1401 }
1402}
1403
1405 CanRenderMultipleBackdropBlurWithSingleBackdropIdDifferentLayers) {
1406 auto image = DlImageImpeller::Make(CreateTextureForFixture("kalimba.jpg"));
1407
1408 DisplayListBuilder builder;
1409
1410 DlPaint paint;
1411 builder.DrawImage(image, DlPoint(50.0, 50.0),
1412 DlImageSampling::kNearestNeighbor, &paint);
1413
1414 for (int i = 0; i < 6; i++) {
1415 if (i != 0) {
1416 DlPaint paint;
1417 paint.setColor(DlColor::kWhite().withAlphaF(0.95));
1418 builder.SaveLayer(std::nullopt, &paint);
1419 }
1421 DlRect::MakeXYWH(50 + (i * 100), 250, 100, 100), 20, 20);
1422 builder.Save();
1423 builder.ClipRoundRect(rrect);
1424
1425 DlPaint save_paint;
1426 save_paint.setBlendMode(DlBlendMode::kSrc);
1427 auto backdrop_filter = DlImageFilter::MakeBlur(30, 30, DlTileMode::kClamp);
1428 builder.SaveLayer(std::nullopt, &save_paint, backdrop_filter.get(),
1429 /*backdrop_id=*/1);
1430 builder.Restore();
1431 builder.Restore();
1432 if (i != 0) {
1433 builder.Restore();
1434 }
1435 }
1436
1437 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1438}
1439
1440TEST_P(AiksTest, BlurGradientWithOpacity) {
1441 DisplayListBuilder builder;
1442 builder.Scale(GetContentScale().x, GetContentScale().y);
1443
1444 std::vector<DlColor> colors = {DlColor(0xFFFF0000), DlColor(0xFF00FF00)};
1445 std::vector<Scalar> stops = {0.0, 1.0};
1446
1447 auto gradient = DlColorSource::MakeLinear(
1448 {0, 0}, {400, 400}, 2, colors.data(), stops.data(), DlTileMode::kClamp);
1449
1450 DlPaint save_paint;
1451 save_paint.setOpacity(0.5);
1452 builder.SaveLayer(std::nullopt, &save_paint);
1453
1454 DlPaint paint;
1455 paint.setColorSource(gradient);
1456 paint.setMaskFilter(DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 1));
1457 builder.DrawRect(DlRect::MakeXYWH(100, 100, 200, 200), paint);
1458
1459 builder.Restore();
1460
1461 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1462}
1463
1464// The artifacts this test attempts to reproduce don't reproduce on playgrounds.
1465// The test is animated as an attempt to catch any ghosting that may happen
1466// when DontCare is used instead of Clear.
1467// https://github.com/flutter/flutter/issues/171772
1468TEST_P(AiksTest, CanRenderNestedBackdropBlur) {
1469 int64_t count = 0;
1470 auto callback = [&]() -> sk_sp<DisplayList> {
1471 DisplayListBuilder builder;
1472
1473 Scalar freq = 1.0;
1474 Scalar amp = 50.0;
1475 Scalar offset = amp * sin(freq * 2.0 * M_PI * count / 60.0);
1476
1477 // Draw some background content to be blurred.
1478 DlPaint paint;
1480 builder.DrawCircle(DlPoint(100 + offset, 100), 50, paint);
1482 builder.DrawCircle(DlPoint(300, 200 + offset), 100, paint);
1484 builder.DrawCircle(DlPoint(140, 170), 75, paint);
1486 builder.DrawCircle(DlPoint(180 + offset, 120 + offset), 100, paint);
1487
1488 // This is the first backdrop blur, simulating the navigation transition.
1489 auto backdrop_filter1 = DlImageFilter::MakeBlur(15, 15, DlTileMode::kClamp);
1490 builder.SaveLayer(std::nullopt, nullptr, backdrop_filter1.get());
1491
1492 // Draw the semi-transparent container from the second screen.
1493 DlPaint transparent_paint;
1494 transparent_paint.setColor(DlColor::kWhite().withAlpha(0.1 * 255));
1495 builder.DrawPaint(transparent_paint);
1496
1497 {
1498 // This is the second, nested backdrop blur.
1499 auto backdrop_filter2 =
1500 DlImageFilter::MakeBlur(10, 10, DlTileMode::kClamp);
1501 builder.Save();
1502 builder.ClipRect(DlRect::MakeXYWH(150, 150, 300, 300));
1503 builder.SaveLayer(std::nullopt, nullptr, backdrop_filter2.get());
1504 builder.Restore(); // Restore from SaveLayer
1505 builder.Restore(); // Restore from ClipRect
1506 }
1507
1508 builder.Restore(); // Restore from the first SaveLayer
1509
1510 count++;
1511 return builder.Build();
1512 };
1513 ASSERT_TRUE(OpenPlaygroundHere(callback));
1514}
1515
1516TEST_P(AiksTest, GaussianBlurFlipped) {
1517 DisplayListBuilder builder;
1518 builder.Scale(GetContentScale().x, GetContentScale().y);
1519
1520 builder.DrawRect(DlRect::MakeXYWH(0, 0, 350, 350),
1521 DlPaint().setColor(DlColor::kWhite()));
1522
1523 builder.Save();
1524 builder.Scale(-1, 1);
1525 DlPaint paint;
1526 paint.setImageFilter(DlBlurImageFilter::Make(10, 10, DlTileMode::kDecal));
1527 builder.SaveLayer(DlRect::MakeLTRB(-150, 100, 150, 200), &paint);
1528 builder.DrawRect(DlRect::MakeLTRB(-150, 0, 150, 300),
1529 DlPaint().setColor(DlColor::kRed()));
1530 builder.Restore();
1531 builder.Restore();
1532
1533 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1534}
1535
1536} // namespace testing
1537} // namespace impeller
#define MASK_BLUR_VARIANT_TEST(config)
void DrawOval(const DlRect &bounds, const DlPaint &paint) override
void ClipRect(const DlRect &rect, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false) override
void DrawImageRect(const sk_sp< DlImage > &image, const DlRect &src, const DlRect &dst, DlImageSampling sampling, const DlPaint *paint=nullptr, DlSrcRectConstraint constraint=DlSrcRectConstraint::kFast) override
void DrawRoundRect(const DlRoundRect &rrect, const DlPaint &paint) override
void DrawImage(const sk_sp< DlImage > &image, const DlPoint &point, DlImageSampling sampling, const DlPaint *paint=nullptr) override
void DrawColor(DlColor color, DlBlendMode mode) override
void DrawCircle(const DlPoint &center, DlScalar radius, const DlPaint &paint) override
void SaveLayer(const std::optional< DlRect > &bounds, const DlPaint *paint=nullptr, const DlImageFilter *backdrop=nullptr, std::optional< int64_t > backdrop_id=std::nullopt) override
void DrawLine(const DlPoint &p0, const DlPoint &p1, const DlPaint &paint) override
void ClipRoundRect(const DlRoundRect &rrect, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false) override
void Rotate(DlScalar degrees) override
void Scale(DlScalar sx, DlScalar sy) override
void Translate(DlScalar tx, DlScalar ty) override
void DrawPaint(const DlPaint &paint) override
sk_sp< DisplayList > Build()
void DrawPath(const DlPath &path, const DlPaint &paint) override
void Transform(const DlMatrix &matrix) override
void DrawRect(const DlRect &rect, const DlPaint &paint) override
static std::shared_ptr< DlImageFilter > Make(DlScalar sigma_x, DlScalar sigma_y, DlTileMode tile_mode, std::optional< DlRect > bounds=std::nullopt)
static std::shared_ptr< DlMaskFilter > Make(DlBlurStyle style, SkScalar sigma, bool respect_ctm=true)
static std::shared_ptr< const DlColorFilter > MakeBlend(DlColor color, DlBlendMode mode)
static std::shared_ptr< const DlColorFilter > MakeMatrix(const float matrix[20])
static std::shared_ptr< DlColorSource > MakeImage(const sk_sp< const DlImage > &image, DlTileMode horizontal_tile_mode, DlTileMode vertical_tile_mode, DlImageSampling sampling=DlImageSampling::kLinear, const DlMatrix *matrix=nullptr)
static std::shared_ptr< DlColorSource > MakeLinear(const DlPoint start_point, const DlPoint end_point, uint32_t stop_count, const DlColor *colors, const float *stops, DlTileMode tile_mode, const DlMatrix *matrix=nullptr)
static std::shared_ptr< DlImageFilter > MakeBlur(DlScalar sigma_x, DlScalar sigma_y, DlTileMode tile_mode)
static std::shared_ptr< DlImageFilter > MakeColorFilter(const std::shared_ptr< const DlColorFilter > &filter)
static std::shared_ptr< DlImageFilter > MakeCompose(const std::shared_ptr< DlImageFilter > &outer, const std::shared_ptr< DlImageFilter > &inner)
DlPaint & setColor(DlColor color)
Definition dl_paint.h:70
DlPaint & setInvertColors(bool isInvertColors)
Definition dl_paint.h:64
DlPaint & setStrokeWidth(float width)
Definition dl_paint.h:115
DlPaint & setBlendMode(DlBlendMode mode)
Definition dl_paint.h:85
DlPaint & setImageFilter(std::nullptr_t filter)
Definition dl_paint.h:167
DlPaint & setMaskFilter(std::nullptr_t filter)
Definition dl_paint.h:185
DlPaint & setDrawStyle(DlDrawStyle style)
Definition dl_paint.h:93
DlPaint & setOpacity(DlScalar opacity)
Definition dl_paint.h:78
DlPaint & setColorFilter(std::nullptr_t filter)
Definition dl_paint.h:149
DlPaint & setColorSource(std::nullptr_t source)
Definition dl_paint.h:131
DlPathBuilder & LineTo(DlPoint p2)
Draw a line from the current point to the indicated point p2.
DlPathBuilder & MoveTo(DlPoint p2)
Start a new contour that will originate at the indicated point p2.
const DlPath TakePath()
Returns the path constructed by this path builder and resets its internal state to the default state ...
DlPathBuilder & Close()
The path is closed back to the location of the most recent MoveTo call. Contours that are filled are ...
static DlPath MakeLine(const DlPoint a, const DlPoint b)
Definition dl_path.cc:89
static DlPath MakeCircle(const DlPoint center, DlScalar radius)
Definition dl_path.cc:68
static DlPath MakeArc(const DlRect &bounds, DlDegrees start, DlDegrees sweep, bool use_center)
Definition dl_path.cc:101
static DlPath MakeRect(const DlRect &rect)
Definition dl_path.cc:39
double x() const
Definition geometry.h:22
double y() const
Definition geometry.h:23
static bool ImGuiBegin(const char *name, bool *p_open, ImGuiWindowFlags flags)
static sk_sp< DlImageImpeller > Make(std::shared_ptr< Texture > texture, OwningContext owning_context=OwningContext::kIO)
Point GetContentScale() const
uint32_t location
int32_t x
FlutterVulkanImage * image
FlutterDesktopBinaryReply callback
FlTexture * texture
double y
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition switch_defs.h:52
impeller::Point DlPoint
TEST_P(AiksTest, DrawAtlasNoColor)
static const std::map< std::string, MaskBlurTestConfig > kPaintVariations
sk_sp< flutter::DisplayList > DoGradientOvalStrokeMaskBlur(Vector2 content_Scale, Scalar sigma, DlBlurStyle style)
static sk_sp< DisplayList > MaskBlurVariantTest(const AiksTest &test_context, const MaskBlurTestConfig &config)
Point Vector2
Definition point.h:430
float Scalar
Definition scalar.h:19
Point DrawPlaygroundPoint(PlaygroundPoint &point)
Definition widgets.cc:11
std::tuple< Point, Point > DrawPlaygroundLine(PlaygroundPoint &point_a, PlaygroundPoint &point_b)
Definition widgets.cc:51
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.
BlendMode
Definition color.h:58
ISize64 ISize
Definition size.h:162
int32_t height
int32_t width
static constexpr DlColor kMagenta()
Definition dl_color.h:75
static constexpr DlColor kWhite()
Definition dl_color.h:70
static constexpr DlColor kBlue()
Definition dl_color.h:73
static constexpr DlColor kDarkMagenta()
Definition dl_color.h:91
static constexpr DlColor RGBA(DlScalar r, DlScalar g, DlScalar b, DlScalar a)
Construct a 32 bit color from floating point R, G, B, and A color channels.
Definition dl_color.h:48
static constexpr DlColor kCrimson()
Definition dl_color.h:85
static constexpr DlColor kMaroon()
Definition dl_color.h:82
static constexpr DlColor kYellow()
Definition dl_color.h:76
static constexpr DlColor kPurple()
Definition dl_color.h:88
static constexpr DlColor kChartreuse()
Definition dl_color.h:94
static constexpr DlColor kCornflowerBlue()
Definition dl_color.h:84
static constexpr DlColor kDarkGreen()
Definition dl_color.h:93
static constexpr DlColor kRed()
Definition dl_color.h:71
static constexpr DlColor kGreen()
Definition dl_color.h:72
static constexpr DlColor kOrange()
Definition dl_color.h:87
static constexpr DlColor kLimeGreen()
Definition dl_color.h:89
static constexpr DlColor kOrangeRed()
Definition dl_color.h:92
static constexpr DlColor kGreenYellow()
Definition dl_color.h:90
static constexpr Color White()
Definition color.h:269
static constexpr Color Red()
Definition color.h:277
static constexpr Color AntiqueWhite()
Definition color.h:291
static constexpr Color Green()
Definition color.h:279
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition matrix.h:95
static constexpr Matrix MakeScale(const Vector3 &s)
Definition matrix.h:104
For convolution filters, the "radius" is the size of the convolution kernel to use on the local space...
Definition sigma.h:48
static RoundRect MakeRectXY(const Rect &rect, Scalar x_radius, Scalar y_radius)
Definition round_rect.h:31
In filters that use Gaussian distributions, "sigma" is a size of one standard deviation in terms of t...
Definition sigma.h:32
Scalar sigma
Definition sigma.h:33
static constexpr TRect MakeEllipseBounds(const TPoint< Type > &center, const TSize< Type > &radii)
Definition rect.h:164
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition rect.h:136
static constexpr TRect MakeCircleBounds(const TPoint< Type > &center, Type radius)
Definition rect.h:156
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition rect.h:129
Type height
Definition size.h:29
Type width
Definition size.h:28
std::shared_ptr< DlImageFilter > image_filter