[perf][MEDIUM] Per-frame text re-shaping for static strings #52

Closed
opened 2026-06-16 16:51:31 +02:00 by jorijnvdgraaf · 0 comments

Subsystem: Font / text shaping
Location: implementations/Crafter.Graphics-UI-Shared.cpp:46-86
Impact: MEDIUM · Effort: Medium

Problem

ShapeText re-decodes UTF-8, re-looks-up every glyph, and recomputes layout every frame for static strings (called from DrawText/EmitCenteredLabel inside per-frame onBuild). EmitCenteredLabel and DrawText also do a second full pass over the glyphs to apply centering.

Proposed fix

Shaped-run cache keyed by (Font*, pxSize, hash(utf8), color) -> vector<GlyphItem> stored origin-relative; on a hit, translate by (x, baselineY) and memcpy into the buffer (GlyphItem is a 48-byte POD). Fold the centering shift into ShapeText to drop the second loop.

Correctness caveat

Pure CPU memoization — the buffer is fully rewritten + re-flushed every frame regardless, so caching is byte-equivalent. On a cache miss the builder must still call Ensure so new glyphs rasterize/dirty the atlas. Invalidate on Font destruction.

**Subsystem:** Font / text shaping **Location:** `implementations/Crafter.Graphics-UI-Shared.cpp:46-86` **Impact:** MEDIUM · **Effort:** Medium ### Problem `ShapeText` re-decodes UTF-8, re-looks-up every glyph, and recomputes layout every frame for static strings (called from `DrawText`/`EmitCenteredLabel` inside per-frame `onBuild`). `EmitCenteredLabel` and `DrawText` also do a second full pass over the glyphs to apply centering. ### Proposed fix Shaped-run cache keyed by `(Font*, pxSize, hash(utf8), color)` -> `vector<GlyphItem>` stored **origin-relative**; on a hit, translate by `(x, baselineY)` and `memcpy` into the buffer (GlyphItem is a 48-byte POD). Fold the centering shift into `ShapeText` to drop the second loop. ### Correctness caveat Pure CPU memoization — the buffer is fully rewritten + re-flushed every frame regardless, so caching is byte-equivalent. On a cache **miss** the builder must still call `Ensure` so new glyphs rasterize/dirty the atlas. Invalidate on Font destruction.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Catcrafts/Crafter.Graphics#52
No description provided.