5 #include "flutter/display_list/testing/dl_test_snippets.h"
6 #include "flutter/testing/testing.h"
7 #include "gtest/gtest.h"
16 #include "third_party/skia/include/core/SkFont.h"
17 #include "third_party/skia/include/core/SkFontMgr.h"
18 #include "third_party/skia/include/core/SkRect.h"
19 #include "third_party/skia/include/core/SkTextBlob.h"
20 #include "third_party/skia/include/core/SkTypeface.h"
21 #include "txt/platform.h"
38 const std::shared_ptr<GlyphAtlasContext>& atlas_context,
39 const std::shared_ptr<TextFrame>& frame) {
46 atlas_context, {render_frame});
55 const std::shared_ptr<GlyphAtlasContext>& atlas_context,
56 const std::vector<std::shared_ptr<TextFrame>>& frames,
57 const std::vector<GlyphProperties>& properties) {
59 std::vector<RenderableText> render_frames;
60 render_frames.reserve(frames.size());
61 for (
auto& frame : frames) {
62 render_frames.emplace_back(frame,
transform, properties[offset++]);
65 atlas_context, render_frames);
69 SkFont font = flutter::testing::CreateTestFontOfSize(12);
70 auto blob = SkTextBlob::MakeFromString(
71 "the quick brown fox jumped over the lazy dog.", font);
74 ASSERT_EQ(frame->GetRunCount(), 1u);
75 for (
const auto& run : frame->GetRuns()) {
76 ASSERT_TRUE(run.IsValid());
77 ASSERT_EQ(run.GetGlyphCount(), 45u);
91 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
92 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
94 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
95 auto blob = SkTextBlob::MakeFromString(
"hello", sk_font);
102 ASSERT_NE(atlas,
nullptr);
103 ASSERT_NE(atlas->GetTexture(),
nullptr);
105 ASSERT_EQ(atlas->GetGlyphCount(), 4llu);
107 std::optional<impeller::ScaledFont> first_scaled_font;
108 std::optional<impeller::SubpixelGlyph> first_glyph;
110 atlas->IterateGlyphs([&](
const ScaledFont& scaled_font,
112 const Rect& rect) ->
bool {
113 first_scaled_font = scaled_font;
119 ASSERT_TRUE(first_scaled_font.has_value());
121 ->FindFontGlyphBounds(
122 {first_scaled_font.value(), first_glyph.value()})
128 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
129 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
131 auto mapping = flutter::testing::OpenFixtureAsSkData(
"Apple Color Emoji.ttc");
133 auto mapping = flutter::testing::OpenFixtureAsSkData(
"NotoColorEmoji.ttf");
135 ASSERT_TRUE(mapping);
136 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
137 SkFont emoji_font(font_mgr->makeFromData(mapping), 50.0);
138 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
140 auto blob = SkTextBlob::MakeFromString(
"hello", sk_font);
151 SkTextBlob::MakeFromString(
"😀 ", emoji_font));
164 ASSERT_FALSE(color_atlas == bitmap_atlas);
172 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
173 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
175 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
176 auto blob = SkTextBlob::MakeFromString(
"AGH", sk_font);
182 ASSERT_NE(atlas,
nullptr);
183 ASSERT_NE(atlas->GetTexture(),
nullptr);
185 EXPECT_EQ(atlas->GetTexture()->GetSize().width, 4096u);
186 EXPECT_EQ(atlas->GetTexture()->GetSize().height, 1024u);
194 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
195 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
197 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
198 auto blob = SkTextBlob::MakeFromString(
"spooky skellingtons", sk_font);
204 ASSERT_NE(atlas,
nullptr);
205 ASSERT_NE(atlas->GetTexture(),
nullptr);
206 ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
214 ASSERT_EQ(atlas, next_atlas);
215 ASSERT_EQ(atlas_context->GetGlyphAtlas(), atlas);
220 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
221 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
227 const char* test_string =
228 "QWERTYUIOPASDFGHJKLZXCVBNMqewrtyuiopasdfghjklzxcvbnm,.<>[]{};':"
229 "2134567890-=!@#$%^&*()_+"
230 "œ∑´®†¥¨ˆøπ““‘‘åß∂ƒ©˙∆˚¬…æ≈ç√∫˜µ≤≥≥≥≥÷¡™£¢∞§¶•ªº–≠⁄€‹›fifl‡°·‚—±Œ„´‰Á¨Ø∏”’/"
233 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
234 auto blob = SkTextBlob::MakeFromString(test_string, sk_font);
237 size_t size_count = 8;
238 std::vector<RenderableText> render_frames;
239 for (
size_t index = 0; index < size_count; index += 1) {
240 Scalar scale = 6.0f * index / 10.0f;
245 auto atlas =
context->CreateGlyphAtlas(
247 atlas_context, render_frames);
248 ASSERT_NE(atlas,
nullptr);
249 ASSERT_NE(atlas->GetTexture(),
nullptr);
251 std::set<uint16_t> unique_glyphs;
252 std::vector<uint16_t> total_glyphs;
253 atlas->IterateGlyphs([&](
const ScaledFont& scaled_font,
261 EXPECT_LE(unique_glyphs.size() * size_count, atlas->GetGlyphCount());
262 EXPECT_EQ(total_glyphs.size(), atlas->GetGlyphCount());
264 EXPECT_TRUE(atlas->GetGlyphCount() > 0);
265 EXPECT_TRUE(atlas->GetTexture()->GetSize().width > 0);
266 EXPECT_TRUE(atlas->GetTexture()->GetSize().height > 0);
271 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
272 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
277 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
278 auto blob = SkTextBlob::MakeFromString(
"spooky 1", sk_font);
284 auto old_packer = atlas_context->GetRectPacker();
286 ASSERT_NE(atlas,
nullptr);
287 ASSERT_NE(atlas->GetTexture(),
nullptr);
288 ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
290 auto* first_texture = atlas->GetTexture().get();
294 auto blob2 = SkTextBlob::MakeFromString(
"spooky 2", sk_font);
299 ASSERT_EQ(atlas, next_atlas);
300 auto* second_texture = next_atlas->GetTexture().get();
302 auto new_packer = atlas_context->GetRectPacker();
304 ASSERT_EQ(second_texture, first_texture);
305 ASSERT_EQ(old_packer, new_packer);
310 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
311 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
313 auto mapping = flutter::testing::OpenFixtureAsSkData(
"Apple Color Emoji.ttc");
315 auto mapping = flutter::testing::OpenFixtureAsSkData(
"NotoColorEmoji.ttf");
317 ASSERT_TRUE(mapping);
318 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
319 SkFont emoji_font(font_mgr->makeFromData(mapping), 50.0);
328 SkTextBlob::MakeFromString(
"😂", emoji_font));
330 SkTextBlob::MakeFromString(
"😂", emoji_font));
331 std::vector<GlyphProperties> properties = {
339 {frame, frame_2}, properties);
341 EXPECT_EQ(next_atlas->GetGlyphCount(), 2u);
346 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
347 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
348 sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
349 sk_sp<SkTypeface> typeface =
350 font_mgr->matchFamilyStyle(
"Arial", SkFontStyle::Normal());
351 SkFont sk_font(typeface, 0.5f);
363 std::vector<GlyphProperties> properties = {
371 {frame, frame_2}, properties);
373 EXPECT_EQ(next_atlas->GetGlyphCount(), 1u);
378 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
379 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
384 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
385 auto blob1 = SkTextBlob::MakeFromString(
"A", sk_font);
386 auto blob2 = SkTextBlob::MakeFromString(
"A", sk_font);
390 std::vector<GlyphProperties> properties = {
401 {frame1, frame2}, properties);
403 #if defined(FML_OS_MACOSX)
405 EXPECT_EQ(next_atlas->GetGlyphCount(), 2u);
408 EXPECT_EQ(next_atlas->GetGlyphCount(), 1u);
414 ASSERT_NE(packer,
nullptr);
415 ASSERT_EQ(packer->PercentFull(), 0);
417 const SkIRect packer_area = SkIRect::MakeXYWH(0, 0, 200, 100);
420 ASSERT_TRUE(packer->AddRect(20, 20, &first_output));
423 const SkIRect first_rect =
424 SkIRect::MakeXYWH(first_output.
x(), first_output.
y(), 20, 20);
425 ASSERT_TRUE(SkIRect::Intersects(packer_area, first_rect));
432 ASSERT_TRUE(packer->AddRect(140, 90, &second_output));
433 const SkIRect second_rect =
434 SkIRect::MakeXYWH(second_output.
x(), second_output.
y(), 140, 90);
437 ASSERT_TRUE(SkIRect::Intersects(packer_area, second_rect));
438 ASSERT_FALSE(SkIRect::Intersects(first_rect, second_rect));
447 ASSERT_FALSE(packer->AddRect(50, 50, &output));
453 ASSERT_EQ(packer->PercentFull(), 0);
461 for (
auto i = 0u; i < 16; i++) {
462 skyline->AddRect(16, 16, &loc);
465 EXPECT_EQ(loc.
x(), 256 - 16);
466 EXPECT_EQ(loc.
y(), 0);
469 for (
auto i = 0u; i < 16; i++) {
470 skyline->AddRect(16, 16, &loc);
473 EXPECT_EQ(loc.
x(), 256 - 16);
474 EXPECT_EQ(loc.
y(), 16);
480 GTEST_SKIP() <<
"Atlas growth isn't supported for OpenGLES currently.";
484 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
485 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
490 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
491 auto blob = SkTextBlob::MakeFromString(
"A", sk_font);
501 constexpr
ISize expected_sizes[13] = {
517 SkFont sk_font_small = flutter::testing::CreateTestFontOfSize(10);
519 for (
int i = 0; i < 13; i++) {
520 SkTextBlobBuilder builder;
522 auto add_char = [&](
const SkFont& sk_font,
char c) {
523 int count = sk_font.countText(&
c, 1, SkTextEncoding::kUTF8);
524 auto buffer = builder.allocRunPos(sk_font, count);
525 sk_font.textToGlyphs(&
c, 1, SkTextEncoding::kUTF8,
526 {buffer.glyphs, count});
527 sk_font.getPos({buffer.glyphs, count}, {buffer.points(), count},
531 SkFont sk_font = flutter::testing::CreateTestFontOfSize(50 + i);
532 add_char(sk_font,
'A');
533 add_char(sk_font_small,
'B');
534 auto blob = builder.make();
541 ASSERT_TRUE(!!atlas);
542 EXPECT_EQ(atlas->GetTexture()->GetTextureDescriptor().size,
549 ASSERT_EQ(atlas->GetGlyphCount(), 2u);
553 SkFont font = flutter::testing::CreateTestFontOfSize(12);
554 auto blob = SkTextBlob::MakeFromString(
555 "the quick brown fox jumped over the lazy dog.", font);
563 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
564 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
568 atlas_context, frame);
571 auto second_atlas_context =
574 EXPECT_FALSE(second_atlas_context->GetGlyphAtlas()->IsValid());
578 Matrix(), second_atlas_context, frame);
580 EXPECT_TRUE(second_atlas_context->GetGlyphAtlas()->IsValid());
588 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
589 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
591 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
592 auto blob = SkTextBlob::MakeFromString(
"A", sk_font);
600 *atlas,
Size{100, 100},
false);
601 EXPECT_EQ(image_info.colorType(), kRGBA_8888_SkColorType);
609 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
610 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
612 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
613 auto blob = SkTextBlob::MakeFromString(
"A", sk_font);
621 *atlas,
Size{100, 100},
false);
622 EXPECT_EQ(image_info.colorType(), kAlpha_8_SkColorType);
630 GetContext()->GetResourceAllocator(), GetContext()->GetIdleWaiter(),
631 GetContext()->GetCapabilities()->GetMinimumUniformAlignment());
633 SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
634 auto blob = SkTextBlob::MakeFromString(
"A", sk_font);
642 *atlas,
Size{100, 100},
true);
643 EXPECT_EQ(image_info.colorType(), kRGBA_8888_SkColorType);
To do anything rendering related with Impeller, you need a context.
Type
Describes how the glyphs are represented in the texture.
static std::shared_ptr< HostBuffer > Create(const std::shared_ptr< Allocator > &allocator, const std::shared_ptr< const IdleWaiter > &idle_waiter, size_t minimum_uniform_alignment)
void AddTextFrame(const std::shared_ptr< TextFrame > &frame, Point position, const Matrix &transform, const GlyphProperties &properties)
const std::shared_ptr< GlyphAtlas > & CreateOrGetGlyphAtlas(Context &context, HostBuffer &host_buffer, GlyphAtlas::Type type)
static std::shared_ptr< RectanglePacker > Factory(int width, int height)
Return an empty packer with area specified by width and height.
The graphics context necessary to render text.
virtual std::shared_ptr< GlyphAtlas > CreateGlyphAtlas(Context &context, GlyphAtlas::Type type, HostBuffer &host_buffer, const std::shared_ptr< GlyphAtlasContext > &atlas_context, const std::vector< RenderableText > &text_frames) const =0
static SkImageInfo GetImageInfo(const GlyphAtlas &atlas, Size size, bool support_light_glyphs)
static std::shared_ptr< TypographerContext > Make()
bool NumberNear(double a, double b)
TEST(AllocationSizeTest, CanCreateTypedAllocations)
TEST_P(AiksTest, DrawAtlasNoColor)
static std::shared_ptr< GlyphAtlas > CreateGlyphAtlas(Context &context, const TypographerContext *typographer_context, HostBuffer &data_host_buffer, GlyphAtlas::Type type, const Matrix &transform, const std::shared_ptr< GlyphAtlasContext > &atlas_context, const std::shared_ptr< TextFrame > &frame)
INSTANTIATE_PLAYGROUND_SUITE(AiksTest)
std::shared_ptr< TextFrame > MakeTextFrameFromTextBlobSkia(const sk_sp< SkTextBlob > &blob)
std::shared_ptr< ContextGLES > context
static constexpr Color Crimson()
static constexpr Color Beige()
static constexpr Color Red()
static constexpr Color Blue()
static Tone ComputeTone(const Color &c)
ToneOrColor tone_or_color
A 4x4 matrix using column-major storage.
static constexpr Matrix MakeScale(const Vector3 &s)
const std::shared_ptr< TextFrame > text_frame
The TextFrame being rendered.
A font and a scale. Used as a key that represents a typeface within a glyph atlas.
A glyph and its subpixel position.