Flutter Engine
 
Loading...
Searching...
No Matches
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
6
15#include "gtest/gtest.h"
16
17namespace flutter {
18namespace testing {
19
23using impeller::Point;
26
28
29TEST_P(DlGoldenTest, CanDrawPaint) {
30 auto draw = [](DlCanvas* canvas,
31 const std::vector<std::unique_ptr<DlImage>>& images) {
32 canvas->Scale(0.2, 0.2);
33 DlPaint paint;
34 paint.setColor(DlColor::kCyan());
35 canvas->DrawPaint(paint);
36 };
37
38 DisplayListBuilder builder;
39 draw(&builder, /*images=*/{});
40
41 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
42}
43
44TEST_P(DlGoldenTest, CanRenderImage) {
45 auto draw = [](DlCanvas* canvas, const std::vector<sk_sp<DlImage>>& images) {
46 FML_CHECK(images.size() >= 1);
47 DlPaint paint;
48 paint.setColor(DlColor::kRed());
49 canvas->DrawImage(images[0], DlPoint(100.0, 100.0),
51 };
52
53 DisplayListBuilder builder;
54 std::vector<sk_sp<DlImage>> images;
55 images.emplace_back(CreateDlImageForFixture("kalimba.jpg"));
56 draw(&builder, images);
57
58 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
59}
60
61// Asserts that subpass rendering of MatrixImageFilters works.
62// https://github.com/flutter/flutter/issues/147807
63TEST_P(DlGoldenTest, Bug147807) {
64 Point content_scale = GetContentScale();
65 auto draw = [content_scale](DlCanvas* canvas,
66 const std::vector<sk_sp<DlImage>>& images) {
67 canvas->Scale(content_scale.x, content_scale.y);
68 DlPaint paint;
69 paint.setColor(DlColor(0xfffef7ff));
70 canvas->DrawRect(DlRect::MakeLTRB(0, 0, 375, 667), paint);
71 paint.setColor(DlColor(0xffff9800));
72 canvas->DrawRect(DlRect::MakeLTRB(0, 0, 187.5, 333.5), paint);
73 paint.setColor(DlColor(0xff9c27b0));
74 canvas->DrawRect(DlRect::MakeLTRB(187.5, 0, 375, 333.5), paint);
75 paint.setColor(DlColor(0xff4caf50));
76 canvas->DrawRect(DlRect::MakeLTRB(0, 333.5, 187.5, 667), paint);
77 paint.setColor(DlColor(0xfff44336));
78 canvas->DrawRect(DlRect::MakeLTRB(187.5, 333.5, 375, 667), paint);
79
80 canvas->Save();
81 {
82 canvas->ClipRoundRect(
83 DlRoundRect::MakeOval(DlRect::MakeLTRB(201.25, 10, 361.25, 170)),
85 DlRect save_layer_bounds = DlRect::MakeLTRB(201.25, 10, 361.25, 170);
86 auto backdrop =
88 0, 3, 0.0, -920, //
89 0, 0, 1.0, 0.0, //
90 0, 0, 0.0, 1.0),
92 canvas->SaveLayer(save_layer_bounds, /*paint=*/nullptr, backdrop.get());
93 {
94 canvas->Translate(201.25, 10);
95 auto paint = DlPaint()
96 .setAntiAlias(true)
97 .setColor(DlColor(0xff2196f3))
100 canvas->DrawCircle(DlPoint(80, 80), 80, paint);
101 }
102 canvas->Restore();
103 }
104 canvas->Restore();
105 };
106
107 DisplayListBuilder builder;
108 std::vector<sk_sp<DlImage>> images;
109 draw(&builder, images);
110
111 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
112}
113
114namespace {
115void DrawBlurGrid(DlCanvas* canvas) {
116 DlPaint paint;
117 paint.setColor(DlColor(0xfffef7ff));
118 Scalar width = 150;
119 Scalar height = 150;
120 Scalar gap = 80;
121 std::vector<Scalar> blur_radii = {10, 30, 50};
122 for (size_t i = 0; i < blur_radii.size(); ++i) {
123 Scalar blur_radius = blur_radii[i];
124 auto blur_filter = std::make_shared<flutter::DlBlurMaskFilter>(
126 paint.setMaskFilter(blur_filter);
127 Scalar yval = gap + i * (gap + height);
128 canvas->DrawRoundRect(
130 10, 10, 10, 10),
131 paint);
132 canvas->DrawRoundRect(
134 DlRect::MakeXYWH(2.0 * gap + width, yval, width, height), //
135 9, 10, 10, 10),
136 paint);
137 }
138}
139} // namespace
140
141TEST_P(DlGoldenTest, GaussianVsRRectBlur) {
142 Point content_scale = GetContentScale();
143 auto draw = [content_scale](DlCanvas* canvas,
144 const std::vector<sk_sp<DlImage>>& images) {
145 canvas->Scale(content_scale.x, content_scale.y);
146 canvas->DrawPaint(DlPaint().setColor(DlColor(0xff112233)));
147 DrawBlurGrid(canvas);
148 };
149
150 DisplayListBuilder builder;
151 std::vector<sk_sp<DlImage>> images;
152 draw(&builder, images);
153
154 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
155}
156
157TEST_P(DlGoldenTest, GaussianVsRRectBlurScaled) {
158 Point content_scale = GetContentScale();
159 auto draw = [content_scale](DlCanvas* canvas,
160 const std::vector<sk_sp<DlImage>>& images) {
161 canvas->Scale(content_scale.x, content_scale.y);
162 canvas->DrawPaint(DlPaint().setColor(DlColor(0xff112233)));
163 canvas->Scale(0.33, 0.33);
164 DrawBlurGrid(canvas);
165 };
166
167 DisplayListBuilder builder;
168 std::vector<sk_sp<DlImage>> images;
169 draw(&builder, images);
170
171 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
172}
173
174TEST_P(DlGoldenTest, GaussianVsRRectBlurScaledRotated) {
175 Point content_scale = GetContentScale();
176 auto draw = [content_scale](DlCanvas* canvas,
177 const std::vector<sk_sp<DlImage>>& images) {
178 canvas->Scale(content_scale.x, content_scale.y);
179 canvas->Translate(200, 200);
180 canvas->DrawPaint(DlPaint().setColor(DlColor(0xff112233)));
181 canvas->Scale(0.33, 0.33);
182 canvas->Translate(300, 300);
183 canvas->Rotate(45);
184 canvas->Translate(-300, -300);
185 DrawBlurGrid(canvas);
186 };
187
188 DisplayListBuilder builder;
189 std::vector<sk_sp<DlImage>> images;
190 draw(&builder, images);
191
192 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
193}
194
195TEST_P(DlGoldenTest, FastVsGeneralGaussianMaskBlur) {
196 DisplayListBuilder builder;
197 builder.Scale(GetContentScale().x, GetContentScale().y);
198 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
199
200 auto blur_sigmas = std::array{5.0f, 10.0f, 20.0f};
201 auto blur_colors = std::array{
205 };
206
207 auto make_rrect_path = [](const DlRect& rect, DlScalar rx,
208 DlScalar ry) -> DlPath {
209 auto add_corner = [](DlPathBuilder& path_builder, DlPoint corner,
210 DlVector2 relative_from, DlVector2 relative_to,
211 bool first) {
212 static const auto magic = DlPathBuilder::kArcApproximationMagic;
213
214 if (first) {
215 path_builder.MoveTo(corner + relative_from);
216 } else {
217 path_builder.LineTo(corner + relative_from);
218 }
219 // These fractions should be (1 - magic) to make a proper rrect
220 // path, but historically these equations were as written here.
221 // On the plus side, they ensure that we will not optimize this
222 // path as "Hey, look, it's an RRect", but the DrawPath gaussians
223 // will otherwise not be identical to the versions drawn with
224 // DrawRoundRect
225 path_builder.CubicCurveTo(corner + relative_from * magic,
226 corner + relative_to * magic,
227 corner + relative_to);
228 };
229
230 DlPathBuilder path_builder;
231 add_corner(path_builder, rect.GetRightTop(), //
232 DlVector2(-rx, 0.0f), DlVector2(0.0f, ry), true);
233 add_corner(path_builder, rect.GetRightBottom(), //
234 DlVector2(0.0f, -ry), DlVector2(-rx, 0.0f), false);
235 add_corner(path_builder, rect.GetLeftBottom(), //
236 DlVector2(rx, 0.0f), DlVector2(0.0f, -ry), false);
237 add_corner(path_builder, rect.GetLeftTop(), //
238 DlVector2(0.0f, ry), DlVector2(rx, 0.0f), false);
239 return path_builder.TakePath();
240 };
241
242 for (size_t i = 0; i < blur_sigmas.size(); i++) {
243 auto rect = DlRect::MakeXYWH(i * 320.0f + 50.0f, 50.0f, 100.0f, 100.0f);
244 DlPaint paint = DlPaint() //
245 .setColor(blur_colors[i])
247 DlBlurStyle::kNormal, blur_sigmas[i]));
248
249 builder.DrawRoundRect(DlRoundRect::MakeRectXY(rect, 10.0f, 10.0f), paint);
250 rect = rect.Shift(150.0f, 0.0f);
251 builder.DrawPath(make_rrect_path(rect, 10.0f, 10.0f), paint);
252 rect = rect.Shift(-150.0f, 0.0f);
253
254 rect = rect.Shift(0.0f, 200.0f);
255 builder.DrawRoundRect(DlRoundRect::MakeRectXY(rect, 10.0f, 30.0f), paint);
256 rect = rect.Shift(150.0f, 0.0f);
257 builder.DrawPath(make_rrect_path(rect, 10.0f, 20.0f), paint);
258 rect = rect.Shift(-150.0f, 0.0f);
259
260 rect = rect.Shift(0.0f, 200.0f);
261 builder.DrawRoundRect(DlRoundRect::MakeRectXY(rect, 30.0f, 10.0f), paint);
262 rect = rect.Shift(150.0f, 0.0f);
263 builder.DrawPath(make_rrect_path(rect, 20.0f, 10.0f), paint);
264 rect = rect.Shift(-150.0f, 0.0f);
265 }
266
267 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
268}
269
270TEST_P(DlGoldenTest, DashedLinesTest) {
271 Point content_scale = GetContentScale();
272 auto draw = [content_scale](DlCanvas* canvas,
273 const std::vector<sk_sp<DlImage>>& images) {
274 canvas->Scale(content_scale.x, content_scale.y);
276
277 auto draw_one = [canvas](DlStrokeCap cap, Scalar x, Scalar y,
278 Scalar dash_on, Scalar dash_off) {
279 Point center = Point(x, y);
280 Scalar inner = 20.0f;
281 Scalar outer = 100.0f;
282 DlPaint thick_paint = DlPaint()
284 .setStrokeCap(cap)
285 .setStrokeWidth(8.0f);
286 DlPaint middle_paint = DlPaint()
288 .setStrokeCap(cap)
289 .setStrokeWidth(5.0f);
290 DlPaint thin_paint = DlPaint()
292 .setStrokeCap(cap)
293 .setStrokeWidth(2.0f);
294 for (int degrees = 0; degrees < 360; degrees += 30) {
295 Point delta = Point(1.0f, 0.0f).Rotate(Degrees(degrees));
296 canvas->DrawDashedLine(center + inner * delta, center + outer * delta,
297 dash_on, dash_off, thick_paint);
298 canvas->DrawDashedLine(center + inner * delta, center + outer * delta,
299 dash_on, dash_off, middle_paint);
300 canvas->DrawDashedLine(center + inner * delta, center + outer * delta,
301 dash_on, dash_off, thin_paint);
302 }
303 };
304
305 draw_one(DlStrokeCap::kButt, 150.0f, 150.0f, 15.0f, 10.0f);
306 draw_one(DlStrokeCap::kSquare, 400.0f, 150.0f, 15.0f, 10.0f);
307 draw_one(DlStrokeCap::kRound, 150.0f, 400.0f, 15.0f, 10.0f);
308 draw_one(DlStrokeCap::kRound, 400.0f, 400.0f, 0.0f, 11.0f);
309
310 // Make sure the rendering op responds appropriately to clipping
311 canvas->Save();
312 DlPathBuilder path_builder;
313 path_builder.MoveTo(DlPoint(275.0f, 225.0f));
314 path_builder.LineTo(DlPoint(325.0f, 275.0f));
315 path_builder.LineTo(DlPoint(275.0f, 325.0f));
316 path_builder.LineTo(DlPoint(225.0f, 275.0f));
317 canvas->ClipPath(path_builder.TakePath());
318 canvas->DrawColor(DlColor::kYellow());
319 draw_one(DlStrokeCap::kRound, 275.0f, 275.0f, 15.0f, 10.0f);
320 canvas->Restore();
321 };
322
323 DisplayListBuilder builder;
324 std::vector<sk_sp<DlImage>> images;
325 draw(&builder, images);
326
327 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
328}
329
330TEST_P(DlGoldenTest, SaveLayerAtFractionalValue) {
331 // Draws a stroked rounded rect at a fractional pixel value. The coverage must
332 // be adjusted so that we still have room to draw it, even though it lies on
333 // the fractional bounds of the saveLayer.
334 DisplayListBuilder builder;
335 builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
336 auto save_paint = DlPaint().setAlpha(100);
337 builder.SaveLayer(std::nullopt, &save_paint);
338
340 DlRect::MakeLTRB(10.5, 10.5, 200.5, 200.5), 10),
341 DlPaint()
342 .setDrawStyle(DlDrawStyle::kStroke)
343 .setStrokeWidth(1.5)
344 .setColor(DlColor::kBlack()));
345 builder.DrawCircle(DlPoint::MakeXY(100, 100), 50.5,
346 DlPaint().setColor(DlColor::kAqua()));
347 builder.DrawCircle(DlPoint::MakeXY(110, 110), 50.5,
348 DlPaint().setColor(DlColor::kCyan()));
349
350 builder.Restore();
351
352 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
353}
354
355namespace {
356int32_t CalculateMaxY(const impeller::testing::Screenshot* img) {
357 const uint32_t* ptr = reinterpret_cast<const uint32_t*>(img->GetBytes());
358 int32_t max_y = 0;
359 for (uint32_t i = 0; i < img->GetHeight(); ++i) {
360 for (uint32_t j = 0; j < img->GetWidth(); ++j) {
361 uint32_t pixel = *ptr++;
362 if ((pixel & 0x00ffffff) != 0) {
363 max_y = std::max(max_y, static_cast<int32_t>(i));
364 }
365 }
366 }
367 return max_y;
368}
369
370int32_t CalculateSpaceBetweenUI(const impeller::testing::Screenshot* img) {
371 const uint32_t* ptr = reinterpret_cast<const uint32_t*>(img->GetBytes());
372 ptr += img->GetWidth() * static_cast<int32_t>(img->GetHeight() / 2.0);
373 std::vector<size_t> boundaries;
374 uint32_t value = *ptr++;
375 for (size_t i = 1; i < img->GetWidth(); ++i) {
376 if (((*ptr & 0x00ffffff) != 0) != ((value & 0x00ffffff) != 0)) {
377 boundaries.push_back(i);
378 }
379 value = *ptr++;
380 }
381
382 assert(boundaries.size() == 6);
383 return boundaries[4] - boundaries[3];
384}
385} // namespace
386
387TEST_P(DlGoldenTest, BaselineHE) {
388 SetWindowSize(impeller::ISize(1024, 200));
390 auto callback = [&](const char* text,
391 impeller::Scalar scale) -> sk_sp<DisplayList> {
392 DisplayListBuilder builder;
393 DlPaint paint;
394 paint.setColor(DlColor::ARGB(1, 0, 0, 0));
395 builder.DrawPaint(paint);
396 builder.Scale(scale, scale);
397 RenderTextInCanvasSkia(&builder, text, "Roboto-Regular.ttf",
398 DlPoint::MakeXY(10, 300),
401 });
402 return builder.Build();
403 };
404
405 std::unique_ptr<impeller::testing::Screenshot> right =
406 MakeScreenshot(callback("h", 0.444));
407 if (!right) {
408 GTEST_SKIP() << "making screenshots not supported.";
409 }
410 std::unique_ptr<impeller::testing::Screenshot> left =
411 MakeScreenshot(callback("e", 0.444));
412
413 int32_t left_max_y = CalculateMaxY(left.get());
414 int32_t right_max_y = CalculateMaxY(right.get());
415 int32_t y_diff = std::abs(left_max_y - right_max_y);
416 EXPECT_TRUE(y_diff <= 2) << "y diff: " << y_diff;
417}
418
419TEST_P(DlGoldenTest, MaintainsSpace) {
420 SetWindowSize(impeller::ISize(1024, 200));
422 auto callback = [&](const char* text,
423 impeller::Scalar scale) -> sk_sp<DisplayList> {
424 DisplayListBuilder builder;
425 DlPaint paint;
426 paint.setColor(DlColor::ARGB(1, 0, 0, 0));
427 builder.DrawPaint(paint);
428 builder.Scale(scale, scale);
429 RenderTextInCanvasSkia(&builder, text, "Roboto-Regular.ttf",
430 DlPoint::MakeXY(10, 300),
433 });
434 return builder.Build();
435 };
436
437 std::optional<int32_t> last_space;
438 for (int i = 0; i <= 100; ++i) {
439 Scalar scale = 0.440 + i / 1000.0;
440 std::unique_ptr<impeller::testing::Screenshot> right =
441 MakeScreenshot(callback("ui", scale));
442 if (!right) {
443 GTEST_SKIP() << "making screenshots not supported.";
444 }
445
446 int32_t space = CalculateSpaceBetweenUI(right.get());
447 if (last_space.has_value()) {
448 int32_t diff = abs(space - *last_space);
449 EXPECT_TRUE(diff <= 1)
450 << "i:" << i << " space:" << space << " last_space:" << *last_space;
451 }
452 last_space = space;
453 }
454}
455
456namespace {
457struct LeftmostIntensity {
458 int32_t x;
459 int32_t value;
460};
461
462/// Returns the highest value in the green channel for leftmost column that
463/// isn't all black.
464LeftmostIntensity CalculateLeftmostIntensity(
466 LeftmostIntensity result = {.x = static_cast<int32_t>(img->GetWidth()),
467 .value = 0};
468 const uint32_t* ptr = reinterpret_cast<const uint32_t*>(img->GetBytes());
469 for (size_t i = 0; i < img->GetHeight(); ++i) {
470 for (int32_t j = 0; j < static_cast<int32_t>(img->GetWidth()); ++j) {
471 if (((*ptr & 0x00ffffff) != 0)) {
472 if (j < result.x) {
473 result.x = j;
474 result.value = (*ptr & 0xff00) >> 8;
475 } else if (j == result.x) {
476 result.value =
477 std::max(static_cast<int32_t>(*ptr & 0xff), result.value);
478 }
479 }
480 ptr++;
481 }
482 }
483 return result;
484}
485} // namespace
486
487// Checks that the left most edge of the glyph is fading out as we push
488// it to the right by fractional pixels.
490 SetWindowSize(impeller::ISize(1024, 200));
492 auto callback = [&](Scalar offset_x) -> sk_sp<DisplayList> {
493 DisplayListBuilder builder;
494 DlPaint paint;
495 paint.setColor(DlColor::ARGB(1, 0, 0, 0));
496 builder.DrawPaint(paint);
497 RenderTextInCanvasSkia(&builder, "ui", "Roboto-Regular.ttf",
498 DlPoint::MakeXY(offset_x, 180),
501 .is_subpixel = true,
502 });
503 return builder.Build();
504 };
505
506 LeftmostIntensity intensity[5];
507 for (int i = 0; i <= 4; ++i) {
508 Scalar offset = 10 + (i / 4.0);
509 std::unique_ptr<impeller::testing::Screenshot> right =
510 MakeScreenshot(callback(offset));
511 if (!right) {
512 GTEST_SKIP() << "making screenshots not supported.";
513 }
514 intensity[i] = CalculateLeftmostIntensity(right.get());
515 ASSERT_NE(intensity[i].value, 0);
516 }
517 for (int i = 1; i < 5; ++i) {
518 EXPECT_TRUE(intensity[i].x - intensity[i - 1].x == 1 ||
519 intensity[i].value < intensity[i - 1].value)
520 << i;
521 }
522 EXPECT_EQ(intensity[4].x - intensity[0].x, 1);
523}
524
525// Checks that the left most edge of the glyph is fading out as we push
526// it to the right by fractional pixels.
527TEST_P(DlGoldenTest, SubpixelScaled) {
528 SetWindowSize(impeller::ISize(1024, 200));
530 Scalar scalar = 0.75;
531 auto callback = [&](Scalar offset_x) -> sk_sp<DisplayList> {
532 DisplayListBuilder builder;
533 builder.Scale(scalar, scalar);
534 DlPaint paint;
535 paint.setColor(DlColor::ARGB(1, 0, 0, 0));
536 builder.DrawPaint(paint);
537 RenderTextInCanvasSkia(&builder, "ui", "Roboto-Regular.ttf",
538 DlPoint::MakeXY(offset_x, 180),
541 .is_subpixel = true,
542 });
543 return builder.Build();
544 };
545
546 LeftmostIntensity intensity[5];
547 Scalar offset_fraction = 0.25 / scalar;
548 for (int i = 0; i <= 4; ++i) {
549 Scalar offset = 10 + (offset_fraction * i);
550 std::unique_ptr<impeller::testing::Screenshot> right =
551 MakeScreenshot(callback(offset));
552 if (!right) {
553 GTEST_SKIP() << "making screenshots not supported.";
554 }
555 intensity[i] = CalculateLeftmostIntensity(right.get());
556 ASSERT_NE(intensity[i].value, 0);
557 }
558 for (int i = 1; i < 5; ++i) {
559 EXPECT_TRUE(intensity[i].x - intensity[i - 1].x == 1 ||
560 intensity[i].value < intensity[i - 1].value)
561 << i;
562 }
563 EXPECT_EQ(intensity[4].x - intensity[0].x, 1);
564}
565
566// Checks that the left most edge of the glyph is fading out as we push
567// it to the right by fractional pixels.
568TEST_P(DlGoldenTest, SubpixelScaledTranslated) {
569 SetWindowSize(impeller::ISize(1024, 200));
571 Scalar scalar = 0.75;
572 auto callback = [&](Scalar offset_x) -> sk_sp<DisplayList> {
573 DisplayListBuilder builder;
574 builder.Scale(scalar, scalar);
575 DlPaint paint;
576 paint.setColor(DlColor::ARGB(1, 0, 0, 0));
577 builder.DrawPaint(paint);
578 builder.Translate(offset_x, 180);
579 RenderTextInCanvasSkia(&builder, "ui", "Roboto-Regular.ttf",
580 DlPoint::MakeXY(0, 0),
583 .is_subpixel = true,
584 });
585 return builder.Build();
586 };
587
588 LeftmostIntensity intensity[5];
589 Scalar offset_fraction = 0.25 / scalar;
590 for (int i = 0; i <= 4; ++i) {
591 Scalar offset = 10 + (offset_fraction * i);
592 std::unique_ptr<impeller::testing::Screenshot> right =
593 MakeScreenshot(callback(offset));
594 if (!right) {
595 GTEST_SKIP() << "making screenshots not supported.";
596 }
597 intensity[i] = CalculateLeftmostIntensity(right.get());
598 ASSERT_NE(intensity[i].value, 0);
599 }
600 for (int i = 1; i < 5; ++i) {
601 EXPECT_TRUE(intensity[i].x - intensity[i - 1].x == 1 ||
602 intensity[i].value < intensity[i - 1].value)
603 << i;
604 }
605 EXPECT_EQ(intensity[4].x - intensity[0].x, 1);
606}
607
608} // namespace testing
609} // namespace flutter
void DrawRoundRect(const DlRoundRect &rrect, const DlPaint &paint) 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 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
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 DrawPaint(const DlPaint &paint)=0
virtual void DrawCircle(const DlPoint &center, DlScalar radius, const DlPaint &paint)=0
virtual void ClipRoundRect(const DlRoundRect &rrect, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false)=0
virtual void DrawRoundRect(const DlRoundRect &rrect, 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 DrawRect(const DlRect &rect, const DlPaint &paint)=0
virtual void DrawImage(const sk_sp< DlImage > &image, const DlPoint &point, DlImageSampling sampling, const DlPaint *paint=nullptr)=0
virtual void Translate(DlScalar tx, DlScalar ty)=0
virtual void DrawColor(DlColor color, DlBlendMode mode=DlBlendMode::kSrcOver)=0
virtual void Rotate(DlScalar degrees)=0
virtual void DrawDashedLine(const DlPoint &p0, const DlPoint &p1, DlScalar on_length, DlScalar off_length, const DlPaint &paint)=0
virtual void Restore()=0
virtual void ClipPath(const DlPath &path, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false)=0
virtual void Scale(DlScalar sx, DlScalar sy)=0
virtual void Save()=0
static std::shared_ptr< DlImageFilter > MakeMatrix(const DlMatrix &matrix, DlImageSampling sampling)
DlPaint & setColor(DlColor color)
Definition dl_paint.h:70
DlPaint & setAntiAlias(bool isAntiAlias)
Definition dl_paint.h:58
DlPaint & setStrokeCap(DlStrokeCap cap)
Definition dl_paint.h:101
DlPaint & setStrokeWidth(float width)
Definition dl_paint.h:115
DlPaint & setAlpha(uint8_t alpha)
Definition dl_paint.h:76
DlPaint & setMaskFilter(std::nullptr_t filter)
Definition dl_paint.h:185
DlPaint & setDrawStyle(DlDrawStyle style)
Definition dl_paint.h:93
DlPathBuilder & LineTo(DlPoint p2)
Draw a line from the current point to the indicated point p2.
static constexpr const DlScalar kArcApproximationMagic
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 & CubicCurveTo(DlPoint cp1, DlPoint cp2, DlPoint p2)
Draw a cubic bezier curve from the current point to the indicated point p2, using the indicated point...
double x() const
Definition geometry.h:22
double y() const
Definition geometry.h:23
virtual const uint8_t * GetBytes() const =0
Access raw data of the screenshot.
virtual size_t GetHeight() const =0
Returns the height of the image in pixels.
virtual size_t GetWidth() const =0
Returns the width of the image in pixels.
int32_t value
int32_t x
FlutterDesktopBinaryReply callback
#define FML_CHECK(condition)
Definition logging.h:104
Vector2 blur_radius
Blur radius in source pixels based on scaled_sigma.
std::u16string text
std::array< MockImage, 3 > images
double y
bool RenderTextInCanvasSkia(DlCanvas *canvas, const std::string &text, const std::string_view &font_fixture, DlPoint position, const TextRenderOptions &options)
TEST_P(DlGoldenTest, TextBlurMaskFilterRespectCTM)
impeller::Scalar DlScalar
DlStrokeCap
Definition dl_paint.h:28
@ kRound
adds circle
@ kButt
no stroke extension
@ kSquare
adds square
@ kStroke
strokes boundary of shapes
@ kNormal
fuzzy inside and outside
impeller::Point DlPoint
impeller::Vector2 DlVector2
float Scalar
Definition scalar.h:19
PlaygroundBackend
Definition playground.h:27
#define INSTANTIATE_PLAYGROUND_SUITE(playground)
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 kBlack()
Definition dl_color.h:69
static constexpr DlColor kMaroon()
Definition dl_color.h:82
static constexpr DlColor ARGB(DlScalar a, DlScalar r, DlScalar g, DlScalar b)
Construct a 32 bit color from floating point A, R, G, and B color channels.
Definition dl_color.h:57
static constexpr DlColor kAqua()
Definition dl_color.h:86
static constexpr DlColor kYellow()
Definition dl_color.h:76
static constexpr DlColor kRed()
Definition dl_color.h:71
static constexpr DlColor kGreen()
Definition dl_color.h:72
static constexpr DlColor kCyan()
Definition dl_color.h:74
static constexpr Matrix MakeRow(Scalar m0, Scalar m1, Scalar m2, Scalar m3, Scalar m4, Scalar m5, Scalar m6, Scalar m7, Scalar m8, Scalar m9, Scalar m10, Scalar m11, Scalar m12, Scalar m13, Scalar m14, Scalar m15)
Definition matrix.h:83
static RoundRect MakeRectRadius(const Rect &rect, Scalar radius)
Definition round_rect.h:27
static RoundRect MakeNinePatch(const Rect &rect, Scalar left, Scalar top, Scalar right, Scalar bottom)
Definition round_rect.h:42
static RoundRect MakeOval(const Rect &rect)
Definition round_rect.h:23
static RoundRect MakeRectXY(const Rect &rect, Scalar x_radius, Scalar y_radius)
Definition round_rect.h:31
static constexpr TPoint< Type > MakeXY(Type x, Type y)
Definition point.h:46
constexpr TPoint< T > GetLeftTop() const
Definition rect.h:359
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition rect.h:136
constexpr TPoint< T > GetRightBottom() const
Definition rect.h:371
constexpr TPoint< T > GetLeftBottom() const
Definition rect.h:367
constexpr TPoint< T > GetRightTop() const
Definition rect.h:363
constexpr TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
Definition rect.h:602
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition rect.h:129
Scalar font_size