Script specific font matching
This commit is contained in:
parent
7e08a63796
commit
f91cb3ce0f
3 changed files with 68 additions and 14 deletions
|
|
@ -24,19 +24,21 @@ mod windows;
|
|||
|
||||
pub struct FontFallbackIter<'a> {
|
||||
fonts: &'a [Font<'a>],
|
||||
locale: &'a str,
|
||||
default_family_opt: Option<&'a str>,
|
||||
scripts: Vec<Script>,
|
||||
locale: &'a str,
|
||||
script_i: (usize, usize),
|
||||
common_i: usize,
|
||||
other_i: usize,
|
||||
}
|
||||
|
||||
impl<'a> FontFallbackIter<'a> {
|
||||
pub fn new(fonts: &'a [Font<'a>], scripts: Vec<Script>, locale: &'a str) -> Self {
|
||||
pub fn new(fonts: &'a [Font<'a>], default_family_opt: Option<&'a str>, scripts: Vec<Script>, locale: &'a str) -> Self {
|
||||
Self {
|
||||
fonts,
|
||||
locale,
|
||||
default_family_opt,
|
||||
scripts,
|
||||
locale,
|
||||
script_i: (0, 0),
|
||||
common_i: 0,
|
||||
other_i: 0,
|
||||
|
|
@ -47,8 +49,18 @@ impl<'a> FontFallbackIter<'a> {
|
|||
impl<'a> Iterator for FontFallbackIter<'a> {
|
||||
type Item = &'a Font<'a>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if let Some(default_family) = self.default_family_opt.take() {
|
||||
for font in self.fonts.iter() {
|
||||
if font.info.family == default_family {
|
||||
return Some(font);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while self.script_i.0 < self.scripts.len() {
|
||||
let script_families = script_fallback(&self.scripts[self.script_i.0], self.locale);
|
||||
let script = self.scripts[self.script_i.0];
|
||||
|
||||
let script_families = script_fallback(&script, self.locale);
|
||||
while self.script_i.1 < script_families.len() {
|
||||
let script_family = script_families[self.script_i.1];
|
||||
self.script_i.1 += 1;
|
||||
|
|
@ -57,7 +69,9 @@ impl<'a> Iterator for FontFallbackIter<'a> {
|
|||
return Some(font);
|
||||
}
|
||||
}
|
||||
log::warn!("failed to find family '{}' for script {:?} and locale '{}'", script_family, script, self.locale)
|
||||
}
|
||||
|
||||
self.script_i.0 += 1;
|
||||
self.script_i.1 = 0;
|
||||
}
|
||||
|
|
@ -68,9 +82,11 @@ impl<'a> Iterator for FontFallbackIter<'a> {
|
|||
self.common_i += 1;
|
||||
for font in self.fonts.iter() {
|
||||
if font.info.family == common_family {
|
||||
log::debug!("Trying '{}' for scripts {:?} and locale '{}'", font.info.family, self.scripts, self.locale);
|
||||
return Some(font);
|
||||
}
|
||||
}
|
||||
log::warn!("failed to find family '{}'", common_family)
|
||||
}
|
||||
|
||||
//TODO: do we need to do this?
|
||||
|
|
@ -78,6 +94,7 @@ impl<'a> Iterator for FontFallbackIter<'a> {
|
|||
while self.other_i < self.fonts.len() {
|
||||
let font = &self.fonts[self.other_i];
|
||||
self.other_i += 1;
|
||||
log::info!("Trying '{}' for scripts {:?} and locale '{}'", font.info.family, self.scripts, self.locale);
|
||||
return Some(font);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ pub fn common_fallback() -> &'static [&'static str] {
|
|||
&[
|
||||
"Fira Sans",
|
||||
"DejaVu Sans",
|
||||
"DejaVu Serif",
|
||||
//"FreeSans",
|
||||
"Noto Sans Symbols",
|
||||
"Noto Sans Symbols2",
|
||||
"Noto Color Emoji",
|
||||
]
|
||||
}
|
||||
|
|
@ -15,6 +17,17 @@ pub fn common_fallback() -> &'static [&'static str] {
|
|||
pub fn script_fallback(script: &Script, locale: &str) -> &'static [&'static str] {
|
||||
//TODO: abstract style (sans/serif/monospaced)
|
||||
match script {
|
||||
Script::Adlam => &["Noto Sans Adlam"],
|
||||
Script::Arabic => &["Noto Sans Arabic"],
|
||||
Script::Bengali => &["Noto Sans Bengali"],
|
||||
Script::Chakma => &["Noto Sans Chakma"],
|
||||
Script::Cherokee => &["Noto Sans Cherokee"],
|
||||
Script::Devanagari => &["Noto Sans Devanagari"],
|
||||
Script::Ethiopic => &["Noto Sans Ethiopic"],
|
||||
Script::Hangul => &["Noto Sans CJK KR"],
|
||||
Script::Grantha => &["Noto Sans Grantha"],
|
||||
Script::Gujarati => &["Noto Sans Gujarati"],
|
||||
Script::Gurmukhi => &["Noto Sans Gurmukhi"],
|
||||
Script::Han => match locale {
|
||||
// Japan
|
||||
"ja" => &["Noto Sans CJK JA"],
|
||||
|
|
@ -28,7 +41,29 @@ pub fn script_fallback(script: &Script, locale: &str) -> &'static [&'static str]
|
|||
"zh-TW" => &["Noto Sans CJK TC"],
|
||||
// Simplified Chinese is the default
|
||||
_ => &["Noto Sans CJK SC"],
|
||||
}
|
||||
},
|
||||
Script::Hiragana => &["Noto Sans CJK JP"],
|
||||
Script::Javanese => &["Noto Sans Javanese"],
|
||||
Script::Kannada => &["Noto Sans Kannada"],
|
||||
Script::Katakana => &["Noto Sans CJK JP"],
|
||||
Script::Khmer => &["Noto Sans Khmer"],
|
||||
Script::Malayalam => &["Noto Sans Malayalam"],
|
||||
Script::Mongolian => &["Noto Sans Mongolian"],
|
||||
Script::Myanmar => &["Noto Sans Myanmar"],
|
||||
Script::Sinhala => &["Noto Sans Sinhala"],
|
||||
Script::Syriac => &["Noto Sans Syriac"],
|
||||
Script::Tai_Le => &["Noto Sans Tai Le"],
|
||||
Script::Tai_Tham => &["Noto Sans Tai Tham"],
|
||||
Script::Tai_Viet => &["Noto Sans Tai Viet"],
|
||||
Script::Tagalog => &["Noto Sans Tagalog"],
|
||||
Script::Tamil => &["Noto Sans Tamil"],
|
||||
Script::Telugu => &["Noto Sans Telugu"],
|
||||
Script::Thaana => &["Noto Sans Thaana"],
|
||||
Script::Thai => &["Noto Sans Thai"],
|
||||
//TODO: no sans script?
|
||||
Script::Tibetan => &["Noto Serif Tibetan"],
|
||||
Script::Vai => &["Noto Sans Vai"],
|
||||
Script::Yi => &["Noto Sans Yi", /*TODO: Choose a CJK font*/],
|
||||
_ => &[],
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ impl<'a> FontMatches<'a> {
|
|||
&line[start_word..end_word],
|
||||
);
|
||||
} else {
|
||||
log::debug!(
|
||||
log::trace!(
|
||||
" Word {:?}{}: '{}'",
|
||||
scripts,
|
||||
if blank { " BLANK" } else { "" },
|
||||
|
|
@ -142,7 +142,8 @@ impl<'a> FontMatches<'a> {
|
|||
);
|
||||
}
|
||||
|
||||
let mut font_iter = FontFallbackIter::new(&self.fonts, scripts, &self.locale);
|
||||
//TODO: configure default family
|
||||
let mut font_iter = FontFallbackIter::new(&self.fonts, Some("Fira Sans"), scripts, &self.locale);
|
||||
|
||||
let (mut glyphs, mut missing) = self.shape_fallback(
|
||||
font_iter.next().unwrap(),
|
||||
|
|
@ -154,10 +155,11 @@ impl<'a> FontMatches<'a> {
|
|||
);
|
||||
|
||||
//TODO: improve performance!
|
||||
while let Some(font) = font_iter.next() {
|
||||
if missing.is_empty() {
|
||||
break;
|
||||
}
|
||||
while !missing.is_empty() {
|
||||
let font = match font_iter.next() {
|
||||
Some(some) => some,
|
||||
None => break,
|
||||
};
|
||||
|
||||
log::trace!("Evaluating fallback with font '{}'", font.info.family);
|
||||
let (mut fb_glyphs, fb_missing) = self.shape_fallback(
|
||||
|
|
@ -243,7 +245,7 @@ impl<'a> FontMatches<'a> {
|
|||
) -> FontShapeSpan {
|
||||
let span = &line[start_span..end_span];
|
||||
|
||||
log::debug!(
|
||||
log::trace!(
|
||||
" Span {}: '{}'",
|
||||
if span_rtl { "RTL" } else { "LTR" },
|
||||
span
|
||||
|
|
@ -311,7 +313,7 @@ impl<'a> FontMatches<'a> {
|
|||
let para_info = &bidi.paragraphs[0];
|
||||
let line_rtl = para_info.level.is_rtl();
|
||||
|
||||
log::debug!("Line {}: '{}'", if line_rtl { "RTL" } else { "LTR" }, line);
|
||||
log::trace!("Line {}: '{}'", if line_rtl { "RTL" } else { "LTR" }, line);
|
||||
|
||||
let paragraph = unicode_bidi::Paragraph::new(&bidi, ¶_info);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue