mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-24 09:46:59 -06:00
Type: the Every-line Composer ends a line after the spaces that follow it
The composer offered a break after a dash, a Thai word or a space even when a space came next, so it could start the next line with that space. A leading space makes the next line wider, and the composer could score that break better. With mixed type sizes now composed in rectangular area type, Thai text whose words come from a Thai font broke as "สวัสดีครับ" and " ภาษาไทยง่าย". The composer now offers only the break after the spaces, as the single-line composer ends its lines.
This commit is contained in:
@@ -1607,7 +1607,9 @@ fn hyphen_breaks(text: &str, g: &[SGlyph], ws: usize, we: usize, opts: &Hyphenat
|
||||
}
|
||||
|
||||
/// Break candidates for the every-line composer: hyphenation points under `hyphenate` (the
|
||||
/// paragraph's Hyphenation options) when it is given.
|
||||
/// paragraph's Hyphenation options) when it is given. No break comes before a space: a line that
|
||||
/// may end after a dash, a Thai word or a space ends after the spaces that follow it, as in
|
||||
/// [`break_line`].
|
||||
fn candidates(text: &str, g: &[SGlyph], hyphenate: Option<&HyphenationOptions>, kinsoku: Kinsoku) -> Vec<Breakpoint> {
|
||||
let mut v = vec![];
|
||||
let mut ws = 0;
|
||||
@@ -1622,7 +1624,7 @@ fn candidates(text: &str, g: &[SGlyph], hyphenate: Option<&HyphenationOptions>,
|
||||
}
|
||||
}
|
||||
let hy = if gl.is_soft_hyphen() { hyphen_glyph(gl).adv } else { 0.0 };
|
||||
if j + 1 < g.len() && g[j + 1].byte != gl.byte && kinsoku_allows(g, j, kinsoku) {
|
||||
if j + 1 < g.len() && g[j + 1].byte != gl.byte && !g[j + 1].is_space() && kinsoku_allows(g, j, kinsoku) {
|
||||
v.push(Breakpoint { end: j + 1, hyphen: hy });
|
||||
}
|
||||
ws = j + 1;
|
||||
|
||||
@@ -387,6 +387,33 @@ fn composer_x_mixed_line_metrics() {
|
||||
assert!(wrong.is_empty(), "{wrong:?}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn composer_x_lines_start_after_the_spaces() {
|
||||
// A line may end after a dash or between two spaces, but the every-line composer breaks after
|
||||
// the spaces that follow, as the single-line composer does: no line starts with a space, in
|
||||
// uniform 12 pt text and with a 24 pt word in it.
|
||||
let st = sans(12.0);
|
||||
let runs = |x: CharStyle| {
|
||||
vec![run("Destroy all creatures \u{2014} with toughness ", st.clone()), run("X", x), run(" or less \u{2014} then draw a card.", st.clone())]
|
||||
};
|
||||
let mut wrong = vec![];
|
||||
for x in [sans(12.0), sans(24.0)] {
|
||||
for justify in [Justify::Left, Justify::JustifyLeft] {
|
||||
for w in (40..400).step_by(4) {
|
||||
let mut t = area(runs(x.clone()), Rect::new(0.0, 0.0, f64::from(w), 2000.0));
|
||||
t.para.composer = Composer::EveryLine;
|
||||
t.para.justify = justify;
|
||||
let text = t.plain_text();
|
||||
let l = layout(db(), &t);
|
||||
if l.lines.iter().any(|li| text[li.start..].starts_with(' ')) {
|
||||
wrong.push((x.size, justify, w, line_texts(&t, &l)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert!(wrong.is_empty(), "{wrong:?}");
|
||||
}
|
||||
|
||||
const INLINE: char = vectorcraft_doc::text::INLINE_CHAR;
|
||||
|
||||
// ---------- vertical alignment × … ----------
|
||||
|
||||
Reference in New Issue
Block a user