Files
designcraft/docs/typography-parity.md
T
Abdelrehman Fouad 62faa8eee2 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.
2026-10-11 03:25:01 +02:00

7.2 KiB
Raw Blame History

Typography and composition parity

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 document tracks both: does the attribute exist, and does it compose like InDesign? Script-specific detail lives in cjk-typography.md, cjk.md and arabic-typography.md. Overall numbers: target-app-parity.md.

Dimension score: ~45% ready (estimated), 120–200 h to parity. Presence is high (76% scored below, nothing absent); fidelity 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 (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): a set of synthetic stories (our own text and fonts: Source Serif 4, Inter, Shippori Mincho from craft-fonts) covering each row below, set in InDesign 2026 by observation on the owner's Mac (results under plan/, never committed), exported as IDML; DesignCraft opens the IDML and a test compares per paragraph: line count, break positions (by character offset), last-line width, overset and frame fit. Report the share of paragraphs whose breaks match exactly. Target for beta: ≥ 90% of Latin body paragraphs identical, 100% fit in the same frames.

Checklist

Status: ✓ present and believed close · ~ present, known differences or partial · ✗ missing. Fidelity: unmeasured unless stated.

Area InDesign 2026 DesignCraft Status Notes / evidence
Paragraph Composer Adobe's multi-line composer Knuth–Plass total fit, fitness classes, hyphen penalties ~ same family of algorithm, Adobe's weights unknown; breaks will differ on some paragraphs
Single-line Composer greedy greedy with the same ranges ✓
World-Ready composers Paragraph / Single-line World-Ready RTL, Arabic and bidi in the main composer ~ Indic scripts (Devanagari etc.) shape through harfrust but are untested
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, 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 ✓
Leading auto (120%), absolute, leading model ✓ ✓ CJK leading models in cjk-typography.md
First baseline ascent, cap height, x-height, leading, fixed, min ✓ ✓
Frame fit / overset baseline of the last line must fit descenders must fit ~ differs (#180): frames go overset where InDesign fits
Baseline grid document and frame grids ✓ ✓
Vertical justification top, centre, bottom, justify, paragraph spacing limit ✓ ✓
Columns, span / split columns ✓ ✓ ✓ split columns within a column (#295); text after a span flows below it (#276)
Column rules ✓ ✓ (screen, PDF, IDML) ~ no stroke types or overprint (#274)
Keep options and breaks keep with next, lines together, start in next column/frame/page/odd/even ✓ ✓ break characters end paragraphs (#285); the line before a break is a last line (#283)
Drop caps, nested, line and GREP styles ✓ ✓ ✓
Bullets and numbering lists, levels, formats, restart, across stories ✓ ~ numbering expressions from IDML (#298); Convert Bullets/Numbering to Text missing
Tabs left/center/right/decimal/align-on, leaders, right-indent tab ✓ ~ Tabs panel missing (#326); wrapping of lines with tabs fixed (#282)
Paragraph rules, borders, shading ✓ ✓ ✓
Balance ragged lines ✓ ✓ ✓
Optical margin alignment ✓ ✓ (hang table of our own) ~ hang amounts are ours, InDesign's unknown
Text wrap bounding box, shape, jump object/column, contour options ✓ ✓
Anchored objects inline, above line, custom ✓ ~ anchored objects in table cells not drawn (#163)
Footnotes, endnotes ✓ ✓ ~ footnotes don't split across columns yet
Type on a path ✓ ✓ ✓
Vertical text (CJK) ✓ ✓ ~ see cjk.md
CJK composition mojikumi, kinsoku, aki, tsume, ruby, kenten, warichu, frame grid most; mojikumi tables kept but not applied; ruby group-only; no frame grid ~ cjk.md, cjk-typography.md
Arabic / Hebrew kashida, digits, diacritic positioning, RTL stories and tables ✓ ~ vendor justification presets unsupported; list bullets and multi-column RTL (#100)
Missing glyphs and fonts pink highlight, substitution ✓ ✓
Installed fonts every activated font system font folders; user folders, font managers and Adobe Fonts not always found ~ #161, #110, #107, #327, #261
Composition highlights H&J, keeps, custom tracking/kerning, substituted fonts ✓ ✓

Measured from the table above (2026-10-10): 34 rows, 18 ✓, 16 ~, 0 ✗, scoring ✓ = 1 and ~ = 0.5: 76%. Every row exists in some form; the ~ rows are where InDesign users will see a difference.

Remaining effort

Work Opus 5.5 h
Oracle harness (synthetic stories, IDML exchange, comparison metric) 20–30
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
Spelling dictionaries beyond English (licence review per language) 10–20 (+ owner review)
Tabs panel, list conversion commands 8–15
Total 120–200

Revision history

Date Change Summary
2026-10-10 major Created: typography checklist (34 rows), fidelity gap and oracle plan