1#[cfg(feature = "font-loading")]
4use font_kit::{family_name::FamilyName, properties::Properties, source::SystemSource};
5use std::fs;
6use std::path::PathBuf;
7use std::sync::Arc;
8
9fn load_font_system(name: String) -> Result<Arc<Vec<u8>>, Box<dyn std::error::Error>> {
13 #[cfg(not(feature = "font-loading"))]
14 {
15 Err("font-loading feature is disabled".into())
16 }
17 #[cfg(feature = "font-loading")]
18 {
19 let handle =
20 SystemSource::new().select_best_match(&[FamilyName::Title(name)], &Properties::new())?;
21 let font = handle.load()?;
22 let data = if let Some(d) = font.copy_font_data() {
23 d
24 } else {
25 return Err("Unable to load font data".into());
26 };
27 Ok(data)
28 }
29}
30fn load_font_path(path: String) -> Result<Arc<Vec<u8>>, Box<dyn std::error::Error>> {
32 let bytes = fs::read(path)?;
33 let arc = Arc::new(bytes);
34 Ok(arc)
35}
36fn bundled_font_bytes() -> Arc<Vec<u8>> {
38 let bytes = include_bytes!("../../fonts/Helvetica.ttf").to_vec();
39 Arc::new(bytes)
40}
41fn is_path(s: &str) -> bool {
42 PathBuf::from(s).extension().is_some() || s.len() > 31 || s.starts_with('.')
43}
44pub enum FontLoaded {
46 SuccessProvided,
48 FailProvided,
50 NoneProvided,
52}
53pub fn load_font(name_or_path: Option<String>) -> (Arc<Vec<u8>>, FontLoaded) {
55 if let Some(name_or_path) = name_or_path {
56 if let Ok(data) = {
57 if is_path(&name_or_path) {
58 load_font_path(name_or_path)
59 } else {
60 load_font_system(name_or_path)
61 }
62 } {
63 (data, FontLoaded::SuccessProvided)
64 } else {
65 (bundled_font_bytes(), FontLoaded::FailProvided)
66 }
67 } else {
68 (bundled_font_bytes(), FontLoaded::NoneProvided)
69 }
70}