Type: a soft hyphen inside a No Break run does not end the first word

When layout looked for room for a line's first word in a frame that is
not a rectangle, a soft hyphen ended the word even inside a No Break
run, although the line does not break there. The word is now measured
across a soft hyphen where kinsoku or a No Break run keeps the line from
breaking after it.
This commit is contained in:
dotCooCoo
2026-11-11 16:20:48 -08:00
parent 253c60a23e
commit b14831d964
2 changed files with 19 additions and 1 deletions
+1 -1
View File
@@ -265,7 +265,7 @@ pub(super) fn word_width(g: &[SGlyph], i: usize, line_end: &[f64], kinsoku: Kins
if gl.is_space() && (end == start || !splits_no_break(g, end)) {
return set(w, trailing, ink);
}
if gl.is_soft_hyphen() {
if gl.is_soft_hyphen() && kinsoku_allows(g, end, kinsoku) && !splits_no_break(g, end + 1) {
return w + hyphen_glyph(gl).adv;
}
w += gl.adv;
+18
View File
@@ -269,6 +269,24 @@ fn no_break_keeps_marked_characters_on_one_line() {
assert!(breaks.iter().all(|b| b.end != 3), "no break between the marked characters: {breaks:?}");
}
/// A soft hyphen inside a No Break run is not a place a line may break, so the word is measured
/// across it, as wide as [`break_line`] keeps it.
#[test]
fn word_width_measures_across_a_soft_hyphen_inside_a_no_break_run() {
let mut glyphs = synthetic_glyphs(&[(0, 1, 10.0, 'A'), (1, 2, 0.0, '\u{00ad}'), (3, 1, 10.0, 'B'), (4, 1, 10.0, 'C')]);
// The hyphen a soft hyphen adds comes from the face, scaled to well under 10 pt.
for g in &mut glyphs {
g.sx = 0.001;
}
let plain = breaking::word_width(&glyphs, 0, &[], Kinsoku::None);
assert!(plain < 30.0, "without the mark the word ends at the soft hyphen: {plain}");
for g in &mut glyphs {
g.no_break = true;
}
let marked = breaking::word_width(&glyphs, 0, &[], Kinsoku::None);
assert!((marked - 30.0).abs() < 1e-9, "the marked run is measured whole: {marked}");
}
/// Synthetic full-width characters `text`, each 10 pt wide on a 10 pt em.
fn full_width(text: &str) -> Vec<SGlyph> {
let specs: Vec<(usize, usize, f64, char)> = text.char_indices().map(|(byte, ch)| (byte, ch.len_utf8(), 10.0, ch)).collect();