Flutter Impeller
impeller::TypographerContextSkia Class Reference

#include <typographer_context_skia.h>

Inheritance diagram for impeller::TypographerContextSkia:
impeller::TypographerContext

Public Member Functions

 TypographerContextSkia ()
 
 ~TypographerContextSkia () override
 
std::shared_ptr< GlyphAtlasContextCreateGlyphAtlasContext () const override
 
std::shared_ptr< GlyphAtlasCreateGlyphAtlas (Context &context, GlyphAtlas::Type type, 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::shared_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 12 of file typographer_context_skia.h.

Constructor & Destructor Documentation

◆ TypographerContextSkia()

impeller::TypographerContextSkia::TypographerContextSkia ( )
default

◆ ~TypographerContextSkia()

impeller::TypographerContextSkia::~TypographerContextSkia ( )
overridedefault

Member Function Documentation

◆ CreateGlyphAtlas()

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

Implements impeller::TypographerContext.

Definition at line 317 of file typographer_context_skia.cc.

321  {
322  TRACE_EVENT0("impeller", __FUNCTION__);
323  if (!IsValid()) {
324  return nullptr;
325  }
326  auto& atlas_context_skia = GlyphAtlasContextSkia::Cast(*atlas_context);
327  std::shared_ptr<GlyphAtlas> last_atlas = atlas_context->GetGlyphAtlas();
328 
329  if (font_glyph_map.empty()) {
330  return last_atlas;
331  }
332 
333  // ---------------------------------------------------------------------------
334  // Step 1: Determine if the atlas type and font glyph pairs are compatible
335  // with the current atlas and reuse if possible.
336  // ---------------------------------------------------------------------------
337  std::vector<FontGlyphPair> new_glyphs;
338  for (const auto& font_value : font_glyph_map) {
339  const ScaledFont& scaled_font = font_value.first;
340  const FontGlyphAtlas* font_glyph_atlas =
341  last_atlas->GetFontGlyphAtlas(scaled_font.font, scaled_font.scale);
342  if (font_glyph_atlas) {
343  for (const Glyph& glyph : font_value.second) {
344  if (!font_glyph_atlas->FindGlyphBounds(glyph)) {
345  new_glyphs.emplace_back(scaled_font, glyph);
346  }
347  }
348  } else {
349  for (const Glyph& glyph : font_value.second) {
350  new_glyphs.emplace_back(scaled_font, glyph);
351  }
352  }
353  }
354  if (last_atlas->GetType() == type && new_glyphs.size() == 0) {
355  return last_atlas;
356  }
357 
358  // ---------------------------------------------------------------------------
359  // Step 2: Determine if the additional missing glyphs can be appended to the
360  // existing bitmap without recreating the atlas. This requires that
361  // the type is identical.
362  // ---------------------------------------------------------------------------
363  std::vector<Rect> glyph_positions;
364  if (last_atlas->GetType() == type &&
365  CanAppendToExistingAtlas(last_atlas, new_glyphs, glyph_positions,
366  atlas_context->GetAtlasSize(),
367  atlas_context->GetRectPacker())) {
368  // The old bitmap will be reused and only the additional glyphs will be
369  // added.
370 
371  // ---------------------------------------------------------------------------
372  // Step 3a: Record the positions in the glyph atlas of the newly added
373  // glyphs.
374  // ---------------------------------------------------------------------------
375  for (size_t i = 0, count = glyph_positions.size(); i < count; i++) {
376  last_atlas->AddTypefaceGlyphPosition(new_glyphs[i], glyph_positions[i]);
377  }
378 
379  // ---------------------------------------------------------------------------
380  // Step 4a: Draw new font-glyph pairs into the existing bitmap.
381  // ---------------------------------------------------------------------------
382  auto bitmap = atlas_context_skia.GetBitmap();
383  if (!UpdateAtlasBitmap(*last_atlas, bitmap, new_glyphs)) {
384  return nullptr;
385  }
386 
387  // ---------------------------------------------------------------------------
388  // Step 5a: Update the existing texture with the updated bitmap.
389  // ---------------------------------------------------------------------------
390  if (!UpdateGlyphTextureAtlas(bitmap, last_atlas->GetTexture())) {
391  return nullptr;
392  }
393  return last_atlas;
394  }
395  // A new glyph atlas must be created.
396 
397  // ---------------------------------------------------------------------------
398  // Step 3b: Get the optimum size of the texture atlas.
399  // ---------------------------------------------------------------------------
400  std::vector<FontGlyphPair> font_glyph_pairs;
401  font_glyph_pairs.reserve(std::accumulate(
402  font_glyph_map.begin(), font_glyph_map.end(), 0,
403  [](const int a, const auto& b) { return a + b.second.size(); }));
404  for (const auto& font_value : font_glyph_map) {
405  const ScaledFont& scaled_font = font_value.first;
406  for (const Glyph& glyph : font_value.second) {
407  font_glyph_pairs.push_back({scaled_font, glyph});
408  }
409  }
410  auto glyph_atlas = std::make_shared<GlyphAtlas>(type);
411  auto atlas_size = OptimumAtlasSizeForFontGlyphPairs(
412  font_glyph_pairs, //
413  glyph_positions, //
414  atlas_context, //
415  type, //
416  context.GetResourceAllocator()->GetMaxTextureSizeSupported() //
417  );
418 
419  atlas_context->UpdateGlyphAtlas(glyph_atlas, atlas_size);
420  if (atlas_size.IsEmpty()) {
421  return nullptr;
422  }
423  // ---------------------------------------------------------------------------
424  // Step 4b: Find location of font-glyph pairs in the atlas. We have this from
425  // the last step. So no need to do create another rect packer. But just do a
426  // sanity check of counts. This could also be just an assertion as only a
427  // construction issue would cause such a failure.
428  // ---------------------------------------------------------------------------
429  if (glyph_positions.size() != font_glyph_pairs.size()) {
430  return nullptr;
431  }
432 
433  // ---------------------------------------------------------------------------
434  // Step 5b: Record the positions in the glyph atlas.
435  // ---------------------------------------------------------------------------
436  {
437  size_t i = 0;
438  for (auto it = font_glyph_pairs.begin(); it != font_glyph_pairs.end();
439  ++i, ++it) {
440  glyph_atlas->AddTypefaceGlyphPosition(*it, glyph_positions[i]);
441  }
442  }
443 
444  // ---------------------------------------------------------------------------
445  // Step 6b: Draw font-glyph pairs in the correct spot in the atlas.
446  // ---------------------------------------------------------------------------
447  auto bitmap = CreateAtlasBitmap(*glyph_atlas, atlas_size);
448  if (!bitmap) {
449  return nullptr;
450  }
451  atlas_context_skia.UpdateBitmap(bitmap);
452 
453  // ---------------------------------------------------------------------------
454  // Step 7b: Upload the atlas as a texture.
455  // ---------------------------------------------------------------------------
456  PixelFormat format;
457  switch (type) {
459  format = context.GetCapabilities()->GetDefaultGlyphAtlasFormat();
460  break;
463  break;
464  }
465  auto texture = UploadGlyphTextureAtlas(context.GetResourceAllocator(), bitmap,
466  atlas_size, format);
467  if (!texture) {
468  return nullptr;
469  }
470 
471  // ---------------------------------------------------------------------------
472  // Step 8b: Record the texture in the glyph atlas.
473  // ---------------------------------------------------------------------------
474  glyph_atlas->SetTexture(std::move(texture));
475 
476  return glyph_atlas;
477 }

References impeller::saturated::b, impeller::CanAppendToExistingAtlas(), impeller::BackendCast< GlyphAtlasContextSkia, GlyphAtlasContext >::Cast(), impeller::CreateAtlasBitmap(), impeller::FontGlyphAtlas::FindGlyphBounds(), impeller::ScaledFont::font, impeller::Context::GetCapabilities(), impeller::Context::GetResourceAllocator(), impeller::TypographerContext::IsValid(), 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::TypographerContextSkia::CreateGlyphAtlasContext ( ) const
overridevirtual

Implements impeller::TypographerContext.

Definition at line 41 of file typographer_context_skia.cc.

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

◆ Make()

std::shared_ptr< TypographerContext > impeller::TypographerContextSkia::Make ( )
static

Definition at line 32 of file typographer_context_skia.cc.

32  {
33  return std::make_shared<TypographerContextSkia>();
34 }

Referenced by impeller::DlPlayground::OpenPlaygroundHere(), and impeller::testing::TEST_P().


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:217
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:190
impeller::PixelFormat
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
Definition: formats.h:100
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:80
impeller::UpdateGlyphTextureAtlas
static bool UpdateGlyphTextureAtlas(std::shared_ptr< SkBitmap > bitmap, const std::shared_ptr< Texture > &texture)
Definition: typographer_context_skia.cc:260
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:276
impeller::saturated::b
SI b
Definition: saturated_math.h:87
impeller::BackendCast< GlyphAtlasContextSkia, GlyphAtlasContext >::Cast
static GlyphAtlasContextSkia & 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_skia.cc:118
impeller::TypographerContext::IsValid
virtual bool IsValid() const
Definition: typographer_context.cc:17