summaryrefslogtreecommitdiff
path: root/cli/src/fonts.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/src/fonts.rs')
-rw-r--r--cli/src/fonts.rs183
1 files changed, 0 insertions, 183 deletions
diff --git a/cli/src/fonts.rs b/cli/src/fonts.rs
deleted file mode 100644
index 75835741..00000000
--- a/cli/src/fonts.rs
+++ /dev/null
@@ -1,183 +0,0 @@
-use std::cell::OnceCell;
-use std::env;
-use std::fs::{self, File};
-use std::path::{Path, PathBuf};
-
-use memmap2::Mmap;
-use typst::diag::StrResult;
-use typst::font::{Font, FontBook, FontInfo, FontVariant};
-use typst::util::Bytes;
-use walkdir::WalkDir;
-
-use crate::args::FontsCommand;
-
-/// Execute a font listing command.
-pub fn fonts(command: FontsCommand) -> StrResult<()> {
- let mut searcher = FontSearcher::new();
- searcher.search(&command.font_paths);
-
- for (name, infos) in searcher.book.families() {
- println!("{name}");
- if command.variants {
- for info in infos {
- let FontVariant { style, weight, stretch } = info.variant;
- println!("- Style: {style:?}, Weight: {weight:?}, Stretch: {stretch:?}");
- }
- }
- }
-
- Ok(())
-}
-
-/// Searches for fonts.
-pub struct FontSearcher {
- /// Metadata about all discovered fonts.
- pub book: FontBook,
- /// Slots that the fonts are loaded into.
- pub fonts: Vec<FontSlot>,
-}
-
-/// Holds details about the location of a font and lazily the font itself.
-pub struct FontSlot {
- /// The path at which the font can be found on the system.
- path: PathBuf,
- /// The index of the font in its collection. Zero if the path does not point
- /// to a collection.
- index: u32,
- /// The lazily loaded font.
- font: OnceCell<Option<Font>>,
-}
-
-impl FontSlot {
- /// Get the font for this slot.
- pub fn get(&self) -> Option<Font> {
- self.font
- .get_or_init(|| {
- let data = fs::read(&self.path).ok()?.into();
- Font::new(data, self.index)
- })
- .clone()
- }
-}
-
-impl FontSearcher {
- /// Create a new, empty system searcher.
- pub fn new() -> Self {
- Self { book: FontBook::new(), fonts: vec![] }
- }
-
- /// Search everything that is available.
- pub fn search(&mut self, font_paths: &[PathBuf]) {
- self.search_system();
-
- #[cfg(feature = "embed-fonts")]
- self.add_embedded();
-
- for path in font_paths {
- self.search_dir(path)
- }
- }
-
- /// Add fonts that are embedded in the binary.
- #[cfg(feature = "embed-fonts")]
- fn add_embedded(&mut self) {
- let mut process = |bytes: &'static [u8]| {
- let buffer = Bytes::from_static(bytes);
- for (i, font) in Font::iter(buffer).enumerate() {
- self.book.push(font.info().clone());
- self.fonts.push(FontSlot {
- path: PathBuf::new(),
- index: i as u32,
- font: OnceCell::from(Some(font)),
- });
- }
- };
-
- macro_rules! add {
- ($filename:literal) => {
- process(include_bytes!(concat!("../../assets/fonts/", $filename,)));
- };
- }
-
- // Embed default fonts.
- add!("LinLibertine_R.ttf");
- add!("LinLibertine_RB.ttf");
- add!("LinLibertine_RBI.ttf");
- add!("LinLibertine_RI.ttf");
- add!("NewCMMath-Book.otf");
- add!("NewCMMath-Regular.otf");
- add!("NewCM10-Regular.otf");
- add!("NewCM10-Bold.otf");
- add!("NewCM10-Italic.otf");
- add!("NewCM10-BoldItalic.otf");
- add!("DejaVuSansMono.ttf");
- add!("DejaVuSansMono-Bold.ttf");
- add!("DejaVuSansMono-Oblique.ttf");
- add!("DejaVuSansMono-BoldOblique.ttf");
- }
-
- /// Search for fonts in the linux system font directories.
- fn search_system(&mut self) {
- if cfg!(target_os = "macos") {
- self.search_dir("/Library/Fonts");
- self.search_dir("/Network/Library/Fonts");
- self.search_dir("/System/Library/Fonts");
- } else if cfg!(unix) {
- self.search_dir("/usr/share/fonts");
- self.search_dir("/usr/local/share/fonts");
- } else if cfg!(windows) {
- self.search_dir(
- env::var_os("WINDIR")
- .map(PathBuf::from)
- .unwrap_or_else(|| "C:\\Windows".into())
- .join("Fonts"),
- );
-
- if let Some(roaming) = dirs::config_dir() {
- self.search_dir(roaming.join("Microsoft\\Windows\\Fonts"));
- }
-
- if let Some(local) = dirs::cache_dir() {
- self.search_dir(local.join("Microsoft\\Windows\\Fonts"));
- }
- }
-
- if let Some(dir) = dirs::font_dir() {
- self.search_dir(dir);
- }
- }
-
- /// Search for all fonts in a directory recursively.
- fn search_dir(&mut self, path: impl AsRef<Path>) {
- for entry in WalkDir::new(path)
- .follow_links(true)
- .sort_by(|a, b| a.file_name().cmp(b.file_name()))
- .into_iter()
- .filter_map(|e| e.ok())
- {
- let path = entry.path();
- if matches!(
- path.extension().and_then(|s| s.to_str()),
- Some("ttf" | "otf" | "TTF" | "OTF" | "ttc" | "otc" | "TTC" | "OTC"),
- ) {
- self.search_file(path);
- }
- }
- }
-
- /// Index the fonts in the file at the given path.
- fn search_file(&mut self, path: &Path) {
- if let Ok(file) = File::open(path) {
- if let Ok(mmap) = unsafe { Mmap::map(&file) } {
- for (i, info) in FontInfo::iter(&mmap).enumerate() {
- self.book.push(info);
- self.fonts.push(FontSlot {
- path: path.into(),
- index: i as u32,
- font: OnceCell::new(),
- });
- }
- }
- }
- }
-}