Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
aiks_dl_text_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
27
29#include "txt/platform.h"
30
31using namespace flutter;
32/////////////////////////////////////////////////////
33
34namespace impeller {
35namespace testing {
36
38 bool stroke = false;
43 std::shared_ptr<DlMaskFilter> filter;
44 bool is_subpixel = false;
45};
46
47bool RenderTextInCanvasSkia(const std::shared_ptr<Context>& context,
48 DisplayListBuilder& canvas,
49 const std::string& text,
50 const std::string_view& font_fixture,
51 const TextRenderOptions& options = {},
52 const std::optional<SkFont>& font = std::nullopt) {
53 // Draw the baseline.
54 DlPaint paint;
55 paint.setColor(DlColor::kAqua().withAlpha(255 * 0.25));
56 canvas.DrawRect(
57 DlRect::MakeXYWH(options.position.x - 50, options.position.y, 900, 10),
58 paint);
59
60 // Mark the point at which the text is drawn.
61 paint.setColor(DlColor::kRed().withAlpha(255 * 0.25));
62 canvas.DrawCircle(options.position, 5.0, paint);
63
64 // Construct the text blob.
65 SkFont selected_font;
66 if (!font.has_value()) {
67 auto c_font_fixture = std::string(font_fixture);
68 auto mapping =
69 flutter::testing::OpenFixtureAsSkData(c_font_fixture.c_str());
70 if (!mapping) {
71 return false;
72 }
73 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
74 selected_font = SkFont(font_mgr->makeFromData(mapping), options.font_size);
75 if (options.is_subpixel) {
76 selected_font.setSubpixel(true);
77 }
78 } else {
79 selected_font = font.value();
80 }
81 auto blob = SkTextBlob::MakeFromString(text.c_str(), selected_font);
82 if (!blob) {
83 return false;
84 }
85
86 // Create the Impeller text frame and draw it at the designated baseline.
87 auto frame = MakeTextFrameFromTextBlobSkia(blob);
88
89 DlPaint text_paint;
90 text_paint.setColor(options.color);
91 text_paint.setMaskFilter(options.filter);
92 text_paint.setStrokeWidth(options.stroke_width);
93 text_paint.setDrawStyle(options.stroke ? DlDrawStyle::kStroke
95 canvas.DrawText(DlTextImpeller::Make(frame), options.position.x,
96 options.position.y, text_paint);
97 return true;
98}
99
100TEST_P(AiksTest, CanRenderTextFrame) {
101 DisplayListBuilder builder;
102
103 DlPaint paint;
104 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
105 builder.DrawPaint(paint);
106 ASSERT_TRUE(RenderTextInCanvasSkia(
107 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
108 "Roboto-Regular.ttf"));
109
110 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
111}
112
113TEST_P(AiksTest, CanRenderTextFrameWithInvertedTransform) {
114 DisplayListBuilder builder;
115
116 DlPaint paint;
117 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
118 builder.DrawPaint(paint);
119 builder.Translate(1000, 0);
120 builder.Scale(-1, 1);
121
122 ASSERT_TRUE(RenderTextInCanvasSkia(
123 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
124 "Roboto-Regular.ttf"));
125
126 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
127}
128
129TEST_P(AiksTest, CanRenderStrokedTextFrame) {
130 DisplayListBuilder builder;
131
132 DlPaint paint;
133 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
134 builder.DrawPaint(paint);
135
136 ASSERT_TRUE(RenderTextInCanvasSkia(
137 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
138 "Roboto-Regular.ttf",
139 {
140 .stroke = true,
141 }));
142 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
143}
144
145TEST_P(AiksTest, CanRenderTextStrokeWidth) {
146 DisplayListBuilder builder;
147
148 DlPaint paint;
149 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
150 builder.DrawPaint(paint);
151
152 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "LMNOP VWXYZ",
153 "Roboto-Medium.ttf",
154 {
155 .stroke = true,
156 .stroke_width = 4,
157 }));
158 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
159}
160
161TEST_P(AiksTest, CanRenderTextFrameWithHalfScaling) {
162 DisplayListBuilder builder;
163
164 DlPaint paint;
165 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
166 builder.DrawPaint(paint);
167 builder.Scale(0.5, 0.5);
168
169 ASSERT_TRUE(RenderTextInCanvasSkia(
170 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
171 "Roboto-Regular.ttf"));
172 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
173}
174
175// This is a test that looks for glyph artifacts we've see.
176TEST_P(AiksTest, ScaledK) {
177 DisplayListBuilder builder;
178 DlPaint paint;
179 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
180 builder.DrawPaint(paint);
181 for (int i = 0; i < 6; ++i) {
182 builder.Save();
183 builder.Translate(300 * i, 0);
184 Scalar scale = 0.445 - (i / 1000.f);
185 builder.Scale(scale, scale);
187 GetContext(), builder, "k", "Roboto-Regular.ttf",
188 TextRenderOptions{.font_size = 600, .position = DlPoint(10, 500)});
190 GetContext(), builder, "k", "Roboto-Regular.ttf",
191 TextRenderOptions{.font_size = 300, .position = DlPoint(10, 800)});
192 builder.Restore();
193 }
194 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
195}
196
197// This is a test that looks for glyph artifacts we've see.
198TEST_P(AiksTest, MassiveScaleConvertToPath) {
199 Scalar scale = 16.0;
200 auto callback = [&]() -> sk_sp<DisplayList> {
201 if (IsPlaygroundEnabled()) {
202 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
203 ImGui::SliderFloat("Scale", &scale, 4, 20);
204 ImGui::End();
205 }
206
207 DisplayListBuilder builder;
208 DlPaint paint;
209 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
210 builder.DrawPaint(paint);
211
212 builder.Scale(scale, scale);
214 GetContext(), builder, "HELLO", "Roboto-Regular.ttf",
216 .color = (16 * scale >= 250) ? DlColor::kYellow()
218 .position = DlPoint(0, 20)});
219 return builder.Build();
220 };
221
222 ASSERT_TRUE(OpenPlaygroundHere(callback));
223}
224
225TEST_P(AiksTest, CanRenderTextFrameWithScalingOverflow) {
226 Scalar scale = 60.0;
227 Scalar offsetx = -500.0;
228 Scalar offsety = 700.0;
229 auto callback = [&]() -> sk_sp<DisplayList> {
230 if (IsPlaygroundEnabled()) {
231 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
232 ImGui::SliderFloat("scale", &scale, 1.f, 300.f);
233 ImGui::SliderFloat("offsetx", &offsetx, -600.f, 100.f);
234 ImGui::SliderFloat("offsety", &offsety, 600.f, 2048.f);
235 ImGui::End();
236 }
237 DisplayListBuilder builder;
238 builder.Scale(GetContentScale().x, GetContentScale().y);
239 DlPaint paint;
240 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
241 builder.DrawPaint(paint);
242 builder.Scale(scale, scale);
243
245 GetContext(), builder, "test", "Roboto-Regular.ttf",
247 .position = DlPoint(offsetx / scale, offsety / scale),
248 });
249 return builder.Build();
250 };
251 ASSERT_TRUE(OpenPlaygroundHere(callback));
252}
253
254TEST_P(AiksTest, CanRenderTextFrameWithFractionScaling) {
255 Scalar fine_scale = 0.f;
256 bool is_subpixel = false;
257 auto callback = [&]() -> sk_sp<DisplayList> {
258 if (IsPlaygroundEnabled()) {
259 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
260 ImGui::SliderFloat("Fine Scale", &fine_scale, -1, 1);
261 ImGui::Checkbox("subpixel", &is_subpixel);
262 ImGui::End();
263 }
264
265 DisplayListBuilder builder;
266 DlPaint paint;
267 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
268 builder.DrawPaint(paint);
269 Scalar scale = 2.625 + fine_scale;
270 builder.Scale(scale, scale);
271 RenderTextInCanvasSkia(GetContext(), builder,
272 "the quick brown fox jumped over the lazy dog!.?",
273 "Roboto-Regular.ttf",
275 return builder.Build();
276 };
277
278 ASSERT_TRUE(OpenPlaygroundHere(callback));
279}
280
281// https://github.com/flutter/flutter/issues/164958
282TEST_P(AiksTest, TextRotated180Degrees) {
283 float fpivot[2] = {200 + 30, 200 - 20};
284 float rotation = 180;
285 float foffset[2] = {200, 200};
286
287 auto callback = [&]() -> sk_sp<DisplayList> {
288 if (IsPlaygroundEnabled()) {
289 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
290 ImGui::SliderFloat("pivotx", &fpivot[0], 0, 300);
291 ImGui::SliderFloat("pivoty", &fpivot[1], 0, 300);
292 ImGui::SliderFloat("rotation", &rotation, 0, 360);
293 ImGui::SliderFloat("foffsetx", &foffset[0], 0, 300);
294 ImGui::SliderFloat("foffsety", &foffset[1], 0, 300);
295 ImGui::End();
296 }
297 DisplayListBuilder builder;
298 builder.Scale(GetContentScale().x, GetContentScale().y);
299 builder.DrawPaint(DlPaint().setColor(DlColor(0xffffeeff)));
300
301 builder.Save();
302 DlPoint pivot = Point(fpivot[0], fpivot[1]);
303 builder.Translate(pivot.x, pivot.y);
304 builder.Rotate(rotation);
305 builder.Translate(-pivot.x, -pivot.y);
306
307 RenderTextInCanvasSkia(GetContext(), builder, "test", "Roboto-Regular.ttf",
310 .position = DlPoint(foffset[0], foffset[1]),
311 });
312
313 builder.Restore();
314 return builder.Build();
315 };
316 ASSERT_TRUE(OpenPlaygroundHere(callback));
317}
318
319TEST_P(AiksTest, TextFrameSubpixelAlignment) {
320 // "Random" numbers between 0 and 1. Hardcoded to avoid flakiness in goldens.
321 std::array<Scalar, 20> phase_offsets = {
322 7.82637e-06, 0.131538, 0.755605, 0.45865, 0.532767,
323 0.218959, 0.0470446, 0.678865, 0.679296, 0.934693,
324 0.383502, 0.519416, 0.830965, 0.0345721, 0.0534616,
325 0.5297, 0.671149, 0.00769819, 0.383416, 0.0668422};
326 auto callback = [&]() -> sk_sp<DisplayList> {
327 static float font_size = 20;
328 static float phase_variation = 0.2;
329 static float speed = 0.5;
330 static float magnitude = 100;
331 if (IsPlaygroundEnabled()) {
332 ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
333 ImGui::SliderFloat("Font size", &font_size, 5, 50);
334 ImGui::SliderFloat("Phase variation", &phase_variation, 0, 1);
335 ImGui::SliderFloat("Oscillation speed", &speed, 0, 2);
336 ImGui::SliderFloat("Oscillation magnitude", &magnitude, 0, 300);
337 ImGui::End();
338 }
339
340 DisplayListBuilder builder;
341 builder.Scale(GetContentScale().x, GetContentScale().y);
342
343 for (size_t i = 0; i < phase_offsets.size(); i++) {
344 DlPoint position = DlPoint(
345 200 +
346 magnitude * std::sin((-phase_offsets[i] * k2Pi * phase_variation +
347 GetSecondsElapsed() * speed)), //
348 200 + i * font_size * 1.1 //
349 );
351 GetContext(), builder,
352 "the quick brown fox jumped over "
353 "the lazy dog!.?",
354 "Roboto-Regular.ttf",
355 {.font_size = font_size, .position = position})) {
356 return nullptr;
357 }
358 }
359 return builder.Build();
360 };
361
362 ASSERT_TRUE(OpenPlaygroundHere(callback));
363}
364
365TEST_P(AiksTest, CanRenderItalicizedText) {
366 DisplayListBuilder builder;
367
368 DlPaint paint;
369 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
370 builder.DrawPaint(paint);
371
372 ASSERT_TRUE(RenderTextInCanvasSkia(
373 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
374 "HomemadeApple.ttf"));
375 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
376}
377
378static constexpr std::string_view kFontFixture =
379#if FML_OS_MACOSX
380 "Apple Color Emoji.ttc";
381#else
382 "NotoColorEmoji.ttf";
383#endif
384
385TEST_P(AiksTest, CanRenderEmojiTextFrame) {
386 DisplayListBuilder builder;
387
388 DlPaint paint;
389 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
390 builder.DrawPaint(paint);
391
392 ASSERT_TRUE(RenderTextInCanvasSkia(
393 GetContext(), builder, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture));
394 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
395}
396
397TEST_P(AiksTest, CanRenderEmojiTextFrameWithBlur) {
398 DisplayListBuilder builder;
399
400 builder.Scale(GetContentScale().x, GetContentScale().y);
401 DlPaint paint;
402 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
403 builder.DrawPaint(paint);
404
405 ASSERT_TRUE(RenderTextInCanvasSkia(
406 GetContext(), builder, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture,
409 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)}));
410 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
411}
412
413TEST_P(AiksTest, CanRenderEmojiTextFrameWithAlpha) {
414 DisplayListBuilder builder;
415
416 DlPaint paint;
417 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
418 builder.DrawPaint(paint);
419
420 ASSERT_TRUE(RenderTextInCanvasSkia(
421 GetContext(), builder, "😀 😃 😄 😁 😆 😅 😂 🤣 🥲 😊", kFontFixture,
422 {.color = DlColor::kBlack().modulateOpacity(0.5)}));
423 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
424}
425
426TEST_P(AiksTest, CanRenderTextInSaveLayer) {
427 DisplayListBuilder builder;
428
429 DlPaint paint;
430 paint.setColor(DlColor::ARGB(0.1, 0.1, 0.1, 0.1));
431 builder.DrawPaint(paint);
432
433 builder.Translate(100, 100);
434 builder.Scale(0.5, 0.5);
435
436 // Blend the layer with the parent pass using kClear to expose the coverage.
437 paint.setBlendMode(DlBlendMode::kClear);
438 builder.SaveLayer(std::nullopt, &paint);
439 ASSERT_TRUE(RenderTextInCanvasSkia(
440 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
441 "Roboto-Regular.ttf"));
442 builder.Restore();
443
444 // Render the text again over the cleared coverage rect.
445 ASSERT_TRUE(RenderTextInCanvasSkia(
446 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
447 "Roboto-Regular.ttf"));
448
449 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
450}
451
452TEST_P(AiksTest, CanRenderTextOutsideBoundaries) {
453 DisplayListBuilder builder;
454 builder.Translate(200, 150);
455
456 // Construct the text blob.
457 auto mapping = flutter::testing::OpenFixtureAsSkData("wtf.otf");
458 ASSERT_NE(mapping, nullptr);
459
460 Scalar font_size = 80;
461 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
462 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
463
464 DlPaint text_paint;
465 text_paint.setColor(DlColor::kBlue().withAlpha(255 * 0.8));
466
467 struct {
468 DlPoint position;
469 const char* text;
470 } text[] = {{DlPoint(0, 0), "0F0F0F0"},
471 {DlPoint(1, 2), "789"},
472 {DlPoint(1, 3), "456"},
473 {DlPoint(1, 4), "123"},
474 {DlPoint(0, 6), "0F0F0F0"}};
475 for (auto& t : text) {
476 builder.Save();
477 builder.Translate(t.position.x * font_size * 2,
478 t.position.y * font_size * 1.1);
479 {
480 auto blob = SkTextBlob::MakeFromString(t.text, sk_font);
481 ASSERT_NE(blob, nullptr);
482 auto frame = MakeTextFrameFromTextBlobSkia(blob);
483 builder.DrawText(DlTextImpeller::Make(frame), 0, 0, text_paint);
484 }
485 builder.Restore();
486 }
487
488 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
489}
490
491TEST_P(AiksTest, TextRotated) {
492 // This test used to be intentionally excluded for impeller_golden_tests
493 // but when the SDF backend variants were added, the explicit exclusions
494 // for those backends were not added to the exclusion list. So it has
495 // actually been running just fine for a while now generating goldens
496 // for the SDF backends.
497 // We will let it run on all backends now in the playground-based golden
498 // mechanism as the underlying flakiness may have been resolved since the
499 // exclusion was added.
500 // https://github.com/flutter/flutter/blame/ad80825c24d770a19e33f67800fc0338a3b89ec7/engine/src/flutter/impeller/golden_tests/golden_playground_test_mac.cc#L107
501
502 DisplayListBuilder builder;
503
504 builder.Scale(GetContentScale().x, GetContentScale().y);
505 DlPaint paint;
506 paint.setColor(DlColor::ARGB(0.1, 0.1, 0.1, 1.0));
507 builder.DrawPaint(paint);
508
509 builder.Transform(Matrix(0.25, -0.3, 0, -0.002, //
510 0, 0.5, 0, 0, //
511 0, 0, 0.3, 0, //
512 100, 100, 0, 1.3));
513 ASSERT_TRUE(RenderTextInCanvasSkia(
514 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
515 "Roboto-Regular.ttf"));
516
517 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
518}
519
520TEST_P(AiksTest, DrawScaledTextWithPerspectiveNoSaveLayer) {
521 DisplayListBuilder builder;
522
523 Matrix matrix = Matrix(1.0, 0.0, 0.0, 0.0, //
524 0.0, 1.0, 0.0, 0.0, //
525 0.0, 0.0, 1.0, 0.01, //
526 0.0, 0.0, 0.0, 1.0) * //
528
529 builder.Transform(matrix);
530
531 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "Hello world",
532 "Roboto-Regular.ttf"));
533 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
534}
535
536TEST_P(AiksTest, DrawScaledTextWithPerspectiveSaveLayer) {
537 DisplayListBuilder builder;
538
539 Matrix matrix = Matrix(1.0, 0.0, 0.0, 0.0, //
540 0.0, 1.0, 0.0, 0.0, //
541 0.0, 0.0, 1.0, 0.01, //
542 0.0, 0.0, 0.0, 1.0) * //
544
545 DlPaint save_paint;
546 DlRect window_bounds =
547 DlRect::MakeXYWH(0, 0, GetWindowSize().width, GetWindowSize().height);
548 // Note: bounds were not needed by the AIKS version, which may indicate a bug.
549 builder.SaveLayer(window_bounds, &save_paint);
550 builder.Transform(matrix);
551
552 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "Hello world",
553 "Roboto-Regular.ttf"));
554
555 builder.Restore();
556 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
557}
558
559TEST_P(AiksTest, CanRenderTextWithLargePerspectiveTransform) {
560 // Verifies that text scales are clamped to work around
561 // https://github.com/flutter/flutter/issues/136112 .
562
563 DisplayListBuilder builder;
564
565 DlPaint save_paint;
566 builder.SaveLayer(std::nullopt, &save_paint);
567 builder.Transform(Matrix(2000, 0, 0, 0, //
568 0, 2000, 0, 0, //
569 0, 0, -1, 9000, //
570 0, 0, -1, 7000 //
571 ));
572
573 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "Hello world",
574 "Roboto-Regular.ttf"));
575 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
576}
577
578TEST_P(AiksTest, CanRenderTextWithPerspectiveTransformInSublist) {
579 DisplayListBuilder text_builder;
580 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), text_builder, "Hello world",
581 "Roboto-Regular.ttf"));
582 auto text_display_list = text_builder.Build();
583
584 DisplayListBuilder builder;
585
586 Matrix matrix = Matrix::MakeRow(2.0, 0.0, 0.0, 0.0, //
587 0.0, 2.0, 0.0, 0.0, //
588 0.0, 0.0, 1.0, 0.0, //
589 0.0, 0.002, 0.0, 1.0);
590
591 DlPaint save_paint;
592 DlRect window_bounds =
593 DlRect::MakeXYWH(0, 0, GetWindowSize().width, GetWindowSize().height);
594 builder.SaveLayer(window_bounds, &save_paint);
595 builder.Transform(matrix);
596 builder.DrawDisplayList(text_display_list, 1.0f);
597 builder.Restore();
598
599 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
600}
601
602// This currently renders solid blue, as the support for text color sources was
603// moved into DLDispatching. Path data requires the SkTextBlobs which are not
604// used in impeller::TextFrames.
605TEST_P(AiksTest, TextForegroundShaderWithTransform) {
606 auto mapping = flutter::testing::OpenFixtureAsSkData("Roboto-Regular.ttf");
607 ASSERT_NE(mapping, nullptr);
608
609 Scalar font_size = 100;
610 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
611 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
612
613 DlPaint text_paint;
614 text_paint.setColor(DlColor::kBlue());
615
616 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
617 DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0)};
618 std::vector<Scalar> stops = {
619 0.0,
620 1.0,
621 };
623 /*start_point=*/DlPoint(0, 0), //
624 /*end_point=*/DlPoint(100, 100), //
625 /*stop_count=*/2, //
626 /*colors=*/colors.data(), //
627 /*stops=*/stops.data(), //
628 /*tile_mode=*/DlTileMode::kRepeat //
629 ));
630
631 DisplayListBuilder builder;
632 builder.Translate(100, 100);
633 builder.Rotate(45);
634
635 auto blob = SkTextBlob::MakeFromString("Hello", sk_font);
636 ASSERT_NE(blob, nullptr);
637 auto frame = MakeTextFrameFromTextBlobSkia(blob);
638 builder.DrawText(DlTextImpeller::Make(frame), 0, 0, text_paint);
639
640 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
641}
642
643// Regression test for https://github.com/flutter/flutter/issues/157885.
644TEST_P(AiksTest, DifferenceClipsMustRenderIdenticallyAcrossBackends) {
645 DisplayListBuilder builder;
646
647 DlPaint paint;
648 DlColor clear_color(1.0, 0.5, 0.5, 0.5, DlColorSpace::kSRGB);
649 paint.setColor(clear_color);
650 builder.DrawPaint(paint);
651
652 DlMatrix identity = {
653 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
654 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
655 };
656 builder.Save();
657 builder.Transform(identity);
658
659 DlRect frame = DlRect::MakeLTRB(1.0, 1.0, 1278.0, 763.0);
660 DlColor white(1.0, 1.0, 1.0, 1.0, DlColorSpace::kSRGB);
661 paint.setColor(white);
662 builder.DrawRect(frame, paint);
663
664 builder.Save();
665 builder.ClipRect(frame, DlClipOp::kIntersect);
666
667 DlMatrix rect_xform = {
668 0.8241262, 0.56640625, 0.0, 0.0, -0.56640625, 0.8241262, 0.0, 0.0,
669 0.0, 0.0, 1.0, 0.0, 271.1137, 489.4733, 0.0, 1.0,
670 };
671 builder.Save();
672 builder.Transform(rect_xform);
673
674 DlRect rect = DlRect::MakeLTRB(0.0, 0.0, 100.0, 100.0);
675 DlColor bluish(1.0, 0.184, 0.501, 0.929, DlColorSpace::kSRGB);
676 paint.setColor(bluish);
677 DlRoundRect rrect = DlRoundRect::MakeRectRadius(rect, 18.0);
678 builder.DrawRoundRect(rrect, paint);
679
680 builder.Save();
681 builder.ClipRect(rect, DlClipOp::kIntersect);
682 builder.Restore();
683
684 builder.Restore();
685
686 DlMatrix path_xform = {
687 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
688 0.0, 0.0, 1.0, 0.0, 675.0, 279.5, 0.0, 1.0,
689 };
690 builder.Save();
691 builder.Transform(path_xform);
692
693 DlPathBuilder path_builder;
694 path_builder.MoveTo(DlPoint(87.5, 349.5));
695 path_builder.LineTo(DlPoint(25.0, 29.5));
696 path_builder.LineTo(DlPoint(150.0, 118.0));
697 path_builder.LineTo(DlPoint(25.0, 118.0));
698 path_builder.LineTo(DlPoint(150.0, 29.5));
699 path_builder.Close();
700 DlPath path = path_builder.TakePath();
701
702 DlColor fill_color(1.0, 1.0, 0.0, 0.0, DlColorSpace::kSRGB);
703 DlColor stroke_color(1.0, 0.0, 0.0, 0.0, DlColorSpace::kSRGB);
704 paint.setColor(fill_color);
705 paint.setDrawStyle(DlDrawStyle::kFill);
706 builder.DrawPath(path, paint);
707
708 paint.setColor(stroke_color);
709 paint.setStrokeWidth(2.0);
710 paint.setDrawStyle(DlDrawStyle::kStroke);
711 builder.DrawPath(path, paint);
712
713 builder.Restore();
714 builder.Restore();
715 builder.Restore();
716
717 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
718}
719
720TEST_P(AiksTest, TextContentsMismatchedTransformTest) {
721 AiksContext aiks_context(GetContext(),
722 std::make_shared<TypographerContextSkia>());
723
724 // Verifies that TextContents only use the scale/transform that is
725 // computed during preroll.
726 constexpr const char* font_fixture = "Roboto-Regular.ttf";
727
728 // Construct the text blob.
729 auto c_font_fixture = std::string(font_fixture);
730 auto mapping = flutter::testing::OpenFixtureAsSkData(c_font_fixture.c_str());
731 ASSERT_TRUE(mapping);
732
733 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
734 SkFont sk_font(font_mgr->makeFromData(mapping), 16);
735
736 auto blob = SkTextBlob::MakeFromString("Hello World", sk_font);
737 ASSERT_TRUE(blob);
738
739 auto text_frame = MakeTextFrameFromTextBlobSkia(blob);
740
741 // Simulate recording the text frame during preroll.
742 Matrix preroll_matrix =
743 Matrix::MakeTranslateScale({1.5, 1.5, 1}, {100, 50, 0});
744 Point preroll_point = Point{23, 45};
745 {
746 aiks_context.GetContentContext().GetLazyGlyphAtlas()->AddTextFrame(
747 text_frame, //
748 preroll_point, //
749 preroll_matrix, //
750 GlyphProperties{} //
751 );
752 }
753
754 // Now simulate rendering with a slightly different scale factor.
755 RenderTarget render_target =
756 aiks_context.GetContentContext()
758 ->CreateOffscreenMSAA(*aiks_context.GetContext(), {100, 100}, 1);
759
760 TextContents text_contents;
761 text_contents.SetTextFrame(text_frame);
762 text_contents.SetPosition(preroll_point);
763 text_contents.SetScreenTransform(preroll_matrix);
764 text_contents.SetColor(Color::Aqua());
765
766 Matrix not_preroll_matrix =
767 preroll_matrix * Matrix::MakeScale({2.0f, 2.0f, 1.0f});
768
769 Entity entity;
770 entity.SetTransform(not_preroll_matrix);
771
772 std::shared_ptr<CommandBuffer> command_buffer =
773 aiks_context.GetContext()->CreateCommandBuffer();
774 std::shared_ptr<RenderPass> render_pass =
775 command_buffer->CreateRenderPass(render_target);
776
777 EXPECT_TRUE(text_contents.Render(aiks_context.GetContentContext(), entity,
778 *render_pass));
779}
780
781TEST_P(AiksTest, CanRenderTextFrameWithThinLightAndDarkColors) {
782 DisplayListBuilder builder;
783 DlPaint paint;
784 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
785 builder.DrawPaint(paint);
786
787 auto mapping =
788 flutter::testing::OpenFixtureAsSkData("RobotoSlab-VariableFont_wght.ttf");
789 ASSERT_TRUE(mapping);
790 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
791
792 // Set the variation axis for weight to 100 (typically "Thin").
793 SkFontArguments::VariationPosition::Coordinate weight_coord{
794 SkSetFourByteTag('w', 'g', 'h', 't'), 100.0f};
795 SkFontArguments args;
796 args.setVariationDesignPosition({&weight_coord, 1});
797
798 SkFont thin_font(font_mgr->makeFromData(mapping)->makeClone(args), 25);
799
800 // Render light text
801 ASSERT_TRUE(RenderTextInCanvasSkia(
802 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
803 "RobotoSlab-VariableFont_wght.ttf",
805 .position = DlPoint(100, 200)},
806 thin_font));
807
808 // Render dark text on a light background
809 DlPaint dart_text_background_paint;
810 dart_text_background_paint.setColor(DlColor::ARGB(1, 0.9, 0.9, 0.9));
811 builder.DrawRect(DlRect::MakeXYWH(50, 250, 900, 100),
812 dart_text_background_paint);
813 ASSERT_TRUE(RenderTextInCanvasSkia(
814 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
815 "RobotoSlab-VariableFont_wght.ttf",
817 .position = DlPoint(100, 300)},
818 thin_font));
819
820 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
821}
822
823TEST_P(AiksTest, TextWithShadowCache) {
824 DisplayListBuilder builder;
825 builder.Scale(GetContentScale().x, GetContentScale().y);
826 DlPaint paint;
827 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
828 builder.DrawPaint(paint);
829
830 AiksContext aiks_context(GetContext(),
831 std::make_shared<TypographerContextSkia>());
832 // Cache empty
833 EXPECT_EQ(aiks_context.GetContentContext()
836 0u);
837
838 ASSERT_TRUE(RenderTextInCanvasSkia(
839 GetContext(), builder, "Hello World", kFontFixture,
842 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)}));
843
844 DisplayListToTexture(builder.Build(), {400, 400}, aiks_context);
845
846 // Text should be cached.
847 EXPECT_EQ(aiks_context.GetContentContext()
850 1u);
851}
852
853TEST_P(AiksTest, MultipleTextWithShadowCache) {
854 DisplayListBuilder builder;
855 builder.Scale(GetContentScale().x, GetContentScale().y);
856 DlPaint paint;
857 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
858 builder.DrawPaint(paint);
859
860 AiksContext aiks_context(GetContext(),
861 std::make_shared<TypographerContextSkia>());
862 // Cache empty
863 EXPECT_EQ(aiks_context.GetContentContext()
866 0u);
867
868 for (auto i = 0; i < 5; i++) {
869 ASSERT_TRUE(RenderTextInCanvasSkia(
870 GetContext(), builder, "Hello World", kFontFixture,
873 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)}));
874 }
875
876 DisplayListToTexture(builder.Build(), {400, 400}, aiks_context);
877
878 // Text should be cached. Each text gets its own entry as we don't analyze the
879 // strings.
880 EXPECT_EQ(aiks_context.GetContentContext()
883 5u);
884}
885
886TEST_P(AiksTest, MultipleColorWithShadowCache) {
887 DisplayListBuilder builder;
888 builder.Scale(GetContentScale().x, GetContentScale().y);
889 DlPaint paint;
890 paint.setColor(DlColor::kWhite());
891 builder.DrawPaint(paint);
892
893 AiksContext aiks_context(GetContext(),
894 std::make_shared<TypographerContextSkia>());
895 // Cache empty
896 EXPECT_EQ(aiks_context.GetContentContext()
899 0u);
900
901 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
902
903 std::array<DlColor, 4> colors{DlColor::kRed(), DlColor::kGreen(),
905 for (const auto& color : colors) {
906 ASSERT_TRUE(RenderTextInCanvasSkia(
907 GetContext(), builder, "A", kFontFixture,
909 .color = color,
910 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)},
911 sk_font));
912 }
913
914 DisplayListToTexture(builder.Build(), {400, 400}, aiks_context);
915
916 // The count of cache entries should match the number of distinct colors
917 // in the list. Repeated usage of a color should not add to the cache.
918 EXPECT_EQ(aiks_context.GetContentContext()
921 3u);
922}
923
924TEST_P(AiksTest, SingleIconShadowTest) {
925 DisplayListBuilder builder;
926 builder.Scale(GetContentScale().x, GetContentScale().y);
927 DlPaint paint;
928 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
929 builder.DrawPaint(paint);
930
931 AiksContext aiks_context(GetContext(),
932 std::make_shared<TypographerContextSkia>());
933 // Cache empty
934 EXPECT_EQ(aiks_context.GetContentContext()
937 0u);
938
939 // Create font instance outside loop so all draws use identical font instance.
940 auto c_font_fixture = std::string(kFontFixture);
941 auto mapping = flutter::testing::OpenFixtureAsSkData(c_font_fixture.c_str());
942 ASSERT_TRUE(mapping);
943 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
944 SkFont sk_font(font_mgr->makeFromData(mapping), 50);
945
946 for (auto i = 0; i < 10; i++) {
947 ASSERT_TRUE(RenderTextInCanvasSkia(
948 GetContext(), builder, "A", kFontFixture,
951 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)},
952 sk_font));
953 }
954
955 DisplayListToTexture(builder.Build(), {400, 400}, aiks_context);
956
957 // Text should be cached. All 10 glyphs use the same cache entry.
958 EXPECT_EQ(aiks_context.GetContentContext()
961 1u);
962}
963
964TEST_P(AiksTest, VarietyOfTextScalesShowingRasterAndPath) {
965 DisplayListBuilder builder;
966 DlPaint paint;
967 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
968 builder.DrawPaint(paint);
969 builder.Scale(GetContentScale().x, GetContentScale().y);
970
971 std::vector<Scalar> scales = {4, 8, 16, 24, 32};
972 std::vector<Scalar> spacing = {8, 8, 8, 8, 8};
973 Scalar space = 16;
974 Scalar x = 0;
975 for (auto i = 0u; i < scales.size(); i++) {
976 builder.Save();
977 builder.Scale(scales[i], scales[i]);
979 GetContext(), builder, "lo", "Roboto-Regular.ttf",
980 TextRenderOptions{.font_size = 16, .position = DlPoint(x, space)});
981 space += spacing[i];
982 if (i == 3) {
983 x = 10;
984 space = 16;
985 }
986 builder.Restore();
987 }
988 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
989}
990
991namespace {
992std::shared_ptr<TextFrame> MakeDefaultTextFrame(const std::string& text,
994 // Construct the text blob.
995 auto mapping = flutter::testing::OpenFixtureAsSkData("Roboto-Regular.ttf");
996 if (mapping == nullptr) {
997 return nullptr;
998 }
999
1000 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
1001 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
1002 sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromString("Hi", sk_font);
1003
1004 std::shared_ptr<TextFrame> text_frame = MakeTextFrameFromTextBlobSkia(blob);
1005 return text_frame;
1006}
1007
1008void DrawTextFramesMultipleScalesWithReuse(AiksTest* test,
1009 Scalar first_scale,
1010 Scalar second_scale) {
1011 DisplayListBuilder builder;
1012 builder.Scale(test->GetContentScale().x, test->GetContentScale().y);
1013 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1014
1015 std::shared_ptr<TextFrame> reuse_frame = MakeDefaultTextFrame("Hi", 20.0f);
1016 ASSERT_NE(reuse_frame, nullptr);
1017
1018 builder.Save();
1019 builder.Translate(100, 100);
1020 builder.Scale(first_scale, first_scale);
1021 builder.DrawText(DlTextImpeller::Make(reuse_frame), 0, 0,
1023 builder.Restore();
1024
1025 builder.Save();
1026 builder.Translate(400, 100);
1027 builder.Scale(second_scale, second_scale);
1028 builder.DrawText(DlTextImpeller::Make(reuse_frame), 0, 0,
1030 builder.Restore();
1031
1032 builder.Save();
1033 builder.Translate(100, 400);
1034 builder.Scale(first_scale, first_scale);
1035 std::shared_ptr<TextFrame> single_use_frame1 =
1036 MakeDefaultTextFrame("Hi", 20.0f);
1037 builder.DrawText(DlTextImpeller::Make(single_use_frame1), 0, 0,
1039 builder.Restore();
1040
1041 builder.Save();
1042 builder.Translate(400, 400);
1043 builder.Scale(second_scale, second_scale);
1044 std::shared_ptr<TextFrame> single_use_frame2 =
1045 MakeDefaultTextFrame("Hi", 20.0f);
1046 builder.DrawText(DlTextImpeller::Make(single_use_frame2), 0, 0,
1048 builder.Restore();
1049
1050 ASSERT_TRUE(test->OpenPlaygroundHere(builder.Build()));
1051}
1052} // namespace
1053
1054TEST_P(AiksTest, TextFramesDoNotShareRenderDataBigSmall) {
1055 DrawTextFramesMultipleScalesWithReuse(this, //
1056 /*first_scale=*/4.0f, //
1057 /*second_scale=*/0.5f);
1058}
1059
1060TEST_P(AiksTest, TextFramesDoNotShareRenderDataSmallBig) {
1061 DrawTextFramesMultipleScalesWithReuse(this, //
1062 /*first_scale=*/0.5f, //
1063 /*second_scale=*/4.0f);
1064}
1065
1066// Verifies that non-uniform (anisotropic) scaling uses bilinear filtering
1067// to avoid jagged/aliased text, while uniform scaling remains pixel-perfect.
1068// Regression test for https://github.com/flutter/flutter/issues/182143
1069TEST_P(AiksTest, TextWithNonUniformScale) {
1070 DisplayListBuilder builder;
1071
1072 DlPaint paint;
1073 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
1074 builder.DrawPaint(paint);
1075
1076 // Row 1: Uniform scale (should use nearest-neighbor, pixel-perfect).
1077 builder.Save();
1078 builder.Scale(2, 2);
1079 ASSERT_TRUE(RenderTextInCanvasSkia(
1080 GetContext(), builder, "Uniform 2x2", "Roboto-Regular.ttf",
1081 TextRenderOptions{.font_size = 30, .position = DlPoint(20, 40)}));
1082 builder.Restore();
1083
1084 // Row 2: Non-uniform scale Y-only (ratio 2.0, triggers bilinear).
1085 builder.Save();
1086 builder.Scale(1, 2);
1087 ASSERT_TRUE(RenderTextInCanvasSkia(
1088 GetContext(), builder, "ScaleY 1x2", "Roboto-Regular.ttf",
1089 TextRenderOptions{.font_size = 30, .position = DlPoint(20, 140)}));
1090 builder.Restore();
1091
1092 // Row 3: Non-uniform scale X-only (ratio 3.0, triggers bilinear).
1093 builder.Save();
1094 builder.Scale(3, 1);
1095 ASSERT_TRUE(RenderTextInCanvasSkia(
1096 GetContext(), builder, "ScaleX 3x1", "Roboto-Regular.ttf",
1097 TextRenderOptions{.font_size = 30, .position = DlPoint(20, 300)}));
1098 builder.Restore();
1099
1100 // Row 4: Slightly non-uniform (ratio 1.1, below threshold, nearest).
1101 builder.Save();
1102 builder.Scale(2, 2.2);
1103 ASSERT_TRUE(RenderTextInCanvasSkia(
1104 GetContext(), builder, "Near-uniform 2x2.2", "Roboto-Regular.ttf",
1105 TextRenderOptions{.font_size = 30, .position = DlPoint(20, 200)}));
1106 builder.Restore();
1107
1108 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1109}
1110
1111TEST_P(AiksTest, TextGammaCorrectionGoldenTest) {
1112 constexpr const char* font_fixture = "Roboto-Regular.ttf";
1113 auto c_font_fixture = std::string(font_fixture);
1114 auto mapping = flutter::testing::OpenFixtureAsSkData(c_font_fixture.c_str());
1115 ASSERT_TRUE(mapping);
1116
1117 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
1118 SkFont sk_font(/*typeface=*/font_mgr->makeFromData(mapping), /*size=*/60);
1119 sk_font.setSubpixel(true);
1120
1121 auto blob_corrected =
1122 SkTextBlob::MakeFromString("Gamma Corrected (true)", sk_font);
1123 ASSERT_TRUE(blob_corrected);
1124 auto text_frame_corrected = MakeTextFrameFromTextBlobSkia(blob_corrected);
1125 text_frame_corrected->SetEnableGammaCorrection(true);
1126
1127 auto blob_uncorrected =
1128 SkTextBlob::MakeFromString("Gamma Corrected (false)", sk_font);
1129 ASSERT_TRUE(blob_uncorrected);
1130 auto text_frame_uncorrected = MakeTextFrameFromTextBlobSkia(blob_uncorrected);
1131 text_frame_uncorrected->SetEnableGammaCorrection(false);
1132
1133 auto callback = [&]() -> sk_sp<flutter::DisplayList> {
1134 DisplayListBuilder builder;
1135
1136 DlPaint bg_paint;
1137 bg_paint.setColor(DlColor::ARGB(1.0, 0.1, 0.1, 0.1));
1138 builder.DrawPaint(bg_paint);
1139
1140 DlPaint text_paint;
1141 text_paint.setColor(DlColor::kWhite());
1142
1143 builder.DrawText(/*text=*/DlTextImpeller::Make(text_frame_corrected),
1144 /*x=*/50, /*y=*/100, /*paint=*/text_paint);
1145 builder.DrawText(/*text=*/DlTextImpeller::Make(text_frame_uncorrected),
1146 /*x=*/50, /*y=*/200, /*paint=*/text_paint);
1147
1148 builder.DrawText(/*text=*/DlTextImpeller::Make(text_frame_corrected),
1149 /*x=*/50, /*y=*/300, /*paint=*/text_paint);
1150 DlPaint diff_paint = text_paint;
1151 diff_paint.setBlendMode(DlBlendMode::kDifference);
1152 builder.DrawText(/*text=*/DlTextImpeller::Make(text_frame_uncorrected),
1153 /*x=*/50, /*y=*/300, /*paint=*/diff_paint);
1154
1155 return builder.Build();
1156 };
1157
1158 ASSERT_TRUE(OpenPlaygroundHere(callback));
1159}
1160
1161TEST_P(AiksTest, TextWithShadowAndPosition) {
1162 DisplayListBuilder builder;
1163 builder.Scale(GetContentScale().x, GetContentScale().y);
1164 builder.Clear(DlColor::kWhite());
1165
1166 auto frame = MakeDefaultTextFrame("Hello", 25.0f);
1167 auto text = DlTextImpeller::Make(frame);
1169 DlPaint shadow_paint_ctm = DlPaint().setMaskFilter(
1170 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 5.0f, true));
1171 DlPaint shadow_paint_no_ctm = DlPaint().setMaskFilter(
1172 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 5.0f, false));
1173
1174 builder.Translate(100, 100);
1175 builder.Scale(4, 4);
1176 for (int x = 10; x <= 100; x += 30) {
1177 builder.DrawText(text, x, 20, shadow_paint_ctm);
1178 builder.DrawText(text, x, 20, paint);
1179
1180 builder.DrawText(text, x, 50, shadow_paint_no_ctm);
1181 builder.DrawText(text, x, 50, paint);
1182 }
1183
1184 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1185}
1186
1187} // namespace testing
1188} // namespace impeller
void ClipRect(const DlRect &rect, DlClipOp clip_op=DlClipOp::kIntersect, bool is_aa=false) override
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 Rotate(DlScalar degrees) override
void DrawText(const std::shared_ptr< DlText > &text, DlScalar x, DlScalar y, const DlPaint &paint) override
void Scale(DlScalar sx, DlScalar sy) override
void DrawDisplayList(const sk_sp< DisplayList > display_list, DlScalar opacity=SK_Scalar1) override
void Translate(DlScalar tx, DlScalar ty) override
void DrawPaint(const DlPaint &paint) override
sk_sp< DisplayList > Build()
void DrawPath(const DlPath &path, const DlPaint &paint) override
void Transform(const DlMatrix &matrix) override
void DrawRect(const DlRect &rect, const DlPaint &paint) override
static std::shared_ptr< DlMaskFilter > Make(DlBlurStyle style, SkScalar sigma, bool respect_ctm=true)
void Clear(DlColor color)
Definition dl_canvas.h:104
static std::shared_ptr< DlColorSource > MakeLinear(const DlPoint start_point, const DlPoint end_point, uint32_t stop_count, const DlColor *colors, const float *stops, DlTileMode tile_mode, const DlMatrix *matrix=nullptr)
DlPaint & setColor(DlColor color)
Definition dl_paint.h:70
DlPaint & setStrokeWidth(float width)
Definition dl_paint.h:115
DlPaint & setBlendMode(DlBlendMode mode)
Definition dl_paint.h:85
DlPaint & setMaskFilter(std::nullptr_t filter)
Definition dl_paint.h:185
DlPaint & setDrawStyle(DlDrawStyle style)
Definition dl_paint.h:93
DlPaint & setColorSource(std::nullptr_t source)
Definition dl_paint.h:131
DlPathBuilder & LineTo(DlPoint p2)
Draw a line from the current point to the indicated point p2.
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 & Close()
The path is closed back to the location of the most recent MoveTo call. Contours that are filled are ...
static std::shared_ptr< DlTextImpeller > Make(const std::shared_ptr< impeller::TextFrame > &frame)
ContentContext & GetContentContext() const
std::shared_ptr< Context > GetContext() const
const std::shared_ptr< RenderTargetAllocator > & GetRenderTargetCache() const
const std::shared_ptr< LazyGlyphAtlas > & GetLazyGlyphAtlas() const
TextShadowCache & GetTextShadowCache() const
void SetTransform(const Matrix &transform)
Set the global transform matrix for this Entity.
Definition entity.cc:62
void SetPosition(Point position)
void SetScreenTransform(const Matrix &transform)
bool Render(const ContentContext &renderer, const Entity &entity, RenderPass &pass) const override
void SetTextFrame(const std::shared_ptr< TextFrame > &frame)
void SetColor(Color color)
size_t GetCacheSizeForTesting() const
int32_t x
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
FlutterDesktopBinaryReply callback
std::u16string text
double y
SkFont CreateTestFontOfSize(DlScalar scalar)
sk_sp< SkData > OpenFixtureAsSkData(const std::string &fixture_name)
Opens a fixture of the given file name and returns a Skia SkData holding its contents.
Definition testing.cc:63
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition switch_defs.h:52
DlDrawStyle
Definition dl_paint.h:19
@ kFill
fills interior of shapes
impeller::Point DlPoint
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)
TEST_P(AiksTest, DrawAtlasNoColor)
AiksPlaygroundWithGoldens AiksTest
static constexpr std::string_view kFontFixture
constexpr float k2Pi
Definition constants.h:29
float Scalar
Definition scalar.h:19
std::shared_ptr< Texture > DisplayListToTexture(const sk_sp< flutter::DisplayList > &display_list, ISize size, AiksContext &context, bool reset_host_buffer, bool generate_mips, std::optional< PixelFormat > target_pixel_format)
Render the provided display list to a texture with the given size.
std::shared_ptr< TextFrame > MakeTextFrameFromTextBlobSkia(const sk_sp< SkTextBlob > &blob)
sk_sp< SkFontMgr > GetDefaultFontManager(uint32_t font_initialization_data)
Definition platform.cc:17
std::shared_ptr< ContextGLES > context
std::shared_ptr< RenderPass > render_pass
std::shared_ptr< CommandBuffer > command_buffer
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 RGBA(DlScalar r, DlScalar g, DlScalar b, DlScalar a)
Construct a 32 bit color from floating point R, G, B, and A color channels.
Definition dl_color.h:48
static constexpr DlColor kBlack()
Definition dl_color.h:69
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 kPurple()
Definition dl_color.h:88
static constexpr DlColor kDarkGreen()
Definition dl_color.h:93
static constexpr DlColor kRed()
Definition dl_color.h:71
static constexpr DlColor kGreen()
Definition dl_color.h:72
static constexpr DlColor kOrange()
Definition dl_color.h:87
constexpr DlColor modulateOpacity(DlScalar opacity) const
Definition dl_color.h:150
static constexpr Color Aqua()
Definition color.h:295
A 4x4 matrix using column-major storage.
Definition matrix.h:37
static Matrix MakeRotationY(Radians r)
Definition matrix.h:208
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 constexpr Matrix MakeTranslateScale(const Vector3 &s, const Vector3 &t)
Definition matrix.h:113
static constexpr Matrix MakeScale(const Vector3 &s)
Definition matrix.h:104
static RoundRect MakeRectRadius(const Rect &rect, Scalar radius)
Definition round_rect.h:27
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
std::shared_ptr< DlMaskFilter > filter
Scalar font_size
bool is_subpixel