This commit is contained in:
Jeremy Soller 2024-01-17 13:26:39 -07:00
parent 329941c4a6
commit a11f68f13d
6 changed files with 66 additions and 26 deletions

View file

@ -534,7 +534,11 @@ impl Buffer {
}
/// Set monospace width monospace glyphs should be resized to match. `None` means don't resize
pub fn set_monospace_width(&mut self, font_system: &mut FontSystem, monospace_width: Option<f32>) {
pub fn set_monospace_width(
&mut self,
font_system: &mut FontSystem,
monospace_width: Option<f32>,
) {
if monospace_width != self.monospace_width {
self.monospace_width = monospace_width;
self.relayout(font_system);

View file

@ -210,7 +210,15 @@ impl BufferLine {
let align = self.align;
let shape = self.shape_in_buffer(scratch, font_system);
let mut layout = Vec::with_capacity(1);
shape.layout_to_buffer(scratch, font_size, width, wrap, align, &mut layout, match_mono_width);
shape.layout_to_buffer(
scratch,
font_size,
width,
wrap,
align,
&mut layout,
match_mono_width,
);
self.layout_opt = Some(layout);
}
self.layout_opt.as_ref().expect("layout not found")

View file

@ -1,13 +1,13 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
use alloc::collections::BTreeSet;
use alloc::sync::Arc;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use alloc::collections::BTreeSet;
use fontdb::Family;
use unicode_script::Script;
use crate::{Font, FontSystem, ShapePlanCache, FontMatchKey};
use crate::{Font, FontMatchKey, FontSystem, ShapePlanCache};
use self::platform::*;
@ -138,9 +138,11 @@ impl<'a> Iterator for FontFallbackIter<'a> {
}
}
let font_match_keys_iter = |is_mono| self.font_match_keys
let font_match_keys_iter = |is_mono| {
self.font_match_keys
.iter()
.filter(move |m_key| m_key.weight_offset == 0 || is_mono);
.filter(move |m_key| m_key.weight_offset == 0 || is_mono)
};
while self.default_i < self.default_families.len() {
self.default_i += 1;
@ -160,7 +162,7 @@ impl<'a> Iterator for FontFallbackIter<'a> {
let fallback_info = MonospaceFallbackInfo {
weight_offset: None,
script_non_matches: None,
id: m_key.id
id: m_key.id,
};
assert_eq!(self.monospace_fallbacks.insert(fallback_info), true);
}
@ -168,25 +170,33 @@ impl<'a> Iterator for FontFallbackIter<'a> {
}
// Set a monospace fallback if Monospace family is not found
if is_mono {
let script_tags = self.scripts.iter()
let script_tags = self
.scripts
.iter()
.filter_map(|script| {
let script_as_lower = script.short_name().to_lowercase();
<[u8; 4]>::try_from(script_as_lower.as_bytes()).ok()
}).collect::<Vec<_>>();
})
.collect::<Vec<_>>();
if let Some(face_info) = self.font_system.db().face(m_key.id) {
// Don't use emoji fonts as Monospace
if face_info.monospaced && !face_info.post_script_name.contains("Emoji") {
if let Some(font) = self.font_system.get_font(m_key.id) {
let script_non_matches = self.scripts.len() - script_tags.iter()
.filter(|&&script_tag| {
font.scripts().iter().any(|&tag_bytes| tag_bytes == script_tag)
}).count();
let script_non_matches = self.scripts.len()
- script_tags
.iter()
.filter(|&&script_tag| {
font.scripts()
.iter()
.any(|&tag_bytes| tag_bytes == script_tag)
})
.count();
let fallback_info = MonospaceFallbackInfo {
weight_offset: Some(m_key.weight_offset),
script_non_matches: Some(script_non_matches),
id: m_key.id
id: m_key.id,
};
assert_eq!(self.monospace_fallbacks.insert(fallback_info), true);
}

View file

@ -78,17 +78,23 @@ impl Font {
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();
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()
let scripts = face
.tables()
.gpos
.into_iter()
.chain(face.tables().gsub)
.map(|table| table.scripts)
.flatten()

View file

@ -120,7 +120,10 @@ impl FontSystem {
match Font::new(&self.db, id) {
Some(font) => Some(Arc::new(font)),
None => {
log::warn!("failed to load font '{}'", self.db.face(id)?.post_script_name);
log::warn!(
"failed to load font '{}'",
self.db.face(id)?.post_script_name
);
None
}
}
@ -140,7 +143,10 @@ impl FontSystem {
.db
.faces()
.filter(|face| attrs.matches(face))
.map(|face| FontMatchKey{ weight_offset: attrs.weight.0 - face.weight.0, id: 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

View file

@ -1247,12 +1247,18 @@ impl ShapeLine {
let match_mono_em_width = match_mono_width.map(|w| w / font_size);
for glyph in included_glyphs {
let glyph_font_size = match(match_mono_em_width, glyph.font_monospace_em_width) {
(Some(match_em_width), Some(glyph_em_width)) if glyph_em_width != match_em_width => {
let glyph_font_size = font_size * (match_em_width / glyph_em_width);
let glyph_font_size = match (
match_mono_em_width,
glyph.font_monospace_em_width,
) {
(Some(match_em_width), Some(glyph_em_width))
if glyph_em_width != match_em_width =>
{
let glyph_font_size =
font_size * (match_em_width / glyph_em_width);
log::trace!("Adjusted glyph font size ({font_size} => {glyph_font_size})");
glyph_font_size
},
}
_ => font_size,
};