553 {
556 return nullptr;
557 }
558 std::shared_ptr<GlyphAtlas> last_atlas = atlas_context->GetGlyphAtlas();
560
561 if (renderable_texts.empty()) {
562 return last_atlas;
563 }
564
565
566
567
568
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
578
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
587 last_atlas, new_glyphs, glyph_positions, glyph_sizes,
588 atlas_context->GetAtlasSize(), atlas_context->GetHeightAdjustment(),
589 atlas_context->GetRectPacker());
590
591
592
593
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
612
613
615 last_atlas->GetTexture(), new_glyphs, 0,
616 first_missing_index)) {
617 return nullptr;
618 }
619
620
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
631
632
633
634
635 bool blit_old_atlas = true;
636 std::shared_ptr<GlyphAtlas> new_atlas = last_atlas;
637 if (atlas_context->GetAtlasSize().height >= max_texture_height ||
639 blit_old_atlas = false;
640 new_atlas = std::make_shared<GlyphAtlas>(
641 type, 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
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;
675 descriptor.format =
676 context.GetCapabilities()->GetDefaultGlyphAtlasFormat();
677 break;
680 break;
681 }
682 descriptor.size = atlas_size;
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
704 auto old_texture = new_atlas->GetTexture();
705 new_atlas->SetTexture(std::move(new_texture));
706
707
708
709
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
718
719
721 new_atlas->GetTexture(), new_glyphs,
722 first_missing_index, new_glyphs.size())) {
723 return nullptr;
724 }
725
726
727 if (blit_old_atlas && old_texture) {
728 blit_pass->AddCopy(old_texture, new_atlas->GetTexture(),
730 {0, 0});
731 }
732
733
734
735
736
737 return new_atlas;
738}
Wraps a closure that is invoked in the destructor unless released by the caller.
virtual bool IsValid() const
#define FML_DCHECK(condition)
std::function< void()> closure
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.
impeller::ShaderType type
static constexpr TRect MakeSize(const TSize< U > &size)
#define TRACE_EVENT0(category_group, name)