Font family things

- Better default font family order
- Remove weird leading dots from font family names
- Public API for retrieving all found font families
This commit is contained in:
Laurenz 2021-08-26 17:05:37 +02:00
parent 0001a965d7
commit 7eeafbd464
2 changed files with 28 additions and 9 deletions

View File

@ -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(),
]),
}
}

View File

@ -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<dyn Loader>,
faces: Vec<Option<Face>>,
families: HashMap<String, Vec<FaceId>>,
families: BTreeMap<String, Vec<FaceId>>,
buffers: HashMap<FileHash, Rc<Vec<u8>>>,
on_load: Option<Box<dyn Fn(FaceId, &Face)>>,
}
@ -44,15 +44,12 @@ impl FontStore {
/// Create a new, empty font store.
pub fn new(loader: Rc<dyn Loader>) -> Self {
let mut faces = vec![];
let mut families = HashMap::<String, Vec<FaceId>>::new();
let mut families = BTreeMap::<String, Vec<FaceId>>::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<Item = &str> + '_ {
// 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)]