Skip to content

fix(text): give the text engine glyph fallback, real units, and the fonts asked for - #153

Merged
LeadcodeDev merged 1 commit into
chantier/audit-remediationfrom
fix/text-fallback-measure-fonts
Aug 8, 2026
Merged

fix(text): give the text engine glyph fallback, real units, and the fonts asked for#153
LeadcodeDev merged 1 commit into
chantier/audit-remediationfrom
fix/text-fallback-measure-fonts

Conversation

@LeadcodeDev

Copy link
Copy Markdown
Owner

Round 3 du chantier d'audit — lot texte & polices, 10 constats vérifiés.

Deux familles de défaut, avec des conséquences très différentes :

A. Du texte qui n'est jamais lisible.

Constat Sévérité Symptôme
Fallback de glyphe absent High Tout texte non-latin (CJK, arabe, devanagari) rendu en tofu. Le moteur choisissait une fonte et dessinait ce qu'elle produisait, .notdef compris.
line-height en % / em High Résolu à 0 à la mesure → taffy réserve une boîte de hauteur nulle → le texte n'est jamais peint.
font-weight / font-style High Totalement ignorés dès qu'une police custom ou Google est déclarée : gras et italique redeviennent silencieusement du regular.
codeblock auto-scroll High L'offset venait de la hauteur totale du code au lieu des lignes révélées : le bloc reste vide pendant la majorité du reveal.
codeblock / terminal Medium N'utilisaient jamais les polices custom/Google du scénario.
is_emoji Medium Classait ©, et comme emoji : couleur du style perdue ou tofu — y compris dans un exemple livré.

B. Mesure et peinture qui divergent — donc validate devient aveugle.

C'est le point le plus grave pour la fiabilité de génération : la passe geometry inspecte la mesure. Quand la peinture fait autre chose, le débordement existe à l'écran et le validateur déclare le scénario propre.

Constat Sévérité Divergence
caption largeur Critical Ignore la largeur donnée par le layout, peint une ligne large qui sort du device.
letter-spacing relatif High Résolu à la peinture, ignoré à la mesure.
caption line-height Medium font_size * 1.4 en dur à la peinture, line_height_for à la boîte.
Terminal typeface Terminal et TerminalIntrinsic résolvaient leur fonte par deux chemins distincts pouvant diverger.

Terminal et TerminalIntrinsic partagent désormais un unique resolve_typeface : la boîte mesurée et les glyphes dessinés ne peuvent plus diverger, et font-family est enfin honoré.

Correction documentaire

CLAUDE.md et rules/module-structure.md désignaient engine::text::cosmic comme le moteur de texte. Ce module n'a aucun appelant sur le chemin de rendu — le vrai chemin est engine::renderer::text + rustmotion-components::intrinsic. Le module reste compilé (candidat pour un futur moteur de shaping réel), mais son doc-comment dit maintenant clairement qu'il est dormant. Sans ça, la prochaine session peut passer son temps à éditer du code mort en croyant modifier le rendu.

Vérification

cargo test -p rustmotion-core -p rustmotion-components sur cette branche seule : 116 + 6 + 3 + 5 + 211 + 3 tests, 0 échec.

…onts asked for

Ten confirmed audit findings on text measure/paint. Three of them make text
that is simply never legible; four more make the geometry validator blind to
overflow it is supposed to catch, because measure and paint disagree.

- No missing-glyph fallback: any non-Latin text (CJK, Arabic, Devanagari)
  rendered as tofu boxes. The engine picked one typeface and drew whatever
  it produced, including .notdef.
- `line-height` in `%` or `em` resolved to 0 at measure time, so taffy
  reserved a zero-height box and the text was never painted at all.
- `letter-spacing` in relative units was resolved at paint but ignored at
  measure — the box was too small, the glyphs overflowed it, and because
  the *measure* was what the geometry pass inspected, `validate` reported
  the scenario clean.
- `caption` ignored the width the layout gave it and painted one wide line
  past the device edge, again invisible to `validate`. Its `line-height`
  was also hardcoded to `font_size * 1.4` at paint while the box was
  measured with `line_height_for`.
- `font-weight` and `font-style` were dropped entirely as soon as a custom
  or Google font was declared — bold and italic silently became regular.
- `codeblock` and `terminal` never used the scenario's custom/Google
  fonts. `Terminal` and `TerminalIntrinsic` also resolved their typeface
  through two separate code paths that could disagree; they now share one
  `resolve_typeface`, so the box measured and the glyphs drawn cannot
  diverge.
- `codeblock` auto-scroll derived its offset from the full code height
  instead of the revealed lines, leaving the block empty for most of the
  reveal.
- `is_emoji` classified ©, ™ and ✓ as emoji, so the style's colour was
  dropped (or a tofu drawn) — including in a shipped example.

Also corrects two entry documents that named `engine::text::cosmic` as the
text engine. It has no callers on the render path; the real path is
`engine::renderer::text` + `rustmotion-components::intrinsic`. The module
keeps building, now with a doc comment saying plainly that it is dormant, so
the next reader does not spend a session editing dead code.

Tests: 116 + 6 + 3 + 5 + 211 + 3 pass on this branch alone.
@LeadcodeDev LeadcodeDev added bug Something isn't working documentation Improvements or additions to documentation labels Aug 8, 2026
@LeadcodeDev LeadcodeDev self-assigned this Aug 8, 2026
@LeadcodeDev
LeadcodeDev merged commit c056b41 into chantier/audit-remediation Aug 8, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant