1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
use cosmic_text::{
FontSystem,
SwashCache,
fontdb::{
ID,
Source,
},
};
use hashbrown::HashMap;
use smart_default::SmartDefault;
use std::sync::Arc;
pub(crate) const DEFAULT_FONT_FAMILY: &'static str = "sans-serif";
pub(crate) const BASE_FONT_SIZE: f32 = 16.0;
pub(crate) const BASE_LINE_HEIGHT: f32 = 22.0;
/// The central font registry managing font loading, aliases, and resolution.
#[derive(Debug, SmartDefault)]
pub struct FontRegistry {
/// The underlying [`FontSystem`] used for shaping and font lookup.
#[default(FontSystem::new())]
pub(crate) system: FontSystem,
/// The mapping from user-defined aliases to loaded font IDs.
pub(crate) aliases: HashMap<String, Vec<ID>>,
/// The cache mapping aliases to resolved family names.
pub(crate) alias_cache: HashMap<String, String>,
/// The [`SwashCache`] used for rendering glyphs.
#[default(SwashCache::new())]
pub(crate) swash_cache: SwashCache,
/// The default font family.
#[default(DEFAULT_FONT_FAMILY)]
pub(crate) default_family: &'static str,
}
impl FontRegistry {
/// Creates a new font registry.
///
/// # Returns
/// - [`Self`]
pub fn new() -> Self {
Self::default()
}
/// Loads a font from raw data and associates it with the provided `alias`.
///
/// # Arguments
/// - `alias`: The alias used to reference the font family.
/// - `data`: The raw font data.
///
/// # Returns
/// - [`Self`]
pub fn load_font<T>(mut self, alias: &str, data: T) -> Self
where
T: Into<Vec<u8>>,
{
self.append_font(alias, data);
self
}
/// Loads all available system fonts into the registry.
///
/// # Note
/// Calls `fontdb`'s [`load_system_fonts`] internally.
///
/// # Returns
/// - [`Self`]
///
/// [`load_system_fonts`]: cosmic_text::fontdb::Database::load_system_fonts
pub fn load_system_fonts(mut self) -> Self {
self.system.db_mut().load_system_fonts();
self
}
/// Sets the default font family.
///
/// # Arguments
/// - `alias`: The default font family alias.
///
/// # Returns
/// - [`Self`]
pub fn default_family(mut self, alias: &'static str) -> Self {
self.default_family = alias;
self
}
/// Registers a font in the underlying font database.
///
/// # Arguments
/// - `alias`: The alias used to reference the font family.
/// - `data`: The raw font data.
pub(crate) fn append_font<T>(&mut self, alias: &str, data: T)
where
T: Into<Vec<u8>>,
{
let source = Source::Binary(Arc::new(data.into()));
let ids = self.system.db_mut().load_font_source(source);
self.aliases.insert(alias.to_string(), ids.to_vec());
}
/// Resolves and returns the default font family name.
///
/// # Returns
/// - The resolved font family name, or the built-in default family if
/// resolution fails.
pub(crate) fn get_default_family(&mut self) -> String {
self.resolve_family_name(self.default_family)
.unwrap_or(DEFAULT_FONT_FAMILY.to_string())
}
/// Resolves a font family alias into a concrete family name.
///
/// # Arguments
/// - `alias`: The font family alias to resolve.
///
/// # Returns
/// - `Some(String)` containing the resolved family name.
/// - `None` if the alias cannot be resolved.
pub(crate) fn resolve_family_name(&mut self, alias: &str) -> Option<String> {
let alias = alias.trim();
let lower = alias.to_ascii_lowercase();
if matches!(
lower.as_str(),
"sans-serif" | "serif" | "mono" | "monospace"
) {
return Some(lower);
}
if let Some(name) = self.alias_cache.get(alias) {
return Some(name.clone());
}
let id = self.aliases.get(alias)?.first()?;
let face = self.system.db().face(*id)?;
let (name, _) = face.families.first()?;
self.alias_cache.insert(alias.to_string(), name.clone());
Some(name.to_owned())
}
}