mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-11-14 06:31:41 +00:00
Type: no justification gap inside a right-to-left warichu block
Justification gaps follow the drawn order, and right to left the bidi order draws a block's first glyph after the others. The glyph drawn second then did not continue the block, so Full Justify and CJK justification opened a gap inside it. Both gap rules now also skip a pair whose glyphs belong to the same block.
This commit is contained in:
@@ -753,12 +753,24 @@ fn gap_pair<'a>(glyph: usize, held: &[usize], after: &[Option<usize>], index: us
|
||||
visible_after(index, glyph, after, sg).and_then(|next| sg.get(next)).map(|b| (a, b))
|
||||
}
|
||||
|
||||
// Are `a` and `b` glyphs of the same warichu block? Right to left, the bidi order can draw a
|
||||
// block's first glyph after the others, so the glyph drawn second need not continue the block.
|
||||
fn same_warichu_block(a: &SGlyph, b: &SGlyph) -> bool {
|
||||
a.wari.zip(b.wari).is_some_and(|(first, second)| first.start == second.start)
|
||||
}
|
||||
|
||||
// Japanese (and Chinese) lines are justified between their characters (JLREQ 3.8): the
|
||||
// gaps next to a CJK character, not inside a Latin word, a tate-chu-yoko or warichu block or a
|
||||
// shaped cluster.
|
||||
fn is_cjk_gap(glyph: usize, held: &[usize], after: &[Option<usize>], index: usize, sg: &[SGlyph]) -> bool {
|
||||
pub(super) fn is_cjk_gap(glyph: usize, held: &[usize], after: &[Option<usize>], index: usize, sg: &[SGlyph]) -> bool {
|
||||
gap_pair(glyph, held, after, index, sg).is_some_and(|(a, b)| {
|
||||
a.byte != b.byte && !a.is_space() && !b.is_space() && !b.continues_block() && a.ch != '\t' && (is_cjk(a.ch) || is_cjk(b.ch))
|
||||
a.byte != b.byte
|
||||
&& !a.is_space()
|
||||
&& !b.is_space()
|
||||
&& !b.continues_block()
|
||||
&& !same_warichu_block(a, b)
|
||||
&& a.ch != '\t'
|
||||
&& (is_cjk(a.ch) || is_cjk(b.ch))
|
||||
}) && !in_pair(glyph, index, after, sg)
|
||||
}
|
||||
|
||||
@@ -788,12 +800,12 @@ fn in_pair(glyph: usize, index: usize, after: &[Option<usize>], sg: &[SGlyph]) -
|
||||
// warichu block (set as one piece), a shaped cluster, whose glyphs (a letter and its combining marks, a conjunct and its matra) stay
|
||||
// together, or an inseparable pair. On a line that ends in a drawn hyphen, the gap before the
|
||||
// hyphen counts too: it follows the line's last visible glyph.
|
||||
fn is_letter_gap(glyph: usize, held: &[usize], after: &[Option<usize>], index: usize, sg: &[SGlyph], hyphen: bool) -> bool {
|
||||
pub(super) fn is_letter_gap(glyph: usize, held: &[usize], after: &[Option<usize>], index: usize, sg: &[SGlyph], hyphen: bool) -> bool {
|
||||
if held.contains(&glyph) || sg.get(glyph).is_none_or(|a| is_format_control(a.ch)) || in_pair(glyph, index, after, sg) {
|
||||
return false;
|
||||
}
|
||||
match gap_pair(glyph, held, after, index, sg) {
|
||||
Some((a, b)) => a.byte != b.byte && !b.continues_block(),
|
||||
Some((a, b)) => a.byte != b.byte && !b.continues_block() && !same_warichu_block(a, b),
|
||||
None => hyphen,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -717,3 +717,26 @@ fn bunri_kinshi_progresses_with_an_overlong_pair_and_no_break() {
|
||||
assert_eq!(line(text, &pairs(text, false), 0, 46.5, Kinsoku::Hard, PushInFirst), 5);
|
||||
assert_eq!(line(text, &pairs(text, true), 0, 46.5, Kinsoku::Hard, PushInFirst), 3);
|
||||
}
|
||||
|
||||
/// Justification adds no gap between two glyphs of one warichu block, whichever of them is drawn
|
||||
/// first: right to left, the block's first glyph (the one that starts it) is drawn after the
|
||||
/// others. Between glyphs of two blocks, the gap stays.
|
||||
#[test]
|
||||
fn justification_adds_no_gap_inside_a_warichu_block_drawn_right_to_left() {
|
||||
let block = |g: &mut SGlyph, start: usize, pen: f64| {
|
||||
g.wari = Some(crate::shape::Wari { start, pen, along: 0.0, across: 0.0, advance: g.adv, em: 10.0 });
|
||||
};
|
||||
// Glyph 1 is drawn first, then glyph 0, which starts the block.
|
||||
let after = [None, Some(0)];
|
||||
for (first, second) in [('א', 'ב'), ('漢', 'א')] {
|
||||
let mut glyphs = synthetic_glyphs(&[(0, 2, 10.0, first), (2, 2, 0.0, second)]);
|
||||
block(&mut glyphs[0], 0, 0.0);
|
||||
block(&mut glyphs[1], 0, 10.0);
|
||||
assert!(!flow::is_letter_gap(1, &[], &after, 0, &glyphs, false), "{first}{second}");
|
||||
assert!(!flow::is_cjk_gap(1, &[], &after, 0, &glyphs), "{first}{second}");
|
||||
// The same two glyphs as the first glyphs of two blocks.
|
||||
block(&mut glyphs[1], 2, 0.0);
|
||||
assert!(flow::is_letter_gap(1, &[], &after, 0, &glyphs, false), "{first}{second}");
|
||||
assert_eq!(flow::is_cjk_gap(1, &[], &after, 0, &glyphs), first == '漢', "{first}{second}");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user