Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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:
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.
 

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}
int count
static GlyphAtlasContextSkia & Cast(GlyphAtlasContext &base)
static bool b
struct MyStruct a[10]
uint32_t uint32_t * format
FlTexture * texture
static std::shared_ptr< Texture > UploadGlyphTextureAtlas(const std::shared_ptr< Allocator > &allocator, std::shared_ptr< SkBitmap > bitmap, const ISize &atlas_size, PixelFormat format)
static std::shared_ptr< SkBitmap > CreateAtlasBitmap(const GlyphAtlas &atlas, const ISize &atlas_size)
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)
static bool UpdateGlyphTextureAtlas(std::shared_ptr< SkBitmap > bitmap, const std::shared_ptr< Texture > &texture)
static bool UpdateAtlasBitmap(const GlyphAtlas &atlas, const std::shared_ptr< SkBitmap > &bitmap, const std::vector< FontGlyphPair > &new_pairs)
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)
#define TRACE_EVENT0(category_group, name)

◆ 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}

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