text_typeset/font/
resolve.rs1use crate::font::registry::FontRegistry;
2use crate::types::FontFaceId;
3
4pub struct ResolvedFont {
6 pub font_face_id: FontFaceId,
7 pub size_px: f32,
8 pub face_index: u32,
9 pub swash_cache_key: swash::CacheKey,
10}
11
12pub fn resolve_font(
20 registry: &FontRegistry,
21 font_family: Option<&str>,
22 font_weight: Option<u32>,
23 font_bold: Option<bool>,
24 font_italic: Option<bool>,
25 font_point_size: Option<u32>,
26) -> Option<ResolvedFont> {
27 let weight = resolve_weight(font_weight, font_bold);
28 let italic = font_italic.unwrap_or(false);
29 let size_px = font_point_size
30 .map(|s| s as f32)
31 .unwrap_or(registry.default_size_px());
32
33 if let Some(family) = font_family
35 && let Some(face_id) = registry.query_font(family, weight, italic)
36 {
37 let entry = registry.get(face_id)?;
38 return Some(ResolvedFont {
39 font_face_id: face_id,
40 size_px,
41 face_index: entry.face_index,
42 swash_cache_key: entry.swash_cache_key,
43 });
44 }
45
46 let default_id = registry.default_font()?;
48 let entry = registry.get(default_id)?;
49 Some(ResolvedFont {
50 font_face_id: default_id,
51 size_px,
52 face_index: entry.face_index,
53 swash_cache_key: entry.swash_cache_key,
54 })
55}
56
57pub fn font_has_glyph(registry: &FontRegistry, face_id: FontFaceId, ch: char) -> bool {
61 let entry = match registry.get(face_id) {
62 Some(e) => e,
63 None => return false,
64 };
65 let font_ref = match swash::FontRef::from_index(&entry.data, entry.face_index as usize) {
66 Some(f) => f,
67 None => return false,
68 };
69 font_ref.charmap().map(ch) != 0
70}
71
72pub fn find_fallback_font(
74 registry: &FontRegistry,
75 ch: char,
76 exclude: FontFaceId,
77) -> Option<FontFaceId> {
78 for (face_id, entry) in registry.all_entries() {
79 if face_id == exclude {
80 continue;
81 }
82 let font_ref = match swash::FontRef::from_index(&entry.data, entry.face_index as usize) {
83 Some(f) => f,
84 None => continue,
85 };
86 if font_ref.charmap().map(ch) != 0 {
87 return Some(face_id);
88 }
89 }
90 None
91}
92
93fn resolve_weight(font_weight: Option<u32>, font_bold: Option<bool>) -> u16 {
95 if let Some(w) = font_weight {
96 return w.min(1000) as u16;
97 }
98 if font_bold == Some(true) {
99 return 700;
100 }
101 400 }