mirror of
https://github.com/typst/typst
synced 2025-05-19 11:35:27 +08:00
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:
parent
0001a965d7
commit
7eeafbd464
@ -233,8 +233,9 @@ impl Default for FamilyState {
|
|||||||
sans_serif: Rc::new(vec!["pt sans".into()]),
|
sans_serif: Rc::new(vec!["pt sans".into()]),
|
||||||
monospace: Rc::new(vec!["inconsolata".into()]),
|
monospace: Rc::new(vec!["inconsolata".into()]),
|
||||||
base: Rc::new(vec![
|
base: Rc::new(vec![
|
||||||
"twitter color emoji".into(),
|
"eb garamond".into(),
|
||||||
"latin modern math".into(),
|
"latin modern math".into(),
|
||||||
|
"twitter color emoji".into(),
|
||||||
]),
|
]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
34
src/font.rs
34
src/font.rs
@ -1,6 +1,6 @@
|
|||||||
//! Font handling.
|
//! 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::fmt::{self, Debug, Display, Formatter};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@ -35,7 +35,7 @@ impl FaceId {
|
|||||||
pub struct FontStore {
|
pub struct FontStore {
|
||||||
loader: Rc<dyn Loader>,
|
loader: Rc<dyn Loader>,
|
||||||
faces: Vec<Option<Face>>,
|
faces: Vec<Option<Face>>,
|
||||||
families: HashMap<String, Vec<FaceId>>,
|
families: BTreeMap<String, Vec<FaceId>>,
|
||||||
buffers: HashMap<FileHash, Rc<Vec<u8>>>,
|
buffers: HashMap<FileHash, Rc<Vec<u8>>>,
|
||||||
on_load: Option<Box<dyn Fn(FaceId, &Face)>>,
|
on_load: Option<Box<dyn Fn(FaceId, &Face)>>,
|
||||||
}
|
}
|
||||||
@ -44,15 +44,12 @@ impl FontStore {
|
|||||||
/// Create a new, empty font store.
|
/// Create a new, empty font store.
|
||||||
pub fn new(loader: Rc<dyn Loader>) -> Self {
|
pub fn new(loader: Rc<dyn Loader>) -> Self {
|
||||||
let mut faces = vec![];
|
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() {
|
for (i, info) in loader.faces().iter().enumerate() {
|
||||||
let id = FaceId(i as u32);
|
let id = FaceId(i as u32);
|
||||||
faces.push(None);
|
faces.push(None);
|
||||||
families
|
families.entry(info.family.to_lowercase()).or_default().push(id);
|
||||||
.entry(info.family.to_lowercase())
|
|
||||||
.and_modify(|vec| vec.push(id))
|
|
||||||
.or_insert_with(|| vec![id]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
@ -146,6 +143,16 @@ impl FontStore {
|
|||||||
pub fn get(&self, id: FaceId) -> &Face {
|
pub fn get(&self, id: FaceId) -> &Face {
|
||||||
self.faces[id.0 as usize].as_ref().expect("font face was not loaded")
|
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.
|
/// A font face.
|
||||||
@ -356,9 +363,14 @@ impl FaceInfo {
|
|||||||
|
|
||||||
(0 .. count).filter_map(move |index| {
|
(0 .. count).filter_map(move |index| {
|
||||||
let face = ttf_parser::Face::from_slice(data, index).ok()?;
|
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))?;
|
.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 {
|
let variant = FontVariant {
|
||||||
style: match (face.is_italic(), face.is_oblique()) {
|
style: match (face.is_italic(), face.is_oblique()) {
|
||||||
(false, false) => FontStyle::Normal,
|
(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.
|
/// The style of a font face.
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user