Layout: spaces and tabs don't make a line taller, as in Word (#931)

Found comparing Microsoft's own specification documents with Word for
Windows: their tables of contents were a third taller in WordCraft
(13.4 pt per entry against Word's 10.9). Each entry's 9 pt text has tab
runs in an 11 pt font, and WordCraft sized the line by them.

Measured in Word with 13 synthetic documents: 11-20 pt tabs, spaces and
ideographic spaces next to 9 pt text leave the 9 pt line as it is,
wherever they are on the line; a line of only such whitespace takes the
paragraph mark's height; a big letter or no-break space does grow the
line. WordCraft now skips spaces and tabs when it sizes a line, and all
13 cases match.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Brandon ThomasandClaude Opus 5.5 authored and GitHub committed 2026-10-12 09:30:34 -04:00
1 parent 6f35313f68
commit 64f656a8bc
4 files changed
+40 -1

No files matched your search

+1
View File
@@ -142,6 +142,7 @@ Ranked, to beta (detail and remaining milestones in [docs/roadmap.md](docs/roadm
| 2026-10-12 | PDF export of long documents with many internal links (a linked table of contents) is linear: NIH's 67-page protocol template 10.6 s → 0.9 s |
| 2026-10-12 | Keytips: Word for Windows' tab letters (File F, Design G, References S, Review R, View W, Help Y) |
| 2026-10-12 | Table-of-contents links look like Word's: plain text, not blue and underlined (Word ignores the Hyperlink style on TOC entry links; measured in 9 cases) |
| 2026-10-12 | Line heights like Word's: spaces and tabs never make a line taller (13 cases measured in Word for Windows); tables of contents with big tab runs were a third taller |
| 2026-10-11 | Hide White Space (#645): `view.hideWhiteSpace` (View › Show checkbox, or double-click the gap between pages) collapses margins, headers and footers between pages to a thin line in Print Layout; screen only, page count unchanged |
| 2026-10-11 | Fonts: Palatino Linotype and Book Antiqua fall back to Palatino (macOS) or TeX Gyre Pagella / P052 / URW Palladio (Linux) before generic serif (#670) |
|---|---|
+4 -1
View File
@@ -1781,7 +1781,10 @@ fn break_lines(pl: &mut ParaLayout, env: &ParaEnv, mark_style: u16, level: Optio
let mut any = false;
let dropped = pl.drop_cap.map_or(0, |d| d.0);
for (k, c) in pl.clusters.get(c0..c1).into_iter().flatten().enumerate() {
if c.kind == ClKind::Marker || c0 + k < dropped {
// 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 {
continue;
}
if let Some(st) = pl.styles.get(c.style as usize) {
+34
View File
@@ -4143,3 +4143,37 @@ fn bulgarian_text_is_hyphenated_by_its_own_rules() {
assert!(wordcraft_proof::hyphen::hyphen_points_in(&word, &lim, wordcraft_proof::ProofLang::Bg).contains(&at), "{head}-{tail}");
}
}
/// Spaces and tabs never make a line taller in Word, whatever their size (measured in Word for
/// Windows: 9 pt text with 11–20 pt tabs, spaces and ideographic spaces kept the 9 pt line; a
/// line of only big spaces took the paragraph mark's height; a big letter or no-break space did
/// grow it). Tables of contents with big tab runs were a third taller than Word's.
#[test]
fn spaces_and_tabs_do_not_make_a_line_taller() {
use wordcraft_doc::props::CharProps;
let small = CharProps { size: Some(9.0), ..Default::default() };
let big = CharProps { size: Some(20.0), ..Default::default() };
let pitch = |middle: &str, middle_props: &CharProps| {
let mut d = Document::new();
d.body = (0..3)
.map(|i| {
let mut p = wordcraft_doc::Paragraph::with_text(&format!("L{i}A"), small.clone());
let n = p.len();
p.insert_text(n, middle, middle_props).unwrap();
let n = p.len();
p.insert_text(n, "B", &small).unwrap();
p.props = ParaProps { space_before: Some(0.0), space_after: Some(0.0), ..Default::default() };
p.mark = small.clone();
wordcraft_doc::para_block(p)
})
.collect();
let l = lay(&d);
l.caret(&Pos::body(1, 0)).unwrap().top - l.caret(&Pos::body(0, 0)).unwrap().top
};
let plain = pitch(" ", &small);
for (what, middle) in [("a tab", "\t"), ("a space", " "), ("two spaces", " "), ("an ideographic space", "\u{3000}")] {
assert!((pitch(middle, &big) - plain).abs() < 0.01, "{what} at 20 pt: {} vs {plain}", pitch(middle, &big));
}
assert!(pitch("x", &big) > plain + 5.0, "a 20 pt letter does make it taller");
assert!(pitch("\u{A0}", &big) > plain + 5.0, "so does a no-break space");
}
+1
View File
@@ -75,6 +75,7 @@ font can't match Word's metrics.
| Date | Change | Summary |
|---|---|---|
| 2026-10-12 | trivial | Spaces, tabs and ideographic spaces don't count toward a line's height, as in Word (a line of only them takes the paragraph mark's) |
| 2026-10-11 | trivial | Chinese documents (#534): indents in characters, a page-anchored floating table after a full page moves to the next page, no blank page from a page break at the bottom of a full page |
| 2026-10-11 | trivial | East Asian list number formats (一、二、三, 第一章, ①); list labels whose characters come from two fonts draw each part with its own font (the digits of "1、" no longer show as other letters); a list level without indents leaves the label at the paragraph edge (#534) |
| 2026-10-11 | trivial | Vertical sections: `w:textDirection` in `w:sectPr`, upright East Asian glyphs (#491) |