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