Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
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 .ok());
36 options.mask_filter = nullptr;
37 options.color = DlColor::kRed();
38 ASSERT_TRUE(RenderTextInCanvasSkia(canvas, "hello world",
39 "Roboto-Regular.ttf", //
40 DlPoint(100, 100), options)
41 .ok());
42 };
43
44 DisplayListBuilder builder;
45 draw(&builder, /*images=*/{});
46
47 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
48}
49
50TEST_P(DlGoldenTest, TextBlurMaskFilterDisrespectCTM) {
51 impeller::Point content_scale = GetContentScale();
52 auto draw = [&](DlCanvas* canvas,
53 const std::vector<std::unique_ptr<DlImage>>& images) {
54 canvas->DrawColor(DlColor(0xff111111));
55 canvas->Scale(content_scale.x, content_scale.y);
56 canvas->Scale(2, 2);
57 TextRenderOptions options;
58 options.mask_filter =
60 /*respect_ctm=*/false);
61 ASSERT_TRUE(RenderTextInCanvasSkia(canvas, "hello world",
62 "Roboto-Regular.ttf", //
63 DlPoint(101, 101), options)
64 .ok());
65 options.mask_filter = nullptr;
66 options.color = DlColor::kRed();
67 ASSERT_TRUE(RenderTextInCanvasSkia(canvas, "hello world",
68 "Roboto-Regular.ttf", //
69 DlPoint(100, 100), options)
70 .ok());
71 };
72
73 DisplayListBuilder builder;
74 draw(&builder, /*images=*/{});
75
76 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
77}
78
79// This is a test to make sure that we don't regress "shimmering" in the
80// gaussian blur. Shimmering is abrupt changes in signal when making tiny
81// changes to the blur parameters.
82//
83// See also:
84// - https://github.com/flutter/flutter/issues/152195
85TEST_P(DlGoldenTest, ShimmerTest) {
86 impeller::Point content_scale = GetContentScale();
87 auto draw = [&](DlCanvas* canvas, const std::vector<sk_sp<DlImage>>& images,
88 float sigma) {
89 canvas->DrawColor(DlColor(0xff111111));
90 canvas->Scale(content_scale.x, content_scale.y);
91
92 DlPaint paint;
93 canvas->DrawImage(images[0], DlPoint(10.135, 10.36334),
95
96 DlRect save_layer_bounds = DlRect::MakeLTRB(0, 0, 1024, 768);
97 auto blur = DlImageFilter::MakeBlur(sigma, sigma, DlTileMode::kDecal);
98 canvas->ClipRect(DlRect::MakeLTRB(11.125, 10.3737, 911.25, 755.3333));
99 canvas->SaveLayer(save_layer_bounds, /*paint=*/nullptr, blur.get());
100 canvas->Restore();
101 };
102
103 std::vector<sk_sp<DlImage>> images;
104 images.emplace_back(CreateDlImageForFixture("boston.jpg"));
105
106 auto make_screenshot = [&](float sigma) {
107 DisplayListBuilder builder;
108 draw(&builder, images, sigma);
109
110 std::unique_ptr<impeller::testing::Screenshot> screenshot =
111 MakeScreenshot(builder.Build());
112 return screenshot;
113 };
114
115 float start_sigma = 10.0f;
116 std::unique_ptr<impeller::testing::Screenshot> left =
117 make_screenshot(start_sigma);
118 if (!left) {
119 GTEST_SKIP() << "making screenshots not supported.";
120 }
121
122 double average_rmse = 0.0;
123 const int32_t sample_count = 200;
124 for (int i = 1; i <= sample_count; ++i) {
125 float sigma = start_sigma + (i / 2.f);
126 std::unique_ptr<impeller::testing::Screenshot> right =
127 make_screenshot(sigma);
128 double rmse = RMSE(left.get(), right.get());
129 average_rmse += rmse;
130
131 // To debug this output the frames can be written out to disk then
132 // transformed to a video with ffmpeg.
133 //
134 // ## save images command
135 // std::stringstream ss;
136 // ss << "_" << std::setw(3) << std::setfill('0') << (i - 1);
137 // SaveScreenshot(std::move(left), ss.str());
138 //
139 // ## ffmpeg command
140 // ```
141 // ffmpeg -framerate 30 -pattern_type glob -i '*.png' \
142 // -c:v libx264 -pix_fmt yuv420p out.mp4
143 // ```
144 left = std::move(right);
145 }
146
147 average_rmse = average_rmse / sample_count;
148
149 // This is a somewhat arbitrary threshold. It could be increased if we wanted.
150 // In the problematic cases previously we should values like 28. Before
151 // increasing this you should manually inspect the behavior in
152 // `AiksTest.GaussianBlurAnimatedBackdrop`. Average RMSE is a able to catch
153 // shimmer but it isn't perfect.
154 EXPECT_TRUE(average_rmse < 1.0) << "average_rmse: " << average_rmse;
155 // An average rmse of 0 would mean that the blur isn't blurring.
156 EXPECT_TRUE(average_rmse >= 0.0) << "average_rmse: " << average_rmse;
157}
158
159TEST_P(DlGoldenTest, StrokedRRectFastBlur) {
160 impeller::Point content_scale = GetContentScale();
161 DlRect rect = DlRect::MakeXYWH(50, 50, 100, 100);
162 DlRoundRect rrect = DlRoundRect::MakeRectRadius(rect, 10.0f);
164 DlPaint stroke =
166 DlPaint blur = DlPaint(fill).setMaskFilter(
168 DlPaint blur_stroke =
170
171 DisplayListBuilder builder;
172 builder.DrawColor(DlColor(0xff111111), DlBlendMode::kSrc);
173 builder.Scale(content_scale.x, content_scale.y);
174 builder.DrawRoundRect(rrect, fill);
175 builder.DrawRoundRect(rrect.Shift(150, 0), stroke);
176 builder.DrawRoundRect(rrect.Shift(0, 150), blur);
177 builder.DrawRoundRect(rrect.Shift(150, 150), blur_stroke);
178
179 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
180}
181
182// Top left and bottom right circles are expected to be comparable (not exactly
183// equal).
184// See also: https://github.com/flutter/flutter/issues/152778
185TEST_P(DlGoldenTest, LargeDownscaleRrect) {
186 impeller::Point content_scale = GetContentScale();
187 auto draw = [&](DlCanvas* canvas, const std::vector<sk_sp<DlImage>>& images) {
188 canvas->Scale(content_scale.x, content_scale.y);
189 canvas->DrawColor(DlColor(0xff111111));
190 {
191 canvas->Save();
192 canvas->Scale(0.25, 0.25);
193 DlPaint paint;
194 paint.setColor(DlColor::kYellow());
195 paint.setMaskFilter(
197 canvas->DrawCircle(DlPoint(0, 0), 1200, paint);
198 canvas->Restore();
199 }
200
201 DlPaint paint;
202 paint.setColor(DlColor::kYellow());
203 paint.setMaskFilter(
205 canvas->DrawCircle(DlPoint(1024, 768), 300, paint);
206 };
207
208 DisplayListBuilder builder;
209 draw(&builder, /*images=*/{});
210
211 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
212}
213
214} // namespace testing
215} // 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()
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:36
std::array< MockImage, 3 > images
double RMSE(const impeller::testing::Screenshot *left, const impeller::testing::Screenshot *right)
Definition rmse.cc:27
TEST_P(DlGoldenTest, TextBlurMaskFilterRespectCTM)
absl::StatusOr< DlRect > RenderTextInCanvasSkia(DlCanvas *canvas, const std::string &text, const std::string_view &font_fixture, DlPoint position, const TextRenderOptions &options)
@ 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