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 (GlyphAtlas::Type type) const override
 
std::shared_ptr< GlyphAtlasCreateGlyphAtlas (Context &context, GlyphAtlas::Type type, HostBuffer &host_buffer, const 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 15 of file typographer_context_stb.h.

Constructor & Destructor Documentation

◆ TypographerContextSTB()

impeller::TypographerContextSTB::TypographerContextSTB ( )

Definition at line 36 of file typographer_context_stb.cc.

36 : TypographerContext() {}

◆ ~TypographerContextSTB()

impeller::TypographerContextSTB::~TypographerContextSTB ( )
overridedefault

Member Function Documentation

◆ CreateGlyphAtlas()

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

Implements impeller::TypographerContext.

Definition at line 399 of file typographer_context_stb.cc.

404  {
405  TRACE_EVENT0("impeller", __FUNCTION__);
406  if (!IsValid()) {
407  return nullptr;
408  }
409  auto& atlas_context_stb = GlyphAtlasContextSTB::Cast(*atlas_context);
410  std::shared_ptr<GlyphAtlas> last_atlas = atlas_context->GetGlyphAtlas();
411 
412  if (font_glyph_map.empty()) {
413  return last_atlas;
414  }
415 
416  // ---------------------------------------------------------------------------
417  // Step 1: Determine if the atlas type and font glyph pairs are compatible
418  // with the current atlas and reuse if possible.
419  // ---------------------------------------------------------------------------
420  std::vector<FontGlyphPair> new_glyphs;
421  std::vector<Rect> new_sizes;
422  for (const auto& font_value : font_glyph_map) {
423  const ScaledFont& scaled_font = font_value.first;
424  const FontGlyphAtlas* font_glyph_atlas =
425  last_atlas->GetFontGlyphAtlas(scaled_font.font, scaled_font.scale);
426  if (font_glyph_atlas) {
427  for (const SubpixelGlyph& glyph : font_value.second) {
428  if (!font_glyph_atlas->FindGlyphBounds(glyph)) {
429  new_glyphs.emplace_back(scaled_font, glyph);
430  new_sizes.push_back(ComputeGlyphSize(scaled_font, glyph));
431  }
432  }
433  } else {
434  for (const SubpixelGlyph& glyph : font_value.second) {
435  new_glyphs.emplace_back(scaled_font, glyph);
436  new_sizes.push_back(ComputeGlyphSize(scaled_font, glyph));
437  }
438  }
439  }
440 
441  if (last_atlas->GetType() == type && new_glyphs.size() == 0) {
442  return last_atlas;
443  }
444 
445  std::shared_ptr<CommandBuffer> cmd_buffer = context.CreateCommandBuffer();
446  std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
447 
448  fml::ScopedCleanupClosure closure([&cmd_buffer, &context]() {
449  context.GetCommandQueue()->Submit({std::move(cmd_buffer)});
450  });
451 
452  // ---------------------------------------------------------------------------
453  // Step 2: Determine if the additional missing glyphs can be appended to the
454  // existing bitmap without recreating the atlas. This requires that
455  // the type is identical.
456  // ---------------------------------------------------------------------------
457  std::vector<Rect> glyph_positions;
458  if (last_atlas->GetType() == type &&
459  CanAppendToExistingAtlas(last_atlas, new_glyphs, glyph_positions,
460  atlas_context->GetAtlasSize(),
461  atlas_context->GetRectPacker())) {
462  // The old bitmap will be reused and only the additional glyphs will be
463  // added.
464 
465  // ---------------------------------------------------------------------------
466  // Step 3a: Record the positions in the glyph atlas of the newly added
467  // glyphs.
468  // ---------------------------------------------------------------------------
469  for (size_t i = 0, count = glyph_positions.size(); i < count; i++) {
470  last_atlas->AddTypefaceGlyphPositionAndBounds(
471  new_glyphs[i], glyph_positions[i], new_sizes[i]);
472  }
473 
474  // ---------------------------------------------------------------------------
475  // Step 4a: Draw new font-glyph pairs into the existing bitmap.
476  // ---------------------------------------------------------------------------
477  // auto bitmap = atlas_context->GetBitmap();
478  auto bitmap = atlas_context_stb.GetBitmap();
479  if (!UpdateAtlasBitmap(*last_atlas, bitmap, new_glyphs)) {
480  return nullptr;
481  }
482 
483  // ---------------------------------------------------------------------------
484  // Step 5a: Update the existing texture with the updated bitmap.
485  // ---------------------------------------------------------------------------
486  if (!UpdateGlyphTextureAtlas(bitmap, context.GetResourceAllocator(),
487  blit_pass, last_atlas->GetTexture())) {
488  return nullptr;
489  }
490  return last_atlas;
491  }
492  // A new glyph atlas must be created.
493 
494  // ---------------------------------------------------------------------------
495  // Step 3b: Get the optimum size of the texture atlas.
496  // ---------------------------------------------------------------------------
497  std::vector<FontGlyphPair> font_glyph_pairs;
498  font_glyph_pairs.reserve(std::accumulate(
499  font_glyph_map.begin(), font_glyph_map.end(), 0,
500  [](const int a, const auto& b) { return a + b.second.size(); }));
501  for (const auto& font_value : font_glyph_map) {
502  const ScaledFont& scaled_font = font_value.first;
503  for (const SubpixelGlyph& glyph : font_value.second) {
504  font_glyph_pairs.push_back({scaled_font, glyph});
505  }
506  }
507  auto glyph_atlas = std::make_shared<GlyphAtlas>(type);
508  auto atlas_size = OptimumAtlasSizeForFontGlyphPairs(
509  font_glyph_pairs, //
510  glyph_positions, //
511  atlas_context, //
512  type, //
513  context.GetResourceAllocator()->GetMaxTextureSizeSupported() //
514  );
515 
516  atlas_context->UpdateGlyphAtlas(glyph_atlas, atlas_size, 0);
517  if (atlas_size.IsEmpty()) {
518  return nullptr;
519  }
520 
521  // ---------------------------------------------------------------------------
522  // Step 4b: Find location of font-glyph pairs in the atlas. We have this from
523  // the last step. So no need to do create another rect packer. But just do a
524  // sanity check of counts. This could also be just an assertion as only a
525  // construction issue would cause such a failure.
526  // ---------------------------------------------------------------------------
527  if (glyph_positions.size() != font_glyph_pairs.size()) {
528  return nullptr;
529  }
530 
531  // ---------------------------------------------------------------------------
532  // Step 5b: Record the positions in the glyph atlas.
533  // ---------------------------------------------------------------------------
534  {
535  size_t i = 0;
536  for (auto it = font_glyph_pairs.begin(); it != font_glyph_pairs.end();
537  ++i, ++it) {
538  glyph_atlas->AddTypefaceGlyphPositionAndBounds(*it, glyph_positions[i],
539  new_sizes[i]);
540  }
541  }
542 
543  // ---------------------------------------------------------------------------
544  // Step 6b: Draw font-glyph pairs in the correct spot in the atlas.
545  // ---------------------------------------------------------------------------
546  auto bitmap = CreateAtlasBitmap(*glyph_atlas, atlas_size);
547  if (!bitmap) {
548  return nullptr;
549  }
550  atlas_context_stb.UpdateBitmap(bitmap);
551 
552  // ---------------------------------------------------------------------------
553  // Step 7b: Upload the atlas as a texture.
554  // ---------------------------------------------------------------------------
555  PixelFormat format;
556  switch (type) {
558  format = context.GetCapabilities()->GetDefaultGlyphAtlasFormat();
559  break;
562  ? context.GetCapabilities()->GetDefaultGlyphAtlasFormat()
564  break;
565  }
566  auto texture = UploadGlyphTextureAtlas(context.GetResourceAllocator(),
567  blit_pass, bitmap, atlas_size, format);
568  if (!texture) {
569  return nullptr;
570  }
571 
572  // ---------------------------------------------------------------------------
573  // Step 8b: Record the texture in the glyph atlas.
574  // ---------------------------------------------------------------------------
575  glyph_atlas->SetTexture(std::move(texture));
576 
577  return glyph_atlas;
578 }

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

◆ CreateGlyphAtlasContext()

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

Implements impeller::TypographerContext.

Definition at line 41 of file typographer_context_stb.cc.

41  {
42  return std::make_shared<GlyphAtlasContextSTB>(type);
43 }

References type.

◆ Make()

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

Definition at line 32 of file typographer_context_stb.cc.

32  {
33  return std::make_unique<TypographerContextSTB>();
34 }

The documentation for this class was generated from the following files:
impeller::CreateAtlasBitmap
static std::shared_ptr< BitmapSTB > CreateAtlasBitmap(const GlyphAtlas &atlas, const ISize &atlas_size)
Definition: typographer_context_stb.cc:291
impeller::GlyphAtlas::Type::kColorBitmap
@ kColorBitmap
impeller::UpdateGlyphTextureAtlas
static bool UpdateGlyphTextureAtlas(std::shared_ptr< BitmapSTB > &bitmap, const std::shared_ptr< Allocator > &allocator, std::shared_ptr< BlitPass > &blit_pass, const std::shared_ptr< Texture > &texture)
Definition: typographer_context_stb.cc:316
impeller::GlyphAtlas::Type::kAlphaBitmap
@ kAlphaBitmap
impeller::UpdateAtlasBitmap
static bool UpdateAtlasBitmap(const GlyphAtlas &atlas, std::shared_ptr< BlitPass > &blit_pass, HostBuffer &host_buffer, const std::shared_ptr< Texture > &texture, const std::vector< FontGlyphPair > &new_pairs, size_t start_index, size_t end_index)
Definition: typographer_context_skia.cc:311
impeller::PixelFormat::kR8G8B8A8UNormInt
@ kR8G8B8A8UNormInt
impeller::UploadGlyphTextureAtlas
static std::shared_ptr< Texture > UploadGlyphTextureAtlas(const std::shared_ptr< Allocator > &allocator, std::shared_ptr< BlitPass > &blit_pass, std::shared_ptr< BitmapSTB > &bitmap, const ISize &atlas_size, PixelFormat format)
Definition: typographer_context_stb.cc:340
impeller::TypographerContext::TypographerContext
TypographerContext()
Create a new context to render text that talks to an underlying graphics context.
Definition: typographer_context.cc:11
impeller::PixelFormat
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:99
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_stb.cc:102
type
GLenum type
Definition: blit_command_gles.cc:127
DISABLE_COLOR_FONT_SUPPORT
#define DISABLE_COLOR_FONT_SUPPORT
Definition: typographer_context_stb.cc:21
impeller::saturated::b
SI b
Definition: saturated_math.h:87
impeller::BackendCast< GlyphAtlasContextSTB, GlyphAtlasContext >::Cast
static GlyphAtlasContextSTB & Cast(GlyphAtlasContext &base)
Definition: backend_cast.h:13
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_stb.cc:160
impeller::ComputeGlyphSize
static Rect ComputeGlyphSize(const SkFont &font, const SubpixelGlyph &glyph, Scalar scale)
Definition: typographer_context_skia.cc:381
impeller::TypographerContext::IsValid
virtual bool IsValid() const
Definition: typographer_context.cc:17