i_slint_renderer_software/fonts/
systemfonts.rs1use core::cell::RefCell;
5
6use alloc::boxed::Box;
7use std::collections::HashMap;
8
9use i_slint_common::sharedfontique::{HashedBlob, fontique};
10use i_slint_core::lengths::ScaleFactor;
11
12use super::super::PhysicalLength;
13use super::vectorfont::VectorFont;
14
15struct CachedFontInfo {
16 swash_key: swash::CacheKey,
17 swash_offset: u32,
18}
19
20i_slint_core::thread_local! {
21 static SWASH_FONTS: RefCell<HashMap<(HashedBlob, u32), CachedFontInfo>> = Default::default();
23}
24
25pub fn get_swash_font_info(blob: &fontique::Blob<u8>, index: u32) -> (swash::CacheKey, u32) {
26 SWASH_FONTS.with(|font_cache| {
27 let mut cache = font_cache.borrow_mut();
28 let info = cache.entry((blob.clone().into(), index)).or_insert_with(move || {
29 let font_ref = swash::FontRef::from_index(blob.data(), index as usize)
30 .expect("fatal: swash is unable to parse truetype font");
31 CachedFontInfo { swash_key: font_ref.key, swash_offset: font_ref.offset }
32 });
33 (info.swash_key, info.swash_offset)
34 })
35}
36
37fn get_swash_font_info_for_query_font(font: &fontique::QueryFont) -> (swash::CacheKey, u32) {
38 get_swash_font_info(&font.blob, font.index)
39}
40
41pub fn match_font(
42 request: &super::FontRequest,
43 scale_factor: super::ScaleFactor,
44 collection: &mut fontique::Collection,
45 source_cache: &mut fontique::SourceCache,
46) -> Option<VectorFont> {
47 if request.family.is_some() {
48 let requested_pixel_size: PhysicalLength =
49 (request.pixel_size.unwrap_or(super::DEFAULT_FONT_SIZE).cast() * scale_factor).cast();
50
51 if let Some(font) = request.query_fontique(collection, source_cache) {
52 let (swash_key, swash_offset) = get_swash_font_info_for_query_font(&font);
53 Some(VectorFont::new(font, swash_key, swash_offset, requested_pixel_size))
54 } else {
55 None
56 }
57 } else {
58 None
59 }
60}
61
62pub fn fallbackfont(
63 font_request: &super::FontRequest,
64 scale_factor: ScaleFactor,
65 collection: &mut fontique::Collection,
66 source_cache: &mut fontique::SourceCache,
67) -> VectorFont {
68 let requested_pixel_size: PhysicalLength =
69 (font_request.pixel_size.unwrap_or(super::DEFAULT_FONT_SIZE).cast() * scale_factor).cast();
70
71 let font = font_request.query_fontique(collection, source_cache).unwrap();
72 let (swash_key, swash_offset) = get_swash_font_info_for_query_font(&font);
73 VectorFont::new(font, swash_key, swash_offset, requested_pixel_size)
74}
75
76pub fn register_font_from_memory(
77 collection: &mut fontique::Collection,
78 data: &'static [u8],
79) -> Result<(), Box<dyn std::error::Error>> {
80 collection.register_fonts(data.to_vec().into(), None);
81 Ok(())
82}
83
84#[cfg(not(target_family = "wasm"))]
85pub fn register_font_from_path(
86 collection: &mut fontique::Collection,
87 path: &std::path::Path,
88) -> Result<(), Box<dyn std::error::Error>> {
89 let requested_path = path.canonicalize().unwrap_or_else(|_| path.into());
90 let contents = std::fs::read(requested_path)?;
91 collection.register_fonts(contents.into(), None);
92 Ok(())
93}