From ca45f97aceb12760f092fd2a20109b62b39c51b1 Mon Sep 17 00:00:00 2001 From: Fin Warman Date: Sun, 18 Oct 2026 15:26:32 +0100 Subject: [PATCH] Layout: exclude floating anchors from line font metrics (task 256) (#2462) Co-authored-by: Brandon Thomas --- ROADMAP.md | 2 ++ crates/layout/src/para.rs | 4 +++- crates/layout/src/tests.rs | 23 +++++++++++++++++++++++ docs/gaps.md | 1 + docs/layout-parity.md | 1 + 5 files changed, 30 insertions(+), 1 deletion(-) diff --git a/ROADMAP.md b/ROADMAP.md index ae56fd537..b53412738 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -165,6 +165,7 @@ Imported Word 97–2003 `.doc`/`.dot` files now ask for a supported DOCX target | 2026-10-14 | Tab stops edited on the ruler: the corner selector picks Left/Center/Right/Decimal/Bar, a click sets a stop (Alt skips the snap), dragging moves it with a guide line and position tooltip, dragging off the ruler clears it; markers draw per kind and mirror for RTL; one `para.tabs` call and one undo step per gesture | | 2026-10-12 | Fields keep `w:dirty` through DOCX saves (#877): a begin marker flagged by a generator that couldn't compute a result (pandoc-style TOC placeholders) keeps the flag on open/save — as a buffered field or a range field — so Word still refreshes it on open; computing a result (Update Field, Update Table) clears it, like Word's F9 | | 2026-10-15 | Exact line spacing keeps the run font baseline around tall equations; automatic and minimum spacing still grow for math. | +| 2026-10-16 | Zero-extent drawing anchors contribute no inline font height. | |---|---| | 2026-10-15 | The font family caches are bounded (4096 families for text, 1024 for math, names over 256 bytes aren't remembered), so a document naming thousands of missing fonts can't grow memory; equation fonts are looked up again after a font is added or removed instead of keeping the old choice (#1354) | | 2026-10-15 | AutoCorrect recognizes `-->` as `→` (#2223), respecting replacement settings and undo without changing paragraph-start arrow bullets. | @@ -512,6 +513,7 @@ Imported Word 97–2003 `.doc`/`.dot` files now ask for a supported DOCX target | 2026-10-14 | trivial | Progress log: Add Font imports every selected font file (#1789) | | 2026-10-15 | trivial | Additive paragraph spacing retains the full before-space after a section page break; ordinary overlapping spacing is unchanged. | | 2026-10-15 | trivial | Exact line spacing keeps the run font baseline around tall equations; automatic and minimum spacing still grow for math. | +| 2026-10-16 | trivial | Zero-extent drawing anchors contribute no inline font height. Synthetic regressions. | | 2026-10-14 | trivial | Progress log: row table border exceptions | | 2026-10-12 | minor | Czech proofing review: short-word splits rank after deletion, NOSUGGEST excludes suggestions while accepting typed forms, affix comments apply only to headers, ratios keep spaces and repeated-word messages use Czech quotes; synthetic engine end-to-end and latency checks | | 2026-10-12 | minor | Czech spelling from the installed Hunspell dictionary, runtime-table suggestions and generic checks; Czech interface writes cs-CZ documents; no Czech hyphenation patterns bundled; estimates unchanged | diff --git a/crates/layout/src/para.rs b/crates/layout/src/para.rs index 5aafa4be4..8e12edddd 100644 --- a/crates/layout/src/para.rs +++ b/crates/layout/src/para.rs @@ -2219,7 +2219,9 @@ fn break_lines(pl: &mut ParaLayout, env: &ParaEnv, mark_style: u32, level: Optio // Spaces and tabs never make a line taller, whatever their size: Word sizes a line by // its other characters (a line of only them takes the paragraph mark's), measured in // Word for Windows with 9 pt text and 11–20 pt tabs, spaces and ideographic spaces. - if matches!(c.kind, ClKind::Marker | ClKind::Space | ClKind::Tab) || c0 + k < dropped { + // Floating and hidden drawings have no inline extent; their anchor font takes no height. + let anchor = matches!(c.kind, ClKind::Object(_)) && c.adv == 0.0 && c.obj_h == 0.0; + if matches!(c.kind, ClKind::Marker | ClKind::Space | ClKind::Tab) || anchor || c0 + k < dropped { continue; } if let Some(st) = pl.styles.get(c.style as usize) { diff --git a/crates/layout/src/tests.rs b/crates/layout/src/tests.rs index b8dc7fe8f..91830a1ee 100644 --- a/crates/layout/src/tests.rs +++ b/crates/layout/src/tests.rs @@ -8223,3 +8223,26 @@ fn exact_math_keeps_run_baseline() { } } } + +#[test] +fn float_font_keeps_line_height() { + use wordcraft_doc::CharProps; + use wordcraft_doc::para::{Float, Wrap}; + + let pitch = |wrap, size| { + let small = CharProps { size: Some(9.0), ..Default::default() }; + let mut p = wordcraft_doc::Paragraph::with_text("Anchor", small.clone()); + p.mark = small; + p.props.space_after = Some(0.0); + p.insert_object(0, picture(1.0, 1.0, Float { wrap, ..Default::default() }), &CharProps { size: Some(size), ..Default::default() }).unwrap(); + let mut d = Document::from_text("After"); + d.body.insert(0, wordcraft_doc::para_block(p)); + let l = lay(&d); + l.caret(&Pos::body(1, 0)).unwrap().top - l.caret(&Pos::body(0, 0)).unwrap().top + }; + + for wrap in [Wrap::BehindText, Wrap::InFrontOfText] { + assert!((pitch(wrap, 40.0) - pitch(wrap, 9.0)).abs() < 0.01, "{wrap:?}"); + } + assert!(pitch(Wrap::Inline, 40.0) > pitch(Wrap::Inline, 9.0)); +} diff --git a/docs/gaps.md b/docs/gaps.md index a5d9a3e1a..034b61105 100644 --- a/docs/gaps.md +++ b/docs/gaps.md @@ -117,6 +117,7 @@ The Language dialog reads effective character formatting, including document def | 2026-10-14 | trivial | #19 narrowed: ODT export done (master page and page layout per section, columned `text:section`s) | | 2026-10-15 | trivial | Additive paragraph spacing retains the full before-space after a section page break; ordinary overlapping spacing is unchanged. | | 2026-10-15 | trivial | Exact line spacing keeps the run font baseline around tall equations; automatic and minimum spacing still grow for math. | +| 2026-10-16 | trivial | Zero-extent drawing anchors contribute no inline font height. Synthetic regressions. | | 2026-10-14 | trivial | Row table border exceptions fixed; other row table exceptions remain unsupported | | 2026-10-12 | minor | Czech proofing review: short-word splits rank after deletion, NOSUGGEST excludes suggestions while accepting typed forms, affix comments apply only to headers, ratios keep spaces and repeated-word messages use Czech quotes; synthetic engine end-to-end and latency checks | | 2026-10-12 | minor | Czech spelling from the installed Hunspell dictionary, runtime-table suggestions and generic checks; Czech interface writes cs-CZ documents; no Czech hyphenation patterns bundled; estimates unchanged | diff --git a/docs/layout-parity.md b/docs/layout-parity.md index 82f072ce2..8667d92c1 100644 --- a/docs/layout-parity.md +++ b/docs/layout-parity.md @@ -217,6 +217,7 @@ Behind-text pictures in table cells participate in centre and bottom vertical al | 2026-10-15 | trivial | Removed the 12 pt line-width floor in narrow cells and float spans; synthetic wrapping and oversized-glyph controls | | 2026-10-15 | trivial | Partial cell margins retain omitted edges through DOCX save and inherit current table defaults during layout. Original import/write and row-height regressions. | | 2026-10-15 | trivial | Exact line spacing keeps the run font baseline around tall equations; automatic and minimum spacing still grow for math. | +| 2026-10-16 | trivial | Zero-extent drawing anchors contribute no inline font height. Synthetic regressions. | | 2026-10-14 | trivial | Row table border exceptions draw without leaking into other rows | | 2026-10-14 | trivial | Consistent cell widths override a stale table grid | | 2026-10-14 | trivial | Paragraphs inside complex-field instructions take no flow height; empty result paragraphs keep their line. |