Flutter Engine
 
Loading...
Searching...
No Matches
dl_golden_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
6
14#include "gtest/gtest.h"
15
16namespace flutter {
17namespace testing {
18
19using impeller::Font;
20
21TEST_P(DlGoldenTest, TextBlurMaskFilterRespectCTM) {
22 impeller::Point content_scale = GetContentScale();
23 auto draw = [&](DlCanvas* canvas,
24 const std::vector<std::unique_ptr<DlImage>>& images) {
25 canvas->DrawColor(DlColor(0xff111111));
26 canvas->Scale(content_scale.x, content_scale.y);
27 canvas->Scale(2, 2);
28 TextRenderOptions options;
29 options.mask_filter =
31 /*respect_ctm=*/true);
32 ASSERT_TRUE(RenderTextInCanvasSkia(canvas, "hello world",
33 "Roboto-Regular.ttf", //
34 DlPoint(101, 101), options));
35 options.mask_filter = nullptr;
36 options.color = DlColor::kRed();
37 ASSERT_TRUE(RenderTextInCanvasSkia(canvas, "hello world",
38 "Roboto-Regular.ttf", //
39 DlPoint(100, 100), options));
40 };
41
42 DisplayListBuilder builder;
43 draw(&builder, /*images=*/{});
44
45 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
46}
47
48TEST_P(DlGoldenTest, TextBlurMaskFilterDisrespectCTM) {
49 impeller::Point content_scale = GetContentScale();
50 auto draw = [&](DlCanvas* canvas,
51 const std::vector<std::unique_ptr<DlImage>>& images) {
52 canvas->DrawColor(DlColor(0xff111111));
53 canvas->Scale(content_scale.x, content_scale.y);
54 canvas->Scale(2, 2);
55 TextRenderOptions options;
56 options.mask_filter =
58 /*respect_ctm=*/false);
59 ASSERT_TRUE(RenderTextInCanvasSkia(canvas, "hello world",
60 "Roboto-Regular.ttf", //
61 DlPoint(101, 101), options));
62 options.mask_filter = nullptr;
63 options.color = DlColor::kRed();
64 ASSERT_TRUE(RenderTextInCanvasSkia(canvas, "hello world",
65 "Roboto-Regular.ttf", //
66 DlPoint(100, 100), options));
67 };
68
69 DisplayListBuilder builder;
70 draw(&builder, /*images=*/{});
71
72 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
73}
74
75// This is a test to make sure that we don't regress "shimmering" in the
76// gaussian blur. Shimmering is abrupt changes in signal when making tiny
77// changes to the blur parameters.
78//
79// See also:
80// - https://github.com/flutter/flutter/issues/152195
81TEST_P(DlGoldenTest, ShimmerTest) {
82 impeller::Point content_scale = GetContentScale();
83 auto draw = [&](DlCanvas* canvas, const std::vector<sk_sp<DlImage>>& images,
84 float sigma) {
85 canvas->DrawColor(DlColor(0xff111111));
86 canvas->Scale(content_scale.x, content_scale.y);
87
88 DlPaint paint;
89 canvas->DrawImage(images[0], DlPoint(10.135, 10.36334),
91
92 DlRect save_layer_bounds = DlRect::MakeLTRB(0, 0, 1024, 768);
93 auto blur = DlImageFilter::MakeBlur(sigma, sigma, DlTileMode::kDecal);
94 canvas->ClipRect(DlRect::MakeLTRB(11.125, 10.3737, 911.25, 755.3333));
95 canvas->SaveLayer(save_layer_bounds, /*paint=*/nullptr, blur.get());
96 canvas->Restore();
97 };
98
99 std::vector<sk_sp<DlImage>> images;
100 images.emplace_back(CreateDlImageForFixture("boston.jpg"));
101
102 auto make_screenshot = [&](float sigma) {
103 DisplayListBuilder builder;
104 draw(&builder, images, sigma);
105
106 std::unique_ptr<impeller::testing::Screenshot> screenshot =
107 MakeScreenshot(builder.Build());
108 return screenshot;
109 };
110
111 float start_sigma = 10.0f;
112 std::unique_ptr<impeller::testing::Screenshot> left =
113 make_screenshot(start_sigma);
114 if (!left) {
115 GTEST_SKIP() << "making screenshots not supported.";
116 }
117
118 double average_rmse = 0.0;
119 const int32_t sample_count = 200;
120 for (int i = 1; i <= sample_count; ++i) {
121 float sigma = start_sigma + (i / 2.f);
122 std::unique_ptr<impeller::testing::Screenshot> right =
123 make_screenshot(sigma);
124 double rmse = RMSE(left.get(), right.get());
125 average_rmse += rmse;
126
127 // To debug this output the frames can be written out to disk then
128 // transformed to a video with ffmpeg.
129 //
130 // ## save images command
131 // std::stringstream ss;
132 // ss << "_" << std::setw(3) << std::setfill('0') << (i - 1);
133 // SaveScreenshot(std::move(left), ss.str());
134 //
135 // ## ffmpeg command
136 // ```
137 // ffmpeg -framerate 30 -pattern_type glob -i '*.png' \
138 // -c:v libx264 -pix_fmt yuv420p out.mp4
139 // ```
140 left = std::move(right);
141 }
142
143 average_rmse = average_rmse / sample_count;
144
145 // This is a somewhat arbitrary threshold. It could be increased if we wanted.
146 // In the problematic cases previously we should values like 28. Before
147 // increasing this you should manually inspect the behavior in
148 // `AiksTest.GaussianBlurAnimatedBackdrop`. Average RMSE is a able to catch
149 // shimmer but it isn't perfect.
150 EXPECT_TRUE(average_rmse < 1.0) << "average_rmse: " << average_rmse;
151 // An average rmse of 0 would mean that the blur isn't blurring.
152 EXPECT_TRUE(average_rmse >= 0.0) << "average_rmse: " << average_rmse;
153}
154
155TEST_P(DlGoldenTest, StrokedRRectFastBlur) {
156 impeller::Point content_scale = GetContentScale();
157 DlRect rect = DlRect::MakeXYWH(50, 50, 100, 100);
158 DlRoundRect rrect = DlRoundRect::MakeRectRadius(rect, 10.0f);
160 DlPaint stroke =
162 DlPaint blur = DlPaint(fill).setMaskFilter(
164 DlPaint blur_stroke =
166
167 DisplayListBuilder builder;
168 builder.DrawColor(DlColor(0xff111111), DlBlendMode::kSrc);
169 builder.Scale(content_scale.x, content_scale.y);
170 builder.DrawRoundRect(rrect, fill);
171 builder.DrawRoundRect(rrect.Shift(150, 0), stroke);
172 builder.DrawRoundRect(rrect.Shift(0, 150), blur);
173 builder.DrawRoundRect(rrect.Shift(150, 150), blur_stroke);
174
175 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
176}
177
178// Top left and bottom right circles are expected to be comparable (not exactly
179// equal).
180// See also: https://github.com/flutter/flutter/issues/152778
181TEST_P(DlGoldenTest, LargeDownscaleRrect) {
182 impeller::Point content_scale = GetContentScale();
183 auto draw = [&](DlCanvas* canvas, const std::vector<sk_sp<DlImage>>& images) {
184 canvas->Scale(content_scale.x, content_scale.y);
185 canvas->DrawColor(DlColor(0xff111111));
186 {
187 canvas->Save();
188 canvas->Scale(0.25, 0.25);
189 DlPaint paint;
190 paint.setColor(DlColor::kYellow());
191 paint.setMaskFilter(
193 canvas->DrawCircle(DlPoint(0, 0), 1200, paint);
194 canvas->Restore();
195 }
196
197 DlPaint paint;
198 paint.setColor(DlColor::kYellow());
199 paint.setMaskFilter(
201 canvas->DrawCircle(DlPoint(1024, 768), 300, paint);
202 };
203
204 DisplayListBuilder builder;
205 draw(&builder, /*images=*/{});
206
207 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
208}
209
210} // namespace testing
211} // namespace flutter
void DrawRoundRect(const DlRoundRect &rrect, const DlPaint &paint) override
void DrawColor(DlColor color, DlBlendMode mode) override
void Scale(DlScalar sx, DlScalar sy) override
sk_sp< DisplayList > Build()
Definition dl_builder.cc:66
static std::shared_ptr< DlMaskFilter > Make(DlBlurStyle style, SkScalar sigma, bool respect_ctm=true)
Developer-facing API for rendering anything within the engine.
Definition dl_canvas.h:32
virtual void ClipRect(const DlRect &rect, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false)=0
virtual void DrawCircle(const DlPoint &center, DlScalar radius, const DlPaint &paint)=0
virtual void SaveLayer(const std::optional< DlRect > &bounds, const DlPaint *paint=nullptr, const DlImageFilter *backdrop=nullptr, std::optional< int64_t > backdrop_id=std::nullopt)=0
virtual void DrawImage(const sk_sp< DlImage > &image, const DlPoint &point, DlImageSampling sampling, const DlPaint *paint=nullptr)=0
virtual void DrawColor(DlColor color, DlBlendMode mode=DlBlendMode::kSrcOver)=0
virtual void Restore()=0
virtual void Scale(DlScalar sx, DlScalar sy)=0
virtual void Save()=0
static std::shared_ptr< DlImageFilter > MakeBlur(DlScalar sigma_x, DlScalar sigma_y, DlTileMode tile_mode)
DlPaint & setColor(DlColor color)
Definition dl_paint.h:70
DlPaint & setStrokeWidth(float width)
Definition dl_paint.h:115
DlPaint & setMaskFilter(std::nullptr_t filter)
Definition dl_paint.h:185
DlPaint & setDrawStyle(DlDrawStyle style)
Definition dl_paint.h:93
Describes a typeface along with any modifications to its intrinsic properties.
Definition font.h:35
std::array< MockImage, 3 > images
bool RenderTextInCanvasSkia(DlCanvas *canvas, const std::string &text, const std::string_view &font_fixture, DlPoint position, const TextRenderOptions &options)
double RMSE(const impeller::testing::Screenshot *left, const impeller::testing::Screenshot *right)
Definition rmse.cc:27
TEST_P(DlGoldenTest, TextBlurMaskFilterRespectCTM)
@ kStroke
strokes boundary of shapes
@ kNormal
fuzzy inside and outside
impeller::Point DlPoint
static constexpr DlColor kBlue()
Definition dl_color.h:73
static constexpr DlColor kYellow()
Definition dl_color.h:76
static constexpr DlColor kRed()
Definition dl_color.h:71
std::shared_ptr< DlMaskFilter > mask_filter
static RoundRect MakeRectRadius(const Rect &rect, Scalar radius)
Definition round_rect.h:27
RoundRect Shift(Scalar dx, Scalar dy) const
Returns a new round rectangle translated by the given offset.
Definition round_rect.h:89
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition rect.h:136
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition rect.h:129