1use super::{FontStyle, FontWeight, FontWidth};
11use fontique::{
12 Attributes, Collection, FamilyId, GenericFamily, QueryFamily, QueryFont, QueryStatus, Script,
13 SourceCache,
14};
15use log::debug;
16#[cfg(feature = "serde")]
17use serde::{Deserialize, Serialize};
18use std::collections::HashMap;
19use std::collections::hash_map::Entry;
20use std::hash::{BuildHasher, Hash};
21
22pub struct Resolver {
24 collection: Collection,
25 cache: SourceCache,
26 families: HashMap<FamilySelector, FamilySet>,
28}
29
30impl Resolver {
31 pub(crate) fn new() -> Self {
32 Resolver {
33 collection: Collection::new(Default::default()),
34 cache: SourceCache::new(Default::default()),
35 families: HashMap::new(),
36 }
37 }
38
39 pub fn font_family(&mut self, id: FamilyId) -> Option<&str> {
41 self.collection.family_name(id)
42 }
43
44 pub fn font_family_from_generic(&mut self, generic: GenericFamily) -> Option<&str> {
46 let id = self.collection.generic_families(generic).next()?;
47 self.collection.family_name(id)
48 }
49
50 pub fn select_families<I, F>(&mut self, families: I) -> FamilySelector
52 where
53 I: IntoIterator<Item = F>,
54 F: Into<FamilyName>,
55 {
56 let set = FamilySet(families.into_iter().map(|f| f.into()).collect());
57 let hash = self.families.hasher().hash_one(&set);
58 let sel = FamilySelector(hash | (1 << 63));
59
60 match self.families.entry(sel) {
61 Entry::Vacant(entry) => {
62 entry.insert(set);
63 }
64 Entry::Occupied(entry) => {
65 log::warn!(
67 "Resolver::select_families: hash collision for family selector {set:?} and {:?}",
68 entry.get()
69 );
70 }
72 }
73
74 sel
75 }
76
77 pub fn resolve_families(&self, selector: &FamilySelector) -> Vec<FamilyName> {
81 if let Some(gf) = selector.as_generic() {
82 vec![FamilyName::Generic(gf)]
83 } else if let Some(set) = self.families.get(selector) {
84 set.0.clone()
85 } else {
86 vec![]
87 }
88 }
89}
90
91#[derive(Clone, Debug, Eq, PartialEq, Hash)]
93#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
94pub enum FamilyName {
95 Named(String),
97 #[cfg_attr(feature = "serde", serde(with = "remote::GenericFamily"))]
99 Generic(GenericFamily),
100}
101
102impl From<GenericFamily> for FamilyName {
103 fn from(gf: GenericFamily) -> Self {
104 FamilyName::Generic(gf)
105 }
106}
107
108impl<'a> From<&'a FamilyName> for QueryFamily<'a> {
109 fn from(family: &'a FamilyName) -> Self {
110 match family {
111 FamilyName::Named(name) => QueryFamily::Named(name),
112 FamilyName::Generic(gf) => QueryFamily::Generic(*gf),
113 }
114 }
115}
116
117#[derive(Clone, Debug, PartialEq, Eq, Hash)]
118struct FamilySet(Vec<FamilyName>);
119
120#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
127pub struct FamilySelector(u64);
128
129impl FamilySelector {
130 pub const SERIF: FamilySelector = FamilySelector(0);
132
133 pub const SANS_SERIF: FamilySelector = FamilySelector(1);
135
136 pub const MONOSPACE: FamilySelector = FamilySelector(2);
138
139 pub const CURSIVE: FamilySelector = FamilySelector(3);
141
142 pub const SYSTEM_UI: FamilySelector = FamilySelector(5);
144
145 pub const EMOJI: FamilySelector = FamilySelector(10);
147
148 pub const MATH: FamilySelector = FamilySelector(11);
150
151 pub const FANG_SONG: FamilySelector = FamilySelector(12);
153
154 pub fn as_generic(self) -> Option<GenericFamily> {
156 match self.0 {
157 0 => Some(GenericFamily::Serif),
158 1 => Some(GenericFamily::SansSerif),
159 2 => Some(GenericFamily::Monospace),
160 3 => Some(GenericFamily::Cursive),
161 5 => Some(GenericFamily::SystemUi),
162 10 => Some(GenericFamily::Emoji),
163 11 => Some(GenericFamily::Math),
164 12 => Some(GenericFamily::FangSong),
165 _ => None,
166 }
167 }
168
169 pub fn generic_name(self) -> Option<&'static str> {
171 Some(match self.as_generic()? {
172 GenericFamily::Serif => "serif",
173 GenericFamily::SansSerif => "sans-serif",
174 GenericFamily::Monospace => "monospace",
175 GenericFamily::Cursive => "cursive",
176 GenericFamily::SystemUi => "system-ui",
177 GenericFamily::Emoji => "emoji",
178 GenericFamily::Math => "math",
179 GenericFamily::FangSong => "fangsong",
180 _ => return None,
181 })
182 }
183
184 pub fn parse_generic(name: &str) -> Option<Self> {
186 Some(match name.trim() {
187 "serif" => Self::SERIF,
188 "sans-serif" => Self::SANS_SERIF,
189 "monospace" => Self::MONOSPACE,
190 "cursive" => Self::CURSIVE,
191 "system-ui" => Self::SYSTEM_UI,
192 "emoji" => Self::EMOJI,
193 "math" => Self::MATH,
194 "fangsong" => Self::FANG_SONG,
195 _ => return None,
196 })
197 }
198}
199
200impl Default for FamilySelector {
202 fn default() -> Self {
203 FamilySelector::SYSTEM_UI
204 }
205}
206
207#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Hash)]
215pub struct FontSelector {
216 pub family: FamilySelector,
218 pub weight: FontWeight,
220 pub width: FontWidth,
222 pub style: FontStyle,
224}
225
226impl FontSelector {
227 #[inline]
232 pub fn new() -> Self {
233 FontSelector::default()
234 }
235
236 pub(crate) fn select<F>(&self, resolver: &mut Resolver, script: Script, add_face: F)
240 where
241 F: FnMut(&QueryFont) -> QueryStatus,
242 {
243 let mut query = resolver.collection.query(&mut resolver.cache);
244 if let Some(gf) = self.family.as_generic() {
245 debug!(
246 "select: Script::{:?}, GenericFamily::{:?}, {:?}, {:?}, {:?}",
247 &script, gf, &self.weight, &self.width, &self.style
248 );
249
250 query.set_families([gf]);
251 } else if let Some(set) = resolver.families.get(&self.family) {
252 debug!(
253 "select: Script::{:?}, {:?}, {:?}, {:?}, {:?}",
254 &script, set, &self.weight, &self.width, &self.style
255 );
256
257 query.set_families(set.0.iter());
258 }
259
260 query.set_attributes(Attributes {
261 width: self.width.into(),
262 style: self.style.into(),
263 weight: self.weight.into(),
264 });
265
266 query.set_fallbacks(script);
267
268 query.matches_with(add_face);
269 }
270
271 pub fn format_css(&self) -> Option<String> {
287 let family = self.family.generic_name()?;
288 let mut s = String::new();
289 if self.style != FontStyle::Normal {
290 s.push_str(&format!("{} ", self.style));
291 }
292 if self.weight != FontWeight::NORMAL {
293 s.push_str(&format!("{} ", self.weight));
294 }
295 if self.width != FontWidth::NORMAL {
296 s.push_str(&format!("{} ", self.width));
297 }
298 s.push_str(family);
299 Some(s)
300 }
301
302 pub fn parse_css(s: &str) -> Option<Self> {
309 let mut weight = FontWeight::NORMAL;
310 let mut width = FontWidth::NORMAL;
311 let mut style = FontStyle::Normal;
312 let mut last_is_oblique = false;
313 for part in s.split_ascii_whitespace() {
314 if last_is_oblique {
315 if part.ends_with("deg") {
317 style = FontStyle::parse(&format!("oblique {part}"))
318 .expect("failed to parse oblique angle");
319 }
320 last_is_oblique = false;
321 } else if let Some(v) = FontStyle::parse(part) {
322 style = v;
323 if style == FontStyle::Oblique(None) {
324 last_is_oblique = true;
325 }
326 } else if let Some(v) = FontWeight::parse(part) {
327 weight = v;
328 } else if let Some(v) = FontWidth::parse(part) {
329 width = v;
330 } else {
331 let family = FamilySelector::parse_generic(part)?;
332 return Some(FontSelector {
333 family,
334 weight,
335 width,
336 style,
337 });
338 }
339 }
340 None
341 }
342}
343
344impl From<FamilySelector> for FontSelector {
345 #[inline]
346 fn from(family: FamilySelector) -> Self {
347 FontSelector {
348 family,
349 ..Default::default()
350 }
351 }
352}
353
354#[cfg(feature = "serde")]
356mod remote {
357 use serde::{Deserialize, Serialize};
358
359 #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Serialize, Deserialize)]
360 #[repr(u8)]
361 #[serde(remote = "fontique::GenericFamily")]
362 pub enum GenericFamily {
363 Serif = 0,
364 SansSerif = 1,
365 Monospace = 2,
366 Cursive = 3,
367 Fantasy = 4,
368 SystemUi = 5,
369 UiSerif = 6,
370 UiSansSerif = 7,
371 UiMonospace = 8,
372 UiRounded = 9,
373 Emoji = 10,
374 Math = 11,
375 FangSong = 12,
376 }
377}
378
379#[cfg(feature = "serde")]
380mod serde_impls {
381 use super::*;
382 use serde::{de, ser};
383 use std::fmt;
384
385 impl ser::Serialize for FamilySelector {
386 fn serialize<S: ser::Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
387 if let Some(name) = self.generic_name() {
388 ser.serialize_str(name)
389 } else {
390 Err(ser::Error::custom(
391 "unable to serialize non-generic family selectors",
392 ))
393 }
394 }
395 }
396
397 impl<'de> de::Deserialize<'de> for FamilySelector {
398 fn deserialize<D: de::Deserializer<'de>>(de: D) -> Result<FamilySelector, D::Error> {
399 struct Visitor;
400 impl<'de> de::Visitor<'de> for Visitor {
401 type Value = FamilySelector;
402
403 fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
404 write!(fmt, "a generic family name")
405 }
406
407 fn visit_str<E: de::Error>(self, s: &str) -> Result<FamilySelector, E> {
408 FamilySelector::parse_generic(s)
410 .ok_or_else(|| de::Error::invalid_value(de::Unexpected::Str(s), &self))
411 }
412 }
413
414 de.deserialize_str(Visitor)
415 }
416 }
417
418 impl ser::Serialize for FontSelector {
419 fn serialize<S: ser::Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
420 if let Some(s) = self.format_css() {
421 ser.serialize_str(&s)
422 } else {
423 Err(ser::Error::custom(
424 "unable to serialize non-generic family selectors",
425 ))
426 }
427 }
428 }
429
430 impl<'de> de::Deserialize<'de> for FontSelector {
431 fn deserialize<D: de::Deserializer<'de>>(de: D) -> Result<FontSelector, D::Error> {
432 struct Visitor;
433 impl<'de> de::Visitor<'de> for Visitor {
434 type Value = FontSelector;
435
436 fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
437 write!(fmt, "a CSS-style font selector")
438 }
439
440 fn visit_str<E: de::Error>(self, s: &str) -> Result<FontSelector, E> {
441 FontSelector::parse_css(s)
442 .ok_or_else(|| de::Error::invalid_value(de::Unexpected::Str(s), &self))
443 }
444 }
445
446 de.deserialize_str(Visitor)
447 }
448 }
449}