7 #include "display_list/dl_color.h"
8 #include "display_list/dl_paint.h"
9 #include "display_list/geometry/dl_geometry_types.h"
10 #include "display_list/geometry/dl_path_builder.h"
11 #include "flutter/display_list/dl_builder.h"
12 #include "flutter/impeller/display_list/testing/render_text_in_canvas.h"
13 #include "flutter/impeller/display_list/testing/rmse.h"
14 #include "flutter/testing/testing.h"
15 #include "gtest/gtest.h"
30 auto draw = [](DlCanvas* canvas,
31 const std::vector<std::unique_ptr<DlImage>>& images) {
32 canvas->Scale(0.2, 0.2);
34 paint.setColor(DlColor::kCyan());
35 canvas->DrawPaint(paint);
38 DisplayListBuilder builder;
41 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
45 auto draw = [](DlCanvas* canvas,
const std::vector<sk_sp<DlImage>>& images) {
46 FML_CHECK(images.size() >= 1);
48 paint.setColor(DlColor::kRed());
49 canvas->DrawImage(images[0],
DlPoint(100.0, 100.0),
50 DlImageSampling::kLinear, &paint);
53 DisplayListBuilder builder;
54 std::vector<sk_sp<DlImage>> images;
55 images.emplace_back(CreateDlImageForFixture(
"kalimba.jpg"));
56 draw(&builder, images);
58 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
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);
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);
82 canvas->ClipRoundRect(
83 DlRoundRect::MakeOval(DlRect::MakeLTRB(201.25, 10, 361.25, 170)),
84 DlClipOp::kIntersect,
true);
85 DlRect save_layer_bounds = DlRect::MakeLTRB(201.25, 10, 361.25, 170);
87 DlImageFilter::MakeMatrix(DlMatrix::MakeRow(3, 0, 0.0, -280,
91 DlImageSampling::kLinear);
92 canvas->SaveLayer(save_layer_bounds,
nullptr, backdrop.get());
94 canvas->Translate(201.25, 10);
95 auto paint = DlPaint()
97 .setColor(DlColor(0xff2196f3))
99 .setDrawStyle(DlDrawStyle::kStroke);
100 canvas->DrawCircle(
DlPoint(80, 80), 80, paint);
107 DisplayListBuilder builder;
108 std::vector<sk_sp<DlImage>> images;
109 draw(&builder, images);
111 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
115 auto draw = [](DlCanvas* canvas) {
116 const DlRect rect = DlRect::MakeLTRB(32, 32, 382, 382);
118 layer_paint.setImageFilter(DlImageFilter::MakeDilate(3.95f, 3.95f));
119 canvas->SaveLayer(rect.Expand(8.0f), &layer_paint);
120 canvas->DrawRect(rect, DlPaint().setColor(DlColor::kRed()));
122 canvas->DrawRect(rect, DlPaint().setColor(DlColor::kBlack()));
125 DisplayListBuilder builder;
126 builder.Scale(GetContentScale().
x, GetContentScale().y);
127 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
131 builder.Translate(440, 0);
132 builder.Scale(1.3f, 1.3f);
135 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
139 void DrawBlurGrid(DlCanvas* canvas) {
141 paint.setColor(DlColor(0xfffef7ff));
145 std::vector<Scalar> blur_radii = {10, 30, 50};
146 for (
size_t i = 0; i < blur_radii.size(); ++i) {
148 auto blur_filter = std::make_shared<flutter::DlBlurMaskFilter>(
150 paint.setMaskFilter(blur_filter);
151 Scalar yval = gap + i * (gap + height);
152 canvas->DrawRoundRect(
153 DlRoundRect::MakeNinePatch(DlRect::MakeXYWH(gap, yval, width, height),
156 canvas->DrawRoundRect(
157 DlRoundRect::MakeNinePatch(
158 DlRect::MakeXYWH(2.0 * gap + width, yval, width, height),
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->DrawPaint(DlPaint().setColor(DlColor(0xff112233)));
171 DrawBlurGrid(canvas);
174 DisplayListBuilder builder;
175 std::vector<sk_sp<DlImage>> images;
176 draw(&builder, images);
178 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
182 Point content_scale = GetContentScale();
183 auto draw = [content_scale](DlCanvas* canvas,
184 const std::vector<sk_sp<DlImage>>& images) {
185 canvas->Scale(content_scale.x, content_scale.y);
186 canvas->DrawPaint(DlPaint().setColor(DlColor(0xff112233)));
187 canvas->Scale(0.33, 0.33);
188 DrawBlurGrid(canvas);
191 DisplayListBuilder builder;
192 std::vector<sk_sp<DlImage>> images;
193 draw(&builder, images);
195 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
199 Point content_scale = GetContentScale();
200 auto draw = [content_scale](DlCanvas* canvas,
201 const std::vector<sk_sp<DlImage>>& images) {
202 canvas->Scale(content_scale.x, content_scale.y);
203 canvas->Translate(200, 200);
204 canvas->DrawPaint(DlPaint().setColor(DlColor(0xff112233)));
205 canvas->Scale(0.33, 0.33);
206 canvas->Translate(300, 300);
208 canvas->Translate(-300, -300);
209 DrawBlurGrid(canvas);
212 DisplayListBuilder builder;
213 std::vector<sk_sp<DlImage>> images;
214 draw(&builder, images);
216 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
220 DisplayListBuilder builder;
221 builder.Scale(GetContentScale().
x, GetContentScale().y);
222 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
224 auto blur_sigmas = std::array{5.0f, 10.0f, 20.0f};
225 auto blur_colors = std::array{
233 auto add_corner = [](DlPathBuilder& path_builder,
DlPoint corner,
234 DlVector2 relative_from, DlVector2 relative_to,
236 static const auto magic = DlPathBuilder::kArcApproximationMagic;
239 path_builder.MoveTo(corner + relative_from);
241 path_builder.LineTo(corner + relative_from);
249 path_builder.CubicCurveTo(corner + relative_from * magic,
250 corner + relative_to * magic,
251 corner + relative_to);
254 DlPathBuilder path_builder;
255 add_corner(path_builder, rect.GetRightTop(),
256 DlVector2(-rx, 0.0f), DlVector2(0.0f, ry),
true);
257 add_corner(path_builder, rect.GetRightBottom(),
258 DlVector2(0.0f, -ry), DlVector2(-rx, 0.0f),
false);
259 add_corner(path_builder, rect.GetLeftBottom(),
260 DlVector2(rx, 0.0f), DlVector2(0.0f, -ry),
false);
261 add_corner(path_builder, rect.GetLeftTop(),
262 DlVector2(0.0f, ry), DlVector2(rx, 0.0f),
false);
263 return path_builder.TakePath();
266 for (
size_t i = 0; i < blur_sigmas.size(); i++) {
267 auto rect = DlRect::MakeXYWH(i * 320.0f + 50.0f, 50.0f, 100.0f, 100.0f);
268 DlPaint paint = DlPaint()
269 .setColor(blur_colors[i])
270 .setMaskFilter(DlBlurMaskFilter::Make(
271 DlBlurStyle::kNormal, blur_sigmas[i]));
273 builder.DrawRoundRect(DlRoundRect::MakeRectXY(rect, 10.0f, 10.0f), paint);
274 rect = rect.Shift(150.0f, 0.0f);
275 builder.DrawPath(make_rrect_path(rect, 10.0f, 10.0f), paint);
276 rect = rect.Shift(-150.0f, 0.0f);
278 rect = rect.Shift(0.0f, 200.0f);
279 builder.DrawRoundRect(DlRoundRect::MakeRectXY(rect, 10.0f, 30.0f), paint);
280 rect = rect.Shift(150.0f, 0.0f);
281 builder.DrawPath(make_rrect_path(rect, 10.0f, 20.0f), paint);
282 rect = rect.Shift(-150.0f, 0.0f);
284 rect = rect.Shift(0.0f, 200.0f);
285 builder.DrawRoundRect(DlRoundRect::MakeRectXY(rect, 30.0f, 10.0f), paint);
286 rect = rect.Shift(150.0f, 0.0f);
287 builder.DrawPath(make_rrect_path(rect, 20.0f, 10.0f), paint);
288 rect = rect.Shift(-150.0f, 0.0f);
291 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
295 Point content_scale = GetContentScale();
296 auto draw = [content_scale](DlCanvas* canvas,
297 const std::vector<sk_sp<DlImage>>& images) {
298 canvas->Scale(content_scale.x, content_scale.y);
299 canvas->DrawPaint(DlPaint().setColor(DlColor::kWhite()));
301 auto draw_one = [canvas](DlStrokeCap cap,
Scalar x,
Scalar y,
306 DlPaint thick_paint = DlPaint()
307 .setColor(DlColor::kBlue())
309 .setStrokeWidth(8.0f);
310 DlPaint middle_paint = DlPaint()
311 .setColor(DlColor::kGreen())
313 .setStrokeWidth(5.0f);
314 DlPaint thin_paint = DlPaint()
315 .setColor(DlColor::kMagenta())
317 .setStrokeWidth(2.0f);
318 for (
int degrees = 0; degrees < 360; degrees += 30) {
320 canvas->DrawDashedLine(center + inner * delta, center + outer * delta,
321 dash_on, dash_off, thick_paint);
322 canvas->DrawDashedLine(center + inner * delta, center + outer * delta,
323 dash_on, dash_off, middle_paint);
324 canvas->DrawDashedLine(center + inner * delta, center + outer * delta,
325 dash_on, dash_off, thin_paint);
329 draw_one(DlStrokeCap::kButt, 150.0f, 150.0f, 15.0f, 10.0f);
330 draw_one(DlStrokeCap::kSquare, 400.0f, 150.0f, 15.0f, 10.0f);
331 draw_one(DlStrokeCap::kRound, 150.0f, 400.0f, 15.0f, 10.0f);
332 draw_one(DlStrokeCap::kRound, 400.0f, 400.0f, 0.0f, 11.0f);
336 DlPathBuilder path_builder;
337 path_builder.MoveTo(
DlPoint(275.0f, 225.0f));
338 path_builder.LineTo(
DlPoint(325.0f, 275.0f));
339 path_builder.LineTo(
DlPoint(275.0f, 325.0f));
340 path_builder.LineTo(
DlPoint(225.0f, 275.0f));
341 canvas->ClipPath(path_builder.TakePath());
342 canvas->DrawColor(DlColor::kYellow());
343 draw_one(DlStrokeCap::kRound, 275.0f, 275.0f, 15.0f, 10.0f);
347 DisplayListBuilder builder;
348 std::vector<sk_sp<DlImage>> images;
349 draw(&builder, images);
351 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
358 DisplayListBuilder builder;
359 builder.DrawPaint(DlPaint().setColor(DlColor::kWhite()));
360 auto save_paint = DlPaint().setAlpha(100);
361 builder.SaveLayer(std::nullopt, &save_paint);
363 builder.DrawRoundRect(DlRoundRect::MakeRectRadius(
364 DlRect::MakeLTRB(10.5, 10.5, 200.5, 200.5), 10),
366 .setDrawStyle(DlDrawStyle::kStroke)
368 .setColor(DlColor::kBlack()));
369 builder.DrawCircle(DlPoint::MakeXY(100, 100), 50.5,
370 DlPaint().setColor(DlColor::kAqua()));
371 builder.DrawCircle(DlPoint::MakeXY(110, 110), 50.5,
372 DlPaint().setColor(DlColor::kCyan()));
376 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
381 const uint32_t* ptr =
reinterpret_cast<const uint32_t*
>(img->
GetBytes());
383 for (uint32_t i = 0; i < img->
GetHeight(); ++i) {
384 for (uint32_t j = 0; j < img->
GetWidth(); ++j) {
385 uint32_t pixel = *ptr++;
386 if ((pixel & 0x00ffffff) != 0) {
387 max_y = std::max(max_y,
static_cast<int32_t
>(i));
395 const uint32_t* ptr =
reinterpret_cast<const uint32_t*
>(img->
GetBytes());
397 std::vector<size_t> boundaries;
398 uint32_t
value = *ptr++;
399 for (
size_t i = 1; i < img->
GetWidth(); ++i) {
400 if (((*ptr & 0x00ffffff) != 0) != ((
value & 0x00ffffff) != 0)) {
401 boundaries.push_back(i);
406 assert(boundaries.size() == 6);
407 return boundaries[4] - boundaries[3];
414 auto callback = [&](
const char* text,
416 DisplayListBuilder builder;
418 paint.setColor(DlColor::ARGB(1, 0, 0, 0));
419 builder.DrawPaint(paint);
420 builder.Scale(scale, scale);
422 DlPoint::MakeXY(10, 300),
426 return builder.Build();
429 std::unique_ptr<impeller::testing::Screenshot> right =
430 MakeScreenshot(callback(
"h", 0.444));
432 GTEST_SKIP() <<
"making screenshots not supported.";
434 std::unique_ptr<impeller::testing::Screenshot> left =
435 MakeScreenshot(callback(
"e", 0.444));
437 int32_t left_max_y = CalculateMaxY(left.get());
438 int32_t right_max_y = CalculateMaxY(right.get());
439 int32_t y_diff = std::abs(left_max_y - right_max_y);
440 EXPECT_TRUE(y_diff <= 2) <<
"y diff: " << y_diff;
446 auto callback = [&](
const char* text,
448 DisplayListBuilder builder;
450 paint.setColor(DlColor::ARGB(1, 0, 0, 0));
451 builder.DrawPaint(paint);
452 builder.Scale(scale, scale);
454 DlPoint::MakeXY(10, 300),
458 return builder.Build();
461 std::optional<int32_t> last_space;
462 for (
int i = 0; i <= 100; ++i) {
463 Scalar scale = 0.440 + i / 1000.0;
464 std::unique_ptr<impeller::testing::Screenshot> right =
465 MakeScreenshot(callback(
"ui", scale));
467 GTEST_SKIP() <<
"making screenshots not supported.";
470 int32_t space = CalculateSpaceBetweenUI(right.get());
471 if (last_space.has_value()) {
472 int32_t diff = abs(space - *last_space);
473 EXPECT_TRUE(diff <= 1)
474 <<
"i:" << i <<
" space:" << space <<
" last_space:" << *last_space;
481 struct LeftmostIntensity {
488 LeftmostIntensity CalculateLeftmostIntensity(
490 LeftmostIntensity result = {.x =
static_cast<int32_t
>(img->
GetWidth()),
492 const uint32_t* ptr =
reinterpret_cast<const uint32_t*
>(img->
GetBytes());
493 for (
size_t i = 0; i < img->
GetHeight(); ++i) {
494 for (int32_t j = 0; j < static_cast<int32_t>(img->
GetWidth()); ++j) {
495 if (((*ptr & 0x00ffffff) != 0)) {
498 result.value = (*ptr & 0xff00) >> 8;
499 }
else if (j == result.x) {
501 std::max(
static_cast<int32_t
>(*ptr & 0xff), result.value);
516 auto callback = [&](
Scalar offset_x) -> sk_sp<DisplayList> {
517 DisplayListBuilder builder;
519 paint.setColor(DlColor::ARGB(1, 0, 0, 0));
520 builder.DrawPaint(paint);
522 DlPoint::MakeXY(offset_x, 180),
527 return builder.Build();
530 LeftmostIntensity intensity[5];
531 for (
int i = 0; i <= 4; ++i) {
532 Scalar offset = 10 + (i / 4.0);
533 std::unique_ptr<impeller::testing::Screenshot> right =
534 MakeScreenshot(callback(offset));
536 GTEST_SKIP() <<
"making screenshots not supported.";
538 intensity[i] = CalculateLeftmostIntensity(right.get());
539 ASSERT_NE(intensity[i].
value, 0);
541 for (
int i = 1; i < 5; ++i) {
542 EXPECT_TRUE(intensity[i].
x - intensity[i - 1].
x == 1 ||
546 EXPECT_EQ(intensity[4].
x - intensity[0].
x, 1);
555 auto callback = [&](
Scalar offset_x) -> sk_sp<DisplayList> {
556 DisplayListBuilder builder;
557 builder.Scale(scalar, scalar);
559 paint.setColor(DlColor::ARGB(1, 0, 0, 0));
560 builder.DrawPaint(paint);
562 DlPoint::MakeXY(offset_x, 180),
567 return builder.Build();
570 LeftmostIntensity intensity[5];
571 Scalar offset_fraction = 0.25 / scalar;
572 for (
int i = 0; i <= 4; ++i) {
573 Scalar offset = 10 + (offset_fraction * i);
574 std::unique_ptr<impeller::testing::Screenshot> right =
575 MakeScreenshot(callback(offset));
577 GTEST_SKIP() <<
"making screenshots not supported.";
579 intensity[i] = CalculateLeftmostIntensity(right.get());
580 ASSERT_NE(intensity[i].
value, 0);
582 for (
int i = 1; i < 5; ++i) {
583 EXPECT_TRUE(intensity[i].
x - intensity[i - 1].
x == 1 ||
587 EXPECT_EQ(intensity[4].
x - intensity[0].
x, 1);
596 auto callback = [&](
Scalar offset_x) -> sk_sp<DisplayList> {
597 DisplayListBuilder builder;
598 builder.Scale(scalar, scalar);
600 paint.setColor(DlColor::ARGB(1, 0, 0, 0));
601 builder.DrawPaint(paint);
602 builder.Translate(offset_x, 180);
604 DlPoint::MakeXY(0, 0),
609 return builder.Build();
612 LeftmostIntensity intensity[5];
613 Scalar offset_fraction = 0.25 / scalar;
614 for (
int i = 0; i <= 4; ++i) {
615 Scalar offset = 10 + (offset_fraction * i);
616 std::unique_ptr<impeller::testing::Screenshot> right =
617 MakeScreenshot(callback(offset));
619 GTEST_SKIP() <<
"making screenshots not supported.";
621 intensity[i] = CalculateLeftmostIntensity(right.get());
622 ASSERT_NE(intensity[i].
value, 0);
624 for (
int i = 1; i < 5; ++i) {
625 EXPECT_TRUE(intensity[i].
x - intensity[i - 1].
x == 1 ||
629 EXPECT_EQ(intensity[4].
x - intensity[0].
x, 1);
virtual size_t GetHeight() const =0
Returns the height of the image in pixels.
virtual const uint8_t * GetBytes() const =0
Access raw data of the screenshot.
virtual size_t GetWidth() const =0
Returns the width of the image in pixels.
Vector2 blur_radius
Blur radius in source pixels based on scaled_sigma.
TEST_P(DlGoldenTest, TextBlurMaskFilterRespectCTM)
INSTANTIATE_PLAYGROUND_SUITE(DlGoldenTest)
bool RenderTextInCanvasSkia(const std::shared_ptr< Context > &context, DisplayListBuilder &canvas, const std::string &text, const std::string_view &font_fixture, const TextRenderOptions &options={}, const std::optional< SkFont > &font=std::nullopt)
flutter::DlScalar DlScalar
constexpr TPoint Rotate(const Radians &angle) const