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
|
|
@ -27,6 +27,8 @@ pub struct Font {
|
|||
rustybuzz: OwnedFace,
|
||||
data: Arc<dyn AsRef<[u8]> + Send + Sync>,
|
||||
id: fontdb::ID,
|
||||
monospace_em_width: Option<f32>,
|
||||
scripts: Vec<[u8; 4]>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Font {
|
||||
|
|
@ -42,6 +44,14 @@ impl Font {
|
|||
self.id
|
||||
}
|
||||
|
||||
pub fn monospace_em_width(&self) -> Option<f32> {
|
||||
self.monospace_em_width
|
||||
}
|
||||
|
||||
pub fn scripts(&self) -> &[[u8; 4]] {
|
||||
&self.scripts
|
||||
}
|
||||
|
||||
pub fn data(&self) -> &[u8] {
|
||||
(*self.data).as_ref()
|
||||
}
|
||||
|
|
@ -62,7 +72,32 @@ impl Font {
|
|||
}
|
||||
|
||||
impl Font {
|
||||
pub fn new(info: &fontdb::FaceInfo) -> Option<Self> {
|
||||
pub fn new(db: &fontdb::Database, id: fontdb::ID) -> Option<Self> {
|
||||
let info = db.face(id)?;
|
||||
|
||||
let (monospace_em_width, scripts) = {
|
||||
db.with_face_data(id, |font_data, face_index| {
|
||||
let face = ttf_parser::Face::parse(font_data, face_index).ok()?;
|
||||
let monospace_em_width = info.monospaced.then(|| {
|
||||
let hor_advance = face.glyph_hor_advance(face.glyph_index(' ')?)? as f32;
|
||||
let upem = face.units_per_em() as f32;
|
||||
Some(hor_advance/upem)
|
||||
}).flatten();
|
||||
|
||||
if info.monospaced && monospace_em_width.is_none() {
|
||||
None?;
|
||||
}
|
||||
|
||||
let scripts = face.tables().gpos.into_iter()
|
||||
.chain(face.tables().gsub)
|
||||
.map(|table| table.scripts)
|
||||
.flatten()
|
||||
.map(|script| script.tag.to_bytes())
|
||||
.collect();
|
||||
Some((monospace_em_width, scripts))
|
||||
})?
|
||||
}?;
|
||||
|
||||
let data = match &info.source {
|
||||
fontdb::Source::Binary(data) => Arc::clone(data),
|
||||
#[cfg(feature = "std")]
|
||||
|
|
@ -76,6 +111,8 @@ impl Font {
|
|||
|
||||
Some(Self {
|
||||
id: info.id,
|
||||
monospace_em_width,
|
||||
scripts,
|
||||
#[cfg(feature = "swash")]
|
||||
swash: {
|
||||
let swash = swash::FontRef::from_index((*data).as_ref(), info.index as usize)?;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue