mirror of
https://github.com/storytold/designcraft.git
synced 2026-10-27 19:56:51 -06:00
Text: a missing font's substitute takes fallback fonts across a colour change
Text is shaped in pieces that differ only in paint, so each piece group, and each piece shaped apart, takes its style's environment: a missing font's substitute draws the characters it lacks from fallback fonts whatever Draw Missing Glyphs from Fallback Fonts says.
This commit is contained in:
@@ -375,14 +375,17 @@ pub(crate) fn shape_para(
|
||||
let range = group[0].range.start..group[j - i - 1].range.end;
|
||||
let runs: Vec<(usize, u32)> = group.iter().map(|p| (p.range.start, p.style)).collect();
|
||||
let start = glyphs.len();
|
||||
shape_run(db, &story.text, range, &first.props, auto_leading, &StyleRuns(&runs), sub, &mut glyphs);
|
||||
// A missing font's substitute stands in for the whole font: fallback fonts help it.
|
||||
// Pieces shaped together share their font, so the first one's says for all.
|
||||
shape_run(db, &story.text, range, &first.props, table.env_for(auto_leading, first.style), &StyleRuns(&runs), sub, &mut glyphs);
|
||||
// A cluster (a ligature, a letter with its marks) that spans two styles would paint one
|
||||
// of them in the other's colour: shape those pieces apart instead.
|
||||
let spans_cut = |g: &Glyph| runs[1..].iter().any(|&(cut, _)| g.byte < cut && cut < g.byte + g.len);
|
||||
if group.len() > 1 && glyphs[start..].iter().any(spans_cut) {
|
||||
glyphs.truncate(start);
|
||||
for p in group {
|
||||
shape_run(db, &story.text, p.range.clone(), &p.props, auto_leading, &StyleRuns(&[(p.range.start, p.style)]), sub, &mut glyphs);
|
||||
let env = table.env_for(auto_leading, p.style);
|
||||
shape_run(db, &story.text, p.range.clone(), &p.props, env, &StyleRuns(&[(p.range.start, p.style)]), sub, &mut glyphs);
|
||||
}
|
||||
}
|
||||
i = j;
|
||||
|
||||
@@ -1570,6 +1570,32 @@ fn missing_glyphs_are_the_fonts_box_unless_fallback_is_on() {
|
||||
assert_ne!(gid, 0, "a fallback font draws it");
|
||||
}
|
||||
|
||||
/// A missing font's substitute draws what it lacks from fallback fonts whatever the setting, also
|
||||
/// in text shaped as one piece across a colour change.
|
||||
#[test]
|
||||
fn a_missing_fonts_substitute_takes_fallback_fonts() {
|
||||
use designcraft_fonts::testing::font_with;
|
||||
designcraft_fonts::FontDb::global().add_font(font_with("DC Test Missing Glyph Helper", &['語']).unwrap());
|
||||
let text = "a語b語";
|
||||
let (mut d, sid, _) = doc_with(text, Rect::new(36.0, 36.0, 300.0, 100.0), ParaAttrs::default());
|
||||
{
|
||||
let s = d.story_mut(sid).unwrap();
|
||||
s.format_chars(0..text.len(), |f| {
|
||||
f.over.language = Some("Japanese".into());
|
||||
f.over.font_family = Some("DC Test No Such Family".into());
|
||||
});
|
||||
s.format_chars("a語".len()..text.len(), |f| f.over.fill = Some("Red".into()));
|
||||
}
|
||||
assert!(!d.settings.glyph_fallback);
|
||||
let cs = compose_story(&d, sid, &ComposeOptions::default());
|
||||
let glyphs: Vec<&PlacedGlyph> = all_lines(&cs).into_iter().flat_map(|l| l.glyphs.iter()).filter(|g| text[g.byte..].starts_with('語')).collect();
|
||||
assert_eq!(glyphs.len(), 2);
|
||||
for g in glyphs {
|
||||
assert_ne!(g.face.family, designcraft_fonts::DEFAULT_FAMILY, "byte {}", g.byte);
|
||||
assert_ne!(g.gid, 0, "byte {}: a fallback font draws it", g.byte);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn kenten_missing_from_the_font_are_its_box_unless_fallback_is_on() {
|
||||
use designcraft_fonts::testing::font_with;
|
||||
|
||||
Reference in New Issue
Block a user