Flutter Impeller
impeller::TypographerContextSTB Class Reference

#include <typographer_context_stb.h>

Inheritance diagram for impeller::TypographerContextSTB:
impeller::TypographerContext

Public Member Functions

 TypographerContextSTB ()
 
 ~TypographerContextSTB () override
 
std::shared_ptr< GlyphAtlasContextCreateGlyphAtlasContext () const override
 
std::shared_ptr< GlyphAtlasCreateGlyphAtlas (Context &context, GlyphAtlas::Type type, std::shared_ptr< GlyphAtlasContext > atlas_context, const FontGlyphMap &font_glyph_map) const override
 
- Public Member Functions inherited from impeller::TypographerContext
virtual ~TypographerContext ()
 
virtual bool IsValid () const
 

Static Public Member Functions

static std::unique_ptr< TypographerContextMake ()
 

Additional Inherited Members

- Protected Member Functions inherited from impeller::TypographerContext
 TypographerContext ()
 Create a new context to render text that talks to an underlying graphics context. More...
 

Detailed Description

Definition at line 14 of file typographer_context_stb.h.

Constructor & Destructor Documentation

◆ TypographerContextSTB()

impeller::TypographerContextSTB::TypographerContextSTB ( )

Definition at line 33 of file typographer_context_stb.cc.

33 : TypographerContext() {}

◆ ~TypographerContextSTB()

impeller::TypographerContextSTB::~TypographerContextSTB ( )
overridedefault

Member Function Documentation

◆ CreateGlyphAtlas()

std::shared_ptr< GlyphAtlas > impeller::TypographerContextSTB::CreateGlyphAtlas ( Context context,
GlyphAtlas::Type  type,
std::shared_ptr< GlyphAtlasContext atlas_context,
const FontGlyphMap font_glyph_map 
) const
overridevirtual

Implements impeller::TypographerContext.

Definition at line 376 of file typographer_context_stb.cc.

380  {
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 }

References impeller::CanAppendToExistingAtlas(), impeller::BackendCast< GlyphAtlasContextSTB, GlyphAtlasContext >::Cast(), impeller::CreateAtlasBitmap(), DISABLE_COLOR_FONT_SUPPORT, impeller::FontGlyphAtlas::FindGlyphBounds(), impeller::ScaledFont::font, impeller::Context::GetResourceAllocator(), impeller::TypographerContext::IsValid(), impeller::kA8UNormInt, impeller::GlyphAtlas::kAlphaBitmap, impeller::GlyphAtlas::kColorBitmap, impeller::kR8G8B8A8UNormInt, impeller::OptimumAtlasSizeForFontGlyphPairs(), impeller::ScaledFont::scale, impeller::UpdateAtlasBitmap(), impeller::UpdateGlyphTextureAtlas(), and impeller::UploadGlyphTextureAtlas().

◆ CreateGlyphAtlasContext()

std::shared_ptr< GlyphAtlasContext > impeller::TypographerContextSTB::CreateGlyphAtlasContext ( ) const
overridevirtual

Implements impeller::TypographerContext.

Definition at line 38 of file typographer_context_stb.cc.

38  {
39  return std::make_shared<GlyphAtlasContextSTB>();
40 }

◆ Make()

std::unique_ptr< TypographerContext > impeller::TypographerContextSTB::Make ( )
static

Definition at line 29 of file typographer_context_stb.cc.

29  {
30  return std::make_unique<TypographerContextSTB>();
31 }

The documentation for this class was generated from the following files:
impeller::GlyphAtlas::Type::kColorBitmap
@ kColorBitmap
impeller::GlyphAtlas::Type::kAlphaBitmap
@ kAlphaBitmap
impeller::CreateAtlasBitmap
static std::shared_ptr< SkBitmap > CreateAtlasBitmap(const GlyphAtlas &atlas, const ISize &atlas_size)
Definition: typographer_context_skia.cc:215
impeller::PixelFormat::kR8G8B8A8UNormInt
@ kR8G8B8A8UNormInt
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::TypographerContext::TypographerContext
TypographerContext()
Create a new context to render text that talks to an underlying graphics context.
Definition: typographer_context.cc:11
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::UpdateGlyphTextureAtlas
static bool UpdateGlyphTextureAtlas(std::shared_ptr< SkBitmap > bitmap, const std::shared_ptr< Texture > &texture)
Definition: typographer_context_skia.cc:256
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
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::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::PixelFormat
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:94
impeller::TypographerContext::IsValid
virtual bool IsValid() const
Definition: typographer_context.cc:17