mirror of
https://github.com/storytold/wordcraft.git
synced 2026-10-13 23:17:49 +00:00
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:
1 parent
6f35313f68
commit
64f656a8bc
4 files changed
+40
-1
No files matched your search
@@ -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) |
|
||||
|---|---|
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
@@ -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) |
|
||||
|
||||
Reference in new issue
Block a user