c2pdf/
font_loader.rs

1//! Functions for loading fonts from the system fonts, a path, or using the bundled `Helvetica` font
2
3#[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
9/// Returns an atomicically reference counted reference to the underlying font data of a system font
10///
11/// This function always returns an error if the `font-loading` feature is disabled
12fn 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    return Ok(data);
28  }
29}
30/// Load font bytes from a specific path
31fn 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}
36/// Loads bytes from bundled font
37fn 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}
44/// Loads a given font - falling back to the bundled font if loading from the system, or from the given path fails
45pub fn load_font(name_or_path: Option<String>) -> (Arc<Vec<u8>>, bool) {
46  let data = name_or_path.and_then(|name_or_path| {
47    if is_path(&name_or_path) {
48      load_font_path(name_or_path)
49    } else {
50      load_font_system(name_or_path)
51    }
52    .ok()
53  });
54
55  match data {
56    Some(d) => (d, false),
57    None => (bundled_font_bytes(), true),
58  }
59}