Text: Optical kerning spaces pairs from their outlines

Optical kerning was treated exactly like Metrics: the font's kern pairs
and nothing else, so text set with Optical in InDesign came out wider,
rewrapped and went overset in tightly fitted frames.

Now the font's pairs are turned off for Optical text and each pair is
spaced from its outlines (crates/compose/src/optical.rs): every glyph's
ink is sampled into 28 bands across the em, the pair's mean and smallest
ink gap over the bands both glyphs ink are compared with the font's
stem-to-stem gap (the pair nn, or HH then oo), and the pair moves 60% of
the way towards it, keeping 30% of that gap and moving at most -0.12 or
+0.06 em. Latin, Greek and Cyrillic letters, digits and Western
punctuation take part; spaces, marks, missing glyphs, right-to-left
runs, upright and tate-chu-yoko glyphs and pairs across a fallback font
keep their font spacing. Profiles and references are cached, bounded.

Tests: AV, To and r. close up and nn stays; HH closes up under Optical
but not Metrics (fails on main); every change on a pangram stays within
the bounds and spaces keep their width; profile, gap, adjustment and
character-class unit tests.

Docs: typography parity Kerning row and remaining effort, gap 4,
ROADMAP milestone 6 and progress log.

Fixes #181.
This commit is contained in:
Abdelrehman Fouad
2026-10-11 03:25:01 +02:00
parent a9124a0517
commit 62faa8eee2
9 changed files with 330 additions and 11 deletions
+4 -4
View File
@@ -1,6 +1,6 @@
# Where DesignCraft falls short of InDesign
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-10 · **Change:** minor (stage re-normalized to pre-alpha by the core-workflow gate; earlier today: major, first version: gaps from the full re-measure and the issue tracker) · **Target:** Adobe InDesign 2026 (21.6)
> **Last reviewed:** 2026-10-11 · **Last updated:** 2026-10-11 · **Change:** minor (Optical kerning from outlines (#181); 2026-10-10: stage re-normalized to pre-alpha by the core-workflow gate; earlier today: major, first version: gaps from the full re-measure and the issue tracker) · **Target:** Adobe InDesign 2026 (21.6)
Every known shortfall against InDesign 2026, one entry each, ranked by how much it stops an
InDesign professional from doing real work. This is the work list: agents pick from the top.
@@ -69,13 +69,13 @@ Kind: **F** feature · **U** UI/UX · **T** typography · **FF** file format ·
### 4. Composition isn't compared with InDesign (T)
- **Missing:** an oracle harness: the same synthetic stories set by InDesign 2026 (observed
black-box, results kept under `plan/`) and by DesignCraft, comparing line breaks, overset and
frame fit. Known differences: optical kerning falls back to metrics, so imported text sets
wider (#181); a frame goes overset when descenders don't fit, InDesign needs only the baseline
frame fit. Known differences: optical kerning is an outline-based approximation, not Adobe's
algorithm (#181); a frame goes overset when descenders don't fit, InDesign needs only the baseline
(#180); setting the text language was missing (#130; Language is now in Properties, #145, the issue is still open); "hyphenation doesn't work"
(#87).
- **Impact:** an opened IDML reflows: different line breaks, different page count, overset text.
Professionals notice on the first page.
- **Estimate:** 80–140 h (harness 20–30, optical kerning 15–25, then fixes by cluster).
- **Estimate:** 70–125 h (harness 20–30, optical kerning tuning 5–10, then fixes by cluster).
- **Doc:** [typography-parity.md](typography-parity.md)
### 5. Startup crashes on some graphics hardware (S, H)
+4 -4
View File
@@ -1,6 +1,6 @@
# Typography and composition parity
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-10 · **Change:** major (first version, from the full re-measure) · **Target:** Adobe InDesign 2026 (21.6)
> **Last reviewed:** 2026-10-11 · **Last updated:** 2026-10-11 · **Change:** minor (Optical kerning from outlines (#181); 2026-10-10: major, first version, from the full re-measure) · **Target:** Adobe InDesign 2026 (21.6)
Typesetting is what InDesign is bought for. A feature can exist and still set text differently
from InDesign: different line breaks, different page count, overset where InDesign fits. This
@@ -14,7 +14,7 @@ against InDesign is **unmeasured**, which is the main gap.
## Fidelity: how we'd know
There is no oracle yet. What exists: unit tests of break points and invariants in
`crates/compose/src/tests.rs` (165 tests in the crate), IDML files built by DesignCraft and opened
`crates/compose/src/tests.rs` (170 tests in the crate), IDML files built by DesignCraft and opened
in InDesign 2026 by hand, and user reports comparing the two (#179, #180, #181, #282–#295).
**Needed (gap 4 in [gaps.md](gaps.md)):** a set of synthetic stories (our own text and fonts:
@@ -38,7 +38,7 @@ Fidelity: **unmeasured** unless stated.
| Justification | word/letter spacing, glyph scaling min/desired/max, single-word, last line | all of these | ✓ | a justified line with a tab now justifies after the tab (#284) |
| Hyphenation | per-language dictionaries (~40), zone, limits, capitalized, last word, across columns | Liang patterns: English (trained from the public-domain Moby list) and Spanish (Bezos); zone, limits, exceptions in the user dictionary | ~ | other languages don't hyphenate (#87 reported "doesn't work") |
| Spelling | per-language dictionaries | English (Moby) + document/user dictionary | ~ | |
| Kerning | Metrics, Optical, manual, none | Metrics, manual, none | ~ | **Optical treated as Metrics** (#181): imported display text sets wider and can overset |
| Kerning | Metrics, Optical, manual, none | Metrics, Optical (outline-based: pairs pulled towards the font's stem gap, `crates/compose/src/optical.rs`), manual, none | ~ | Optical is an approximation of Adobe's algorithm (#181), not a match: imported display text can still break differently |
| Tracking, scale, skew, baseline shift | ✓ | ✓ | ✓ | |
| OpenType features | ligatures, discretionary, swash, fractions, ordinals, figures, small caps, stylistic sets, positional forms | through harfrust | ✓ | |
| Variable fonts | axes in Character panel | named instances and free axis values; PDF embeds the instance | ✓ | |
@@ -75,7 +75,7 @@ Measured from the table above (2026-10-10): 34 rows, 18 ✓, 16 ~, 0 ✗, scorin
| Work | Opus 5.5 h |
|---|---|
| Oracle harness (synthetic stories, IDML exchange, comparison metric) | 20–30 |
| Optical kerning approximation (outline-based side-bearing model) + preflight warning | 15–25 |
| Optical kerning tuning against InDesign (measured pairs per class, once the oracle harness exists) | 5–10 |
| Overset rule (baseline fits) and frame-fit parity | 5–10 |
| Fixing composer differences the harness finds (weights, penalties, glyph-scaling order) | 40–70 |
| Hyphenation patterns for the top 15 InDesign languages (permissive sources) | 20–35 |