Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
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 (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 std::vector< RenderableText > &renderable_texts) const override
 
- Public Member Functions inherited from impeller::TypographerContext
virtual ~TypographerContext ()
 
virtual bool IsValid () const
 

Static Public Member Functions

static std::shared_ptr< TypographerContextMake ()
 
static SkImageInfo GetImageInfo (const GlyphAtlas &atlas, Size size, bool support_light_glyphs)
 

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 13 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,
HostBuffer host_buffer,
const std::shared_ptr< GlyphAtlasContext > &  atlas_context,
const std::vector< RenderableText > &  renderable_texts 
) const
overridevirtual

Implements impeller::TypographerContext.

Definition at line 548 of file typographer_context_skia.cc.

553 {
554 TRACE_EVENT0("impeller", __FUNCTION__);
555 if (!IsValid()) {
556 return nullptr;
557 }
558 std::shared_ptr<GlyphAtlas> last_atlas = atlas_context->GetGlyphAtlas();
559 FML_DCHECK(last_atlas->GetType() == type);
560
561 if (renderable_texts.empty()) {
562 return last_atlas;
563 }
564
565 // ---------------------------------------------------------------------------
566 // Step 1: Determine if the atlas type and font glyph pairs are compatible
567 // with the current atlas and reuse if possible. For each new font and
568 // glyph pair, compute the glyph size at scale.
569 // ---------------------------------------------------------------------------
570 auto [new_glyphs, glyph_sizes] =
571 CollectNewGlyphs(last_atlas, renderable_texts);
572 if (new_glyphs.size() == 0) {
573 return last_atlas;
574 }
575
576 // ---------------------------------------------------------------------------
577 // Step 2: Determine if the additional missing glyphs can be appended to the
578 // existing bitmap without recreating the atlas.
579 // ---------------------------------------------------------------------------
580 std::vector<Rect> glyph_positions;
581 glyph_positions.reserve(new_glyphs.size());
582 size_t first_missing_index = 0;
583
584 if (last_atlas->GetTexture()) {
585 // Append all glyphs that fit into the current atlas.
586 first_missing_index = AppendToExistingAtlas(
587 last_atlas, new_glyphs, glyph_positions, glyph_sizes,
588 atlas_context->GetAtlasSize(), atlas_context->GetHeightAdjustment(),
589 atlas_context->GetRectPacker());
590
591 // ---------------------------------------------------------------------------
592 // Step 3a: Record the positions in the glyph atlas of the newly added
593 // glyphs.
594 // ---------------------------------------------------------------------------
595 for (size_t i = 0; i < first_missing_index; i++) {
596 last_atlas->AddTypefaceGlyphPositionAndBounds(
597 new_glyphs[i], glyph_positions[i], glyph_sizes[i]);
598 }
599
600 std::shared_ptr<CommandBuffer> cmd_buffer = context.CreateCommandBuffer();
601 std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
602
604 blit_pass->EncodeCommands();
605 if (!context.EnqueueCommandBuffer(std::move(cmd_buffer))) {
606 VALIDATION_LOG << "Failed to submit glyph atlas command buffer";
607 }
608 });
609
610 // ---------------------------------------------------------------------------
611 // Step 4a: Draw new font-glyph pairs into the a host buffer and encode
612 // the uploads into the blit pass.
613 // ---------------------------------------------------------------------------
614 if (!UpdateAtlasBitmap(*last_atlas, blit_pass, data_host_buffer,
615 last_atlas->GetTexture(), new_glyphs, 0,
616 first_missing_index)) {
617 return nullptr;
618 }
619
620 // If all glyphs fit, just return the old atlas.
621 if (first_missing_index == new_glyphs.size()) {
622 return last_atlas;
623 }
624 }
625
626 int64_t height_adjustment = atlas_context->GetAtlasSize().height;
627 const int64_t max_texture_height =
628 context.GetResourceAllocator()->GetMaxTextureSizeSupported().height;
629
630 // IF the current atlas size is as big as it can get, then "GC" and create an
631 // atlas with only the required glyphs. OpenGLES cannot reliably perform the
632 // blit required here, as 1) it requires attaching textures as read and write
633 // framebuffers which has substantially smaller size limits that max textures
634 // and 2) is missing a GLES 2.0 implementation and cap check.
635 bool blit_old_atlas = true;
636 std::shared_ptr<GlyphAtlas> new_atlas = last_atlas;
637 if (atlas_context->GetAtlasSize().height >= max_texture_height ||
638 context.GetBackendType() == Context::BackendType::kOpenGLES) {
639 blit_old_atlas = false;
640 new_atlas = std::make_shared<GlyphAtlas>(
641 type, /*initial_generation=*/last_atlas->GetAtlasGeneration() + 1);
642
643 auto [update_glyphs, update_sizes] =
644 CollectNewGlyphs(new_atlas, renderable_texts);
645 new_glyphs = std::move(update_glyphs);
646 glyph_sizes = std::move(update_sizes);
647
648 glyph_positions.clear();
649 glyph_positions.reserve(new_glyphs.size());
650 first_missing_index = 0;
651
652 height_adjustment = 0;
653 atlas_context->UpdateRectPacker(nullptr);
654 atlas_context->UpdateGlyphAtlas(new_atlas, {0, 0}, 0);
655 }
656
657 // A new glyph atlas must be created.
658 ISize atlas_size = ComputeNextAtlasSize(atlas_context, //
659 new_glyphs, //
660 glyph_positions, //
661 glyph_sizes, //
662 first_missing_index, //
663 max_texture_height //
664 );
665
666 atlas_context->UpdateGlyphAtlas(new_atlas, atlas_size, height_adjustment);
667 if (atlas_size.IsEmpty()) {
668 return nullptr;
669 }
670 FML_DCHECK(new_glyphs.size() == glyph_positions.size());
671
672 TextureDescriptor descriptor;
673 switch (type) {
675 descriptor.format =
676 context.GetCapabilities()->GetDefaultGlyphAtlasFormat();
677 break;
679 descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
680 break;
681 }
682 descriptor.size = atlas_size;
683 descriptor.storage_mode = StorageMode::kDevicePrivate;
684 descriptor.usage = TextureUsage::kShaderRead;
685 std::shared_ptr<Texture> new_texture =
686 context.GetResourceAllocator()->CreateTexture(descriptor);
687 if (!new_texture) {
688 return nullptr;
689 }
690
691 new_texture->SetLabel("GlyphAtlas");
692
693 std::shared_ptr<CommandBuffer> cmd_buffer = context.CreateCommandBuffer();
694 std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
695
697 blit_pass->EncodeCommands();
698 if (!context.EnqueueCommandBuffer(std::move(cmd_buffer))) {
699 VALIDATION_LOG << "Failed to submit glyph atlas command buffer";
700 }
701 });
702
703 // Now append all remaining glyphs. This should never have any missing data...
704 auto old_texture = new_atlas->GetTexture();
705 new_atlas->SetTexture(std::move(new_texture));
706
707 // ---------------------------------------------------------------------------
708 // Step 3a: Record the positions in the glyph atlas of the newly added
709 // glyphs.
710 // ---------------------------------------------------------------------------
711 for (size_t i = first_missing_index; i < glyph_positions.size(); i++) {
712 new_atlas->AddTypefaceGlyphPositionAndBounds(
713 new_glyphs[i], glyph_positions[i], glyph_sizes[i]);
714 }
715
716 // ---------------------------------------------------------------------------
717 // Step 4a: Draw new font-glyph pairs into the a host buffer and encode
718 // the uploads into the blit pass.
719 // ---------------------------------------------------------------------------
720 if (!BulkUpdateAtlasBitmap(*new_atlas, blit_pass, data_host_buffer,
721 new_atlas->GetTexture(), new_glyphs,
722 first_missing_index, new_glyphs.size())) {
723 return nullptr;
724 }
725
726 // Blit the old texture to the top left of the new atlas.
727 if (blit_old_atlas && old_texture) {
728 blit_pass->AddCopy(old_texture, new_atlas->GetTexture(),
729 IRect::MakeSize(new_atlas->GetTexture()->GetSize()),
730 {0, 0});
731 }
732
733 // ---------------------------------------------------------------------------
734 // Step 8b: Record the texture in the glyph atlas.
735 // ---------------------------------------------------------------------------
736
737 return new_atlas;
738}
Wraps a closure that is invoked in the destructor unless released by the caller.
Definition closure.h:32
#define FML_DCHECK(condition)
Definition logging.h:122
std::function< void()> closure
Definition closure.h:14
static bool UpdateAtlasBitmap(const GlyphAtlas &atlas, std::shared_ptr< BlitPass > &blit_pass, HostBuffer &data_host_buffer, const std::shared_ptr< Texture > &texture, const std::vector< FontGlyphPair > &new_pairs, size_t start_index, size_t end_index)
static size_t AppendToExistingAtlas(const std::shared_ptr< GlyphAtlas > &atlas, const std::vector< FontGlyphPair > &extra_pairs, std::vector< Rect > &glyph_positions, const std::vector< Rect > &glyph_sizes, ISize atlas_size, int64_t height_adjustment, const std::shared_ptr< RectanglePacker > &rect_packer)
static ISize ComputeNextAtlasSize(const std::shared_ptr< GlyphAtlasContext > &atlas_context, const std::vector< FontGlyphPair > &extra_pairs, std::vector< Rect > &glyph_positions, const std::vector< Rect > &glyph_sizes, size_t glyph_index_start, int64_t max_texture_height)
static bool BulkUpdateAtlasBitmap(const GlyphAtlas &atlas, std::shared_ptr< BlitPass > &blit_pass, HostBuffer &data_host_buffer, const std::shared_ptr< Texture > &texture, const std::vector< FontGlyphPair > &new_pairs, size_t start_index, size_t end_index)
Batch render to a single surface.
ISize64 ISize
Definition size.h:162
impeller::ShaderType type
static constexpr TRect MakeSize(const TSize< U > &size)
Definition rect.h:150
#define TRACE_EVENT0(category_group, name)

