summaryrefslogtreecommitdiff
path: root/src/env/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/env/mod.rs')
-rw-r--r--src/env/mod.rs243
1 files changed, 0 insertions, 243 deletions
diff --git a/src/env/mod.rs b/src/env/mod.rs
deleted file mode 100644
index 84be3e81..00000000
--- a/src/env/mod.rs
+++ /dev/null
@@ -1,243 +0,0 @@
-//! Font and image loading.
-
-#[cfg(feature = "fs")]
-mod fs;
-mod image;
-
-pub use self::image::*;
-#[cfg(feature = "fs")]
-pub use fs::*;
-
-use std::collections::{hash_map::Entry, HashMap};
-use std::rc::Rc;
-
-use serde::{Deserialize, Serialize};
-
-use crate::font::{Face, FaceInfo, FontVariant};
-
-/// Handles font and image loading.
-pub struct Env {
- /// The loader that serves the font face and file buffers.
- loader: Box<dyn Loader>,
- /// Faces indexed by [`FaceId`]. `None` if not yet loaded.
- faces: Vec<Option<Face>>,
- /// Maps a family name to the ids of all faces that are part of the family.
- families: HashMap<String, Vec<FaceId>>,
- /// Loaded images indexed by [`ImageId`].
- images: Vec<Image>,
- /// Maps from paths to loaded images.
- paths: HashMap<String, ImageId>,
- /// Callback for loaded font faces.
- on_face_load: Option<Box<dyn Fn(FaceId, &Face)>>,
- /// Callback for loaded images.
- on_image_load: Option<Box<dyn Fn(ImageId, &Image)>>,
-}
-
-impl Env {
- /// Create an environment from a `loader`.
- pub fn new(loader: impl Loader + 'static) -> Self {
- let infos = loader.faces();
-
- let mut faces = vec![];
- let mut families = HashMap::<String, Vec<FaceId>>::new();
-
- for (i, info) in infos.iter().enumerate() {
- let id = FaceId(i as u32);
- faces.push(None);
- families
- .entry(info.family.to_lowercase())
- .and_modify(|vec| vec.push(id))
- .or_insert_with(|| vec![id]);
- }
-
- Self {
- loader: Box::new(loader),
- faces,
- families,
- images: vec![],
- paths: HashMap::new(),
- on_face_load: None,
- on_image_load: None,
- }
- }
-
- /// Create an empty environment for testing purposes.
- pub fn blank() -> Self {
- struct BlankLoader;
-
- impl Loader for BlankLoader {
- fn faces(&self) -> &[FaceInfo] {
- &[]
- }
-
- fn load_face(&mut self, _: usize) -> Option<Buffer> {
- None
- }
-
- fn load_file(&mut self, _: &str) -> Option<Buffer> {
- None
- }
- }
-
- Self::new(BlankLoader)
- }
-
- /// Query for and load the font face from the given `family` that most
- /// closely matches the given `variant`.
- pub fn query_face(&mut self, family: &str, variant: FontVariant) -> Option<FaceId> {
- // Check whether a family with this name exists.
- let ids = self.families.get(family)?;
- let infos = self.loader.faces();
-
- let mut best = None;
- let mut best_key = None;
-
- // Find the best matching variant of this font.
- for &id in ids {
- let current = infos[id.0 as usize].variant;
-
- // This is a perfect match, no need to search further.
- if current == variant {
- best = Some(id);
- break;
- }
-
- // If this is not a perfect match, we compute a key that we want to
- // minimize among all variants. This key prioritizes style, then
- // stretch distance and then weight distance.
- let key = (
- current.style != variant.style,
- current.stretch.distance(variant.stretch),
- current.weight.distance(variant.weight),
- );
-
- if best_key.map_or(true, |b| key < b) {
- best = Some(id);
- best_key = Some(key);
- }
- }
-
- // Load the face if it's not already loaded.
- let id = best?;
- let idx = id.0 as usize;
- let slot = &mut self.faces[idx];
- if slot.is_none() {
- let index = infos[idx].index;
- let buffer = self.loader.load_face(idx)?;
- let face = Face::new(buffer, index)?;
- if let Some(callback) = &self.on_face_load {
- callback(id, &face);
- }
- *slot = Some(face);
- }
-
- best
- }
-
- /// Get a reference to a queried face.
- ///
- /// This panics if no face with this id was loaded. This function should
- /// only be called with ids returned by [`query_face()`](Self::query_face).
- #[track_caller]
- pub fn face(&self, id: FaceId) -> &Face {
- self.faces[id.0 as usize].as_ref().expect("font face was not loaded")
- }
-
- /// Register a callback which is invoked when a font face was loaded.
- pub fn on_face_load<F>(&mut self, f: F)
- where
- F: Fn(FaceId, &Face) + 'static,
- {
- self.on_face_load = Some(Box::new(f));
- }
-
- /// Load and decode an image file from a path.
- pub fn load_image(&mut self, path: &str) -> Option<ImageId> {
- Some(match self.paths.entry(path.to_string()) {
- Entry::Occupied(entry) => *entry.get(),
- Entry::Vacant(entry) => {
- let buffer = self.loader.load_file(path)?;
- let image = Image::parse(&buffer)?;
- let id = ImageId(self.images.len() as u32);
- if let Some(callback) = &self.on_image_load {
- callback(id, &image);
- }
- self.images.push(image);
- *entry.insert(id)
- }
- })
- }
-
- /// Get a reference to a loaded image.
- ///
- /// This panics if no image with this id was loaded. This function should
- /// only be called with ids returned by [`load_image()`](Self::load_image).
- #[track_caller]
- pub fn image(&self, id: ImageId) -> &Image {
- &self.images[id.0 as usize]
- }
-
- /// Register a callback which is invoked when an image was loaded.
- pub fn on_image_load<F>(&mut self, f: F)
- where
- F: Fn(ImageId, &Image) + 'static,
- {
- self.on_image_load = Some(Box::new(f));
- }
-}
-
-/// Loads fonts and images from a remote or local source.
-pub trait Loader {
- /// Descriptions of all font faces this loader serves.
- fn faces(&self) -> &[FaceInfo];
-
- /// Load the font face with the given index in [`faces()`](Self::faces).
- fn load_face(&mut self, idx: usize) -> Option<Buffer>;
-
- /// Load a file from a path.
- fn load_file(&mut self, path: &str) -> Option<Buffer>;
-}
-
-/// A shared byte buffer.
-pub type Buffer = Rc<Vec<u8>>;
-
-/// A unique identifier for a loaded font face.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
-pub struct FaceId(u32);
-
-impl FaceId {
- /// A blank initialization value.
- pub const MAX: Self = Self(u32::MAX);
-
- /// Create a face id from the raw underlying value.
- ///
- /// This should only be called with values returned by
- /// [`into_raw`](Self::into_raw).
- pub fn from_raw(v: u32) -> Self {
- Self(v)
- }
-
- /// Convert into the raw underlying value.
- pub fn into_raw(self) -> u32 {
- self.0
- }
-}
-
-/// A unique identifier for a loaded image.
-#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
-pub struct ImageId(u32);
-
-impl ImageId {
- /// Create an image id from the raw underlying value.
- ///
- /// This should only be called with values returned by
- /// [`into_raw`](Self::into_raw).
- pub fn from_raw(v: u32) -> Self {
- Self(v)
- }
-
- /// Convert into the raw underlying value.
- pub fn into_raw(self) -> u32 {
- self.0
- }
-}