From 77a6501cede6bd71a9434d87cd2fcd0fe06d2116 Mon Sep 17 00:00:00 2001 From: catbot Date: Tue, 16 Jun 2026 15:43:58 +0000 Subject: [PATCH] perf(text): fold Ensure+Lookup into FontAtlas::EnsureAndGet (#53) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per glyph, ShapeText did cache_.contains(key) (in Ensure) then cache_.find(key) (in Lookup) — two independent hashes + node-chases of the same key. Add EnsureAndGet returning const Glyph* with a single find, insert-on-miss, returning &it->second. It returns nullptr only on ShelfPlace failure, preserving the existing `if (g==nullptr) continue;` behavior. Ensure now delegates to it. Co-Authored-By: Claude Opus 4.8 --- implementations/Crafter.Graphics-FontAtlas.cpp | 11 +++++++---- implementations/Crafter.Graphics-UI-Shared.cpp | 3 +-- interfaces/Crafter.Graphics-FontAtlas.cppm | 5 +++++ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/implementations/Crafter.Graphics-FontAtlas.cpp b/implementations/Crafter.Graphics-FontAtlas.cpp index 44179c0..362161d 100644 --- a/implementations/Crafter.Graphics-FontAtlas.cpp +++ b/implementations/Crafter.Graphics-FontAtlas.cpp @@ -70,8 +70,12 @@ bool FontAtlas::ShelfPlace(int w, int h, int& outX, int& outY) { } bool FontAtlas::Ensure(Font& font, std::uint32_t codepoint) { + return EnsureAndGet(font, codepoint) != nullptr; +} + +const Glyph* FontAtlas::EnsureAndGet(Font& font, std::uint32_t codepoint) { Key key{&font, codepoint}; - if (cache_.contains(key)) return true; + if (auto it = cache_.find(key); it != cache_.end()) return &it->second; float fontScale = stbtt_ScaleForPixelHeight(&font.font, kBaseSize); @@ -94,7 +98,7 @@ bool FontAtlas::Ensure(Font& font, std::uint32_t codepoint) { int px = 0, py = 0; if (!ShelfPlace(sw, sh, px, py)) { stbtt_FreeSDF(sdf, nullptr); - return false; + return nullptr; } std::uint8_t* dst = PixelPtr(); for (int row = 0; row < sh; ++row) { @@ -115,8 +119,7 @@ bool FontAtlas::Ensure(Font& font, std::uint32_t codepoint) { dirty = true; } - cache_.emplace(key, g); - return true; + return &cache_.emplace(key, g).first->second; } const Glyph* FontAtlas::Lookup(Font& font, std::uint32_t codepoint) const { diff --git a/implementations/Crafter.Graphics-UI-Shared.cpp b/implementations/Crafter.Graphics-UI-Shared.cpp index 9e75653..6ac2c62 100644 --- a/implementations/Crafter.Graphics-UI-Shared.cpp +++ b/implementations/Crafter.Graphics-UI-Shared.cpp @@ -75,8 +75,7 @@ std::uint32_t UIRenderer::ShapeText(Font& font, float pxSize, if (cp == 0) break; if (cp == '\n') { continue; } - fontAtlas->Ensure(font, cp); - const Glyph* g = fontAtlas->Lookup(font, cp); + const Glyph* g = fontAtlas->EnsureAndGet(font, cp); if (g == nullptr) continue; if (g->w > 0 && g->h > 0) { diff --git a/interfaces/Crafter.Graphics-FontAtlas.cppm b/interfaces/Crafter.Graphics-FontAtlas.cppm index f80e9c6..5e7bd9c 100644 --- a/interfaces/Crafter.Graphics-FontAtlas.cppm +++ b/interfaces/Crafter.Graphics-FontAtlas.cppm @@ -66,6 +66,11 @@ export namespace Crafter { std::uint8_t* PixelPtr() noexcept; bool Ensure(Font& font, std::uint32_t codepoint); + // Ensure the glyph is in the atlas and return a pointer to it in one + // hash+probe. Returns nullptr only when a brand-new glyph cannot be + // placed (ShelfPlace failure); a glyph with no SDF coverage (e.g. + // space) still returns a valid pointer. + const Glyph* EnsureAndGet(Font& font, std::uint32_t codepoint); const Glyph* Lookup(Font& font, std::uint32_t codepoint) const; void Update(GraphicsCommandBuffer cmd);