Type: a warichu line holds the ascent and descent of its outer block lines

A block's line took the tallest ascent and deepest descent of its
characters, or the height of the stack's em boxes, whichever was larger.
The top block line's characters reach above the stack by their ascent
past the em box, and the bottom line's below it by their descent, so with
a wide Line Gap the line was too short for them. The line's ascent and
descent now also take in each character's reach from its own block line's
baseline.
This commit is contained in:
dotCooCoo
2026-11-14 13:46:56 -08:00
parent 9ddbf25bef
commit f1cffdd8c0
3 changed files with 28 additions and 4 deletions
+8 -3
View File
@@ -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;
}
+18
View File
@@ -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]
+2 -1
View File
@@ -8965,7 +8965,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