fix(text): re-lay-out cached glyph quads after the SDF atlas grows

Glyph quads bake the atlas UV of their tile. `grow_height` rescales every
cached entry's V and bumps the atlas generation, and the tessellation memo
folds that generation in — but the caches that hold finished wires do not:
the resident wire set is keyed by geometry epoch, block definitions by
block epoch, and a full build can grow the atlas part-way through (a CJK
sheet set bakes thousands of tiles on first sight). Text tessellated before
the growth then samples the wrong tiles for as long as those caches live,
which on a big drawing is forever: whole tables of scrambled glyphs, and
the block contents stayed scrambled even after a REGEN.

- `resident_wires_for` rebuilds (dropping the block definition cache) until
  the atlas generation is stable across the pass.
- `Scene::update` compares the live generation with the one the scene's
  caches were built against and bumps geometry once when it moved, so a
  later growth (opening a layout, editing text) re-lays-out everything.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Chris YehandClaude Opus 5 committed 2026-09-21 21:01:05 +08:00
1 parent ff4981ffe6
commit 24f8e124d5
2 files changed
+47 -1

No files matched your search

+12 -1
View File
@@ -1566,5 +1566,16 @@ impl Scene {
self.camera_generation += 1;
}
pub fn update(&mut self, _dt: Duration) {}
pub fn update(&mut self, _dt: Duration) {
// The glyph atlas grew or re-baked since this scene last built its
// caches (a CJK sheet set bakes thousands of tiles on first sight):
// every quad laid out before that samples the wrong tile — scrambled
// text in the affected blocks / viewports. One structural bump
// re-lays-out all text against the settled atlas.
let atlas_gen = crate::scene::text::sdf_atlas::generation();
if self.last_atlas_generation.get() != atlas_gen {
self.last_atlas_generation.set(atlas_gen);
self.bump_geometry();
}
}
}