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 (AiksTest::ImGuiBegin("Controls", nullptr,
202 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 (AiksTest::ImGuiBegin("Controls", nullptr,
231 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 (AiksTest::ImGuiBegin("Controls", nullptr,
259 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 (AiksTest::ImGuiBegin("Controls", nullptr,
289 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 (AiksTest::ImGuiBegin("Controls", nullptr,
332 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 DisplayListBuilder builder;
493
494 builder.Scale(GetContentScale().x, GetContentScale().y);
495 DlPaint paint;
496 paint.setColor(DlColor::ARGB(0.1, 0.1, 0.1, 1.0));
497 builder.DrawPaint(paint);
498
499 builder.Transform(Matrix(0.25, -0.3, 0, -0.002, //
500 0, 0.5, 0, 0, //
501 0, 0, 0.3, 0, //
502 100, 100, 0, 1.3));
503 ASSERT_TRUE(RenderTextInCanvasSkia(
504 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
505 "Roboto-Regular.ttf"));
506
507 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
508}
509
510TEST_P(AiksTest, DrawScaledTextWithPerspectiveNoSaveLayer) {
511 DisplayListBuilder builder;
512
513 Matrix matrix = Matrix(1.0, 0.0, 0.0, 0.0, //
514 0.0, 1.0, 0.0, 0.0, //
515 0.0, 0.0, 1.0, 0.01, //
516 0.0, 0.0, 0.0, 1.0) * //
518
519 builder.Transform(matrix);
520
521 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "Hello world",
522 "Roboto-Regular.ttf"));
523 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
524}
525
526TEST_P(AiksTest, DrawScaledTextWithPerspectiveSaveLayer) {
527 DisplayListBuilder builder;
528
529 Matrix matrix = Matrix(1.0, 0.0, 0.0, 0.0, //
530 0.0, 1.0, 0.0, 0.0, //
531 0.0, 0.0, 1.0, 0.01, //
532 0.0, 0.0, 0.0, 1.0) * //
534
535 DlPaint save_paint;
536 DlRect window_bounds =
537 DlRect::MakeXYWH(0, 0, GetWindowSize().width, GetWindowSize().height);
538 // Note: bounds were not needed by the AIKS version, which may indicate a bug.
539 builder.SaveLayer(window_bounds, &save_paint);
540 builder.Transform(matrix);
541
542 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "Hello world",
543 "Roboto-Regular.ttf"));
544
545 builder.Restore();
546 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
547}
548
549TEST_P(AiksTest, CanRenderTextWithLargePerspectiveTransform) {
550 // Verifies that text scales are clamped to work around
551 // https://github.com/flutter/flutter/issues/136112 .
552
553 DisplayListBuilder builder;
554
555 DlPaint save_paint;
556 builder.SaveLayer(std::nullopt, &save_paint);
557 builder.Transform(Matrix(2000, 0, 0, 0, //
558 0, 2000, 0, 0, //
559 0, 0, -1, 9000, //
560 0, 0, -1, 7000 //
561 ));
562
563 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), builder, "Hello world",
564 "Roboto-Regular.ttf"));
565 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
566}
567
568TEST_P(AiksTest, CanRenderTextWithPerspectiveTransformInSublist) {
569 DisplayListBuilder text_builder;
570 ASSERT_TRUE(RenderTextInCanvasSkia(GetContext(), text_builder, "Hello world",
571 "Roboto-Regular.ttf"));
572 auto text_display_list = text_builder.Build();
573
574 DisplayListBuilder builder;
575
576 Matrix matrix = Matrix::MakeRow(2.0, 0.0, 0.0, 0.0, //
577 0.0, 2.0, 0.0, 0.0, //
578 0.0, 0.0, 1.0, 0.0, //
579 0.0, 0.002, 0.0, 1.0);
580
581 DlPaint save_paint;
582 DlRect window_bounds =
583 DlRect::MakeXYWH(0, 0, GetWindowSize().width, GetWindowSize().height);
584 builder.SaveLayer(window_bounds, &save_paint);
585 builder.Transform(matrix);
586 builder.DrawDisplayList(text_display_list, 1.0f);
587 builder.Restore();
588
589 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
590}
591
592// This currently renders solid blue, as the support for text color sources was
593// moved into DLDispatching. Path data requires the SkTextBlobs which are not
594// used in impeller::TextFrames.
595TEST_P(AiksTest, TextForegroundShaderWithTransform) {
596 auto mapping = flutter::testing::OpenFixtureAsSkData("Roboto-Regular.ttf");
597 ASSERT_NE(mapping, nullptr);
598
599 Scalar font_size = 100;
600 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
601 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
602
603 DlPaint text_paint;
604 text_paint.setColor(DlColor::kBlue());
605
606 std::vector<DlColor> colors = {DlColor::RGBA(0.9568, 0.2627, 0.2118, 1.0),
607 DlColor::RGBA(0.1294, 0.5882, 0.9529, 1.0)};
608 std::vector<Scalar> stops = {
609 0.0,
610 1.0,
611 };
613 /*start_point=*/DlPoint(0, 0), //
614 /*end_point=*/DlPoint(100, 100), //
615 /*stop_count=*/2, //
616 /*colors=*/colors.data(), //
617 /*stops=*/stops.data(), //
618 /*tile_mode=*/DlTileMode::kRepeat //
619 ));
620
621 DisplayListBuilder builder;
622 builder.Translate(100, 100);
623 builder.Rotate(45);
624
625 auto blob = SkTextBlob::MakeFromString("Hello", sk_font);
626 ASSERT_NE(blob, nullptr);
627 auto frame = MakeTextFrameFromTextBlobSkia(blob);
628 builder.DrawText(DlTextImpeller::Make(frame), 0, 0, text_paint);
629
630 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
631}
632
633// Regression test for https://github.com/flutter/flutter/issues/157885.
634TEST_P(AiksTest, DifferenceClipsMustRenderIdenticallyAcrossBackends) {
635 DisplayListBuilder builder;
636
637 DlPaint paint;
638 DlColor clear_color(1.0, 0.5, 0.5, 0.5, DlColorSpace::kSRGB);
639 paint.setColor(clear_color);
640 builder.DrawPaint(paint);
641
642 DlMatrix identity = {
643 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
644 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0,
645 };
646 builder.Save();
647 builder.Transform(identity);
648
649 DlRect frame = DlRect::MakeLTRB(1.0, 1.0, 1278.0, 763.0);
650 DlColor white(1.0, 1.0, 1.0, 1.0, DlColorSpace::kSRGB);
651 paint.setColor(white);
652 builder.DrawRect(frame, paint);
653
654 builder.Save();
655 builder.ClipRect(frame, DlClipOp::kIntersect);
656
657 DlMatrix rect_xform = {
658 0.8241262, 0.56640625, 0.0, 0.0, -0.56640625, 0.8241262, 0.0, 0.0,
659 0.0, 0.0, 1.0, 0.0, 271.1137, 489.4733, 0.0, 1.0,
660 };
661 builder.Save();
662 builder.Transform(rect_xform);
663
664 DlRect rect = DlRect::MakeLTRB(0.0, 0.0, 100.0, 100.0);
665 DlColor bluish(1.0, 0.184, 0.501, 0.929, DlColorSpace::kSRGB);
666 paint.setColor(bluish);
667 DlRoundRect rrect = DlRoundRect::MakeRectRadius(rect, 18.0);
668 builder.DrawRoundRect(rrect, paint);
669
670 builder.Save();
671 builder.ClipRect(rect, DlClipOp::kIntersect);
672 builder.Restore();
673
674 builder.Restore();
675
676 DlMatrix path_xform = {
677 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0,
678 0.0, 0.0, 1.0, 0.0, 675.0, 279.5, 0.0, 1.0,
679 };
680 builder.Save();
681 builder.Transform(path_xform);
682
683 DlPathBuilder path_builder;
684 path_builder.MoveTo(DlPoint(87.5, 349.5));
685 path_builder.LineTo(DlPoint(25.0, 29.5));
686 path_builder.LineTo(DlPoint(150.0, 118.0));
687 path_builder.LineTo(DlPoint(25.0, 118.0));
688 path_builder.LineTo(DlPoint(150.0, 29.5));
689 path_builder.Close();
690 DlPath path = path_builder.TakePath();
691
692 DlColor fill_color(1.0, 1.0, 0.0, 0.0, DlColorSpace::kSRGB);
693 DlColor stroke_color(1.0, 0.0, 0.0, 0.0, DlColorSpace::kSRGB);
694 paint.setColor(fill_color);
695 paint.setDrawStyle(DlDrawStyle::kFill);
696 builder.DrawPath(path, paint);
697
698 paint.setColor(stroke_color);
699 paint.setStrokeWidth(2.0);
700 paint.setDrawStyle(DlDrawStyle::kStroke);
701 builder.DrawPath(path, paint);
702
703 builder.Restore();
704 builder.Restore();
705 builder.Restore();
706
707 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
708}
709
710TEST_P(AiksTest, TextContentsMismatchedTransformTest) {
711 AiksContext aiks_context(GetContext(),
712 std::make_shared<TypographerContextSkia>());
713
714 // Verifies that TextContents only use the scale/transform that is
715 // computed during preroll.
716 constexpr const char* font_fixture = "Roboto-Regular.ttf";
717
718 // Construct the text blob.
719 auto c_font_fixture = std::string(font_fixture);
720 auto mapping = flutter::testing::OpenFixtureAsSkData(c_font_fixture.c_str());
721 ASSERT_TRUE(mapping);
722
723 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
724 SkFont sk_font(font_mgr->makeFromData(mapping), 16);
725
726 auto blob = SkTextBlob::MakeFromString("Hello World", sk_font);
727 ASSERT_TRUE(blob);
728
729 auto text_frame = MakeTextFrameFromTextBlobSkia(blob);
730
731 // Simulate recording the text frame during preroll.
732 Matrix preroll_matrix =
733 Matrix::MakeTranslateScale({1.5, 1.5, 1}, {100, 50, 0});
734 Point preroll_point = Point{23, 45};
735 {
736 aiks_context.GetContentContext().GetLazyGlyphAtlas()->AddTextFrame(
737 text_frame, //
738 preroll_point, //
739 preroll_matrix, //
740 GlyphProperties{} //
741 );
742 }
743
744 // Now simulate rendering with a slightly different scale factor.
745 RenderTarget render_target =
746 aiks_context.GetContentContext()
748 ->CreateOffscreenMSAA(*aiks_context.GetContext(), {100, 100}, 1);
749
750 TextContents text_contents;
751 text_contents.SetTextFrame(text_frame);
752 text_contents.SetPosition(preroll_point);
753 text_contents.SetScreenTransform(preroll_matrix);
754 text_contents.SetColor(Color::Aqua());
755
756 Matrix not_preroll_matrix =
757 preroll_matrix * Matrix::MakeScale({2.0f, 2.0f, 1.0f});
758
759 Entity entity;
760 entity.SetTransform(not_preroll_matrix);
761
762 std::shared_ptr<CommandBuffer> command_buffer =
763 aiks_context.GetContext()->CreateCommandBuffer();
764 std::shared_ptr<RenderPass> render_pass =
765 command_buffer->CreateRenderPass(render_target);
766
767 EXPECT_TRUE(text_contents.Render(aiks_context.GetContentContext(), entity,
768 *render_pass));
769}
770
771TEST_P(AiksTest, CanRenderTextFrameWithThinLightAndDarkColors) {
772 DisplayListBuilder builder;
773 DlPaint paint;
774 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
775 builder.DrawPaint(paint);
776
777 auto mapping =
778 flutter::testing::OpenFixtureAsSkData("RobotoSlab-VariableFont_wght.ttf");
779 ASSERT_TRUE(mapping);
780 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
781
782 // Set the variation axis for weight to 100 (typically "Thin").
783 SkFontArguments::VariationPosition::Coordinate weight_coord{
784 SkSetFourByteTag('w', 'g', 'h', 't'), 100.0f};
785 SkFontArguments args;
786 args.setVariationDesignPosition({&weight_coord, 1});
787
788 SkFont thin_font(font_mgr->makeFromData(mapping)->makeClone(args), 25);
789
790 // Render light text
791 ASSERT_TRUE(RenderTextInCanvasSkia(
792 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
793 "RobotoSlab-VariableFont_wght.ttf",
795 .position = DlPoint(100, 200)},
796 thin_font));
797
798 // Render dark text on a light background
799 DlPaint dart_text_background_paint;
800 dart_text_background_paint.setColor(DlColor::ARGB(1, 0.9, 0.9, 0.9));
801 builder.DrawRect(DlRect::MakeXYWH(50, 250, 900, 100),
802 dart_text_background_paint);
803 ASSERT_TRUE(RenderTextInCanvasSkia(
804 GetContext(), builder, "the quick brown fox jumped over the lazy dog!.?",
805 "RobotoSlab-VariableFont_wght.ttf",
807 .position = DlPoint(100, 300)},
808 thin_font));
809
810 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
811}
812
813TEST_P(AiksTest, TextWithShadowCache) {
814 DisplayListBuilder builder;
815 builder.Scale(GetContentScale().x, GetContentScale().y);
816 DlPaint paint;
817 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
818 builder.DrawPaint(paint);
819
820 AiksContext aiks_context(GetContext(),
821 std::make_shared<TypographerContextSkia>());
822 // Cache empty
823 EXPECT_EQ(aiks_context.GetContentContext()
826 0u);
827
828 ASSERT_TRUE(RenderTextInCanvasSkia(
829 GetContext(), builder, "Hello World", kFontFixture,
832 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)}));
833
834 DisplayListToTexture(builder.Build(), {400, 400}, aiks_context);
835
836 // Text should be cached.
837 EXPECT_EQ(aiks_context.GetContentContext()
840 1u);
841}
842
843TEST_P(AiksTest, MultipleTextWithShadowCache) {
844 DisplayListBuilder builder;
845 builder.Scale(GetContentScale().x, GetContentScale().y);
846 DlPaint paint;
847 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
848 builder.DrawPaint(paint);
849
850 AiksContext aiks_context(GetContext(),
851 std::make_shared<TypographerContextSkia>());
852 // Cache empty
853 EXPECT_EQ(aiks_context.GetContentContext()
856 0u);
857
858 for (auto i = 0; i < 5; i++) {
859 ASSERT_TRUE(RenderTextInCanvasSkia(
860 GetContext(), builder, "Hello World", kFontFixture,
863 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)}));
864 }
865
866 DisplayListToTexture(builder.Build(), {400, 400}, aiks_context);
867
868 // Text should be cached. Each text gets its own entry as we don't analyze the
869 // strings.
870 EXPECT_EQ(aiks_context.GetContentContext()
873 5u);
874}
875
876TEST_P(AiksTest, MultipleColorWithShadowCache) {
877 DisplayListBuilder builder;
878 builder.Scale(GetContentScale().x, GetContentScale().y);
879 DlPaint paint;
880 paint.setColor(DlColor::kWhite());
881 builder.DrawPaint(paint);
882
883 AiksContext aiks_context(GetContext(),
884 std::make_shared<TypographerContextSkia>());
885 // Cache empty
886 EXPECT_EQ(aiks_context.GetContentContext()
889 0u);
890
891 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
892
893 std::array<DlColor, 4> colors{DlColor::kRed(), DlColor::kGreen(),
895 for (const auto& color : colors) {
896 ASSERT_TRUE(RenderTextInCanvasSkia(
897 GetContext(), builder, "A", kFontFixture,
899 .color = color,
900 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)},
901 sk_font));
902 }
903
904 DisplayListToTexture(builder.Build(), {400, 400}, aiks_context);
905
906 // The count of cache entries should match the number of distinct colors
907 // in the list. Repeated usage of a color should not add to the cache.
908 EXPECT_EQ(aiks_context.GetContentContext()
911 3u);
912}
913
914TEST_P(AiksTest, SingleIconShadowTest) {
915 DisplayListBuilder builder;
916 builder.Scale(GetContentScale().x, GetContentScale().y);
917 DlPaint paint;
918 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
919 builder.DrawPaint(paint);
920
921 AiksContext aiks_context(GetContext(),
922 std::make_shared<TypographerContextSkia>());
923 // Cache empty
924 EXPECT_EQ(aiks_context.GetContentContext()
927 0u);
928
929 // Create font instance outside loop so all draws use identical font instance.
930 auto c_font_fixture = std::string(kFontFixture);
931 auto mapping = flutter::testing::OpenFixtureAsSkData(c_font_fixture.c_str());
932 ASSERT_TRUE(mapping);
933 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
934 SkFont sk_font(font_mgr->makeFromData(mapping), 50);
935
936 for (auto i = 0; i < 10; i++) {
937 ASSERT_TRUE(RenderTextInCanvasSkia(
938 GetContext(), builder, "A", kFontFixture,
941 .filter = DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 4)},
942 sk_font));
943 }
944
945 DisplayListToTexture(builder.Build(), {400, 400}, aiks_context);
946
947 // Text should be cached. All 10 glyphs use the same cache entry.
948 EXPECT_EQ(aiks_context.GetContentContext()
951 1u);
952}
953
954TEST_P(AiksTest, VarietyOfTextScalesShowingRasterAndPath) {
955 DisplayListBuilder builder;
956 DlPaint paint;
957 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
958 builder.DrawPaint(paint);
959 builder.Scale(GetContentScale().x, GetContentScale().y);
960
961 std::vector<Scalar> scales = {4, 8, 16, 24, 32};
962 std::vector<Scalar> spacing = {8, 8, 8, 8, 8};
963 Scalar space = 16;
964 Scalar x = 0;
965 for (auto i = 0u; i < scales.size(); i++) {
966 builder.Save();
967 builder.Scale(scales[i], scales[i]);
969 GetContext(), builder, "lo", "Roboto-Regular.ttf",
970 TextRenderOptions{.font_size = 16, .position = DlPoint(x, space)});
971 space += spacing[i];
972 if (i == 3) {
973 x = 10;
974 space = 16;
975 }
976 builder.Restore();
977 }
978 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
979}
980
981namespace {
982std::shared_ptr<TextFrame> MakeDefaultTextFrame(const std::string& text,
984 // Construct the text blob.
985 auto mapping = flutter::testing::OpenFixtureAsSkData("Roboto-Regular.ttf");
986 if (mapping == nullptr) {
987 return nullptr;
988 }
989
990 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
991 SkFont sk_font(font_mgr->makeFromData(mapping), font_size);
992 sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromString("Hi", sk_font);
993
994 std::shared_ptr<TextFrame> text_frame = MakeTextFrameFromTextBlobSkia(blob);
995 return text_frame;
996}
997
998void DrawTextFramesMultipleScalesWithReuse(AiksTest* test,
999 Scalar first_scale,
1000 Scalar second_scale) {
1001 DisplayListBuilder builder;
1002 builder.Scale(test->GetContentScale().x, test->GetContentScale().y);
1003 builder.DrawColor(DlColor::kWhite(), DlBlendMode::kSrc);
1004
1005 std::shared_ptr<TextFrame> reuse_frame = MakeDefaultTextFrame("Hi", 20.0f);
1006 ASSERT_NE(reuse_frame, nullptr);
1007
1008 builder.Save();
1009 builder.Translate(100, 100);
1010 builder.Scale(first_scale, first_scale);
1011 builder.DrawText(DlTextImpeller::Make(reuse_frame), 0, 0,
1013 builder.Restore();
1014
1015 builder.Save();
1016 builder.Translate(400, 100);
1017 builder.Scale(second_scale, second_scale);
1018 builder.DrawText(DlTextImpeller::Make(reuse_frame), 0, 0,
1020 builder.Restore();
1021
1022 builder.Save();
1023 builder.Translate(100, 400);
1024 builder.Scale(first_scale, first_scale);
1025 std::shared_ptr<TextFrame> single_use_frame1 =
1026 MakeDefaultTextFrame("Hi", 20.0f);
1027 builder.DrawText(DlTextImpeller::Make(single_use_frame1), 0, 0,
1029 builder.Restore();
1030
1031 builder.Save();
1032 builder.Translate(400, 400);
1033 builder.Scale(second_scale, second_scale);
1034 std::shared_ptr<TextFrame> single_use_frame2 =
1035 MakeDefaultTextFrame("Hi", 20.0f);
1036 builder.DrawText(DlTextImpeller::Make(single_use_frame2), 0, 0,
1038 builder.Restore();
1039
1040 ASSERT_TRUE(test->OpenPlaygroundHere(builder.Build()));
1041}
1042} // namespace
1043
1044TEST_P(AiksTest, TextFramesDoNotShareRenderDataBigSmall) {
1045 DrawTextFramesMultipleScalesWithReuse(this, //
1046 /*first_scale=*/4.0f, //
1047 /*second_scale=*/0.5f);
1048}
1049
1050TEST_P(AiksTest, TextFramesDoNotShareRenderDataSmallBig) {
1051 DrawTextFramesMultipleScalesWithReuse(this, //
1052 /*first_scale=*/0.5f, //
1053 /*second_scale=*/4.0f);
1054}
1055
1056// Verifies that non-uniform (anisotropic) scaling uses bilinear filtering
1057// to avoid jagged/aliased text, while uniform scaling remains pixel-perfect.
1058// Regression test for https://github.com/flutter/flutter/issues/182143
1059TEST_P(AiksTest, TextWithNonUniformScale) {
1060 DisplayListBuilder builder;
1061
1062 DlPaint paint;
1063 paint.setColor(DlColor::ARGB(1, 0.1, 0.1, 0.1));
1064 builder.DrawPaint(paint);
1065
1066 // Row 1: Uniform scale (should use nearest-neighbor, pixel-perfect).
1067 builder.Save();
1068 builder.Scale(2, 2);
1069 ASSERT_TRUE(RenderTextInCanvasSkia(
1070 GetContext(), builder, "Uniform 2x2", "Roboto-Regular.ttf",
1071 TextRenderOptions{.font_size = 30, .position = DlPoint(20, 40)}));
1072 builder.Restore();
1073
1074 // Row 2: Non-uniform scale Y-only (ratio 2.0, triggers bilinear).
1075 builder.Save();
1076 builder.Scale(1, 2);
1077 ASSERT_TRUE(RenderTextInCanvasSkia(
1078 GetContext(), builder, "ScaleY 1x2", "Roboto-Regular.ttf",
1079 TextRenderOptions{.font_size = 30, .position = DlPoint(20, 140)}));
1080 builder.Restore();
1081
1082 // Row 3: Non-uniform scale X-only (ratio 3.0, triggers bilinear).
1083 builder.Save();
1084 builder.Scale(3, 1);
1085 ASSERT_TRUE(RenderTextInCanvasSkia(
1086 GetContext(), builder, "ScaleX 3x1", "Roboto-Regular.ttf",
1087 TextRenderOptions{.font_size = 30, .position = DlPoint(20, 300)}));
1088 builder.Restore();
1089
1090 // Row 4: Slightly non-uniform (ratio 1.1, below threshold, nearest).
1091 builder.Save();
1092 builder.Scale(2, 2.2);
1093 ASSERT_TRUE(RenderTextInCanvasSkia(
1094 GetContext(), builder, "Near-uniform 2x2.2", "Roboto-Regular.ttf",
1095 TextRenderOptions{.font_size = 30, .position = DlPoint(20, 200)}));
1096 builder.Restore();
1097
1098 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1099}
1100
1101TEST_P(AiksTest, TextGammaCorrectionGoldenTest) {
1102 constexpr const char* font_fixture = "Roboto-Regular.ttf";
1103 auto c_font_fixture = std::string(font_fixture);
1104 auto mapping = flutter::testing::OpenFixtureAsSkData(c_font_fixture.c_str());
1105 ASSERT_TRUE(mapping);
1106
1107 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
1108 SkFont sk_font(/*typeface=*/font_mgr->makeFromData(mapping), /*size=*/60);
1109 sk_font.setSubpixel(true);
1110
1111 auto blob_corrected =
1112 SkTextBlob::MakeFromString("Gamma Corrected (true)", sk_font);
1113 ASSERT_TRUE(blob_corrected);
1114 auto text_frame_corrected = MakeTextFrameFromTextBlobSkia(blob_corrected);
1115 text_frame_corrected->SetEnableGammaCorrection(true);
1116
1117 auto blob_uncorrected =
1118 SkTextBlob::MakeFromString("Gamma Corrected (false)", sk_font);
1119 ASSERT_TRUE(blob_uncorrected);
1120 auto text_frame_uncorrected = MakeTextFrameFromTextBlobSkia(blob_uncorrected);
1121 text_frame_uncorrected->SetEnableGammaCorrection(false);
1122
1123 auto callback = [&]() -> sk_sp<flutter::DisplayList> {
1124 DisplayListBuilder builder;
1125
1126 DlPaint bg_paint;
1127 bg_paint.setColor(DlColor::ARGB(1.0, 0.1, 0.1, 0.1));
1128 builder.DrawPaint(bg_paint);
1129
1130 DlPaint text_paint;
1131 text_paint.setColor(DlColor::kWhite());
1132
1133 builder.DrawText(/*text=*/DlTextImpeller::Make(text_frame_corrected),
1134 /*x=*/50, /*y=*/100, /*paint=*/text_paint);
1135 builder.DrawText(/*text=*/DlTextImpeller::Make(text_frame_uncorrected),
1136 /*x=*/50, /*y=*/200, /*paint=*/text_paint);
1137
1138 builder.DrawText(/*text=*/DlTextImpeller::Make(text_frame_corrected),
1139 /*x=*/50, /*y=*/300, /*paint=*/text_paint);
1140 DlPaint diff_paint = text_paint;
1141 diff_paint.setBlendMode(DlBlendMode::kDifference);
1142 builder.DrawText(/*text=*/DlTextImpeller::Make(text_frame_uncorrected),
1143 /*x=*/50, /*y=*/300, /*paint=*/diff_paint);
1144
1145 return builder.Build();
1146 };
1147
1148 ASSERT_TRUE(OpenPlaygroundHere(callback));
1149}
1150
1151TEST_P(AiksTest, TextWithShadowAndPosition) {
1152 DisplayListBuilder builder;
1153 builder.Scale(GetContentScale().x, GetContentScale().y);
1154 builder.Clear(DlColor::kWhite());
1155
1156 auto frame = MakeDefaultTextFrame("Hello", 25.0f);
1157 auto text = DlTextImpeller::Make(frame);
1159 DlPaint shadow_paint_ctm = DlPaint().setMaskFilter(
1160 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 5.0f, true));
1161 DlPaint shadow_paint_no_ctm = DlPaint().setMaskFilter(
1162 DlBlurMaskFilter::Make(DlBlurStyle::kNormal, 5.0f, false));
1163
1164 builder.Translate(100, 100);
1165 builder.Scale(4, 4);
1166 for (int x = 10; x <= 100; x += 30) {
1167 builder.DrawText(text, x, 20, shadow_paint_ctm);
1168 builder.DrawText(text, x, 20, paint);
1169
1170 builder.DrawText(text, x, 50, shadow_paint_no_ctm);
1171 builder.DrawText(text, x, 50, paint);
1172 }
1173
1174 ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
1175}
1176
1177} // namespace testing
1178} // 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
static bool ImGuiBegin(const char *name, bool *p_open, ImGuiWindowFlags flags)
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
AiksPlayground AiksTest
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)
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