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"
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);
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());
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());
135 ASSERT_TRUE(mapping);
137 SkFont emoji_font(font_mgr->makeFromData(mapping), 50.0);
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());
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());
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‡°·‚—±Œ„´‰Á¨Ø∏”’/"
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());
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());
317 ASSERT_TRUE(mapping);
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());
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());
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());
491 auto blob = SkTextBlob::MakeFromString(
"A", sk_font);
501 constexpr ISize expected_sizes[13] = {
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,
527 sk_font.getPos({
buffer.glyphs, count}, {
buffer.points(), count},
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);
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());
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());
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());
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()
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.
bool NumberNear(double a, double b)
TEST(FrameTimingsRecorderTest, RecordVsync)
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 to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set profile Make the profiler discard new samples once the profiler sample buffer is full When this flag is not the profiler sample buffer is used as a ring buffer
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)
TEST_P(AiksTest, DrawAtlasNoColor)
std::shared_ptr< TextFrame > MakeTextFrameFromTextBlobSkia(const sk_sp< SkTextBlob > &blob)
sk_sp< SkFontMgr > GetDefaultFontManager(uint32_t font_initialization_data)
#define INSTANTIATE_PLAYGROUND_SUITE(playground)
std::shared_ptr< ContextGLES > context
impeller::ShaderType type
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.