blitz_dom/
font_fallback.rs1use std::sync::{Arc, OnceLock};
14
15use parley::fontique::{Blob, FamilyId, FontInfoOverride, GenericFamily, Script};
16
17use crate::FontContext;
18
19pub type FamilyFallback = fn(&str) -> Option<&'static str>;
21
22static FAMILY_FALLBACK: OnceLock<FamilyFallback> = OnceLock::new();
23
24pub(crate) fn set(fallback: FamilyFallback) {
25 let _ = FAMILY_FALLBACK.set(fallback);
26}
27
28pub(crate) fn lookup(name: &str) -> Option<&'static str> {
30 let mapped = FAMILY_FALLBACK.get()?(name)?;
31 (!mapped.eq_ignore_ascii_case(name)).then_some(mapped)
32}
33
34pub fn register_face(ctx: &mut FontContext, bytes: &'static [u8]) {
36 ctx.collection
37 .register_fonts(Blob::new(Arc::new(bytes) as _), None);
38}
39
40pub fn register_family(
46 ctx: &mut FontContext,
47 family: &str,
48 bytes: &'static [u8],
49) -> Option<FamilyId> {
50 let registered = ctx.collection.register_fonts(
51 Blob::new(Arc::new(bytes) as _),
52 Some(FontInfoOverride {
53 family_name: Some(family),
54 ..FontInfoOverride::default()
55 }),
56 );
57 registered.into_iter().next().map(|(id, _)| id)
58}
59
60pub fn bind(
68 ctx: &mut FontContext,
69 sans: FamilyId,
70 serif: FamilyId,
71 mono: FamilyId,
72 extra: &[FamilyId],
73 scripts: &[[u8; 4]],
74) {
75 let with_extra = |primary: FamilyId| std::iter::once(primary).chain(extra.iter().copied());
76 for generic in [
77 GenericFamily::SansSerif,
78 GenericFamily::SystemUi,
79 GenericFamily::UiSansSerif,
80 ] {
81 ctx.collection
82 .set_generic_families(generic, with_extra(sans));
83 }
84 for generic in [GenericFamily::Serif, GenericFamily::UiSerif] {
85 ctx.collection
86 .set_generic_families(generic, with_extra(serif));
87 }
88 for generic in [GenericFamily::Monospace, GenericFamily::UiMonospace] {
89 ctx.collection
90 .set_generic_families(generic, with_extra(mono));
91 }
92 for script in scripts {
93 ctx.collection
94 .append_fallbacks(Script::from_bytes(*script), extra.iter().copied());
95 }
96}