| Flutter Impeller |

dl_golden_unittests.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "impeller/display_list/dl_golden_unittests.h"
6
7 #include "flutter/display_list/dl_builder.h"
8 #include "flutter/impeller/geometry/path_builder.h"
9 #include "flutter/testing/testing.h"
10 #include "gtest/gtest.h"
11
12 namespace flutter {
13 namespace testing {
14
15 using impeller::Degrees;
16 using impeller::PlaygroundBackend;
17 using impeller::PlaygroundTest;
18 using impeller::Point;
19 using impeller::Radians;
20 using impeller::Scalar;
21
22 INSTANTIATE_PLAYGROUND_SUITE(DlGoldenTest);
23
24 TEST_P(DlGoldenTest, CanDrawPaint) {
25 auto draw = [](DlCanvas* canvas,
26 const std::vector<std::unique_ptr<DlImage>>& images) {
27 canvas->Scale(0.2, 0.2);
28 DlPaint paint;
29 paint.setColor(DlColor::kCyan());
30 canvas->DrawPaint(paint);
31 };
32
33 DisplayListBuilder builder;
34 draw(&builder, /*images=*/{});
35
36 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
37 }
38
39 TEST_P(DlGoldenTest, CanRenderImage) {
40 auto draw = [](DlCanvas* canvas, const std::vector<sk_sp<DlImage>>& images) {
41 FML_CHECK(images.size() >= 1);
42 DlPaint paint;
43 paint.setColor(DlColor::kRed());
44 canvas->DrawImage(images[0], SkPoint::Make(100.0, 100.0),
45 DlImageSampling::kLinear, &paint);
46 };
47
48 DisplayListBuilder builder;
49 std::vector<sk_sp<DlImage>> images;
50 images.emplace_back(CreateDlImageForFixture("kalimba.jpg"));
51 draw(&builder, images);
52
53 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
54 }
55
56 // Asserts that subpass rendering of MatrixImageFilters works.
57 // https://github.com/flutter/flutter/issues/147807
58 TEST_P(DlGoldenTest, Bug147807) {
59 Point content_scale = GetContentScale();
60 auto draw = [content_scale](DlCanvas* canvas,
61 const std::vector<sk_sp<DlImage>>& images) {
62 canvas->Scale(content_scale.x, content_scale.y);
63 DlPaint paint;
64 paint.setColor(DlColor(0xfffef7ff));
65 canvas->DrawRect(SkRect::MakeLTRB(0, 0, 375, 667), paint);
66 paint.setColor(DlColor(0xffff9800));
67 canvas->DrawRect(SkRect::MakeLTRB(0, 0, 187.5, 333.5), paint);
68 paint.setColor(DlColor(0xff9c27b0));
69 canvas->DrawRect(SkRect::MakeLTRB(187.5, 0, 375, 333.5), paint);
70 paint.setColor(DlColor(0xff4caf50));
71 canvas->DrawRect(SkRect::MakeLTRB(0, 333.5, 187.5, 667), paint);
72 paint.setColor(DlColor(0xfff44336));
73 canvas->DrawRect(SkRect::MakeLTRB(187.5, 333.5, 375, 667), paint);
74
75 canvas->Save();
76 {
77 canvas->ClipRRect(
78 SkRRect::MakeOval(SkRect::MakeLTRB(201.25, 10, 361.25, 170)),
79 DlCanvas::ClipOp::kIntersect, true);
80 SkRect save_layer_bounds = SkRect::MakeLTRB(201.25, 10, 361.25, 170);
81 DlMatrixImageFilter backdrop(SkMatrix::MakeAll(3, 0, -280, //
82 0, 3, -920, //
83 0, 0, 1),
84 DlImageSampling::kLinear);
85 canvas->SaveLayer(&save_layer_bounds, /*paint=*/nullptr, &backdrop);
86 {
87 canvas->Translate(201.25, 10);
88 auto paint = DlPaint()
89 .setAntiAlias(true)
90 .setColor(DlColor(0xff2196f3))
91 .setStrokeWidth(5)
92 .setDrawStyle(DlDrawStyle::kStroke);
93 canvas->DrawCircle(SkPoint::Make(80, 80), 80, paint);
94 }
95 canvas->Restore();
96 }
97 canvas->Restore();
98 };
99
100 DisplayListBuilder builder;
101 std::vector<sk_sp<DlImage>> images;
102 draw(&builder, images);
103
104 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
105 }
106
107 namespace {
108 void DrawBlurGrid(DlCanvas* canvas) {
109 DlPaint paint;
110 paint.setColor(DlColor(0xfffef7ff));
111 Scalar width = 150;
112 Scalar height = 150;
113 Scalar gap = 80;
114 std::vector<Scalar> blur_radii = {10, 30, 50};
115 for (size_t i = 0; i < blur_radii.size(); ++i) {
116 Scalar blur_radius = blur_radii[i];
117 auto blur_filter = std::make_shared<flutter::DlBlurMaskFilter>(
118 flutter::DlBlurStyle::kNormal, blur_radius);
119 paint.setMaskFilter(blur_filter);
120 SkRRect rrect;
121 Scalar yval = gap + i * (gap + height);
122 rrect.setNinePatch(SkRect::MakeXYWH(gap, yval, width, height), 10, 10, 10,
123 10);
124 canvas->DrawRRect(rrect, paint);
125 rrect.setNinePatch(SkRect::MakeXYWH(2.0 * gap + width, yval, width, height),
126 9, 10, 10, 10);
127 canvas->DrawRRect(rrect, paint);
128 }
129 }
130 } // namespace
131
132 TEST_P(DlGoldenTest, GaussianVsRRectBlur) {
133 Point content_scale = GetContentScale();
134 auto draw = [content_scale](DlCanvas* canvas,
135 const std::vector<sk_sp<DlImage>>& images) {
136 canvas->Scale(content_scale.x, content_scale.y);
137 canvas->DrawPaint(DlPaint().setColor(DlColor(0xff112233)));
138 DrawBlurGrid(canvas);
139 };
140
141 DisplayListBuilder builder;
142 std::vector<sk_sp<DlImage>> images;
143 draw(&builder, images);
144
145 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
146 }
147
148 TEST_P(DlGoldenTest, GaussianVsRRectBlurScaled) {
149 Point content_scale = GetContentScale();
150 auto draw = [content_scale](DlCanvas* canvas,
151 const std::vector<sk_sp<DlImage>>& images) {
152 canvas->Scale(content_scale.x, content_scale.y);
153 canvas->DrawPaint(DlPaint().setColor(DlColor(0xff112233)));
154 canvas->Scale(0.33, 0.33);
155 DrawBlurGrid(canvas);
156 };
157
158 DisplayListBuilder builder;
159 std::vector<sk_sp<DlImage>> images;
160 draw(&builder, images);
161
162 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
163 }
164
165 TEST_P(DlGoldenTest, GaussianVsRRectBlurScaledRotated) {
166 Point content_scale = GetContentScale();
167 auto draw = [content_scale](DlCanvas* canvas,
168 const std::vector<sk_sp<DlImage>>& images) {
169 canvas->Scale(content_scale.x, content_scale.y);
170 canvas->Translate(200, 200);
171 canvas->DrawPaint(DlPaint().setColor(DlColor(0xff112233)));
172 canvas->Scale(0.33, 0.33);
173 canvas->Translate(300, 300);
174 canvas->Rotate(45);
175 canvas->Translate(-300, -300);
176 DrawBlurGrid(canvas);
177 };
178
179 DisplayListBuilder builder;
180 std::vector<sk_sp<DlImage>> images;
181 draw(&builder, images);
182
183 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
184 }
185
186 TEST_P(DlGoldenTest, FastVsGeneralGaussianMaskBlur) {
187 DisplayListBuilder builder;
188 builder.Scale(GetContentScale().x, GetContentScale().y);
189 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
190
191 auto blur_sigmas = std::array{5.0f, 10.0f, 20.0f};
192 auto blur_colors = std::array{
193 DlColor::kBlue(),
194 DlColor::kGreen(),
195 DlColor::kMaroon(),
196 };
197
198 auto make_rrect_path = [](const SkRect& rect, DlScalar rx,
199 DlScalar ry) -> SkPath {
200 auto add_corner = [](SkPath& path, SkPoint rCorner, SkPoint rEnd) {
201 static const auto magic = impeller::PathBuilder::kArcApproximationMagic;
202 path.rCubicTo(rCorner.fX * (1.0f - magic), rCorner.fY * (1.0f - magic),
203 rCorner.fX + rEnd.fX * magic, rCorner.fY + rEnd.fY * magic,
204 rCorner.fX + rEnd.fX, rCorner.fY + rEnd.fY);
205 };
206
207 SkPath path;
208 path.moveTo(rect.fRight - rx, rect.fTop);
209 add_corner(path, {rx, 0.0f}, {0.0f, ry});
210 path.lineTo(rect.fRight, rect.fBottom - ry);
211 add_corner(path, {0.0f, ry}, {-rx, 0.0f});
212 path.lineTo(rect.fLeft + rx, rect.fBottom);
213 add_corner(path, {-rx, 0.0f}, {0.0f, -ry});
214 path.lineTo(rect.fLeft, rect.fTop + ry);
215 add_corner(path, {0.0f, -ry}, {rx, 0.0f});
216 path.close();
217 return path;
218 };
219
220 for (size_t i = 0; i < blur_sigmas.size(); i++) {
221 auto rect = SkRect::MakeXYWH(i * 320.0f + 50.0f, 50.0f, 100.0f, 100.0f);
222 DlPaint paint = DlPaint() //
223 .setColor(blur_colors[i])
224 .setMaskFilter(DlBlurMaskFilter::Make(
225 DlBlurStyle::kNormal, blur_sigmas[i]));
226
227 builder.DrawRRect(SkRRect::MakeRectXY(rect, 10.0f, 10.0f), paint);
228 rect = rect.makeOffset(150.0f, 0.0f);
229 builder.DrawPath(make_rrect_path(rect, 10.0f, 10.0f), paint);
230 rect = rect.makeOffset(-150.0f, 0.0f);
231
232 rect = rect.makeOffset(0.0f, 200.0f);
233 builder.DrawRRect(SkRRect::MakeRectXY(rect, 10.0f, 30.0f), paint);
234 rect = rect.makeOffset(150.0f, 0.0f);
235 builder.DrawPath(make_rrect_path(rect, 10.0f, 20.0f), paint);
236 rect = rect.makeOffset(-150.0f, 0.0f);
237
238 rect = rect.makeOffset(0.0f, 200.0f);
239 builder.DrawRRect(SkRRect::MakeRectXY(rect, 30.0f, 10.0f), paint);
240 rect = rect.makeOffset(150.0f, 0.0f);
241 builder.DrawPath(make_rrect_path(rect, 20.0f, 10.0f), paint);
242 rect = rect.makeOffset(-150.0f, 0.0f);
243 }
244
245 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
246 }
247
248 TEST_P(DlGoldenTest, DashedLinesTest) {
249 Point content_scale = GetContentScale();
250 auto draw = [content_scale](DlCanvas* canvas,
251 const std::vector<sk_sp<DlImage>>& images) {
252 canvas->Scale(content_scale.x, content_scale.y);
253 canvas->DrawPaint(DlPaint().setColor(DlColor::kWhite()));
254
255 auto draw_one = [canvas](DlStrokeCap cap, Scalar x, Scalar y,
256 Scalar dash_on, Scalar dash_off) {
257 Point center = Point(x, y);
258 Scalar inner = 20.0f;
259 Scalar outer = 100.0f;
260 DlPaint thick_paint = DlPaint()
261 .setColor(DlColor::kBlue())
262 .setStrokeCap(cap)
263 .setStrokeWidth(8.0f);
264 DlPaint middle_paint = DlPaint()
265 .setColor(DlColor::kGreen())
266 .setStrokeCap(cap)
267 .setStrokeWidth(5.0f);
268 DlPaint thin_paint = DlPaint()
269 .setColor(DlColor::kMagenta())
270 .setStrokeCap(cap)
271 .setStrokeWidth(2.0f);
272 for (int degrees = 0; degrees < 360; degrees += 30) {
273 Point delta = Point(1.0f, 0.0f).Rotate(Degrees(degrees));
274 canvas->DrawDashedLine(center + inner * delta, center + outer * delta,
275 dash_on, dash_off, thick_paint);
276 canvas->DrawDashedLine(center + inner * delta, center + outer * delta,
277 dash_on, dash_off, middle_paint);
278 canvas->DrawDashedLine(center + inner * delta, center + outer * delta,
279 dash_on, dash_off, thin_paint);
280 }
281 };
282
283 draw_one(DlStrokeCap::kButt, 150.0f, 150.0f, 15.0f, 10.0f);
284 draw_one(DlStrokeCap::kSquare, 400.0f, 150.0f, 15.0f, 10.0f);
285 draw_one(DlStrokeCap::kRound, 150.0f, 400.0f, 15.0f, 10.0f);
286 draw_one(DlStrokeCap::kRound, 400.0f, 400.0f, 0.0f, 11.0f);
287
288 // Make sure the rendering op responds appropriately to clipping
289 canvas->Save();
290 SkPath clip_path = SkPath();
291 clip_path.moveTo(275.0f, 225.0f);
292 clip_path.lineTo(325.0f, 275.0f);
293 clip_path.lineTo(275.0f, 325.0f);
294 clip_path.lineTo(225.0f, 275.0f);
295 canvas->ClipPath(clip_path);
296 canvas->DrawColor(DlColor::kYellow());
297 draw_one(DlStrokeCap::kRound, 275.0f, 275.0f, 15.0f, 10.0f);
298 canvas->Restore();
299 };
300
301 DisplayListBuilder builder;
302 std::vector<sk_sp<DlImage>> images;
303 draw(&builder, images);
304
305 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
306 }
307
308 } // namespace testing
309 } // namespace flutter
impeller::Scalar
float Scalar
Definition: scalar.h:18
path_builder.h
impeller::PlaygroundBackend
PlaygroundBackend
Definition: playground.h:26
impeller::PathBuilder::kArcApproximationMagic
constexpr static const Scalar kArcApproximationMagic
Definition: path_builder.h:23
flutter::testing::TEST_P
TEST_P(DlGoldenTest, TextBlurMaskFilterRespectCTM)
Definition: dl_golden_blur_unittests.cc:60
dl_golden_unittests.h
impeller::Point
TPoint< Scalar > Point
Definition: point.h:327
impeller::Radians
Definition: scalar.h:43
flutter
Definition: dl_golden_blur_unittests.cc:15
blur_radius
Vector2 blur_radius
Blur radius in source pixels based on scaled_sigma.
Definition: gaussian_blur_filter_contents.cc:83
impeller::Degrees
Definition: scalar.h:51
impeller::TPoint::Rotate
constexpr TPoint Rotate(const Radians &angle) const
Definition: point.h:226
impeller::PlaygroundTest
Definition: playground_test.h:21
impeller::DlScalar
flutter::DlScalar DlScalar
Definition: dl_dispatcher.h:21
flutter::testing::DlGoldenTest
impeller::DlPlayground DlGoldenTest
Definition: dl_golden_unittests.h:17
flutter::testing::INSTANTIATE_PLAYGROUND_SUITE
INSTANTIATE_PLAYGROUND_SUITE(DlGoldenTest)
impeller::DlPlayground
Definition: dl_playground.h:16