1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-23 13:21:38 +03:00

fonts: defer best match until we have font_dirs + locator + builtin

A user reported an issue where having just Roboto Thin installed
caused the title font to use that one, rather than the desired
Roboto Bold.

This commit adjusts the font matching code to accumulate candidates
from each of the font_dirs, locator and built-in font locations,
and then find the best match.
This commit is contained in:
Wez Furlong 2022-01-01 11:34:39 -07:00
parent e148cfe8e3
commit 58ece29f00
2 changed files with 69 additions and 40 deletions

View File

@ -75,9 +75,6 @@ impl FontDatabase {
pixel_size: u16,
) {
for attr in fonts {
if loaded.contains(attr) {
continue;
}
if let Some(handle) = self.resolve(attr, pixel_size) {
handles.push(handle.clone().synthesize(attr));
loaded.insert(attr.clone());
@ -112,6 +109,19 @@ impl FontDatabase {
Ok(matches)
}
pub fn candidates(&self, font_attr: &FontAttributes) -> Vec<&ParsedFont> {
self.by_full_name
.values()
.filter_map(|parsed| {
if parsed.matches_name(font_attr) {
Some(parsed)
} else {
None
}
})
.collect()
}
pub fn resolve(&self, font_attr: &FontAttributes, pixel_size: u16) -> Option<&ParsedFont> {
let candidates: Vec<&ParsedFont> = self
.by_full_name

View File

@ -531,8 +531,6 @@ impl FontConfigInner {
let (sys_font, sys_size) = self.compute_title_font(&config);
let mut handles = vec![];
let font_size = config.window_frame.font_size.unwrap_or(sys_size);
let text_style = config
@ -545,27 +543,7 @@ impl FontConfigInner {
let pixel_size = (font_size * dpi as f64 / 72.0) as u16;
let attributes = text_style.font_with_fallback();
let preferred_attributes = attributes
.iter()
.filter(|a| !a.is_fallback)
.map(|a| a.clone())
.collect::<Vec<_>>();
let fallback_attributes = attributes
.iter()
.filter(|a| a.is_fallback)
.map(|a| a.clone())
.collect::<Vec<_>>();
let mut loaded = HashSet::new();
for attrs in &[&preferred_attributes, &fallback_attributes] {
self.font_dirs
.borrow()
.resolve_multiple(attrs, &mut handles, &mut loaded, pixel_size);
handles.append(&mut self.locator.load_fonts(attrs, &mut loaded, pixel_size)?);
self.built_in
.borrow()
.resolve_multiple(attrs, &mut handles, &mut loaded, pixel_size);
}
let (handles, _loaded) = self.resolve_font_helper_impl(&attributes, pixel_size)?;
let shaper = new_shaper(&*config, &handles)?;
@ -594,13 +572,11 @@ impl FontConfigInner {
Ok(loaded)
}
fn resolve_font_helper(
fn resolve_font_helper_impl(
&self,
style: &TextStyle,
config: &ConfigHandle,
attributes: &[FontAttributes],
pixel_size: u16,
) -> anyhow::Result<(Box<dyn FontShaper>, Vec<ParsedFont>)> {
let attributes = style.font_with_fallback();
) -> anyhow::Result<(Vec<ParsedFont>, HashSet<FontAttributes>)> {
let preferred_attributes = attributes
.iter()
.filter(|a| !a.is_fallback)
@ -612,18 +588,61 @@ impl FontConfigInner {
.map(|a| a.clone())
.collect::<Vec<_>>();
let mut loaded = HashSet::new();
let mut handles = vec![];
for attrs in &[&preferred_attributes, &fallback_attributes] {
self.font_dirs
.borrow()
.resolve_multiple(attrs, &mut handles, &mut loaded, pixel_size);
handles.append(&mut self.locator.load_fonts(attrs, &mut loaded, pixel_size)?);
self.built_in
.borrow()
.resolve_multiple(attrs, &mut handles, &mut loaded, pixel_size);
for &attrs in &[&preferred_attributes, &fallback_attributes] {
let mut candidates = vec![];
let font_dirs = self.font_dirs.borrow();
for attr in attrs {
candidates.append(&mut font_dirs.candidates(attr));
}
let mut loaded_ignored = HashSet::new();
let located = self
.locator
.load_fonts(attrs, &mut loaded_ignored, pixel_size)?;
for font in &located {
candidates.push(font);
}
let built_in = self.built_in.borrow();
for attr in attrs {
candidates.append(&mut built_in.candidates(attr));
}
for attr in attrs {
if loaded.contains(attr) {
continue;
}
let named_candidates: Vec<&ParsedFont> = candidates
.iter()
.filter_map(|&p| if p.matches_name(attr) { Some(p) } else { None })
.collect();
if let Some(idx) =
ParsedFont::best_matching_index(attr, &named_candidates, pixel_size)
{
named_candidates.get(idx).map(|&p| {
loaded.insert(attr.clone());
handles.push(p.clone().synthesize(attr))
});
}
}
}
Ok((handles, loaded))
}
fn resolve_font_helper(
&self,
style: &TextStyle,
config: &ConfigHandle,
pixel_size: u16,
) -> anyhow::Result<(Box<dyn FontShaper>, Vec<ParsedFont>)> {
let attributes = style.font_with_fallback();
let (handles, loaded) = self.resolve_font_helper_impl(&attributes, pixel_size)?;
for attr in &attributes {
if !attr.is_synthetic && !attr.is_fallback && !loaded.contains(attr) {
let styled_extra = if attr.weight != FontWeight::default()