diff --git a/src/eval/state.rs b/src/eval/state.rs index d7ca014dd..2037c695e 100644 --- a/src/eval/state.rs +++ b/src/eval/state.rs @@ -233,8 +233,9 @@ impl Default for FamilyState { sans_serif: Rc::new(vec!["pt sans".into()]), monospace: Rc::new(vec!["inconsolata".into()]), base: Rc::new(vec![ - "twitter color emoji".into(), + "eb garamond".into(), "latin modern math".into(), + "twitter color emoji".into(), ]), } } diff --git a/src/font.rs b/src/font.rs index 00bff02ea..2e935d3b4 100644 --- a/src/font.rs +++ b/src/font.rs @@ -1,6 +1,6 @@ //! Font handling. -use std::collections::{hash_map::Entry, HashMap}; +use std::collections::{hash_map::Entry, BTreeMap, HashMap}; use std::fmt::{self, Debug, Display, Formatter}; use std::path::{Path, PathBuf}; use std::rc::Rc; @@ -35,7 +35,7 @@ impl FaceId { pub struct FontStore { loader: Rc, faces: Vec>, - families: HashMap>, + families: BTreeMap>, buffers: HashMap>>, on_load: Option>, } @@ -44,15 +44,12 @@ impl FontStore { /// Create a new, empty font store. pub fn new(loader: Rc) -> Self { let mut faces = vec![]; - let mut families = HashMap::>::new(); + let mut families = BTreeMap::>::new(); for (i, info) in loader.faces().iter().enumerate() { let id = FaceId(i as u32); faces.push(None); - families - .entry(info.family.to_lowercase()) - .and_modify(|vec| vec.push(id)) - .or_insert_with(|| vec![id]); + families.entry(info.family.to_lowercase()).or_default().push(id); } Self { @@ -146,6 +143,16 @@ impl FontStore { pub fn get(&self, id: FaceId) -> &Face { self.faces[id.0 as usize].as_ref().expect("font face was not loaded") } + + /// Returns an ordered iterator over all font family names this loader + /// knows. + pub fn families(&self) -> impl Iterator + '_ { + // Since the keys are lowercased, we instead use the family field of the + // first face's info. + self.families + .values() + .map(move |id| self.loader.faces()[id[0].0 as usize].family.as_str()) + } } /// A font face. @@ -356,9 +363,14 @@ impl FaceInfo { (0 .. count).filter_map(move |index| { let face = ttf_parser::Face::from_slice(data, index).ok()?; - let family = find_name(face.names(), name_id::TYPOGRAPHIC_FAMILY) + let mut family = find_name(face.names(), name_id::TYPOGRAPHIC_FAMILY) .or_else(|| find_name(face.names(), name_id::FAMILY))?; + // Remove weird leading dot appearing in some fonts. + if let Some(undotted) = family.strip_prefix('.') { + family = undotted.to_string(); + } + let variant = FontVariant { style: match (face.is_italic(), face.is_oblique()) { (false, false) => FontStyle::Normal, @@ -415,6 +427,12 @@ impl FontVariant { } } +impl Display for FontVariant { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { + write!(f, "{}-{}-{}", self.style, self.weight, self.stretch) + } +} + /// The style of a font face. #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] #[derive(Serialize, Deserialize)]