Flutter Impeller
typographer_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 
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"
22 
23 // TODO(zanderso): https://github.com/flutter/flutter/issues/127701
24 // NOLINTBEGIN(bugprone-unchecked-optional-access)
25 
26 namespace impeller {
27 namespace testing {
28 
31 
32 static std::shared_ptr<GlyphAtlas> CreateGlyphAtlas(
33  Context& context,
34  const TypographerContext* typographer_context,
35  HostBuffer& host_buffer,
37  Scalar scale,
38  const std::shared_ptr<GlyphAtlasContext>& atlas_context,
39  const TextFrame& frame) {
40  FontGlyphMap font_glyph_map;
41  frame.CollectUniqueFontGlyphPairs(font_glyph_map, scale, {0, 0}, {});
42  return typographer_context->CreateGlyphAtlas(context, type, host_buffer,
43  atlas_context, font_glyph_map);
44 }
45 
46 static std::shared_ptr<GlyphAtlas> CreateGlyphAtlas(
47  Context& context,
48  const TypographerContext* typographer_context,
49  HostBuffer& host_buffer,
51  Scalar scale,
52  const std::shared_ptr<GlyphAtlasContext>& atlas_context,
53  const std::vector<std::shared_ptr<TextFrame>>& frames,
54  const std::vector<GlyphProperties>& properties) {
55  FontGlyphMap font_glyph_map;
56  size_t offset = 0;
57  for (auto& frame : frames) {
58  frame->CollectUniqueFontGlyphPairs(font_glyph_map, scale, {0, 0},
59  properties[offset++]);
60  }
61  return typographer_context->CreateGlyphAtlas(context, type, host_buffer,
62  atlas_context, font_glyph_map);
63 }
64 
65 TEST_P(TypographerTest, CanConvertTextBlob) {
66  SkFont font = flutter::testing::CreateTestFontOfSize(12);
67  auto blob = SkTextBlob::MakeFromString(
68  "the quick brown fox jumped over the lazy dog.", font);
69  ASSERT_TRUE(blob);
70  auto frame = MakeTextFrameFromTextBlobSkia(blob);
71  ASSERT_EQ(frame->GetRunCount(), 1u);
72  for (const auto& run : frame->GetRuns()) {
73  ASSERT_TRUE(run.IsValid());
74  ASSERT_EQ(run.GetGlyphCount(), 45u);
75  }
76 }
77 
78 TEST_P(TypographerTest, CanCreateRenderContext) {
79  auto context = TypographerContextSkia::Make();
80  ASSERT_TRUE(context && context->IsValid());
81 }
82 
83 TEST_P(TypographerTest, CanCreateGlyphAtlas) {
84  auto context = TypographerContextSkia::Make();
85  auto atlas_context =
86  context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
87  auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
88  ASSERT_TRUE(context && context->IsValid());
89  SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
90  auto blob = SkTextBlob::MakeFromString("hello", sk_font);
91  ASSERT_TRUE(blob);
92  auto atlas =
93  CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
94  GlyphAtlas::Type::kAlphaBitmap, 1.0f, atlas_context,
96  ASSERT_NE(atlas, nullptr);
97  ASSERT_NE(atlas->GetTexture(), nullptr);
98  ASSERT_EQ(atlas->GetType(), GlyphAtlas::Type::kAlphaBitmap);
99  ASSERT_EQ(atlas->GetGlyphCount(), 4llu);
100 
101  std::optional<impeller::ScaledFont> first_scaled_font;
102  std::optional<impeller::SubpixelGlyph> first_glyph;
103  Rect first_rect;
104  atlas->IterateGlyphs([&](const ScaledFont& scaled_font,
105  const SubpixelGlyph& glyph,
106  const Rect& rect) -> bool {
107  first_scaled_font = scaled_font;
108  first_glyph = glyph;
109  first_rect = rect;
110  return false;
111  });
112 
113  ASSERT_TRUE(first_scaled_font.has_value());
114  ASSERT_TRUE(atlas
115  ->FindFontGlyphBounds(
116  {first_scaled_font.value(), first_glyph.value()})
117  .has_value());
118 }
119 
120 TEST_P(TypographerTest, LazyAtlasTracksColor) {
121  auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
122 #if FML_OS_MACOSX
123  auto mapping = flutter::testing::OpenFixtureAsSkData("Apple Color Emoji.ttc");
124 #else
125  auto mapping = flutter::testing::OpenFixtureAsSkData("NotoColorEmoji.ttf");
126 #endif
127  ASSERT_TRUE(mapping);
128  sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
129  SkFont emoji_font(font_mgr->makeFromData(mapping), 50.0);
130  SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
131 
132  auto blob = SkTextBlob::MakeFromString("hello", sk_font);
133  ASSERT_TRUE(blob);
134  auto frame = MakeTextFrameFromTextBlobSkia(blob);
135 
136  ASSERT_FALSE(frame->GetAtlasType() == GlyphAtlas::Type::kColorBitmap);
137 
139 
140  lazy_atlas.AddTextFrame(*frame, 1.0f, {0, 0}, {});
141 
143  SkTextBlob::MakeFromString("😀 ", emoji_font));
144 
145  ASSERT_TRUE(frame->GetAtlasType() == GlyphAtlas::Type::kColorBitmap);
146 
147  lazy_atlas.AddTextFrame(*frame, 1.0f, {0, 0}, {});
148 
149  // Creates different atlases for color and red bitmap.
150  auto color_atlas = lazy_atlas.CreateOrGetGlyphAtlas(
151  *GetContext(), *host_buffer, GlyphAtlas::Type::kColorBitmap);
152 
153  auto bitmap_atlas = lazy_atlas.CreateOrGetGlyphAtlas(
154  *GetContext(), *host_buffer, GlyphAtlas::Type::kAlphaBitmap);
155 
156  ASSERT_FALSE(color_atlas == bitmap_atlas);
157 }
158 
159 TEST_P(TypographerTest, GlyphAtlasWithOddUniqueGlyphSize) {
160  auto context = TypographerContextSkia::Make();
161  auto atlas_context =
162  context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
163  auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
164  ASSERT_TRUE(context && context->IsValid());
165  SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
166  auto blob = SkTextBlob::MakeFromString("AGH", sk_font);
167  ASSERT_TRUE(blob);
168  auto atlas =
169  CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
170  GlyphAtlas::Type::kAlphaBitmap, 1.0f, atlas_context,
172  ASSERT_NE(atlas, nullptr);
173  ASSERT_NE(atlas->GetTexture(), nullptr);
174 
175  EXPECT_EQ(atlas->GetTexture()->GetSize().width, 4096u);
176  EXPECT_EQ(atlas->GetTexture()->GetSize().height, 1024u);
177 }
178 
179 TEST_P(TypographerTest, GlyphAtlasIsRecycledIfUnchanged) {
180  auto context = TypographerContextSkia::Make();
181  auto atlas_context =
182  context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
183  auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
184  ASSERT_TRUE(context && context->IsValid());
185  SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
186  auto blob = SkTextBlob::MakeFromString("spooky skellingtons", sk_font);
187  ASSERT_TRUE(blob);
188  auto atlas =
189  CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
190  GlyphAtlas::Type::kAlphaBitmap, 1.0f, atlas_context,
192  ASSERT_NE(atlas, nullptr);
193  ASSERT_NE(atlas->GetTexture(), nullptr);
194  ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
195 
196  // now attempt to re-create an atlas with the same text blob.
197 
198  auto next_atlas =
199  CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
200  GlyphAtlas::Type::kAlphaBitmap, 1.0f, atlas_context,
202  ASSERT_EQ(atlas, next_atlas);
203  ASSERT_EQ(atlas_context->GetGlyphAtlas(), atlas);
204 }
205 
206 TEST_P(TypographerTest, GlyphAtlasWithLotsOfdUniqueGlyphSize) {
207  auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
208  auto context = TypographerContextSkia::Make();
209  auto atlas_context =
210  context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
211  ASSERT_TRUE(context && context->IsValid());
212 
213  const char* test_string =
214  "QWERTYUIOPASDFGHJKLZXCVBNMqewrtyuiopasdfghjklzxcvbnm,.<>[]{};':"
215  "2134567890-=!@#$%^&*()_+"
216  "œ∑´®†¥¨ˆøπ““‘‘åß∂ƒ©˙∆˚¬…æ≈ç√∫˜µ≤≥≥≥≥÷¡™£¢∞§¶•ªº–≠⁄€‹›fifl‡°·‚—±Œ„´‰Á¨Ø∏”’/"
217  "* Í˝ */¸˛Ç◊ı˜Â¯˘¿";
218 
219  SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
220  auto blob = SkTextBlob::MakeFromString(test_string, sk_font);
221  ASSERT_TRUE(blob);
222 
223  FontGlyphMap font_glyph_map;
224  size_t size_count = 8;
225  for (size_t index = 0; index < size_count; index += 1) {
226  MakeTextFrameFromTextBlobSkia(blob)->CollectUniqueFontGlyphPairs(
227  font_glyph_map, 0.6 * index, {0, 0}, {});
228  };
229  auto atlas =
230  context->CreateGlyphAtlas(*GetContext(), GlyphAtlas::Type::kAlphaBitmap,
231  *host_buffer, atlas_context, font_glyph_map);
232  ASSERT_NE(atlas, nullptr);
233  ASSERT_NE(atlas->GetTexture(), nullptr);
234 
235  std::set<uint16_t> unique_glyphs;
236  std::vector<uint16_t> total_glyphs;
237  atlas->IterateGlyphs([&](const ScaledFont& scaled_font,
238  const SubpixelGlyph& glyph, const Rect& rect) {
239  unique_glyphs.insert(glyph.glyph.index);
240  total_glyphs.push_back(glyph.glyph.index);
241  return true;
242  });
243 
244  // These numbers may be different due to subpixel positions.
245  EXPECT_LE(unique_glyphs.size() * size_count, atlas->GetGlyphCount());
246  EXPECT_EQ(total_glyphs.size(), atlas->GetGlyphCount());
247 
248  EXPECT_TRUE(atlas->GetGlyphCount() > 0);
249  EXPECT_TRUE(atlas->GetTexture()->GetSize().width > 0);
250  EXPECT_TRUE(atlas->GetTexture()->GetSize().height > 0);
251 }
252 
253 TEST_P(TypographerTest, GlyphAtlasTextureIsRecycledIfUnchanged) {
254  auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
255  auto context = TypographerContextSkia::Make();
256  auto atlas_context =
257  context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
258  ASSERT_TRUE(context && context->IsValid());
259  SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
260  auto blob = SkTextBlob::MakeFromString("spooky 1", sk_font);
261  ASSERT_TRUE(blob);
262  auto atlas =
263  CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
264  GlyphAtlas::Type::kAlphaBitmap, 1.0f, atlas_context,
266  auto old_packer = atlas_context->GetRectPacker();
267 
268  ASSERT_NE(atlas, nullptr);
269  ASSERT_NE(atlas->GetTexture(), nullptr);
270  ASSERT_EQ(atlas, atlas_context->GetGlyphAtlas());
271 
272  auto* first_texture = atlas->GetTexture().get();
273 
274  // Now create a new glyph atlas with a nearly identical blob.
275 
276  auto blob2 = SkTextBlob::MakeFromString("spooky 2", sk_font);
277  auto next_atlas =
278  CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
279  GlyphAtlas::Type::kAlphaBitmap, 1.0f, atlas_context,
281  ASSERT_EQ(atlas, next_atlas);
282  auto* second_texture = next_atlas->GetTexture().get();
283 
284  auto new_packer = atlas_context->GetRectPacker();
285 
286  ASSERT_EQ(second_texture, first_texture);
287  ASSERT_EQ(old_packer, new_packer);
288 }
289 
290 TEST_P(TypographerTest, GlyphColorIsPartOfCacheKey) {
291  auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
292 #if FML_OS_MACOSX
293  auto mapping = flutter::testing::OpenFixtureAsSkData("Apple Color Emoji.ttc");
294 #else
295  auto mapping = flutter::testing::OpenFixtureAsSkData("NotoColorEmoji.ttf");
296 #endif
297  ASSERT_TRUE(mapping);
298  sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
299  SkFont emoji_font(font_mgr->makeFromData(mapping), 50.0);
300 
301  auto context = TypographerContextSkia::Make();
302  auto atlas_context =
303  context->CreateGlyphAtlasContext(GlyphAtlas::Type::kColorBitmap);
304 
305  // Create two frames with the same character and a different color, expect
306  // that it adds a character.
307  auto frame = MakeTextFrameFromTextBlobSkia(
308  SkTextBlob::MakeFromString("😂", emoji_font));
309  auto frame_2 = MakeTextFrameFromTextBlobSkia(
310  SkTextBlob::MakeFromString("😂", emoji_font));
311  auto properties = {
314  };
315 
316  auto next_atlas =
317  CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
318  GlyphAtlas::Type::kColorBitmap, 1.0f, atlas_context,
319  {frame, frame_2}, properties);
320 
321  EXPECT_EQ(next_atlas->GetGlyphCount(), 2u);
322 }
323 
324 TEST_P(TypographerTest, GlyphColorIsIgnoredForNonEmojiFonts) {
325  auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
326  sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
327  sk_sp<SkTypeface> typeface =
328  font_mgr->matchFamilyStyle("Arial", SkFontStyle::Normal());
329  SkFont sk_font(typeface, 0.5f);
330 
331  auto context = TypographerContextSkia::Make();
332  auto atlas_context =
333  context->CreateGlyphAtlasContext(GlyphAtlas::Type::kColorBitmap);
334 
335  // Create two frames with the same character and a different color, but as a
336  // non-emoji font the text frame constructor will ignore it.
337  auto frame =
338  MakeTextFrameFromTextBlobSkia(SkTextBlob::MakeFromString("A", sk_font));
339  auto frame_2 =
340  MakeTextFrameFromTextBlobSkia(SkTextBlob::MakeFromString("A", sk_font));
341  auto properties = {
342  GlyphProperties{},
343  GlyphProperties{},
344  };
345 
346  auto next_atlas =
347  CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
348  GlyphAtlas::Type::kColorBitmap, 1.0f, atlas_context,
349  {frame, frame_2}, properties);
350 
351  EXPECT_EQ(next_atlas->GetGlyphCount(), 1u);
352 }
353 
354 TEST_P(TypographerTest, RectanglePackerAddsNonoverlapingRectangles) {
355  auto packer = RectanglePacker::Factory(200, 100);
356  ASSERT_NE(packer, nullptr);
357  ASSERT_EQ(packer->PercentFull(), 0);
358 
359  const SkIRect packer_area = SkIRect::MakeXYWH(0, 0, 200, 100);
360 
361  IPoint16 first_output = {-1, -1}; // Fill with sentinel values
362  ASSERT_TRUE(packer->AddRect(20, 20, &first_output));
363  // Make sure the rectangle is placed such that it is inside the bounds of
364  // the packer's area.
365  const SkIRect first_rect =
366  SkIRect::MakeXYWH(first_output.x(), first_output.y(), 20, 20);
367  ASSERT_TRUE(SkIRect::Intersects(packer_area, first_rect));
368 
369  // Initial area was 200 x 100 = 20_000
370  // We added 20x20 = 400. 400 / 20_000 == 0.02 == 2%
371  ASSERT_TRUE(flutter::testing::NumberNear(packer->PercentFull(), 0.02));
372 
373  IPoint16 second_output = {-1, -1};
374  ASSERT_TRUE(packer->AddRect(140, 90, &second_output));
375  const SkIRect second_rect =
376  SkIRect::MakeXYWH(second_output.x(), second_output.y(), 140, 90);
377  // Make sure the rectangle is placed such that it is inside the bounds of
378  // the packer's area but not in the are of the first rectangle.
379  ASSERT_TRUE(SkIRect::Intersects(packer_area, second_rect));
380  ASSERT_FALSE(SkIRect::Intersects(first_rect, second_rect));
381 
382  // We added another 90 x 140 = 12_600 units, now taking us to 13_000
383  // 13_000 / 20_000 == 0.65 == 65%
384  ASSERT_TRUE(flutter::testing::NumberNear(packer->PercentFull(), 0.65));
385 
386  // There's enough area to add this rectangle, but no space big enough for
387  // the 50 units of width.
388  IPoint16 output;
389  ASSERT_FALSE(packer->AddRect(50, 50, &output));
390  // Should be unchanged.
391  ASSERT_TRUE(flutter::testing::NumberNear(packer->PercentFull(), 0.65));
392 
393  packer->Reset();
394  // Should be empty now.
395  ASSERT_EQ(packer->PercentFull(), 0);
396 }
397 
398 TEST(TypographerTest, RectanglePackerFillsRows) {
399  auto skyline = RectanglePacker::Factory(257, 256);
400 
401  // Fill up the first row.
402  IPoint16 loc;
403  for (auto i = 0u; i < 16; i++) {
404  skyline->AddRect(16, 16, &loc);
405  }
406  // Last rectangle still in first row.
407  EXPECT_EQ(loc.x(), 256 - 16);
408  EXPECT_EQ(loc.y(), 0);
409 
410  // Fill up second row.
411  for (auto i = 0u; i < 16; i++) {
412  skyline->AddRect(16, 16, &loc);
413  }
414 
415  EXPECT_EQ(loc.x(), 256 - 16);
416  EXPECT_EQ(loc.y(), 16);
417 }
418 
419 TEST_P(TypographerTest, GlyphAtlasTextureWillGrowTilMaxTextureSize) {
420  if (GetBackend() == PlaygroundBackend::kOpenGLES) {
421  GTEST_SKIP() << "Atlas growth isn't supported for OpenGLES currently.";
422  }
423 
424  auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
425  auto context = TypographerContextSkia::Make();
426  auto atlas_context =
427  context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
428  ASSERT_TRUE(context && context->IsValid());
429  SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
430  auto blob = SkTextBlob::MakeFromString("A", sk_font);
431  ASSERT_TRUE(blob);
432  auto atlas =
433  CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
434  GlyphAtlas::Type::kAlphaBitmap, 1.0f, atlas_context,
436  // Continually append new glyphs until the glyph size grows to the maximum.
437  // Note that the sizes here are more or less experimentally determined, but
438  // the important expectation is that the atlas size will shrink again after
439  // growing to the maximum size.
440  constexpr ISize expected_sizes[13] = {
441  {4096, 4096}, //
442  {4096, 4096}, //
443  {4096, 8192}, //
444  {4096, 8192}, //
445  {4096, 8192}, //
446  {4096, 8192}, //
447  {4096, 16384}, //
448  {4096, 16384}, //
449  {4096, 16384}, //
450  {4096, 16384}, //
451  {4096, 16384}, //
452  {4096, 16384}, //
453  {4096, 4096} // Shrinks!
454  };
455 
456  for (int i = 0; i < 13; i++) {
457  SkFont sk_font = flutter::testing::CreateTestFontOfSize(50 + i);
458  auto blob = SkTextBlob::MakeFromString("A", sk_font);
459 
460  atlas =
461  CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
462  GlyphAtlas::Type::kAlphaBitmap, 50 + i, atlas_context,
464  ASSERT_TRUE(!!atlas);
465  EXPECT_EQ(atlas->GetTexture()->GetTextureDescriptor().size,
466  expected_sizes[i]);
467  }
468 }
469 
470 } // namespace testing
471 } // namespace impeller
472 
473 // NOLINTEND(bugprone-unchecked-optional-access)
impeller::GlyphAtlas::Type::kColorBitmap
@ kColorBitmap
impeller::Color::Blue
static constexpr Color Blue()
Definition: color.h:278
NumberNear
bool NumberNear(double a, double b)
Definition: geometry_asserts.h:18
lazy_glyph_atlas.h
impeller::LazyGlyphAtlas::AddTextFrame
void AddTextFrame(const TextFrame &frame, Scalar scale, Point offset, const GlyphProperties &properties)
Definition: lazy_glyph_atlas.cc:33
host_buffer.h
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::TypographerContext
The graphics context necessary to render text.
Definition: typographer_context.h:22
impeller::GlyphAtlas::Type::kAlphaBitmap
@ kAlphaBitmap
impeller::Color::Red
static constexpr Color Red()
Definition: color.h:274
impeller::GlyphProperties
Definition: font_glyph_pair.h:19
impeller::TextFrame
Represents a collection of shaped text runs.
Definition: text_frame.h:19
impeller::HostBuffer
Definition: host_buffer.h:28
impeller::SubpixelGlyph
A glyph and its subpixel position.
Definition: font_glyph_pair.h:40
impeller::TypographerContext::CreateGlyphAtlas
virtual std::shared_ptr< GlyphAtlas > CreateGlyphAtlas(Context &context, GlyphAtlas::Type type, HostBuffer &host_buffer, const std::shared_ptr< GlyphAtlasContext > &atlas_context, const FontGlyphMap &font_glyph_map) const =0
impeller::testing::TEST
TEST(AiksCanvasTest, EmptyCullRect)
Definition: canvas_unittests.cc:18
impeller::HostBuffer::Create
static std::shared_ptr< HostBuffer > Create(const std::shared_ptr< Allocator > &allocator)
Definition: host_buffer.cc:20
playground.h
impeller::IPoint16::x
int16_t x() const
Definition: rectangle_packer.h:16
impeller::LazyGlyphAtlas::CreateOrGetGlyphAtlas
const std::shared_ptr< GlyphAtlas > & CreateOrGetGlyphAtlas(Context &context, HostBuffer &host_buffer, GlyphAtlas::Type type) const
Definition: lazy_glyph_atlas.cc:54
offset
SeparatedVector2 offset
Definition: stroke_path_geometry.cc:311
impeller::GlyphProperties::color
Color color
Definition: font_glyph_pair.h:20
impeller::IPoint16::y
int16_t y() const
Definition: rectangle_packer.h:17
typographer_context_skia.h
impeller::testing::TEST_P
TEST_P(AiksTest, CanRenderAdvancedBlendColorFilterWithSaveLayer)
Definition: aiks_blend_unittests.cc:21
impeller::testing::INSTANTIATE_PLAYGROUND_SUITE
INSTANTIATE_PLAYGROUND_SUITE(AiksTest)
text_frame_skia.h
impeller::TSize
Definition: size.h:19
rectangle_packer.h
impeller::GlyphAtlas::Type
Type
Describes how the glyphs are represented in the texture.
Definition: glyph_atlas.h:31
impeller::FontGlyphMap
std::unordered_map< ScaledFont, std::unordered_set< SubpixelGlyph > > FontGlyphMap
Definition: font_glyph_pair.h:54
font_glyph_pair.h
type
GLenum type
Definition: blit_command_gles.cc:126
impeller::SubpixelGlyph::glyph
Glyph glyph
Definition: font_glyph_pair.h:41
impeller::RectanglePacker::Factory
static std::shared_ptr< RectanglePacker > Factory(int width, int height)
Return an empty packer with area specified by width and height.
Definition: rectangle_packer.cc:174
impeller::Glyph::index
uint16_t index
Definition: glyph.h:22
impeller::testing::CreateGlyphAtlas
static std::shared_ptr< GlyphAtlas > CreateGlyphAtlas(Context &context, const TypographerContext *typographer_context, HostBuffer &host_buffer, GlyphAtlas::Type type, Scalar scale, const std::shared_ptr< GlyphAtlasContext > &atlas_context, const TextFrame &frame)
Definition: typographer_unittests.cc:32
impeller::TextFrame::CollectUniqueFontGlyphPairs
void CollectUniqueFontGlyphPairs(FontGlyphMap &glyph_map, Scalar scale, Point offset, const GlyphProperties &properties) const
Definition: text_frame.cc:87
impeller::MakeTextFrameFromTextBlobSkia
std::shared_ptr< TextFrame > MakeTextFrameFromTextBlobSkia(const sk_sp< SkTextBlob > &blob)
Definition: text_frame_skia.cc:61
impeller::PlaygroundBackend::kOpenGLES
@ kOpenGLES
impeller::Context
To do anything rendering related with Impeller, you need a context.
Definition: context.h:45
impeller::IPoint16
Definition: rectangle_packer.h:15
scale
const Scalar scale
Definition: stroke_path_geometry.cc:308
impeller::PlaygroundTest
Definition: playground_test.h:21
impeller::LazyGlyphAtlas
Definition: lazy_glyph_atlas.h:15
impeller
Definition: aiks_blend_unittests.cc:18
playground_test.h
impeller::TypographerContextSkia::Make
static std::shared_ptr< TypographerContext > Make()
Definition: typographer_context_skia.cc:78
impeller::TRect
Definition: rect.h:122
impeller::ScaledFont
A font and a scale. Used as a key that represents a typeface within a glyph atlas.
Definition: font_glyph_pair.h:32