diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-09-19 17:44:40 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-09-19 17:44:40 +0200 |
| commit | e29f55bb294cc298daad97accf6d8a76976b409c (patch) | |
| tree | cc4db3b61fa23e13f781e992c63427d36e77ef8c /src/loading | |
| parent | 59f67b79c7ff50f0bc9a27373d0fa36d1523e08a (diff) | |
Remove font store
Diffstat (limited to 'src/loading')
| -rw-r--r-- | src/loading/fs.rs | 136 | ||||
| -rw-r--r-- | src/loading/mem.rs | 97 | ||||
| -rw-r--r-- | src/loading/mod.rs | 108 |
3 files changed, 0 insertions, 341 deletions
diff --git a/src/loading/fs.rs b/src/loading/fs.rs deleted file mode 100644 index 55aa967b..00000000 --- a/src/loading/fs.rs +++ /dev/null @@ -1,136 +0,0 @@ -use std::fs::{self, File}; -use std::io; -use std::path::Path; - -use memmap2::Mmap; -use same_file::Handle; -use walkdir::WalkDir; - -use super::{Buffer, FileHash, Loader}; -use crate::font::FontInfo; - -/// Loads fonts and files from the local file system. -/// -/// _This is only available when the `fs` feature is enabled._ -pub struct FsLoader { - fonts: Vec<FontInfo>, -} - -impl FsLoader { - /// Create a new loader without any fonts. - pub fn new() -> Self { - Self { fonts: vec![] } - } - - /// Builder-style variant of [`search_system`](Self::search_system). - pub fn with_system(mut self) -> Self { - self.search_system(); - self - } - - /// Builder-style variant of [`search_path`](Self::search_path). - pub fn with_path(mut self, dir: impl AsRef<Path>) -> Self { - self.search_path(dir); - self - } - - /// Search for fonts in the operating system's font directories. - pub fn search_system(&mut self) { - self.search_system_impl(); - } - - #[cfg(all(unix, not(target_os = "macos")))] - fn search_system_impl(&mut self) { - self.search_path("/usr/share/fonts"); - self.search_path("/usr/local/share/fonts"); - - if let Some(dir) = dirs::font_dir() { - self.search_path(dir); - } - } - - #[cfg(target_os = "macos")] - fn search_system_impl(&mut self) { - self.search_path("/Library/Fonts"); - self.search_path("/Network/Library/Fonts"); - self.search_path("/System/Library/Fonts"); - - if let Some(dir) = dirs::font_dir() { - self.search_path(dir); - } - } - - #[cfg(windows)] - fn search_system_impl(&mut self) { - let windir = - std::env::var("WINDIR").unwrap_or_else(|_| "C:\\Windows".to_string()); - - self.search_path(Path::new(&windir).join("Fonts")); - - if let Some(roaming) = dirs::config_dir() { - self.search_path(roaming.join("Microsoft\\Windows\\Fonts")); - } - - if let Some(local) = dirs::cache_dir() { - self.search_path(local.join("Microsoft\\Windows\\Fonts")); - } - } - - /// Search for all fonts at a path. - /// - /// If the path is a directory, all contained fonts will be searched for - /// recursively. - pub fn search_path(&mut self, path: impl AsRef<Path>) { - let walk = WalkDir::new(path) - .follow_links(true) - .sort_by(|a, b| a.file_name().cmp(b.file_name())) - .into_iter() - .filter_map(|e| e.ok()); - - for entry in walk { - let path = entry.path(); - if let Some(ext) = path.extension().and_then(|s| s.to_str()) { - if matches!( - ext, - "ttf" | "otf" | "TTF" | "OTF" | "ttc" | "otc" | "TTC" | "OTC", - ) { - self.search_file(path); - } - } - } - } - - /// Index the fonts in the file at the given path. - /// - /// The file may form a font collection and contain multiple fonts, - /// which will then all be indexed. - fn search_file(&mut self, path: impl AsRef<Path>) { - let path = path.as_ref(); - let path = path.strip_prefix(".").unwrap_or(path); - if let Ok(file) = File::open(path) { - if let Ok(mmap) = unsafe { Mmap::map(&file) } { - self.fonts.extend(FontInfo::from_data(path, &mmap)); - } - } - } -} - -impl Loader for FsLoader { - fn fonts(&self) -> &[FontInfo] { - &self.fonts - } - - fn resolve(&self, path: &Path) -> io::Result<FileHash> { - let meta = fs::metadata(path)?; - if meta.is_file() { - let handle = Handle::from_path(path)?; - Ok(FileHash(fxhash::hash64(&handle))) - } else { - Err(io::ErrorKind::NotFound.into()) - } - } - - fn load(&self, path: &Path) -> io::Result<Buffer> { - Ok(fs::read(path)?.into()) - } -} diff --git a/src/loading/mem.rs b/src/loading/mem.rs deleted file mode 100644 index 36e920d9..00000000 --- a/src/loading/mem.rs +++ /dev/null @@ -1,97 +0,0 @@ -use std::borrow::Cow; -use std::collections::HashMap; -use std::io; -use std::path::{Path, PathBuf}; - -use super::{Buffer, FileHash, Loader}; -use crate::font::FontInfo; -use crate::util::PathExt; - -/// Loads fonts and files from an in-memory storage. -#[derive(Default)] -pub struct MemLoader { - fonts: Vec<FontInfo>, - files: HashMap<PathBuf, Cow<'static, [u8]>>, -} - -impl MemLoader { - /// Create a new from-memory loader. - pub fn new() -> Self { - Self { fonts: vec![], files: HashMap::new() } - } - - /// Builder-style variant of [`insert`](Self::insert). - pub fn with<P, D>(mut self, path: P, data: D) -> Self - where - P: AsRef<Path>, - D: Into<Cow<'static, [u8]>>, - { - self.insert(path, data); - self - } - - /// Insert a path-file mapping. If the data forms a font, then that font - /// will be available for layouting. - /// - /// The data can either be owned or referenced, but the latter only if its - /// lifetime is `'static`. - pub fn insert<P, D>(&mut self, path: P, data: D) - where - P: AsRef<Path>, - D: Into<Cow<'static, [u8]>>, - { - let path = path.as_ref().normalize(); - let data = data.into(); - self.fonts.extend(FontInfo::from_data(&path, &data)); - self.files.insert(path, data); - } -} - -impl Loader for MemLoader { - fn fonts(&self) -> &[FontInfo] { - &self.fonts - } - - fn resolve(&self, path: &Path) -> io::Result<FileHash> { - let norm = path.normalize(); - if self.files.contains_key(&norm) { - Ok(FileHash(fxhash::hash64(&norm))) - } else { - Err(io::ErrorKind::NotFound.into()) - } - } - - fn load(&self, path: &Path) -> io::Result<Buffer> { - self.files - .get(&path.normalize()) - .map(|cow| cow.clone().into_owned().into()) - .ok_or_else(|| io::ErrorKind::NotFound.into()) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::font::FontVariant; - - #[test] - fn test_recognize_and_load_font() { - let data = include_bytes!("../../fonts/PTSans-Regular.ttf"); - let path = Path::new("PTSans.ttf"); - let loader = MemLoader::new().with(path, &data[..]); - - // Test that the font was found. - let info = &loader.fonts[0]; - assert_eq!(info.path, path); - assert_eq!(info.index, 0); - assert_eq!(info.family, "PT Sans"); - assert_eq!(info.variant, FontVariant::default()); - assert_eq!(loader.fonts.len(), 1); - - // Test that the file can be loaded. - assert_eq!( - loader.load(Path::new("directory/../PTSans.ttf")).unwrap().as_slice(), - data - ); - } -} diff --git a/src/loading/mod.rs b/src/loading/mod.rs deleted file mode 100644 index ecc1e8d5..00000000 --- a/src/loading/mod.rs +++ /dev/null @@ -1,108 +0,0 @@ -//! Resource loading. - -#[cfg(feature = "fs")] -mod fs; -mod mem; - -#[cfg(feature = "fs")] -pub use fs::*; -pub use mem::*; - -use std::fmt::{self, Debug, Formatter}; -use std::io; -use std::ops::Deref; -use std::path::Path; -use std::sync::Arc; - -use crate::font::FontInfo; -use crate::util::Prehashed; - -/// A hash that identifies a file. -/// -/// Such a hash can be [resolved](Loader::resolve) from a path. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] -pub struct FileHash(pub u64); - -/// Loads resources from a local or remote source. -pub trait Loader { - /// Descriptions of all fonts this loader serves. - fn fonts(&self) -> &[FontInfo]; - - /// Resolve a hash that is the same for this and all other paths pointing to - /// the same file. - fn resolve(&self, path: &Path) -> io::Result<FileHash>; - - /// Load a file from a path. - fn load(&self, path: &Path) -> io::Result<Buffer>; -} - -/// A loader which serves nothing. -pub struct BlankLoader; - -impl Loader for BlankLoader { - fn fonts(&self) -> &[FontInfo] { - &[] - } - - fn resolve(&self, _: &Path) -> io::Result<FileHash> { - Err(io::ErrorKind::NotFound.into()) - } - - fn load(&self, _: &Path) -> io::Result<Buffer> { - Err(io::ErrorKind::NotFound.into()) - } -} - -/// A shared buffer that is cheap to clone. -#[derive(Clone, Hash, Eq, PartialEq)] -pub struct Buffer(Prehashed<Arc<Vec<u8>>>); - -impl Buffer { - /// Return a view into the buffer. - pub fn as_slice(&self) -> &[u8] { - self - } - - /// Return a copy of the buffer as a vector. - pub fn to_vec(&self) -> Vec<u8> { - self.0.to_vec() - } -} - -impl From<&[u8]> for Buffer { - fn from(slice: &[u8]) -> Self { - Self(Prehashed::new(Arc::new(slice.to_vec()))) - } -} - -impl From<Vec<u8>> for Buffer { - fn from(vec: Vec<u8>) -> Self { - Self(Prehashed::new(Arc::new(vec))) - } -} - -impl From<Arc<Vec<u8>>> for Buffer { - fn from(arc: Arc<Vec<u8>>) -> Self { - Self(Prehashed::new(arc)) - } -} - -impl Deref for Buffer { - type Target = [u8]; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl AsRef<[u8]> for Buffer { - fn as_ref(&self) -> &[u8] { - self - } -} - -impl Debug for Buffer { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - f.pad("Buffer(..)") - } -} |
