| Flutter Impeller |

Public Member Functions | Static Public Member Functions | List of all members
impeller::TypographerContextSkia Class Reference

`#include <typographer_context_skia.h>`

Inheritance diagram for impeller::TypographerContextSkia:

## Public Member Functions
| TypographerContextSkia ()
| ~TypographerContextSkia () override
std::shared_ptr< GlyphAtlasContext > | CreateGlyphAtlasContext () const override
std::shared_ptr< GlyphAtlas > | CreateGlyphAtlas (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::shared_ptr< TypographerContext > | Make ()

## 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 | ( |  | ) |
| override default

## Member Function Documentation

## ◆ CreateGlyphAtlas()

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

Implements impeller::TypographerContext.

Definition at line 313 of file typographer_context_skia.cc.

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

References impeller::CanAppendToExistingAtlas(), impeller::BackendCast< GlyphAtlasContextSkia, GlyphAtlasContext >::Cast(), impeller::CreateAtlasBitmap(), 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::TypographerContextSkia::CreateGlyphAtlasContext | ( |  | ) | const
| override virtual

Implements impeller::TypographerContext.

Definition at line 39 of file typographer_context_skia.cc.

39 {
40 return std::make_shared<GlyphAtlasContextSkia>();
41 }

## ◆ Make()

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

Definition at line 30 of file typographer_context_skia.cc.

30 {
31 return std::make_shared<TypographerContextSkia>();
32 }

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

The documentation for this class was generated from the following files:

- impeller/typographer/backends/skia/typographer_context_skia.h
- impeller/typographer/backends/skia/typographer_context_skia.cc

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::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
impeller::BackendCast< GlyphAtlasContextSkia, GlyphAtlasContext >::Cast
static GlyphAtlasContextSkia & 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