mirror of
https://github.com/wez/wezterm.git
synced 2024-12-24 13:52:55 +03:00
fonts: start breaking out the loader/locator concept
This commit is contained in:
parent
151a915128
commit
6f867ac3e2
59
src/font/loader/font_config.rs
Normal file
59
src/font/loader/font_config.rs
Normal file
@ -0,0 +1,59 @@
|
||||
use crate::config::FontAttributes;
|
||||
use crate::font::loader::{FontDataHandle, FontLocator};
|
||||
use failure::Fallible;
|
||||
|
||||
/// A FontLocator implemented using the system font loading
|
||||
/// functions provided by font-config
|
||||
pub struct FontConfigFontLocator {}
|
||||
|
||||
impl FontLocator for FontLoaderFontLocator {
|
||||
fn load_fonts(&self, fonts_selection: &[FontAttributes]) -> Fallible<Vec<FontDataHandle>> {
|
||||
let mut fonts = vec![];
|
||||
let mut fallback = vec![];
|
||||
|
||||
for attr in style.font_with_fallback() {
|
||||
let mut pattern = FontPattern::new()?;
|
||||
pattern.family(&attr.family)?;
|
||||
if attr.bold {
|
||||
pattern.add_integer("weight", 200)?;
|
||||
}
|
||||
if attr.italic {
|
||||
pattern.add_integer("slant", 100)?;
|
||||
}
|
||||
/*
|
||||
pattern.add_double("size", config.font_size * font_scale)?;
|
||||
pattern.add_double("dpi", config.dpi)?;
|
||||
*/
|
||||
pattern.monospace()?;
|
||||
pattern.config_substitute(fcwrap::MatchKind::Pattern)?;
|
||||
pattern.default_substitute();
|
||||
// and obtain the selection with the best preference
|
||||
// at index 0.
|
||||
let font_list = pattern.sort(true)?;
|
||||
|
||||
for (idx, pat) in font_list.iter().enumerate() {
|
||||
pattern.render_prepare(&pat)?;
|
||||
let file = pat.get_file()?;
|
||||
|
||||
let handle = FontDataHandle::OnDisk {
|
||||
path: file.into(),
|
||||
index: 0, // FIXME: extract this from pat!
|
||||
};
|
||||
|
||||
// When it comes to handling fallback, we prefer our
|
||||
// user specified set of names so we take those first.
|
||||
// The additional items in this loop are fallback fonts
|
||||
// suggested by fontconfig and are lower precedence
|
||||
if idx == 0 {
|
||||
self.fonts.push(handle);
|
||||
} else {
|
||||
self.fallback.push(handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fonts.extend_from_slice(&mut fallback);
|
||||
|
||||
Ok(fonts)
|
||||
}
|
||||
}
|
106
src/font/loader/font_kit.rs
Normal file
106
src/font/loader/font_kit.rs
Normal file
@ -0,0 +1,106 @@
|
||||
use crate::config::FontAttributes;
|
||||
use crate::font::loader::{FontDataHandle, FontLocator};
|
||||
use ::font_kit::error::SelectionError;
|
||||
use ::font_kit::family_handle::FamilyHandle;
|
||||
use ::font_kit::family_name::FamilyName;
|
||||
use ::font_kit::handle::Handle;
|
||||
use ::font_kit::properties::Properties;
|
||||
use ::font_kit::source::Source;
|
||||
use ::font_kit::sources::mem::MemSource;
|
||||
use failure::Fallible;
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// A FontLocator implemented using the font loading
|
||||
/// functions provided by Source's from font-kit crate.
|
||||
impl<S> FontLocator for S
|
||||
where
|
||||
S: Source,
|
||||
{
|
||||
fn load_fonts(&self, fonts_selection: &[FontAttributes]) -> Fallible<Vec<FontDataHandle>> {
|
||||
let mut handles = vec![];
|
||||
|
||||
for font in fonts_selection {
|
||||
let mut props = Properties::new();
|
||||
if font.bold {
|
||||
props.weight(font_kit::properties::Weight::BOLD);
|
||||
}
|
||||
if font.italic {
|
||||
props.style(font_kit::properties::Style::Italic);
|
||||
}
|
||||
let family = FamilyName::Title(font.family.clone());
|
||||
match self.select_best_match(&[family.clone()], &props) {
|
||||
Ok(Handle::Path { path, font_index }) => handles.push(FontDataHandle::OnDisk {
|
||||
path,
|
||||
index: font_index,
|
||||
}),
|
||||
Ok(Handle::Memory { bytes, font_index }) => handles.push(FontDataHandle::Memory {
|
||||
data: bytes.to_vec(),
|
||||
index: font_index,
|
||||
}),
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(handles)
|
||||
}
|
||||
}
|
||||
|
||||
/// A FontLocator that uses a set of fonts discovered in an arbitrary
|
||||
/// location on the local filesystem
|
||||
pub struct FileSystemDirectorySource {
|
||||
mem_source: MemSource,
|
||||
}
|
||||
|
||||
impl FileSystemDirectorySource {
|
||||
pub fn new(paths: &[PathBuf]) -> Self {
|
||||
let mut fonts = vec![];
|
||||
|
||||
for path in paths {
|
||||
for entry in walkdir::WalkDir::new(path).into_iter() {
|
||||
let entry = match entry {
|
||||
Ok(entry) => entry,
|
||||
Err(_) => continue,
|
||||
};
|
||||
|
||||
let path = entry.path();
|
||||
let mut file = match std::fs::File::open(path) {
|
||||
Err(_) => continue,
|
||||
Ok(file) => file,
|
||||
};
|
||||
|
||||
use font_kit::file_type::FileType;
|
||||
match font_kit::font::Font::analyze_file(&mut file) {
|
||||
Err(_) => continue,
|
||||
Ok(FileType::Single) => fonts.push(Handle::from_path(path.to_owned(), 0)),
|
||||
Ok(FileType::Collection(font_count)) => {
|
||||
for font_index in 0..font_count {
|
||||
fonts.push(Handle::from_path(path.to_owned(), font_index))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Self {
|
||||
mem_source: MemSource::from_fonts(fonts.into_iter()).unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Source for FileSystemDirectorySource {
|
||||
fn all_fonts(&self) -> Result<Vec<Handle>, SelectionError> {
|
||||
self.mem_source.all_fonts()
|
||||
}
|
||||
|
||||
fn all_families(&self) -> Result<Vec<String>, SelectionError> {
|
||||
self.mem_source.all_families()
|
||||
}
|
||||
|
||||
fn select_family_by_name(&self, family_name: &str) -> Result<FamilyHandle, SelectionError> {
|
||||
self.mem_source.select_family_by_name(family_name)
|
||||
}
|
||||
|
||||
fn select_by_postscript_name(&self, postscript_name: &str) -> Result<Handle, SelectionError> {
|
||||
self.mem_source.select_by_postscript_name(postscript_name)
|
||||
}
|
||||
}
|
39
src/font/loader/font_loader.rs
Normal file
39
src/font/loader/font_loader.rs
Normal file
@ -0,0 +1,39 @@
|
||||
use crate::config::FontAttributes;
|
||||
use crate::font::loader::{FontDataHandle, FontLocator};
|
||||
use ::font_loader::system_fonts;
|
||||
use failure::Fallible;
|
||||
|
||||
/// A FontLocator implemented using the system font loading
|
||||
/// functions provided by the font-loader crate.
|
||||
pub struct FontLoaderFontLocator {}
|
||||
|
||||
impl FontLocator for FontLoaderFontLocator {
|
||||
fn load_fonts(&self, fonts_selection: &[FontAttributes]) -> Fallible<Vec<FontDataHandle>> {
|
||||
let mut fonts = Vec::new();
|
||||
for font_attr in fonts_selection {
|
||||
let mut font_props = system_fonts::FontPropertyBuilder::new()
|
||||
.family(&font_attr.family)
|
||||
.monospace();
|
||||
font_props = if font_attr.bold {
|
||||
font_props.bold()
|
||||
} else {
|
||||
font_props
|
||||
};
|
||||
font_props = if font_attr.italic {
|
||||
font_props.italic()
|
||||
} else {
|
||||
font_props
|
||||
};
|
||||
let font_props = font_props.build();
|
||||
|
||||
if let Some((data, index)) = system_fonts::get(&font_props) {
|
||||
let handle = FontDataHandle::Memory {
|
||||
data,
|
||||
index: index as u32,
|
||||
};
|
||||
fonts.push(handle);
|
||||
}
|
||||
}
|
||||
Ok(fonts)
|
||||
}
|
||||
}
|
27
src/font/loader/mod.rs
Normal file
27
src/font/loader/mod.rs
Normal file
@ -0,0 +1,27 @@
|
||||
use crate::config::FontAttributes;
|
||||
use failure::Fallible;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[cfg(all(unix, any(feature = "fontconfig", not(target_os = "macos"))))]
|
||||
pub mod font_config;
|
||||
#[cfg(any(target_os = "macos", windows))]
|
||||
pub mod font_kit;
|
||||
#[cfg(any(target_os = "macos", windows))]
|
||||
pub mod font_loader;
|
||||
|
||||
/// Represents the data behind a font.
|
||||
/// This may be a font file that we can read off disk,
|
||||
/// or some data that resides in memory.
|
||||
/// The `index` parameter is the index into a font
|
||||
/// collection if the data represents a collection of
|
||||
/// fonts.
|
||||
pub enum FontDataHandle {
|
||||
OnDisk { path: PathBuf, index: u32 },
|
||||
Memory { data: Vec<u8>, index: u32 },
|
||||
}
|
||||
|
||||
pub trait FontLocator {
|
||||
/// Given a font selection, return the list of successfully loadable
|
||||
/// FontDataHandle's that correspond to it
|
||||
fn load_fonts(&self, fonts_selection: &[FontAttributes]) -> Fallible<Vec<FontDataHandle>>;
|
||||
}
|
@ -9,6 +9,8 @@ use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub mod loader;
|
||||
|
||||
pub mod system;
|
||||
pub use self::system::*;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user