diff --git a/ROADMAP.md b/ROADMAP.md index 91a9516..5c994e2 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -138,6 +138,7 @@ Newest first. - **2026-10-12** · Window close and application/menu Quit ask about unsaved documents; later Cancel keeps every tab open, including earlier Don't Save choices. Approvals are rechecked after edits. Cancelable macOS Dock Quit remains open (#544). No readiness percentage change. - **2026-10-12** · Each running app keeps recovery data in its own locked folder; current folder and lock ownership are checked before writes and cleanup. Failed isolation disables recovery with a warning instead of sharing document IDs. No readiness percentage change. - **2026-10-12** · Native engine saves and exports replace files atomically; failed writes retain the original, private staging preserves Unix permissions, and valid long filenames work. Desktop Services and CLI raster exports remain separate follow-ups. No readiness percentage change. +- **2026-10-12** · Hyphenation Zone applies to the Single-line Composer only, as in InDesign. With the default Paragraph Composer, ragged text hyphenates where InDesign does (aper-natem), giving the same line breaks. No readiness percentage change. - **2026-10-12** · Words in capitals hyphenate like capitalized words (FERRUM COM-MODI), as in InDesign; Hyphenate Capitalized Words off keeps them whole. No readiness percentage change. - **2026-10-11** · `transform.move {copy}`, Edit › Duplicate and Step and Repeat return the copies' ids, so a script can go on with them. No readiness percentage change. - **2026-10-11** · `object.fill` and `object.stroke` refuse a swatch name the document doesn't have (it painted nothing) and suggest the name meant (`Paper` → `[Paper]`). No readiness percentage change. diff --git a/crates/compose/src/lib.rs b/crates/compose/src/lib.rs index ee12315..e84f0cb 100644 --- a/crates/compose/src/lib.rs +++ b/crates/compose/src/lib.rs @@ -1477,7 +1477,9 @@ fn spacing_for(pp: &ParaProps, base_size: f64) -> Spacing { hyphen_penalty: 50.0 + 450.0 * pp.hyph_weight, hyphen_limit: pp.hyph_limit, ragged_stretch: base_size * 2.0, - hyph_zone: if pp.align.is_justified() { 0.0 } else { pp.hyph_zone }, + // The zone is the Single-line Composer's (unjustified text only), as in InDesign: the + // Paragraph Composer weighs every break of the paragraph instead. + hyph_zone: if pp.align.is_justified() || pp.composer != Composer::SingleLine { 0.0 } else { pp.hyph_zone }, optical: pp.optical_margin, korean_char_breaks: pp.korean_char_breaks, } diff --git a/crates/compose/src/tests.rs b/crates/compose/src/tests.rs index 55bf3c0..4ab1168 100644 --- a/crates/compose/src/tests.rs +++ b/crates/compose/src/tests.rs @@ -288,11 +288,16 @@ fn hyphenation_zone_limits_ragged_hyphens() { let cs = compose_story(&d, sid, &ComposeOptions::default()); all_lines(&cs).iter().filter(|l| l.hyphenated).count() }; - for c in [designcraft_doc::Composer::Paragraph, designcraft_doc::Composer::SingleLine] { - let (free, zoned, huge) = (count(0.0, c), count(36.0, c), count(1000.0, c)); - // A huge zone leaves only words that start a line (no space to break at) hyphenable. - assert!(free > 0 && zoned <= free && huge * 4 <= free, "{c:?}: {free} {zoned} {huge}"); - } + // Single-line Composer: a huge zone leaves only words that start a line (no space to break + // at) hyphenable. + let c = designcraft_doc::Composer::SingleLine; + let (free, zoned, huge) = (count(0.0, c), count(36.0, c), count(1000.0, c)); + assert!(free > 0 && zoned <= free && huge * 4 <= free, "{c:?}: {free} {zoned} {huge}"); + // The zone is the Single-line Composer's only (InDesign): the Paragraph Composer hyphenates + // the same whatever it is. + let c = designcraft_doc::Composer::Paragraph; + let (free, zoned, huge) = (count(0.0, c), count(36.0, c), count(1000.0, c)); + assert!(free > 0 && zoned == free && huge == free, "{c:?}: {free} {zoned} {huge}"); } #[test]