mirror of
https://github.com/wez/wezterm.git
synced 2024-12-25 14:22:37 +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::collections::HashMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
pub mod loader;
|
||||||
|
|
||||||
pub mod system;
|
pub mod system;
|
||||||
pub use self::system::*;
|
pub use self::system::*;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user