Skip trying monospace fallbacks if default font supports all codepoints
Instead of blindly pushing default font to the start of the monospace fallbacks map. Actually collect codepoint support info for it, and if it supports all codepoints, skip collecting that info from other monospace fonts. If it doesn't, push it to the start of the map as before. This actually provides a big performance boost, while the sophisticated monospace fallback process is still done whenever needed. Signed-off-by: Mohammad AlSaleh <CE.Mohammad.AlSaleh@gmail.com>
This commit is contained in:
parent
729dc868c2
commit
18c3d2acec
1 changed files with 63 additions and 25 deletions
|
|
@ -130,6 +130,16 @@ impl<'a> FontFallbackIter<'a> {
|
|||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn default_font_match_key(&self) -> Option<&FontMatchKey> {
|
||||
let default_family = self.default_families[self.default_i - 1];
|
||||
let default_family_name = self.font_system.db().family_name(default_family);
|
||||
|
||||
self.font_match_keys
|
||||
.iter()
|
||||
.filter(|m_key| m_key.font_weight_diff == 0)
|
||||
.find(|m_key| self.face_contains_family(m_key.id, default_family_name))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Iterator for FontFallbackIter<'a> {
|
||||
|
|
@ -147,9 +157,58 @@ impl<'a> Iterator for FontFallbackIter<'a> {
|
|||
.filter(move |m_key| m_key.font_weight_diff == 0 || is_mono)
|
||||
};
|
||||
|
||||
while self.default_i < self.default_families.len() {
|
||||
'DEF_FAM: while self.default_i < self.default_families.len() {
|
||||
self.default_i += 1;
|
||||
let is_mono = self.default_families[self.default_i - 1] == &Family::Monospace;
|
||||
let default_font_match_key = self.default_font_match_key().cloned();
|
||||
let word_chars_count = self.word.chars().count();
|
||||
|
||||
macro_rules! mk_mono_fallback_info {
|
||||
($m_key:expr) => {{
|
||||
let supported_cp_count_opt = self
|
||||
.font_system
|
||||
.get_font_supported_codepoints_in_word($m_key.id, self.word);
|
||||
|
||||
supported_cp_count_opt.map(|supported_cp_count| {
|
||||
let codepoint_non_matches = word_chars_count - supported_cp_count;
|
||||
|
||||
MonospaceFallbackInfo {
|
||||
font_weight_diff: Some($m_key.font_weight_diff),
|
||||
codepoint_non_matches: Some(codepoint_non_matches),
|
||||
font_weight: $m_key.font_weight,
|
||||
id: $m_key.id,
|
||||
}
|
||||
})
|
||||
}};
|
||||
}
|
||||
|
||||
match (is_mono, default_font_match_key.as_ref()) {
|
||||
(false, None) => break 'DEF_FAM,
|
||||
(false, Some(m_key)) => {
|
||||
if let Some(font) = self.font_system.get_font(m_key.id) {
|
||||
return Some(font);
|
||||
} else {
|
||||
break 'DEF_FAM;
|
||||
}
|
||||
}
|
||||
(true, None) => (),
|
||||
(true, Some(m_key)) => {
|
||||
// Default Monospace font
|
||||
if let Some(mut fallback_info) = mk_mono_fallback_info!(m_key) {
|
||||
fallback_info.font_weight_diff = None;
|
||||
|
||||
// Return early if default Monospace font supports all word codepoints.
|
||||
// Otherewise, add to fallbacks set
|
||||
if fallback_info.codepoint_non_matches == Some(0) {
|
||||
if let Some(font) = self.font_system.get_font(m_key.id) {
|
||||
return Some(font);
|
||||
}
|
||||
} else {
|
||||
assert!(self.monospace_fallbacks.insert(fallback_info));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let mono_ids_for_scripts = if is_mono && !self.scripts.is_empty() {
|
||||
let scripts = self.scripts.iter().filter_map(|script| {
|
||||
|
|
@ -162,35 +221,14 @@ impl<'a> Iterator for FontFallbackIter<'a> {
|
|||
};
|
||||
|
||||
for m_key in font_match_keys_iter(is_mono) {
|
||||
let default_family = self
|
||||
.font_system
|
||||
.db()
|
||||
.family_name(self.default_families[self.default_i - 1]);
|
||||
if self.face_contains_family(m_key.id, default_family) {
|
||||
if let Some(font) = self.font_system.get_font(m_key.id) {
|
||||
if !is_mono {
|
||||
return Some(font);
|
||||
} else if m_key.font_weight_diff == 0 {
|
||||
// Default font
|
||||
let fallback_info = MonospaceFallbackInfo {
|
||||
font_weight_diff: None,
|
||||
codepoint_non_matches: None,
|
||||
font_weight: m_key.font_weight,
|
||||
id: m_key.id,
|
||||
};
|
||||
assert!(self.monospace_fallbacks.insert(fallback_info));
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set a monospace fallback if Monospace family is not found
|
||||
if is_mono {
|
||||
let include_mono_id = if mono_ids_for_scripts.is_empty() {
|
||||
if Some(m_key.id) != default_font_match_key.as_ref().map(|m_key| m_key.id) {
|
||||
let is_mono_id = if mono_ids_for_scripts.is_empty() {
|
||||
self.font_system.is_monospace(m_key.id)
|
||||
} else {
|
||||
mono_ids_for_scripts.binary_search(&m_key.id).is_ok()
|
||||
};
|
||||
|
||||
if include_mono_id {
|
||||
if is_mono_id {
|
||||
let supported_cp_count_opt = self
|
||||
.font_system
|
||||
.get_font_supported_codepoints_in_word(m_key.id, self.word);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue