// System TrueType/OpenType font discovery. // // Wraps a `fontdb` database loaded with the user's installed system fonts so // the rest of the app can (a) list available font families for the text-style // picker and (b) borrow a face's raw bytes to extract glyph outlines (see the // TTF glyph engine). LFF stroke fonts stay separate — this is purely the // TrueType side of the renderer. use std::sync::OnceLock; struct SysFonts { db: fontdb::Database, /// Sorted, de-duplicated family names for the picker. families: Vec, } static FONTS: OnceLock = OnceLock::new(); fn fonts() -> &'static SysFonts { FONTS.get_or_init(|| { let mut db = fontdb::Database::new(); db.load_system_fonts(); let mut families: Vec = db .faces() .filter_map(|face| face.families.first().map(|(name, _)| name.clone())) .collect(); families.sort_by_key(|n| n.to_lowercase()); families.dedup(); SysFonts { db, families } }) } /// All installed system font families, sorted case-insensitively, de-duped. pub fn families() -> &'static [String] { &fonts().families } /// Resolve a family name to a concrete face id (regular weight/style). fn face_id(family: &str) -> Option { let db = &fonts().db; let query = fontdb::Query { families: &[fontdb::Family::Name(family)], ..Default::default() }; db.query(&query) } /// Borrow the raw face bytes for `family` and run `f` over them. The byte slice /// is only valid inside the closure, so callers extract everything they need /// (e.g. flattened glyph outlines) before returning. `index` is the face index /// within a TrueType collection. Returns `None` if the family is unknown. pub fn with_face_data(family: &str, f: impl FnOnce(&[u8], u32) -> T) -> Option { let id = face_id(family)?; fonts().db.with_face_data(id, f) } /// Whether `family` matches an installed system font (case-insensitive via /// fontdb's own matching). pub fn has_family(family: &str) -> bool { face_id(family).is_some() }