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