| 1 | // Copyright © SixtyFPS GmbH <info@slint.dev> |
| 2 | // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0 |
| 3 | |
| 4 | use core::cell::RefCell; |
| 5 | |
| 6 | use alloc::boxed::Box; |
| 7 | use alloc::rc::Rc; |
| 8 | use std::collections::HashMap; |
| 9 | |
| 10 | use crate::lengths::ScaleFactor; |
| 11 | use i_slint_common::sharedfontdb::{self, fontdb}; |
| 12 | |
| 13 | use super::super::PhysicalLength; |
| 14 | use super::vectorfont::VectorFont; |
| 15 | |
| 16 | crate::thread_local! { |
| 17 | static FONTDUE_FONTS: RefCell<HashMap<fontdb::ID, Rc<fontdue::Font>>> = Default::default(); |
| 18 | } |
| 19 | |
| 20 | fn get_or_create_fontdue_font(fontdb: &fontdb::Database, id: fontdb::ID) -> Rc<fontdue::Font> { |
| 21 | FONTDUE_FONTS.with(|font_cache: &RefCell>>| { |
| 22 | font_cache&mut Rc |
| 23 | .borrow_mut() |
| 24 | .entry(id) |
| 25 | .or_insert_with(|| { |
| 26 | fontdbOption> |
| 27 | .with_face_data(id, |face_data: &[u8], font_index: u32| { |
| 28 | fontdueFont::Font::from_bytes( |
| 29 | face_data, |
| 30 | fontdue::FontSettings { |
| 31 | collection_index: font_index, |
| 32 | scale: 40., |
| 33 | ..Default::default() |
| 34 | }, |
| 35 | ) |
| 36 | .expect(msg:"fatal: fontdue is unable to parse truetype font" ) |
| 37 | .into() |
| 38 | }) |
| 39 | .unwrap() |
| 40 | }) |
| 41 | .clone() |
| 42 | }) |
| 43 | } |
| 44 | |
| 45 | pub fn match_font( |
| 46 | request: &super::FontRequest, |
| 47 | scale_factor: super::ScaleFactor, |
| 48 | ) -> Option<VectorFont> { |
| 49 | request.family.as_ref().and_then(|family_str: &SharedString| { |
| 50 | let query: Query<'_> = request.to_fontdb_query(); |
| 51 | |
| 52 | let requested_pixel_size: PhysicalLength = |
| 53 | (request.pixel_size.unwrap_or(default:super::DEFAULT_FONT_SIZE).cast() * scale_factor).cast(); |
| 54 | |
| 55 | sharedfontdb::FONT_DB.with(|fonts: &RefCell| { |
| 56 | let borrowed_fontdb: Ref<'_, FontDatabase> = fonts.borrow(); |
| 57 | borrowed_fontdb.query_with_family(query, family:Some(family_str)).map(|font_id: ID| { |
| 58 | let fontdue_font: Rc = get_or_create_fontdue_font(&borrowed_fontdb, font_id); |
| 59 | VectorFont::new(font_id, fontdue_font.clone(), requested_pixel_size) |
| 60 | }) |
| 61 | }) |
| 62 | }) |
| 63 | } |
| 64 | |
| 65 | pub fn fallbackfont(font_request: &super::FontRequest, scale_factor: ScaleFactor) -> VectorFont { |
| 66 | let requested_pixel_size: PhysicalLength = |
| 67 | (font_request.pixel_size.unwrap_or(default:super::DEFAULT_FONT_SIZE).cast() * scale_factor).cast(); |
| 68 | |
| 69 | sharedfontdb::FONT_DB.with_borrow(|fonts: &FontDatabase| { |
| 70 | let query: Query<'_> = font_request.to_fontdb_query(); |
| 71 | |
| 72 | let fallback_font_id: ID = fonts |
| 73 | .query_with_family(query, None) |
| 74 | .expect(msg:"fatal: query for fallback font returned empty font list" ); |
| 75 | |
| 76 | let fontdue_font: Rc = get_or_create_fontdue_font(fontdb:fonts, fallback_font_id); |
| 77 | VectorFont::new(fallback_font_id, fontdue_font, requested_pixel_size) |
| 78 | }) |
| 79 | } |
| 80 | |
| 81 | pub fn register_font_from_memory(data: &'static [u8]) -> Result<(), Box<dyn std::error::Error>> { |
| 82 | sharedfontdb::FONT_DB.with_borrow_mut(|fonts: &mut FontDatabase| { |
| 83 | fonts.make_mut().load_font_source(fontdb::Source::Binary(std::sync::Arc::new(data))) |
| 84 | }); |
| 85 | Ok(()) |
| 86 | } |
| 87 | |
| 88 | #[cfg (not(target_family = "wasm" ))] |
| 89 | pub fn register_font_from_path(path: &std::path::Path) -> Result<(), Box<dyn std::error::Error>> { |
| 90 | let requested_path: PathBuf = path.canonicalize().unwrap_or_else(|_| path.into()); |
| 91 | sharedfontdb::FONT_DB.with_borrow_mut(|fonts: &mut FontDatabase| { |
| 92 | for face_info in fonts.faces() { |
| 93 | match &face_info.source { |
| 94 | fontdb::Source::Binary(_) => {} |
| 95 | fontdb::Source::File(loaded_path: &PathBuf) | fontdb::Source::SharedFile(loaded_path: &PathBuf, ..) => { |
| 96 | if *loaded_path == requested_path { |
| 97 | return Ok(()); |
| 98 | } |
| 99 | } |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | fonts.make_mut().load_font_file(requested_path).map_err(|e: Error| e.into()) |
| 104 | }) |
| 105 | } |
| 106 | |