References impeller::AppendToExistingAtlas(), impeller::BulkUpdateAtlasBitmap(), impeller::ComputeNextAtlasSize(), impeller::Context::CreateCommandBuffer(), impeller::Context::EnqueueCommandBuffer(), FML_DCHECK, impeller::TextureDescriptor::format, impeller::Context::GetBackendType(), impeller::Context::GetCapabilities(), impeller::Context::GetResourceAllocator(), i, impeller::TSize< T >::IsEmpty(), impeller::TypographerContext::IsValid(), impeller::GlyphAtlas::kAlphaBitmap, impeller::GlyphAtlas::kColorBitmap, impeller::kDevicePrivate, impeller::Context::kOpenGLES, impeller::kR8G8B8A8UNormInt, impeller::kShaderRead, impeller::TRect< T >::MakeSize(), impeller::TextureDescriptor::size, impeller::TextureDescriptor::storage_mode, TRACE_EVENT0, type, impeller::UpdateAtlasBitmap(), and impeller::TextureDescriptor::usage.

◆ CreateGlyphAtlasContext()

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

Implements impeller::TypographerContext.

Definition at line 119 of file typographer_context_skia.cc.

119 {
120 return std::make_shared<GlyphAtlasContext>(type);
121}

References type.

◆ GetImageInfo()

SkImageInfo impeller::TypographerContextSkia::GetImageInfo ( const GlyphAtlas atlas,
Size  size,
bool  support_light_glyphs 
)
static

Definition at line 123 of file typographer_context_skia.cc.

125 {
126 SkISize skia_size = {static_cast<int32_t>(size.width),
127 static_cast<int32_t>(size.height)};
128
129 switch (atlas.GetType()) {
131 return support_light_glyphs
132 ? SkImageInfo::Make(skia_size, kRGBA_8888_SkColorType,
133 kPremul_SkAlphaType)
134 : SkImageInfo::MakeA8(skia_size);
136 return SkImageInfo::Make(skia_size, kRGBA_8888_SkColorType,
137 kPremul_SkAlphaType);
138 }
140}
#define FML_UNREACHABLE()
Definition logging.h:128
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size

References FML_UNREACHABLE, impeller::GlyphAtlas::GetType(), impeller::GlyphAtlas::kAlphaBitmap, and impeller::GlyphAtlas::kColorBitmap.

Referenced by impeller::BulkUpdateAtlasBitmap(), impeller::testing::TEST_P(), impeller::testing::TEST_P(), impeller::testing::TEST_P(), and impeller::UpdateAtlasBitmap().

◆ Make()


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