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 // Making sure this test is run on a wide gamut enabled backend
569 EXPECT_EQ(GetContext()->GetCapabilities()->GetDefaultColorFormat(),
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
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
598static 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(
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));
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
679static 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
728MASK_BLUR_VARIANT_TEST(NormalTranslucentZeroSigma)
729MASK_BLUR_VARIANT_TEST(NormalTranslucent)
730MASK_BLUR_VARIANT_TEST(SolidTranslucent)
731MASK_BLUR_VARIANT_TEST(SolidOpaque)
732MASK_BLUR_VARIANT_TEST(SolidTranslucentWithFilters)
733MASK_BLUR_VARIANT_TEST(SolidTranslucentExclusionBlend)
734MASK_BLUR_VARIANT_TEST(InnerTranslucent)
735MASK_BLUR_VARIANT_TEST(InnerTranslucentWithBlurImageFilter)
736MASK_BLUR_VARIANT_TEST(OuterTranslucent)
737MASK_BLUR_VARIANT_TEST(OuterOpaqueWithBlurImageFilter)
738
739#undef MASK_BLUR_VARIANT_TEST
740
741TEST_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
768TEST_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
795TEST_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
822TEST_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
851TEST_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
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
886TEST_P(AiksTest, GaussianBlurAtPeripheryVertical) {
887 DisplayListBuilder builder;
888
889 DlPaint paint;
890 builder.Scale(GetContentScale().x, GetContentScale().y);
891
894 DlRect::MakeLTRB(0, 0, GetWindowSize().width, 100), 10, 10);
895 builder.DrawRoundRect(rrect, paint);
896
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
914TEST_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;
927
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
943TEST_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
991TEST_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{};
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
1029TEST_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{};
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
1065TEST_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{};
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
1101TEST_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
1134TEST_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
1189TEST_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.
1211TEST_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
1248TEST_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
1289TEST_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;
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
1352TEST_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;
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
1377TEST_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
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 }
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
1436TEST_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
1464TEST_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;
1476 builder.DrawCircle(DlPoint(100 + offset, 100), 50, paint);
1478 builder.DrawCircle(DlPoint(300, 200 + offset), 100, paint);
1480 builder.DrawCircle(DlPoint(140, 170), 75, paint);
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
#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()
Definition dl_builder.cc:66
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:429
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:264
static constexpr Color Red()
Definition color.h:272
static constexpr Color AntiqueWhite()
Definition color.h:286
static constexpr Color Green()
Definition color.h:274
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 MakeXYWH(Type x, Type y, Type width, Type height)
Definition rect.h:136
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
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