diff --git a/crates/text/src/layout/warichu.rs b/crates/text/src/layout/warichu.rs index dd816599c6..b68b69efd9 100644 --- a/crates/text/src/layout/warichu.rs +++ b/crates/text/src/layout/warichu.rs @@ -287,6 +287,10 @@ fn place_block(g: &mut [SGlyph], s: &WariStyle, (vertical, whole): (bool, bool)) let rtl = !vertical && g.first().is_some_and(|gl| gl.level.is_rtl()); let (inset, outset) = if rtl { (after, before) } else { (before, after) }; let length = inset + block + outset; + // How far the glyphs reach above and below the line's baseline, each from its block line's + // baseline. + let above = g.iter().zip(&places).map(|(gl, p)| gl.ascent - p.1).fold(0.0, f64::max); + let below = g.iter().zip(&places).map(|(gl, p)| gl.descent + p.1).fold(0.0, f64::max); let glyphs = g.len(); for (i, (gl, (along, across, advance))) in g.iter_mut().zip(places).enumerate() { let em = gl.face.units_per_em() * gl.sy / r; @@ -300,9 +304,10 @@ fn place_block(g: &mut [SGlyph], s: &WariStyle, (vertical, whole): (bool, bool)) if i + 1 < glyphs { gl.keeps_next = true; } - // The line keeps the height of the block's own size, and holds the whole stack. - gl.ascent = (ascent / r).max(-top); - gl.descent = (descent / r).max(bottom); + // The line keeps the height of the block's own size, and holds the whole stack with each + // block line's glyphs. + gl.ascent = (ascent / r).max(-top).max(above); + gl.descent = (descent / r).max(bottom).max(below); if s.auto_leading { gl.leading /= r; } diff --git a/crates/text/src/tests/warichu.rs b/crates/text/src/tests/warichu.rs index 6aee052cbd..cbefb86bb5 100644 --- a/crates/text/src/tests/warichu.rs +++ b/crates/text/src/tests/warichu.rs @@ -626,6 +626,24 @@ fn a_block_of_several_fonts_keeps_the_tallest_of_them() { assert!(first_short.0 >= plain[pair.0].0 - 1e-6 && first_short.1 >= deepest - 1e-6, "{first_short:?} {plain:?}"); } +/// The line holds each block line's characters at their own height: with a wide Line Gap, the +/// ascent of the top block line's characters and the descent of the bottom one's stay inside the +/// line. +#[test] +fn a_wide_line_gap_keeps_the_outer_block_lines_inside_the_line() { + let small = layout(db(), &point("x", style(10.0))); + let (ascent, descent) = (small.lines[0].ascent, small.lines[0].descent); + for lines in [2, 3] { + let l = layout(db(), &with_block("cdefgh", CharStyle { warichu_lines: lines, warichu_gap: 20.0, ..marked(20.0) })); + let line = &l.lines[0]; + let block = &l.glyphs[2..8]; + let top = block.iter().map(|g| g.origin.y).fold(f64::INFINITY, f64::min); + let bottom = block.iter().map(|g| g.origin.y).fold(f64::NEG_INFINITY, f64::max); + assert!(line.baseline - line.ascent <= top - ascent + 1e-6, "{lines}: {} {} {top} {ascent}", line.baseline, line.ascent); + assert!(line.baseline + line.descent >= bottom + descent - 1e-6, "{lines}: {} {} {bottom} {descent}", line.baseline, line.descent); + } +} + /// Warichu Settings on characters not marked Warichu leave their shaping alone: "fi" keeps its /// ligature when only the f has other settings. #[test] diff --git a/docs/mcp.md b/docs/mcp.md index f7606a5b11..1976af7faf 100644 --- a/docs/mcp.md +++ b/docs/mcp.md @@ -9015,7 +9015,8 @@ Options). Warichu characters are set at `warichuScale` percent of their size (10 `warichuLines` lines (a whole number from 1 to 6, default 2) inside their line: one above the other in horizontal type and side by side across the column in vertical type, the first line above or to the right. `warichuGap` is the space between the lines in points (0 to 100, default 0, document points as `baselineShift`). The stack is centered across the -line on the center of the line's ideographic em box, and the line keeps the height of the characters' own size. +line on the center of the line's ideographic em box, and the line keeps the height of the characters' own size, or +more when the stack needs it: the line's ascent and descent take in the characters of the outer lines. A stretch of warichu characters is one block that takes the settings of its first character; a character with other settings, another size or the other kind of leading (Auto or a number) starts a new one, and a tab, a forced line break or a tate-chu-yoko character ends it. In vertical type a character marked `tateChuYoko` as well is set as tate-chu-yoko at its own size, and two or three digits