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 pub scale_factor: f32,
15}
16
17pub fn resolve_font(
25 registry: &FontRegistry,
26 font_family: Option<&str>,
27 font_weight: Option<u32>,
28 font_bold: Option<bool>,
29 font_italic: Option<bool>,
30 font_point_size: Option<u32>,
31 scale_factor: f32,
32) -> Option<ResolvedFont> {
33 let weight = resolve_weight(font_weight, font_bold);
34 let italic = font_italic.unwrap_or(false);
35 let size_px = font_point_size
36 .map(|s| s as f32)
37 .unwrap_or(registry.default_size_px());
38
39 if let Some(family) = font_family
41 && let Some(face_id) = registry.query_font(family, weight, italic)
42 {
43 let entry = registry.get(face_id)?;
44 return Some(ResolvedFont {
45 font_face_id: face_id,
46 size_px,
47 face_index: entry.face_index,
48 swash_cache_key: entry.swash_cache_key,
49 scale_factor,
50 });
51 }
52
53 let default_id = registry.default_font()?;
56 if (weight != 400 || italic)
57 && let Some(variant_id) = registry.query_variant(default_id, weight, italic)
58 {
59 let variant_entry = registry.get(variant_id)?;
60 return Some(ResolvedFont {
61 font_face_id: variant_id,
62 size_px,
63 face_index: variant_entry.face_index,
64 swash_cache_key: variant_entry.swash_cache_key,
65 scale_factor,
66 });
67 }
68 let entry = registry.get(default_id)?;
69 Some(ResolvedFont {
70 font_face_id: default_id,
71 size_px,
72 face_index: entry.face_index,
73 swash_cache_key: entry.swash_cache_key,
74 scale_factor,
75 })
76}
77
78pub fn font_has_glyph(registry: &FontRegistry, face_id: FontFaceId, ch: char) -> bool {
82 let entry = match registry.get(face_id) {
83 Some(e) => e,
84 None => return false,
85 };
86 let font_ref = match swash::FontRef::from_index(&entry.data, entry.face_index as usize) {
87 Some(f) => f,
88 None => return false,
89 };
90 font_ref.charmap().map(ch) != 0
91}
92
93pub fn find_fallback_font(
95 registry: &FontRegistry,
96 ch: char,
97 exclude: FontFaceId,
98) -> Option<FontFaceId> {
99 for (face_id, entry) in registry.all_entries() {
100 if face_id == exclude {
101 continue;
102 }
103 let font_ref = match swash::FontRef::from_index(&entry.data, entry.face_index as usize) {
104 Some(f) => f,
105 None => continue,
106 };
107 if font_ref.charmap().map(ch) != 0 {
108 return Some(face_id);
109 }
110 }
111 None
112}
113
114fn resolve_weight(font_weight: Option<u32>, font_bold: Option<bool>) -> u16 {
116 if let Some(w) = font_weight {
117 return w.min(1000) as u16;
118 }
119 if font_bold == Some(true) {
120 return 700;
121 }
122 400 }