mirror of
https://github.com/wez/wezterm.git
synced 2024-12-25 22:33:52 +03:00
fonts: refine fallback some more
* Log which codepoints we're about to perform fallback resolution for * Rank the fallback fonts by decreasing amount of coverage * If a fallback covers the desired codepoints, remove those codepoints from the set and reduce, so that we only add the minimal set of fallback fonts for the set of codepoints You can see what triggered fallback processing using: ``` ; WEZTERM_LOG=wezterm_font=trace wezterm -n 2> /tmp/font.txt ; grep 'fallback font' /tmp/font.txt 2021-04-11T21:41:09.653Z TRACE wezterm_font > Looking for \u{d604}\u{c7ac}\u{be0c}\u{b79c}\u{ce58} in fallback fonts 2021-04-11T21:41:12.132Z TRACE wezterm_font > Looking for \u{f4e9} in fallback fonts ``` refs: https://github.com/wez/wezterm/issues/559#issuecomment-817260512
This commit is contained in:
parent
0ab6382bb4
commit
903c7a47b6
@ -5,7 +5,6 @@ use crate::parser::{load_built_in_fonts, parse_and_collect_font_info, ParsedFont
|
||||
use anyhow::Context;
|
||||
use config::{Config, FontAttributes};
|
||||
use rangeset::RangeSet;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
pub struct FontDatabase {
|
||||
@ -109,26 +108,12 @@ impl FontDatabase {
|
||||
let covered = parsed
|
||||
.coverage_intersection(&wanted_range)
|
||||
.with_context(|| format!("coverage_interaction for {:?}", parsed))?;
|
||||
let len = covered.len();
|
||||
if len > 0 {
|
||||
matches.push((len, parsed.clone()));
|
||||
if !covered.is_empty() {
|
||||
matches.push(parsed.clone());
|
||||
}
|
||||
}
|
||||
|
||||
// Add the handles in order of descending coverage; the idea being
|
||||
// that if a font has a large coverage then it is probably a better
|
||||
// candidate and more likely to result in other glyphs matching
|
||||
// in future shaping calls.
|
||||
matches.sort_by(|(a_len, a), (b_len, b)| {
|
||||
let primary = a_len.cmp(&b_len).reverse();
|
||||
if primary == Ordering::Equal {
|
||||
a.cmp(b)
|
||||
} else {
|
||||
primary
|
||||
}
|
||||
});
|
||||
|
||||
Ok(matches.into_iter().map(|(_len, handle)| handle).collect())
|
||||
Ok(matches)
|
||||
}
|
||||
|
||||
pub fn resolve(&self, font_attr: &FontAttributes) -> Option<&ParsedFont> {
|
||||
|
@ -7,6 +7,7 @@ use anyhow::{Context, Error};
|
||||
use config::{
|
||||
configuration, ConfigHandle, FontRasterizerSelection, FontStretch, FontWeight, TextStyle,
|
||||
};
|
||||
use rangeset::RangeSet;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::rc::{Rc, Weak};
|
||||
@ -214,6 +215,11 @@ impl FontConfigInner {
|
||||
let fallback_str = no_glyphs.iter().collect::<String>();
|
||||
let mut extra_handles = vec![];
|
||||
|
||||
log::trace!(
|
||||
"Looking for {} in fallback fonts",
|
||||
fallback_str.escape_unicode()
|
||||
);
|
||||
|
||||
match font_dirs.locate_fallback_for_codepoints(&no_glyphs) {
|
||||
Ok(ref mut handles) => extra_handles.append(handles),
|
||||
Err(err) => log::error!(
|
||||
@ -241,11 +247,44 @@ impl FontConfigInner {
|
||||
),
|
||||
}
|
||||
|
||||
let mut wanted = RangeSet::new();
|
||||
for c in no_glyphs {
|
||||
wanted.add(c as u32);
|
||||
}
|
||||
|
||||
// Sort by ascending coverage
|
||||
extra_handles.sort_by_cached_key(|p| {
|
||||
p.coverage_intersection(&wanted)
|
||||
.map(|r| r.len())
|
||||
.unwrap_or(0)
|
||||
});
|
||||
// Re-arrange to descending coverage
|
||||
extra_handles.reverse();
|
||||
// iteratively reduce to just the fonts that we need
|
||||
extra_handles.retain(|p| match p.coverage_intersection(&wanted) {
|
||||
Ok(cov) if cov.is_empty() => false,
|
||||
Ok(cov) => {
|
||||
// Remove the matches from the set, so that we avoid
|
||||
// picking up multiple fonts for the same glyphs
|
||||
wanted = wanted.difference(&cov);
|
||||
true
|
||||
}
|
||||
Err(_) => false,
|
||||
});
|
||||
|
||||
if !extra_handles.is_empty() {
|
||||
let mut pending = pending.lock().unwrap();
|
||||
pending.append(&mut extra_handles);
|
||||
completion();
|
||||
} else {
|
||||
}
|
||||
|
||||
if !wanted.is_empty() {
|
||||
// There were some glyphs we couldn't resolve!
|
||||
let fallback_str = wanted
|
||||
.iter_values()
|
||||
.map(|c| std::char::from_u32(c).unwrap_or(' '))
|
||||
.collect::<String>();
|
||||
|
||||
if config.warn_about_missing_glyphs {
|
||||
mux::connui::show_configuration_error_message(&format!(
|
||||
"No fonts contain glyphs for these codepoints: {}.\n\
|
||||
|
Loading…
Reference in New Issue
Block a user