diff --git a/ROADMAP.md b/ROADMAP.md index 63a0c195f..ac8472d57 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -2,9 +2,20 @@ - FID1: PDF export normalizes mixed emitted gradient color spaces to RGB with an explicit warning; homogeneous device-space gradients retain their components. Linear/radial, midpoint, archival and print policies have synthetic regression coverage. +- FONT7: replacement recommendations check the characters actually used; placeholder LastResort fonts and glyph-zero mappings cannot masquerade as glyph coverage or suppress missing-glyph diagnostics. + +- FONT6: localized and legacy family/style names share canonical resolution across shaping, inventory and replacement. Known compatible and script-based substitutes retain missing status; Find Font shows the resolved face and offers it as the replacement, while preflight reports unavailable styles. + +- FONT5: missing-glyph preflight inspects rendered characters in generated labels, including zero-length continuation glyphs, and identifies the owning page frame for nested text. + +- FONT4: generated note labels resolve composite character mappings and glyph fallback while retaining a single source anchor; composed glyphs retain the actual rendered character for diagnostics. + - AR1.1: Kashida justification tests verify space fallback without Tatweel fonts using an isolated font database, while retaining elongation assertions when fonts support it. - AR1: Arabic IDML controls now retain character direction, kashida switches, diacritic offsets/forms, paragraph policy values and independent story/table directions. Shaping preserves joining context and script/language selection; paragraph-level bidi, contextual digit conversion, mark-safe elongation, RTL columns/tables and physical column insertion have regression coverage. Vendor-specific justification and diacritic presets remain explicit preflight warnings; see docs/arabic-typography.md. +- FONT3: opening documents with unavailable font families or styles automatically offers Find/Replace Font. The dialog supports repeated replacements, refreshed inventory and visible validation errors; native builds without craft-fonts use system CJK fonts for readable names. +- FONT2: font replacements validate available targets and resolve inherited formatting in nested text and empty paragraphs, with undo and composite component preservation. +- FONT1: composite-font references resolve by resource identity, retain literal display names, and export as object references. Font inventory and preflight share the character-selected component fonts, including nested notes and cells. - CJK1: IDML composite fonts now retain character mappings and metrics; explicit aki, tsume, jidori, em alignment/leading, named/custom kinsoku boundaries, hanging punctuation, tate-chu-yoko offsets and kenten symbols flow through composition and IDML export. Automatic kerning no longer imports inactive numeric values as enormous manual spacing. Composite definitions are editable through commands with undo/cache invalidation. Mojikumi definitions are retained and unsupported spacing-table / push-in-push-out policies are reported by preflight. Full InDesign CJK composition parity, frame-grid layout and detailed ruby/warichu remain unfinished. DesignCraft aims at full Adobe InDesign parity — and to be better: faster, open (documented JSON format + IDML), scriptable by agents (MCP), and available on the web. diff --git a/crates/compose/src/lib.rs b/crates/compose/src/lib.rs index 31a662ad3..861272cfc 100644 --- a/crates/compose/src/lib.rs +++ b/crates/compose/src/lib.rs @@ -102,6 +102,8 @@ impl RunStyle { /// A positioned glyph. `x` is absolute in frame inner space; `y` is relative to the line baseline. #[derive(Clone, Debug)] pub struct PlacedGlyph { + /// Actual character drawn, including generated labels. + pub rendered_char: char, pub face: designcraft_fonts::FaceRef, pub gid: u32, pub x: f64, @@ -2132,6 +2134,7 @@ fn tab_leader(tab: &Glyph, leader: &str, x: f64, w: f64, origin: f64, out: &mut while at + pw <= end + 0.01 && n < 2000 { for &(gid, adv) in &glyphs { out.push(PlacedGlyph { + rendered_char: '\t', face: tab.face, gid, x: at, @@ -2235,6 +2238,7 @@ fn place(g: &Glyph, x: f64) -> PlacedGlyph { || g.ch == shape::SOFT_HYPHEN || g.ch == shape::HIDDEN); PlacedGlyph { + rendered_char: g.rendered_char, face: g.face, gid: g.gid, x: x + g.dx, diff --git a/crates/compose/src/ruby.rs b/crates/compose/src/ruby.rs index cea4a5545..b39f11eef 100644 --- a/crates/compose/src/ruby.rs +++ b/crates/compose/src/ruby.rs @@ -22,6 +22,7 @@ fn set(base: &PlacedGlyph, text: &str, size: f64, base_size: f64) -> (Vec