use crate::font::registry::FontRegistry;
use crate::types::FontFaceId;
pub struct ResolvedFont {
pub font_face_id: FontFaceId,
pub size_px: f32,
pub face_index: u32,
pub swash_cache_key: swash::CacheKey,
}
pub fn resolve_font(
registry: &FontRegistry,
font_family: Option<&str>,
font_weight: Option<u32>,
font_bold: Option<bool>,
font_italic: Option<bool>,
font_point_size: Option<u32>,
) -> Option<ResolvedFont> {
let weight = resolve_weight(font_weight, font_bold);
let italic = font_italic.unwrap_or(false);
let size_px = font_point_size
.map(|s| s as f32)
.unwrap_or(registry.default_size_px());
if let Some(family) = font_family
&& let Some(face_id) = registry.query_font(family, weight, italic)
{
let entry = registry.get(face_id)?;
return Some(ResolvedFont {
font_face_id: face_id,
size_px,
face_index: entry.face_index,
swash_cache_key: entry.swash_cache_key,
});
}
let default_id = registry.default_font()?;
if (weight != 400 || italic)
&& let Some(variant_id) = registry.query_variant(default_id, weight, italic)
{
let variant_entry = registry.get(variant_id)?;
return Some(ResolvedFont {
font_face_id: variant_id,
size_px,
face_index: variant_entry.face_index,
swash_cache_key: variant_entry.swash_cache_key,
});
}
let entry = registry.get(default_id)?;
Some(ResolvedFont {
font_face_id: default_id,
size_px,
face_index: entry.face_index,
swash_cache_key: entry.swash_cache_key,
})
}
pub fn font_has_glyph(registry: &FontRegistry, face_id: FontFaceId, ch: char) -> bool {
let entry = match registry.get(face_id) {
Some(e) => e,
None => return false,
};
let font_ref = match swash::FontRef::from_index(&entry.data, entry.face_index as usize) {
Some(f) => f,
None => return false,
};
font_ref.charmap().map(ch) != 0
}
pub fn find_fallback_font(
registry: &FontRegistry,
ch: char,
exclude: FontFaceId,
) -> Option<FontFaceId> {
for (face_id, entry) in registry.all_entries() {
if face_id == exclude {
continue;
}
let font_ref = match swash::FontRef::from_index(&entry.data, entry.face_index as usize) {
Some(f) => f,
None => continue,
};
if font_ref.charmap().map(ch) != 0 {
return Some(face_id);
}
}
None
}
fn resolve_weight(font_weight: Option<u32>, font_bold: Option<bool>) -> u16 {
if let Some(w) = font_weight {
return w.min(1000) as u16;
}
if font_bold == Some(true) {
return 700;
}
400 }