508 {
511 return nullptr;
512 }
513 std::shared_ptr<GlyphAtlas> last_atlas = atlas_context->GetGlyphAtlas();
515
516 if (text_frames.empty()) {
517 return last_atlas;
518 }
519
520
521
522
523
524
525 auto [new_glyphs, glyph_sizes] = CollectNewGlyphs(last_atlas, text_frames);
526 if (new_glyphs.size() == 0) {
527 return last_atlas;
528 }
529
530
531
532
533
534 std::vector<Rect> glyph_positions;
535 glyph_positions.reserve(new_glyphs.size());
536 size_t first_missing_index = 0;
537
538 if (last_atlas->GetTexture()) {
539
541 last_atlas, new_glyphs, glyph_positions, glyph_sizes,
542 atlas_context->GetAtlasSize(), atlas_context->GetHeightAdjustment(),
543 atlas_context->GetRectPacker());
544
545
546
547
548
549 for (
size_t i = 0;
i < first_missing_index;
i++) {
550 last_atlas->AddTypefaceGlyphPositionAndBounds(
551 new_glyphs[
i], glyph_positions[
i], glyph_sizes[
i]);
552 }
553
554 std::shared_ptr<CommandBuffer> cmd_buffer = context.CreateCommandBuffer();
555 std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
556
558 blit_pass->EncodeCommands();
559 if (!context.EnqueueCommandBuffer(std::move(cmd_buffer))) {
560 VALIDATION_LOG << "Failed to submit glyph atlas command buffer";
561 }
562 });
563
564
565
566
567
569 last_atlas->GetTexture(), new_glyphs, 0,
570 first_missing_index)) {
571 return nullptr;
572 }
573
574
575 if (first_missing_index == new_glyphs.size()) {
576 return last_atlas;
577 }
578 }
579
580 int64_t height_adjustment = atlas_context->GetAtlasSize().height;
581 const int64_t max_texture_height =
582 context.GetResourceAllocator()->GetMaxTextureSizeSupported().height;
583
584
585
586
587
588
589 bool blit_old_atlas = true;
590 std::shared_ptr<GlyphAtlas> new_atlas = last_atlas;
591 if (atlas_context->GetAtlasSize().height >= max_texture_height ||
593 blit_old_atlas = false;
594 new_atlas = std::make_shared<GlyphAtlas>(
595 type, last_atlas->GetAtlasGeneration() + 1);
596
597 auto [update_glyphs, update_sizes] =
598 CollectNewGlyphs(new_atlas, text_frames);
599 new_glyphs = std::move(update_glyphs);
600 glyph_sizes = std::move(update_sizes);
601
602 glyph_positions.clear();
603 glyph_positions.reserve(new_glyphs.size());
604 first_missing_index = 0;
605
606 height_adjustment = 0;
607 atlas_context->UpdateRectPacker(nullptr);
608 atlas_context->UpdateGlyphAtlas(new_atlas, {0, 0}, 0);
609 }
610
611
613 new_glyphs,
614 glyph_positions,
615 glyph_sizes,
616 first_missing_index,
617 max_texture_height
618 );
619
620 atlas_context->UpdateGlyphAtlas(new_atlas, atlas_size, height_adjustment);
621 if (atlas_size.IsEmpty()) {
622 return nullptr;
623 }
624 FML_DCHECK(new_glyphs.size() == glyph_positions.size());
625
626 TextureDescriptor descriptor;
629 descriptor.format =
630 context.GetCapabilities()->GetDefaultGlyphAtlasFormat();
631 break;
634 break;
635 }
636 descriptor.size = atlas_size;
639 std::shared_ptr<Texture> new_texture =
640 context.GetResourceAllocator()->CreateTexture(descriptor);
641 if (!new_texture) {
642 return nullptr;
643 }
644
645 new_texture->SetLabel("GlyphAtlas");
646
647 std::shared_ptr<CommandBuffer> cmd_buffer = context.CreateCommandBuffer();
648 std::shared_ptr<BlitPass> blit_pass = cmd_buffer->CreateBlitPass();
649
651 blit_pass->EncodeCommands();
652 if (!context.EnqueueCommandBuffer(std::move(cmd_buffer))) {
653 VALIDATION_LOG << "Failed to submit glyph atlas command buffer";
654 }
655 });
656
657
658 auto old_texture = new_atlas->GetTexture();
659 new_atlas->SetTexture(std::move(new_texture));
660
661
662
663
664
665 for (
size_t i = first_missing_index;
i < glyph_positions.size();
i++) {
666 new_atlas->AddTypefaceGlyphPositionAndBounds(
667 new_glyphs[
i], glyph_positions[
i], glyph_sizes[
i]);
668 }
669
670
671
672
673
675 new_atlas->GetTexture(), new_glyphs,
676 first_missing_index, new_glyphs.size())) {
677 return nullptr;
678 }
679
680
681 if (blit_old_atlas && old_texture) {
682 blit_pass->AddCopy(old_texture, new_atlas->GetTexture(),
684 {0, 0});
685 }
686
687
688
689
690
691 return new_atlas;
692}
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.
static constexpr TRect MakeSize(const TSize< U > &size)
#define TRACE_EVENT0(category_group, name)