Flutter Impeller
typographer_context_stb.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 
6 
7 #include <numeric>
8 #include <utility>
9 
10 #include "flutter/fml/logging.h"
11 #include "flutter/fml/trace_event.h"
16 #include "typeface_stb.h"
17 
18 #define DISABLE_COLOR_FONT_SUPPORT 1
19 #ifdef DISABLE_COLOR_FONT_SUPPORT
20 constexpr auto kColorFontBitsPerPixel = 1;
21 #else
22 constexpr auto kColorFontBitsPerPixel = 4;
23 #endif
24 
25 namespace impeller {
26 
27 constexpr size_t kPadding = 1;
28 
29 std::unique_ptr<TypographerContext> TypographerContextSTB::Make() {
30  return std::make_unique<TypographerContextSTB>();
31 }
32 
34 
36 
37 std::shared_ptr<GlyphAtlasContext>
39  return std::make_shared<GlyphAtlasContextSTB>();
40 }
41 
42 // Function returns the count of "remaining pairs" not packed into rect of given
43 // size.
44 static size_t PairsFitInAtlasOfSize(
45  const std::vector<FontGlyphPair>& pairs,
46  const ISize& atlas_size,
47  std::vector<Rect>& glyph_positions,
48  const std::shared_ptr<RectanglePacker>& rect_packer) {
49  if (atlas_size.IsEmpty()) {
50  return false;
51  }
52 
53  glyph_positions.clear();
54  glyph_positions.reserve(pairs.size());
55 
56  size_t i = 0;
57  for (auto it = pairs.begin(); it != pairs.end(); ++i, ++it) {
58  const auto& pair = *it;
59  const Font& font = pair.scaled_font.font;
60 
61  // We downcast to the correct typeface type to access `stb` specific
62  // methods.
63  std::shared_ptr<TypefaceSTB> typeface_stb =
64  std::reinterpret_pointer_cast<TypefaceSTB>(font.GetTypeface());
65  // Conversion factor to scale font size in Points to pixels.
66  // Note this assumes typical DPI.
67  float text_size_pixels =
69 
70  ISize glyph_size;
71  {
72  int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
73  // NOTE: We increase the size of the glyph by one pixel in all dimensions
74  // to allow us to cut out padding later.
75  float scale = stbtt_ScaleForPixelHeight(typeface_stb->GetFontInfo(),
76  text_size_pixels);
77  stbtt_GetGlyphBitmapBox(typeface_stb->GetFontInfo(), pair.glyph.index,
78  scale, scale, &x0, &y0, &x1, &y1);
79 
80  glyph_size = ISize(x1 - x0, y1 - y0);
81  }
82 
83  IPoint16 location_in_atlas;
84  if (!rect_packer->addRect(glyph_size.width + kPadding, //
85  glyph_size.height + kPadding, //
86  &location_in_atlas //
87  )) {
88  return pairs.size() - i;
89  }
90  glyph_positions.emplace_back(Rect::MakeXYWH(location_in_atlas.x(), //
91  location_in_atlas.y(), //
92  glyph_size.width, //
93  glyph_size.height //
94  ));
95  }
96 
97  return 0;
98 }
99 
101  const std::shared_ptr<GlyphAtlas>& atlas,
102  const std::vector<FontGlyphPair>& extra_pairs,
103  std::vector<Rect>& glyph_positions,
104  ISize atlas_size,
105  const std::shared_ptr<RectanglePacker>& rect_packer) {
106  TRACE_EVENT0("impeller", __FUNCTION__);
107  if (!rect_packer || atlas_size.IsEmpty()) {
108  return false;
109  }
110 
111  // We assume that all existing glyphs will fit. After all, they fit before.
112  // The glyph_positions only contains the values for the additional glyphs
113  // from extra_pairs.
114  FML_DCHECK(glyph_positions.size() == 0);
115  glyph_positions.reserve(extra_pairs.size());
116  for (size_t i = 0; i < extra_pairs.size(); i++) {
117  const FontGlyphPair& pair = extra_pairs[i];
118  const Font& font = pair.scaled_font.font;
119 
120  // We downcast to the correct typeface type to access `stb` specific methods
121  std::shared_ptr<TypefaceSTB> typeface_stb =
122  std::reinterpret_pointer_cast<TypefaceSTB>(font.GetTypeface());
123  // Conversion factor to scale font size in Points to pixels.
124  // Note this assumes typical DPI.
125  float text_size_pixels =
127 
128  ISize glyph_size;
129  {
130  int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
131  // NOTE: We increase the size of the glyph by one pixel in all dimensions
132  // to allow us to cut out padding later.
133  float scale_y = stbtt_ScaleForPixelHeight(typeface_stb->GetFontInfo(),
134  text_size_pixels);
135  float scale_x = scale_y;
136  stbtt_GetGlyphBitmapBox(typeface_stb->GetFontInfo(), pair.glyph.index,
137  scale_x, scale_y, &x0, &y0, &x1, &y1);
138 
139  glyph_size = ISize(x1 - x0, y1 - y0);
140  }
141 
142  IPoint16 location_in_atlas;
143  if (!rect_packer->addRect(glyph_size.width + kPadding, //
144  glyph_size.height + kPadding, //
145  &location_in_atlas //
146  )) {
147  return false;
148  }
149  glyph_positions.emplace_back(Rect::MakeXYWH(location_in_atlas.x(), //
150  location_in_atlas.y(), //
151  glyph_size.width, //
152  glyph_size.height //
153  ));
154  }
155 
156  return true;
157 }
158 
160  const std::vector<FontGlyphPair>& pairs,
161  std::vector<Rect>& glyph_positions,
162  const std::shared_ptr<GlyphAtlasContext>& atlas_context,
163  GlyphAtlas::Type type,
164  const ISize& max_texture_size) {
165  static constexpr auto kMinAtlasSize = 8u;
166  static constexpr auto kMinAlphaBitmapSize = 1024u;
167 
168  TRACE_EVENT0("impeller", __FUNCTION__);
169 
170  ISize current_size = type == GlyphAtlas::Type::kAlphaBitmap
171  ? ISize(kMinAlphaBitmapSize, kMinAlphaBitmapSize)
172  : ISize(kMinAtlasSize, kMinAtlasSize);
173  size_t total_pairs = pairs.size() + 1;
174  do {
175  auto rect_packer = std::shared_ptr<RectanglePacker>(
176  RectanglePacker::Factory(current_size.width, current_size.height));
177 
178  auto remaining_pairs = PairsFitInAtlasOfSize(pairs, current_size,
179  glyph_positions, rect_packer);
180  if (remaining_pairs == 0) {
181  atlas_context->UpdateRectPacker(rect_packer);
182  return current_size;
183  } else if (remaining_pairs < std::ceil(total_pairs / 2)) {
184  current_size = ISize::MakeWH(
185  std::max(current_size.width, current_size.height),
187  std::min(current_size.width, current_size.height) + 1));
188  } else {
189  current_size = ISize::MakeWH(
190  Allocation::NextPowerOfTwoSize(current_size.width + 1),
191  Allocation::NextPowerOfTwoSize(current_size.height + 1));
192  }
193  } while (current_size.width <= max_texture_size.width &&
194  current_size.height <= max_texture_size.height);
195  return ISize{0, 0};
196 }
197 
198 static void DrawGlyph(BitmapSTB* bitmap,
199  const ScaledFont& scaled_font,
200  const Glyph& glyph,
201  const Rect& location,
202  bool has_color) {
203  const auto& metrics = scaled_font.font.GetMetrics();
204 
205  const impeller::Font& font = scaled_font.font;
206  auto typeface = font.GetTypeface();
207  // We downcast to the correct typeface type to access `stb` specific methods
208  std::shared_ptr<TypefaceSTB> typeface_stb =
209  std::reinterpret_pointer_cast<TypefaceSTB>(typeface);
210  // Conversion factor to scale font size in Points to pixels.
211  // Note this assumes typical DPI.
212  float text_size_pixels = metrics.point_size * TypefaceSTB::kPointsToPixels;
213  float scale_y =
214  stbtt_ScaleForPixelHeight(typeface_stb->GetFontInfo(), text_size_pixels);
215  float scale_x = scale_y;
216 
217  auto output =
218  bitmap->GetPixelAddress({static_cast<size_t>(location.origin.x),
219  static_cast<size_t>(location.origin.y)});
220  // For Alpha and Signed Distance field bitmaps we can use STB to draw the
221  // Glyph in place
222  if (!has_color || DISABLE_COLOR_FONT_SUPPORT) {
223  stbtt_MakeGlyphBitmap(typeface_stb->GetFontInfo(), output,
224  location.size.width - kPadding,
225  location.size.height - kPadding,
226  bitmap->GetRowBytes(), scale_x, scale_y, glyph.index);
227  } else {
228  // But for color bitmaps we need to get the glyph pixels and then carry all
229  // channels into the atlas bitmap. This may not be performant but I'm unsure
230  // of any other approach currently.
231  int glyph_bitmap_width = 0;
232  int glyph_bitmap_height = 0;
233  int glyph_bitmap_xoff = 0;
234  int glyph_bitmap_yoff = 0;
235  auto glyph_pixels = stbtt_GetGlyphBitmap(
236  typeface_stb->GetFontInfo(), scale_x, scale_y, glyph.index,
237  &glyph_bitmap_width, &glyph_bitmap_height, &glyph_bitmap_xoff,
238  &glyph_bitmap_yoff);
239 
240  uint8_t* write_pos = output;
241  for (auto y = 0; y < glyph_bitmap_height; ++y) {
242  for (auto x = 0; x < glyph_bitmap_width; ++x) {
243  // Color bitmaps write as White (i.e. what is 0 in an alpha bitmap is
244  // 255 in a color bitmap) But not alpha. Alpha still carries
245  // transparency info in the normal way.
246  // There's some issue with color fonts, in that if the pixel color is
247  // nonzero, the alpha is ignored during rendering. That is, partially
248  // (or fully) transparent pixels with nonzero color are rendered as
249  // fully opaque.
250  uint8_t a = glyph_pixels[x + y * glyph_bitmap_width];
251  uint8_t c = 255 - a;
252 
253  // Red channel
254  *write_pos = c;
255  write_pos++;
256  // Green channel
257  *write_pos = c;
258  write_pos++;
259  // Blue channel
260  *write_pos = c;
261  write_pos++;
262  // Alpha channel
263  *write_pos = a;
264  write_pos++;
265  }
266  // next row
267  write_pos = output + (y * bitmap->GetRowBytes());
268  }
269  stbtt_FreeBitmap(glyph_pixels, nullptr);
270  }
271 }
272 
273 static bool UpdateAtlasBitmap(const GlyphAtlas& atlas,
274  const std::shared_ptr<BitmapSTB>& bitmap,
275  const std::vector<FontGlyphPair>& new_pairs) {
276  TRACE_EVENT0("impeller", __FUNCTION__);
277  FML_DCHECK(bitmap != nullptr);
278 
279  bool has_color = atlas.GetType() == GlyphAtlas::Type::kColorBitmap;
280 
281  for (const FontGlyphPair& pair : new_pairs) {
282  auto pos = atlas.FindFontGlyphBounds(pair);
283  if (!pos.has_value()) {
284  continue;
285  }
286  DrawGlyph(bitmap.get(), pair.scaled_font, pair.glyph, pos.value(),
287  has_color);
288  }
289  return true;
290 }
291 
292 static std::shared_ptr<BitmapSTB> CreateAtlasBitmap(const GlyphAtlas& atlas,
293  const ISize& atlas_size) {
294  TRACE_EVENT0("impeller", __FUNCTION__);
295 
296  size_t bytes_per_pixel = 1;
297  if (atlas.GetType() == GlyphAtlas::Type::kColorBitmap &&
299  bytes_per_pixel = kColorFontBitsPerPixel;
300  }
301  auto bitmap = std::make_shared<BitmapSTB>(atlas_size.width, atlas_size.height,
302  bytes_per_pixel);
303 
304  bool has_color = atlas.GetType() == GlyphAtlas::Type::kColorBitmap;
305 
306  atlas.IterateGlyphs([&bitmap, has_color](const ScaledFont& scaled_font,
307  const Glyph& glyph,
308  const Rect& location) -> bool {
309  DrawGlyph(bitmap.get(), scaled_font, glyph, location, has_color);
310  return true;
311  });
312 
313  return bitmap;
314 }
315 
316 // static bool UpdateGlyphTextureAtlas(std::shared_ptr<SkBitmap> bitmap,
317 static bool UpdateGlyphTextureAtlas(std::shared_ptr<BitmapSTB>& bitmap,
318  const std::shared_ptr<Texture>& texture) {
319  TRACE_EVENT0("impeller", __FUNCTION__);
320 
321  FML_DCHECK(bitmap != nullptr);
322 
323  auto texture_descriptor = texture->GetTextureDescriptor();
324 
325  auto mapping = std::make_shared<fml::NonOwnedMapping>(
326  reinterpret_cast<const uint8_t*>(bitmap->GetPixels()), // data
327  texture_descriptor.GetByteSizeOfBaseMipLevel() // size
328  // As the bitmap is static in this module I believe we don't need to
329  // specify a release proc.
330  );
331 
332  return texture->SetContents(mapping);
333 }
334 
335 static std::shared_ptr<Texture> UploadGlyphTextureAtlas(
336  const std::shared_ptr<Allocator>& allocator,
337  std::shared_ptr<BitmapSTB>& bitmap,
338  const ISize& atlas_size,
339  PixelFormat format) {
340  TRACE_EVENT0("impeller", __FUNCTION__);
341  if (!allocator) {
342  return nullptr;
343  }
344 
345  FML_DCHECK(bitmap != nullptr);
346 
347  TextureDescriptor texture_descriptor;
348  texture_descriptor.storage_mode = StorageMode::kHostVisible;
349  texture_descriptor.format = format;
350  texture_descriptor.size = atlas_size;
351 
352  if (bitmap->GetRowBytes() * bitmap->GetHeight() !=
353  texture_descriptor.GetByteSizeOfBaseMipLevel()) {
354  return nullptr;
355  }
356 
357  auto texture = allocator->CreateTexture(texture_descriptor);
358  if (!texture || !texture->IsValid()) {
359  return nullptr;
360  }
361  texture->SetLabel("GlyphAtlas");
362 
363  auto mapping = std::make_shared<fml::NonOwnedMapping>(
364  reinterpret_cast<const uint8_t*>(bitmap->GetPixels()), // data
365  texture_descriptor.GetByteSizeOfBaseMipLevel() // size
366  // As the bitmap is static in this module I believe we don't need to
367  // specify a release proc.
368  );
369 
370  if (!texture->SetContents(mapping)) {
371  return nullptr;
372  }
373  return texture;
374 }
375 
376 std::shared_ptr<GlyphAtlas> TypographerContextSTB::CreateGlyphAtlas(
377  Context& context,
378  GlyphAtlas::Type type,
379  std::shared_ptr<GlyphAtlasContext> atlas_context,
380  const FontGlyphMap& font_glyph_map) const {
381  TRACE_EVENT0("impeller", __FUNCTION__);
382  if (!IsValid()) {
383  return nullptr;
384  }
385  auto& atlas_context_stb = GlyphAtlasContextSTB::Cast(*atlas_context);
386  std::shared_ptr<GlyphAtlas> last_atlas = atlas_context->GetGlyphAtlas();
387 
388  if (font_glyph_map.empty()) {
389  return last_atlas;
390  }
391 
392  // ---------------------------------------------------------------------------
393  // Step 1: Determine if the atlas type and font glyph pairs are compatible
394  // with the current atlas and reuse if possible.
395  // ---------------------------------------------------------------------------
396  std::vector<FontGlyphPair> new_glyphs;
397  for (const auto& font_value : font_glyph_map) {
398  const ScaledFont& scaled_font = font_value.first;
399  const FontGlyphAtlas* font_glyph_atlas =
400  last_atlas->GetFontGlyphAtlas(scaled_font.font, scaled_font.scale);
401  if (font_glyph_atlas) {
402  for (const Glyph& glyph : font_value.second) {
403  if (!font_glyph_atlas->FindGlyphBounds(glyph)) {
404  new_glyphs.emplace_back(scaled_font, glyph);
405  }
406  }
407  } else {
408  for (const Glyph& glyph : font_value.second) {
409  new_glyphs.emplace_back(scaled_font, glyph);
410  }
411  }
412  }
413  if (last_atlas->GetType() == type && new_glyphs.size() == 0) {
414  return last_atlas;
415  }
416 
417  // ---------------------------------------------------------------------------
418  // Step 2: Determine if the additional missing glyphs can be appended to the
419  // existing bitmap without recreating the atlas. This requires that
420  // the type is identical.
421  // ---------------------------------------------------------------------------
422  std::vector<Rect> glyph_positions;
423  if (last_atlas->GetType() == type &&
424  CanAppendToExistingAtlas(last_atlas, new_glyphs, glyph_positions,
425  atlas_context->GetAtlasSize(),
426  atlas_context->GetRectPacker())) {
427  // The old bitmap will be reused and only the additional glyphs will be
428  // added.
429 
430  // ---------------------------------------------------------------------------
431  // Step 3a: Record the positions in the glyph atlas of the newly added
432  // glyphs.
433  // ---------------------------------------------------------------------------
434  for (size_t i = 0, count = glyph_positions.size(); i < count; i++) {
435  last_atlas->AddTypefaceGlyphPosition(new_glyphs[i], glyph_positions[i]);
436  }
437 
438  // ---------------------------------------------------------------------------
439  // Step 4a: Draw new font-glyph pairs into the existing bitmap.
440  // ---------------------------------------------------------------------------
441  // auto bitmap = atlas_context->GetBitmap();
442  auto bitmap = atlas_context_stb.GetBitmap();
443  if (!UpdateAtlasBitmap(*last_atlas, bitmap, new_glyphs)) {
444  return nullptr;
445  }
446 
447  // ---------------------------------------------------------------------------
448  // Step 5a: Update the existing texture with the updated bitmap.
449  // ---------------------------------------------------------------------------
450  if (!UpdateGlyphTextureAtlas(bitmap, last_atlas->GetTexture())) {
451  return nullptr;
452  }
453  return last_atlas;
454  }
455  // A new glyph atlas must be created.
456 
457  // ---------------------------------------------------------------------------
458  // Step 3b: Get the optimum size of the texture atlas.
459  // ---------------------------------------------------------------------------
460  std::vector<FontGlyphPair> font_glyph_pairs;
461  font_glyph_pairs.reserve(std::accumulate(
462  font_glyph_map.begin(), font_glyph_map.end(), 0,
463  [](const int a, const auto& b) { return a + b.second.size(); }));
464  for (const auto& font_value : font_glyph_map) {
465  const ScaledFont& scaled_font = font_value.first;
466  for (const Glyph& glyph : font_value.second) {
467  font_glyph_pairs.push_back({scaled_font, glyph});
468  }
469  }
470  auto glyph_atlas = std::make_shared<GlyphAtlas>(type);
471  auto atlas_size = OptimumAtlasSizeForFontGlyphPairs(
472  font_glyph_pairs, //
473  glyph_positions, //
474  atlas_context, //
475  type, //
476  context.GetResourceAllocator()->GetMaxTextureSizeSupported() //
477  );
478 
479  atlas_context->UpdateGlyphAtlas(glyph_atlas, atlas_size);
480  if (atlas_size.IsEmpty()) {
481  return nullptr;
482  }
483 
484  // ---------------------------------------------------------------------------
485  // Step 4b: Find location of font-glyph pairs in the atlas. We have this from
486  // the last step. So no need to do create another rect packer. But just do a
487  // sanity check of counts. This could also be just an assertion as only a
488  // construction issue would cause such a failure.
489  // ---------------------------------------------------------------------------
490  if (glyph_positions.size() != font_glyph_pairs.size()) {
491  return nullptr;
492  }
493 
494  // ---------------------------------------------------------------------------
495  // Step 5b: Record the positions in the glyph atlas.
496  // ---------------------------------------------------------------------------
497  {
498  size_t i = 0;
499  for (auto it = font_glyph_pairs.begin(); it != font_glyph_pairs.end();
500  ++i, ++it) {
501  glyph_atlas->AddTypefaceGlyphPosition(*it, glyph_positions[i]);
502  }
503  }
504 
505  // ---------------------------------------------------------------------------
506  // Step 6b: Draw font-glyph pairs in the correct spot in the atlas.
507  // ---------------------------------------------------------------------------
508  auto bitmap = CreateAtlasBitmap(*glyph_atlas, atlas_size);
509  if (!bitmap) {
510  return nullptr;
511  }
512  atlas_context_stb.UpdateBitmap(bitmap);
513 
514  // ---------------------------------------------------------------------------
515  // Step 7b: Upload the atlas as a texture.
516  // ---------------------------------------------------------------------------
517  PixelFormat format;
518  switch (type) {
520  format = PixelFormat::kA8UNormInt;
521  break;
525  break;
526  }
527  auto texture = UploadGlyphTextureAtlas(context.GetResourceAllocator(), bitmap,
528  atlas_size, format);
529  if (!texture) {
530  return nullptr;
531  }
532 
533  // ---------------------------------------------------------------------------
534  // Step 8b: Record the texture in the glyph atlas.
535  // ---------------------------------------------------------------------------
536  glyph_atlas->SetTexture(std::move(texture));
537 
538  return glyph_atlas;
539 }
540 
541 } // namespace impeller
impeller::GlyphAtlas::Type::kColorBitmap
@ kColorBitmap
typeface_stb.h
impeller::TRect::size
TSize< Type > size
Definition: rect.h:24
impeller::TPoint::y
Type y
Definition: point.h:24
impeller::TypographerContext
The graphics context necessary to render text.
Definition: typographer_context.h:22
impeller::Font
Describes a typeface along with any modifications to its intrinsic properties.
Definition: font.h:21
impeller::GlyphAtlas::Type::kAlphaBitmap
@ kAlphaBitmap
impeller::GlyphAtlas::FindFontGlyphBounds
std::optional< Rect > FindFontGlyphBounds(const FontGlyphPair &pair) const
Find the location of a specific font-glyph pair in the atlas.
Definition: glyph_atlas.cc:66
allocation.h
impeller::TRect< Scalar >::MakeXYWH
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:47
impeller::FontGlyphAtlas
An object that can look up glyph locations within the GlyphAtlas for a particular typeface.
Definition: glyph_atlas.h:179
impeller::TypographerContextSTB::TypographerContextSTB
TypographerContextSTB()
Definition: typographer_context_stb.cc:33
impeller::Allocation::NextPowerOfTwoSize
static uint32_t NextPowerOfTwoSize(uint32_t x)
Definition: allocation.cc:42
impeller::CreateAtlasBitmap
static std::shared_ptr< SkBitmap > CreateAtlasBitmap(const GlyphAtlas &atlas, const ISize &atlas_size)
Definition: typographer_context_skia.cc:215
impeller::TextureDescriptor::format
PixelFormat format
Definition: texture_descriptor.h:42
impeller::ScaledFont::font
Font font
Definition: font_glyph_pair.h:24
impeller::PairsFitInAtlasOfSize
static size_t PairsFitInAtlasOfSize(const std::vector< FontGlyphPair > &pairs, const ISize &atlas_size, std::vector< Rect > &glyph_positions, const std::shared_ptr< RectanglePacker > &rect_packer)
Definition: typographer_context_skia.cc:43
impeller::FontGlyphMap
std::unordered_map< ScaledFont, std::unordered_set< Glyph > > FontGlyphMap
Definition: font_glyph_pair.h:28
impeller::PixelFormat::kR8G8B8A8UNormInt
@ kR8G8B8A8UNormInt
impeller::IPoint16::x
int16_t x() const
Definition: rectangle_packer.h:14
impeller::UpdateAtlasBitmap
static bool UpdateAtlasBitmap(const GlyphAtlas &atlas, const std::shared_ptr< SkBitmap > &bitmap, const std::vector< FontGlyphPair > &new_pairs)
Definition: typographer_context_skia.cc:188
impeller::StorageMode::kHostVisible
@ kHostVisible
impeller::BitmapSTB::GetPixelAddress
uint8_t * GetPixelAddress(TPoint< size_t > coords)
Definition: glyph_atlas_context_stb.cc:23
impeller::BitmapSTB
Definition: glyph_atlas_context_stb.h:12
kColorFontBitsPerPixel
constexpr auto kColorFontBitsPerPixel
Definition: typographer_context_stb.cc:20
impeller::IPoint16::y
int16_t y() const
Definition: rectangle_packer.h:15
impeller::Font::GetTypeface
const std::shared_ptr< Typeface > & GetTypeface() const
The typeface whose intrinsic properties this font modifies.
Definition: font.cc:23
impeller::GlyphAtlas::IterateGlyphs
size_t IterateGlyphs(const std::function< bool(const ScaledFont &scaled_font, const Glyph &glyph, const Rect &rect)> &iterator) const
Iterate of all the glyphs along with their locations in the atlas.
Definition: glyph_atlas.cc:91
impeller::CanAppendToExistingAtlas
static bool CanAppendToExistingAtlas(const std::shared_ptr< GlyphAtlas > &atlas, const std::vector< FontGlyphPair > &extra_pairs, std::vector< Rect > &glyph_positions, ISize atlas_size, const std::shared_ptr< RectanglePacker > &rect_packer)
Definition: typographer_context_skia.cc:78
impeller::Glyph
The glyph index in the typeface.
Definition: glyph.h:19
impeller::TSize
Definition: size.h:18
impeller::UpdateGlyphTextureAtlas
static bool UpdateGlyphTextureAtlas(std::shared_ptr< SkBitmap > bitmap, const std::shared_ptr< Texture > &texture)
Definition: typographer_context_skia.cc:256
impeller::FontGlyphPair::glyph
const Glyph & glyph
Definition: font_glyph_pair.h:38
impeller::TypographerContextSTB::~TypographerContextSTB
~TypographerContextSTB() override
impeller::BitmapSTB::GetRowBytes
size_t GetRowBytes() const
Definition: glyph_atlas_context_stb.cc:30
impeller::FontGlyphPair::scaled_font
const ScaledFont & scaled_font
Definition: font_glyph_pair.h:37
impeller::GlyphAtlas::GetType
Type GetType() const
Describes how the glyphs are represented in the texture.
Definition: glyph_atlas.cc:49
glyph_atlas_context_stb.h
impeller::GlyphAtlas::Type
Type
Describes how the glyphs are represented in the texture.
Definition: glyph_atlas.h:32
font_glyph_pair.h
impeller::TypographerContextSTB::Make
static std::unique_ptr< TypographerContext > Make()
Definition: typographer_context_stb.cc:29
impeller::UploadGlyphTextureAtlas
static std::shared_ptr< Texture > UploadGlyphTextureAtlas(const std::shared_ptr< Allocator > &allocator, std::shared_ptr< SkBitmap > bitmap, const ISize &atlas_size, PixelFormat format)
Definition: typographer_context_skia.cc:272
impeller::Font::Metrics::point_size
Scalar point_size
Definition: font.h:34
impeller::TRect::origin
TPoint< Type > origin
Definition: rect.h:23
impeller::Glyph::index
uint16_t index
Definition: glyph.h:25
impeller::FontGlyphPair
A font along with a glyph in that font rendered at a particular scale.
Definition: font_glyph_pair.h:34
impeller::Font::GetMetrics
const Metrics & GetMetrics() const
Definition: font.cc:37
impeller::kPadding
constexpr auto kPadding
Definition: typographer_context_skia.cc:28
impeller::TSize::width
Type width
Definition: size.h:21
impeller::TPoint::x
Type x
Definition: point.h:23
impeller::ISize
TSize< int64_t > ISize
Definition: size.h:136
impeller::TextureDescriptor::size
ISize size
Definition: texture_descriptor.h:43
impeller::RectanglePacker::Factory
static RectanglePacker * Factory(int width, int height)
Return an empty packer with area specified by width and height.
Definition: rectangle_packer.cc:169
impeller::ScaledFont::scale
Scalar scale
Definition: font_glyph_pair.h:25
allocator.h
impeller::TypographerContextSTB::CreateGlyphAtlasContext
std::shared_ptr< GlyphAtlasContext > CreateGlyphAtlasContext() const override
Definition: typographer_context_stb.cc:38
impeller::GlyphAtlas
A texture containing the bitmap representation of glyphs in different fonts along with the ability to...
Definition: glyph_atlas.h:28
impeller::TypographerContextSTB::CreateGlyphAtlas
std::shared_ptr< GlyphAtlas > CreateGlyphAtlas(Context &context, GlyphAtlas::Type type, std::shared_ptr< GlyphAtlasContext > atlas_context, const FontGlyphMap &font_glyph_map) const override
Definition: typographer_context_stb.cc:376
impeller::Context
To do anything rendering related with Impeller, you need a context.
Definition: context.h:47
impeller::TextureDescriptor::GetByteSizeOfBaseMipLevel
constexpr size_t GetByteSizeOfBaseMipLevel() const
Definition: texture_descriptor.h:50
impeller::TypefaceSTB::kPointsToPixels
static constexpr float kPointsToPixels
Definition: typeface_stb.h:20
DISABLE_COLOR_FONT_SUPPORT
#define DISABLE_COLOR_FONT_SUPPORT
Definition: typographer_context_stb.cc:18
impeller::BackendCast< GlyphAtlasContextSTB, GlyphAtlasContext >::Cast
static GlyphAtlasContextSTB & Cast(GlyphAtlasContext &base)
Definition: backend_cast.h:14
impeller::IPoint16
Definition: rectangle_packer.h:13
impeller::PixelFormat::kA8UNormInt
@ kA8UNormInt
impeller::OptimumAtlasSizeForFontGlyphPairs
static ISize OptimumAtlasSizeForFontGlyphPairs(const std::vector< FontGlyphPair > &pairs, std::vector< Rect > &glyph_positions, const std::shared_ptr< GlyphAtlasContext > &atlas_context, GlyphAtlas::Type type, const ISize &max_texture_size)
Definition: typographer_context_skia.cc:116
impeller::FontGlyphAtlas::FindGlyphBounds
std::optional< Rect > FindGlyphBounds(const Glyph &glyph) const
Find the location of a glyph in the atlas.
Definition: glyph_atlas.cc:111
impeller::TextureDescriptor::storage_mode
StorageMode storage_mode
Definition: texture_descriptor.h:40
impeller::TSize::height
Type height
Definition: size.h:22
typographer_context_stb.h
impeller::TextureDescriptor
A lightweight object that describes the attributes of a texture that can then used an allocator to cr...
Definition: texture_descriptor.h:39
impeller::TSize::IsEmpty
constexpr bool IsEmpty() const
Definition: size.h:105
impeller::PixelFormat
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:94
impeller::TSize< int64_t >::MakeWH
static constexpr TSize MakeWH(Type width, Type height)
Definition: size.h:33
impeller
Definition: aiks_context.cc:10
impeller::Context::GetResourceAllocator
virtual std::shared_ptr< Allocator > GetResourceAllocator() const =0
Returns the allocator used to create textures and buffers on the device.
impeller::TRect
Definition: rect.h:20
impeller::DrawGlyph
static void DrawGlyph(SkCanvas *canvas, const ScaledFont &scaled_font, const Glyph &glyph, const Rect &location, bool has_color)
Definition: typographer_context_skia.cc:155
impeller::ScaledFont
A font and a scale. Used as a key that represents a typeface within a glyph atlas.
Definition: font_glyph_pair.h:23
impeller::TypographerContext::IsValid
virtual bool IsValid() const
Definition: typographer_context.cc:17