Fix variable font weight matching in FontMatchKey
Add variable_weight_match flag to FontMatchKey: when a face has a wght axis covering the requested weight, let it pass the font_weight_diff == 0 filter without altering sort priority. The check is done inline via db.with_face_data() in FontMatchKey::new() so it participates in the existing font_matches_cache invalidation — no separate caching needed.
This commit is contained in:
parent
29034e56b4
commit
5b9e2f2588
2 changed files with 18 additions and 8 deletions
|
|
@ -282,7 +282,7 @@ impl<'a> FontFallbackIter<'a> {
|
|||
|
||||
self.font_match_keys
|
||||
.iter()
|
||||
.filter(|m_key| m_key.font_weight_diff == 0)
|
||||
.filter(|m_key| m_key.font_weight_diff == 0 || m_key.variable_weight_match)
|
||||
.find(|m_key| self.face_contains_family(m_key.id, default_family_name))
|
||||
}
|
||||
|
||||
|
|
@ -297,9 +297,9 @@ impl<'a> FontFallbackIter<'a> {
|
|||
}
|
||||
|
||||
let font_match_keys_iter = |is_mono| {
|
||||
self.font_match_keys
|
||||
.iter()
|
||||
.filter(move |m_key| m_key.font_weight_diff == 0 || is_mono)
|
||||
self.font_match_keys.iter().filter(move |m_key| {
|
||||
m_key.font_weight_diff == 0 || m_key.variable_weight_match || is_mono
|
||||
})
|
||||
};
|
||||
|
||||
'DEF_FAM: while self.default_i < self.default_families.len() {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use core::fmt;
|
|||
use core::ops::{Deref, DerefMut};
|
||||
use fontdb::{FaceInfo, Query, Style};
|
||||
use skrifa::raw::{ReadError, TableProvider as _};
|
||||
use skrifa::MetadataProvider;
|
||||
|
||||
// re-export fontdb and harfrust
|
||||
pub use fontdb;
|
||||
|
|
@ -25,14 +26,22 @@ pub struct FontMatchKey {
|
|||
pub(crate) font_weight: u16,
|
||||
pub(crate) font_stretch: u16,
|
||||
pub(crate) id: fontdb::ID,
|
||||
pub(crate) variable_weight_match: bool,
|
||||
}
|
||||
|
||||
impl FontMatchKey {
|
||||
fn new(attrs: &Attrs, face: &FaceInfo) -> FontMatchKey {
|
||||
fn new(attrs: &Attrs, face: &FaceInfo, db: &fontdb::Database) -> FontMatchKey {
|
||||
// TODO: smarter way of detecting emoji
|
||||
let not_emoji = !face.post_script_name.contains("Emoji");
|
||||
// TODO: correctly take variable axes into account
|
||||
let font_weight_diff = attrs.weight.0.abs_diff(face.weight.0);
|
||||
|
||||
let variable_weight_match = font_weight_diff != 0
|
||||
&& db.with_face_data(face.id, |font_data, face_index| {
|
||||
let font_ref = skrifa::FontRef::from_index(font_data, face_index).ok()?;
|
||||
let axis = font_ref.axes().get_by_tag(skrifa::Tag::new(b"wght"))?;
|
||||
let w = attrs.weight.0 as f32;
|
||||
Some(w >= axis.min_value() && w <= axis.max_value())
|
||||
}) == Some(Some(true));
|
||||
let font_weight = face.weight.0;
|
||||
let font_stretch_diff = attrs.stretch.to_number().abs_diff(face.stretch.to_number());
|
||||
let font_stretch = face.stretch.to_number();
|
||||
|
|
@ -55,6 +64,7 @@ impl FontMatchKey {
|
|||
font_weight,
|
||||
font_stretch,
|
||||
id,
|
||||
variable_weight_match,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -363,7 +373,7 @@ impl FontSystem {
|
|||
let mut font_match_keys = self
|
||||
.db
|
||||
.faces()
|
||||
.map(|face| FontMatchKey::new(attrs, face))
|
||||
.map(|face| FontMatchKey::new(attrs, face, &self.db))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Sort so we get the keys with weight_offset=0 first
|
||||
|
|
@ -389,7 +399,7 @@ impl FontSystem {
|
|||
font_match_keys.insert(0, match_key);
|
||||
} else if let Some(face) = self.db.face(id) {
|
||||
// else insert in front
|
||||
let match_key = FontMatchKey::new(attrs, face);
|
||||
let match_key = FontMatchKey::new(attrs, face, &self.db);
|
||||
font_match_keys.insert(0, match_key);
|
||||
} else {
|
||||
log::error!("Could not get face from db, that should've been there.");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue