Files
ARCADIA-Studio/harness/scenario-label-font-lifetime-20260913.md
T

6.0 KiB
Raw Blame History

Scenario label font lifetime: bounded source investigation

Source-only review, 2026-09-13. Application pin: c4a2cf63f11818cf7fc766acf3a2779768a2a658, branch codex/scenario-spacing-ytr83r-20260913; working tree observed clean. No compilation, tests, renderer execution, or production edits. Repository references below resolve at that commit. Dependency references identify the exact published Cargo package and its relative source path, reproducible from the commit's Cargo.lock checksums without another machine's local directories. The lockfile pins iced_widget 0.14.2, but iced, iced_core, iced_graphics, iced_wgpu, iced_winit and iced_program 0.14.0, cosmic-text 0.15.0 and fontdb 0.23.0; describing all of these as Iced 0.14.2 would be imprecise. Package archives are available from crates.io, e.g. iced_graphics 0.14.0, cosmic-text 0.15.0, and fontdb 0.23.0.

Verified startup sequence

  1. Repository crates/oa-desktop/src/main.rs:38–61 passes App::new to iced::application, then configures title/theme/subscription/window and runs. It supplies neither .font(...) nor custom font settings. iced-0.14.0/src/application.rs:163 uses default settings; iced_core-0.14.0/src/settings.rs:45–54 initializes fonts to an empty vector.
  2. iced_winit-0.14.0/src/lib.rs:105 constructs program::Instance before window/compositor setup. iced_program-0.14.0/src/lib.rs:673–676 calls the boot function there. Repository crates/oa-desktop/src/app.rs:556–566,642 constructs text_editor::Content::with_text during App::new -> with_project. iced_widget-0.14.2/src/text_editor.rs:400–407 delegates to the renderer Editor; WGPU uses graphics Editor (iced_wgpu-0.14.0/src/lib.rs:70,720). iced_graphics-0.14.0/src/text/editor.rs:89–110 synchronously acquires the shared font system and sets/shapes the source text.
  3. iced_graphics-0.14.0/src/text.rs:115–133 initializes that shared system through OnceLock, using Cosmic's font database, embedded Iced Icons, and feature-conditional Fira Sans. It records Version::default() after construction. Cosmic src/font/system.rs:144–163,396–403 synchronously creates the database, scans system fonts, then loads supplied embedded fonts. Thus the database and its initial version exist before App::new returns, not necessarily before entry to App::new. They exist before the first normal App view or draw.
  4. iced_winit-0.14.0/src/lib.rs:590–603 creates the compositor and loads settings fonts (empty in this application). src/window.rs:51–68 then creates the renderer. Only afterward does lib.rs:683–692,1279–1290 build the first UI and call program.view. WGPU src/lib.rs:99–117 starts new text state; src/text.rs:305–318 gives it an initially empty buffer cache/storage.

What lazy fallback does, and what Version covers

Cosmic src/font/system.rs:255–274 lazily obtains fonts for already indexed face IDs, populates its font cache, and calls fontdb::Database::make_shared_face_data. This can map a font file and replace its existing source with shared data (fontdb-0.23.0/src/lib.rs:742–775). It does not call Iced's font-loading wrapper or increment Iced's Version. “Settled fonts” can therefore mean a fixed indexed font set; it must not mean all fallback glyphs/files are eagerly loaded.

Iced's FontSystem::load_font is the tracked mutation boundary (iced_graphics/src/text.rs:152–170). It changes the database and increments Version, apart from its duplicate borrowed-pointer early return. Runtime Action::LoadFont reaches this through iced_winit/src/lib.rs:1776–1782 and iced_graphics/src/compositor.rs:69–73. A production-source search found no application call to font::load, load_font, db_mut, or any other direct global font mutation; the only explicit loading is in the unwired scenario-label experiment tests. Existing font choices such as MONOSPACE select a font; they do not load another font set. Opening documents, rebuilding the source editor, changing zoom, and normal fallback shaping therefore do not themselves advance Version.

Version is not a universal font-content fingerprint. The exposed FontSystem::raw() would permit a future caller to mutate Cosmic's database without that increment. Fontdb scans predefined Windows system/user font directories once (src/lib.rs:390–422); this is not a live OS font watcher. Its mapped-file safety contract explicitly allows externally changed file bytes to become visible (src/lib.rs:728–739). Stable installed font files during the run remain an assumption, not a guarantee supplied by Version.

Smallest truthful production boundary

For this fixed-font normal desktop startup, capture and retain one render session on the first measured-label use reached through the normal App::view path, after initial renderer creation. Initial creation satisfies the fresh-renderer requirement; no extra reset, fallback warm-up, or asynchronous font-loading wait is justified by current production source. Capturing the existing after_fonts_settled_and_renderer_reset attestation inside App::new would be too early because the renderer has not been created yet. A headless/direct-view evaluator must establish its own renderer/session ordering rather than inherit the desktop proof.

The session can remain valid across ordinary Scene/document rebuilds while the font set stays fixed. Keep the existing zoom/session/version consumer guards. If later work adds runtime font loading, invalidate label artifacts and establish a genuinely fresh renderer/text-cache lifecycle before taking a replacement session; simply recapturing the version is insufficient. WGPU src/text.rs:455–504 uses graphics Cache, whose key (iced_graphics/src/text/cache.rs:104–130) omits font-system Version and whose existing entries are reused (:30–43). This report does not establish dynamic-font support, raster ink bounds, placement policy, or native measured-label parity.