Compose: spaces at the end of a paragraph take no room on the line

The paragraph composer counted a trailing space (or several) before the
paragraph end or a forced line break in the line's width, so "2 VOOR " in a
frame exactly as wide as "2 VOOR" broke before "VOOR" and the frame went
overset. InDesign lets those spaces hang past the edge. They now add no
width; the line's visible range already left them out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Govinda Roy
2026-10-14 00:16:42 +06:00
co-authored by Claude Opus 5.5
parent e862e0a613
commit 7e344e85f1
2 changed files with 24 additions and 0 deletions
+9
View File
@@ -303,8 +303,17 @@ fn items(glyphs: &[Glyph], hyph_after: &[bool], emergency_after: &[bool], sp: &S
let n = glyphs.len();
let mut hy_cache = Vec::new();
let mut last_space = NONE;
// Spaces before the paragraph end or a forced break hang: they take no room on the line (as
// in InDesign, where "2 VOOR " fits a frame as wide as "2 VOOR").
let mut hangs = vec![false; n];
for i in (0..n).rev() {
hangs[i] = glyphs[i].is_space() && glyphs.get(i + 1).is_none_or(|nx| hangs[i + 1] || is_forced(nx.ch));
}
for (i, g) in glyphs.iter().enumerate() {
let prev_hang = if i > 0 { right_hang(&glyphs[i - 1], sp) } else { 0.0 };
if hangs[i] {
continue;
}
if is_forced(g.ch) {
it.push(Item::glue(0.0, INF, 0.0));
ig.push(i);
+15
View File
@@ -2929,3 +2929,18 @@ fn empty_paragraphs_get_no_bullet_or_number() {
assert_eq!(list_labels(&cs, LABEL_CHARS), ["1.", "", "2.", ""], "list `{name}`");
}
}
#[test]
fn spaces_at_the_end_of_a_paragraph_take_no_room() {
// A frame as wide as "2 VOOR" also holds "2 VOOR " on one line: the trailing space hangs.
let (d, sid, _) = doc_with("2 VOOR", Rect::new(0.0, 0.0, 500.0, 100.0), ParaAttrs::default());
let cs = compose_story(&d, sid, &ComposeOptions::default());
let l = all_lines(&cs)[0];
let width = l.end_x - l.x0;
for text in ["2 VOOR ", "2 VOOR ", "2 VOOR \u{2028}more"] {
let (d, sid, _) = doc_with(text, Rect::new(0.0, 0.0, width + 0.02, 100.0), ParaAttrs::default());
let cs = compose_story(&d, sid, &ComposeOptions::default());
let first = all_lines(&cs)[0];
assert_eq!(&text[first.range.clone()].trim_end(), &"2 VOOR", "{text:?}");
}
}