Try harder to succeed at fall-backing to a Monospace font
A combination of some ideas: * Try all Monospace fonts before giving up. * Relax exact weight restriction on font matching when trying Monospace fall-back. Try smaller weights if needed. * Make the fall-back try order weight-offset aware, AND script-aware. * And finally, add the option to adjust the font size of glyphs using fall-back Monospace fonts, so the width of them matches the default font width. For my use-case, the current fall-back attempt always fails with Arabic script. And none of the Arabic-supporting Monospace fonts in my system also support medium weight. So, if my default font is set to medium weight, script-aware fall-back alone will still not work. Signed-off-by: Mohammad AlSaleh <CE.Mohammad.AlSaleh@gmail.com>
This commit is contained in:
parent
054b7da828
commit
329941c4a6
8 changed files with 177 additions and 39 deletions
|
|
@ -9,6 +9,12 @@ use core::ops::{Deref, DerefMut};
|
|||
pub use fontdb;
|
||||
pub use rustybuzz;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct FontMatchKey {
|
||||
pub(crate) weight_offset: u16,
|
||||
pub(crate) id: fontdb::ID,
|
||||
}
|
||||
|
||||
/// Access to the system fonts.
|
||||
pub struct FontSystem {
|
||||
/// The locale of the system.
|
||||
|
|
@ -21,7 +27,7 @@ pub struct FontSystem {
|
|||
font_cache: HashMap<fontdb::ID, Option<Arc<Font>>>,
|
||||
|
||||
/// Cache for font matches.
|
||||
font_matches_cache: HashMap<AttrsOwned, Arc<Vec<fontdb::ID>>>,
|
||||
font_matches_cache: HashMap<AttrsOwned, Arc<Vec<FontMatchKey>>>,
|
||||
|
||||
/// Cache for rustybuzz shape plans.
|
||||
shape_plan_cache: ShapePlanCache,
|
||||
|
|
@ -111,11 +117,10 @@ impl FontSystem {
|
|||
unsafe {
|
||||
self.db.make_shared_face_data(id);
|
||||
}
|
||||
let face = self.db.face(id)?;
|
||||
match Font::new(face) {
|
||||
match Font::new(&self.db, id) {
|
||||
Some(font) => Some(Arc::new(font)),
|
||||
None => {
|
||||
log::warn!("failed to load font '{}'", face.post_script_name);
|
||||
log::warn!("failed to load font '{}'", self.db.face(id)?.post_script_name);
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
@ -123,7 +128,7 @@ impl FontSystem {
|
|||
.clone()
|
||||
}
|
||||
|
||||
pub fn get_font_matches(&mut self, attrs: Attrs<'_>) -> Arc<Vec<fontdb::ID>> {
|
||||
pub fn get_font_matches(&mut self, attrs: Attrs<'_>) -> Arc<Vec<FontMatchKey>> {
|
||||
self.font_matches_cache
|
||||
//TODO: do not create AttrsOwned unless entry does not already exist
|
||||
.entry(AttrsOwned::new(attrs))
|
||||
|
|
@ -131,20 +136,23 @@ impl FontSystem {
|
|||
#[cfg(all(feature = "std", not(target_arch = "wasm32")))]
|
||||
let now = std::time::Instant::now();
|
||||
|
||||
let ids = self
|
||||
let mut font_match_keys = self
|
||||
.db
|
||||
.faces()
|
||||
.filter(|face| attrs.matches(face))
|
||||
.map(|face| face.id)
|
||||
.map(|face| FontMatchKey{ weight_offset: attrs.weight.0 - face.weight.0, id: face.id })
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Sort so we get the keys with weight_offset=0 first
|
||||
font_match_keys.sort();
|
||||
|
||||
#[cfg(all(feature = "std", not(target_arch = "wasm32")))]
|
||||
{
|
||||
let elapsed = now.elapsed();
|
||||
log::debug!("font matches for {:?} in {:?}", attrs, elapsed);
|
||||
}
|
||||
|
||||
Arc::new(ids)
|
||||
Arc::new(font_match_keys)
|
||||
})
|
||||
.clone()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue