1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-23 21:32:13 +03:00

wezterm-font: remove font-loader dependency

This commit replaces it with the underlying core text calls
on macos.

refs: #337
This commit is contained in:
Wez Furlong 2020-11-22 11:19:44 -08:00
parent 9ca428c4e1
commit 30cc10d4cf
8 changed files with 139 additions and 179 deletions

131
Cargo.lock generated
View File

@ -656,15 +656,6 @@ dependencies = [
"bitflags 1.2.1", "bitflags 1.2.1",
] ]
[[package]]
name = "cmake"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e56268c17a6248366d66d4a47a3381369d068cce8409bb1716ed77ea32163bb"
dependencies = [
"cc",
]
[[package]] [[package]]
name = "cocoa" name = "cocoa"
version = "0.20.2" version = "0.20.2"
@ -780,16 +771,6 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
[[package]]
name = "core-foundation"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d"
dependencies = [
"core-foundation-sys 0.6.2",
"libc",
]
[[package]] [[package]]
name = "core-foundation" name = "core-foundation"
version = "0.7.0" version = "0.7.0"
@ -801,10 +782,14 @@ dependencies = [
] ]
[[package]] [[package]]
name = "core-foundation-sys" name = "core-foundation"
version = "0.6.2" version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62"
dependencies = [
"core-foundation-sys 0.8.2",
"libc",
]
[[package]] [[package]]
name = "core-foundation-sys" name = "core-foundation-sys"
@ -813,16 +798,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac"
[[package]] [[package]]
name = "core-graphics" name = "core-foundation-sys"
version = "0.14.0" version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e54c4ab33705fa1fc8af375bb7929d68e1c1546c1ecef408966d8c3e49a1d84a" checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b"
dependencies = [
"bitflags 1.2.1",
"core-foundation 0.6.4",
"foreign-types",
"libc",
]
[[package]] [[package]]
name = "core-graphics" name = "core-graphics"
@ -837,25 +816,38 @@ dependencies = [
] ]
[[package]] [[package]]
name = "core-text" name = "core-graphics"
version = "10.0.0" version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81f59bff773954e5cd058a3f5983406b52bec7cc65202bef340ba64a0c40ac91" checksum = "fc239bba52bab96649441699533a68de294a101533b0270b2d65aa402b29a7f9"
dependencies = [ dependencies = [
"core-foundation 0.6.4", "bitflags 1.2.1",
"core-graphics 0.14.0", "core-foundation 0.9.1",
"core-graphics-types",
"foreign-types",
"libc",
]
[[package]]
name = "core-graphics-types"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b"
dependencies = [
"bitflags 1.2.1",
"core-foundation 0.9.1",
"foreign-types", "foreign-types",
"libc", "libc",
] ]
[[package]] [[package]]
name = "core-text" name = "core-text"
version = "15.0.0" version = "19.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "131b3fd1f8bd5db9f2b398fa4fdb6008c64afc04d447c306ac2c7e98fba2a61d" checksum = "d2c7f46e8b820fd5f4b28528104b28b0a91cbe9e9c5bde8017087fb44bc93a60"
dependencies = [ dependencies = [
"core-foundation 0.7.0", "core-foundation 0.9.1",
"core-graphics 0.19.2", "core-graphics 0.22.1",
"foreign-types", "foreign-types",
"libc", "libc",
] ]
@ -1150,16 +1142,6 @@ dependencies = [
"smallvec 0.6.13", "smallvec 0.6.13",
] ]
[[package]]
name = "expat-sys"
version = "2.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "658f19728920138342f68408b7cf7644d90d4784353d8ebc32e7e8663dbe45fa"
dependencies = [
"cmake",
"pkg-config",
]
[[package]] [[package]]
name = "fake-simd" name = "fake-simd"
version = "0.1.2" version = "0.1.2"
@ -1239,19 +1221,6 @@ version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "font-loader"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ece0e8a5dd99a65f8de977b4a3f89e3b5a5259e15ae610952cdb894e96f5e2e"
dependencies = [
"core-foundation 0.6.4",
"core-text 10.0.0",
"libc",
"servo-fontconfig",
"winapi 0.3.9",
]
[[package]] [[package]]
name = "fontconfig" name = "fontconfig"
version = "0.1.0" version = "0.1.0"
@ -3332,37 +3301,6 @@ dependencies = [
"serial-core", "serial-core",
] ]
[[package]]
name = "servo-fontconfig"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a088f8d775a5c5314aae09bd77340bc9c67d72b9a45258be34c83548b4814cd9"
dependencies = [
"libc",
"servo-fontconfig-sys",
]
[[package]]
name = "servo-fontconfig-sys"
version = "4.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0aa080856db55f188aaf36f01cae8c03448a6056552adb77d461179e44e1a14"
dependencies = [
"expat-sys",
"pkg-config",
"servo-freetype-sys",
]
[[package]]
name = "servo-freetype-sys"
version = "4.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9232032c2e85118c0282c6562c84cab12316e655491ba0a5d1905b2320060d1b"
dependencies = [
"cmake",
"pkg-config",
]
[[package]] [[package]]
name = "sha-1" name = "sha-1"
version = "0.8.2" version = "0.8.2"
@ -4348,11 +4286,10 @@ dependencies = [
"allsorts", "allsorts",
"anyhow", "anyhow",
"config", "config",
"core-foundation 0.7.0", "core-foundation 0.9.1",
"core-text 15.0.0", "core-text",
"dwrote", "dwrote",
"euclid 0.20.14", "euclid 0.20.14",
"font-loader",
"fontconfig", "fontconfig",
"freetype", "freetype",
"harfbuzz", "harfbuzz",

View File

@ -227,9 +227,8 @@ pub enum FontLocatorSelection {
FontConfig, FontConfig,
/// Use the EnumFontFamilies call on win32 systems /// Use the EnumFontFamilies call on win32 systems
EnumFontFamilies, EnumFontFamilies,
/// Use the fontloader crate to use a system specific method of /// Use CoreText on macOS
/// resolving fonts CoreText,
FontLoader,
/// Use only the font_dirs configuration to locate fonts /// Use only the font_dirs configuration to locate fonts
ConfigDirsOnly, ConfigDirsOnly,
} }
@ -243,7 +242,7 @@ impl Default for FontLocatorSelection {
if cfg!(windows) { if cfg!(windows) {
FontLocatorSelection::EnumFontFamilies FontLocatorSelection::EnumFontFamilies
} else if cfg!(target_os = "macos") { } else if cfg!(target_os = "macos") {
FontLocatorSelection::FontLoader FontLocatorSelection::CoreText
} else { } else {
FontLocatorSelection::FontConfig FontLocatorSelection::FontConfig
} }
@ -264,7 +263,7 @@ impl FontLocatorSelection {
pub fn variants() -> Vec<&'static str> { pub fn variants() -> Vec<&'static str> {
vec![ vec![
"FontConfig", "FontConfig",
"FontLoader", "CoreText",
"ConfigDirsOnly", "ConfigDirsOnly",
"EnumFontFamilies", "EnumFontFamilies",
] ]
@ -276,7 +275,7 @@ impl std::str::FromStr for FontLocatorSelection {
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_ref() { match s.to_lowercase().as_ref() {
"fontconfig" => Ok(Self::FontConfig), "fontconfig" => Ok(Self::FontConfig),
"fontloader" => Ok(Self::FontLoader), "coretext" => Ok(Self::CoreText),
"configdirsonly" => Ok(Self::ConfigDirsOnly), "configdirsonly" => Ok(Self::ConfigDirsOnly),
"enumfontfamilies" => Ok(Self::EnumFontFamilies), "enumfontfamilies" => Ok(Self::EnumFontFamilies),
_ => Err(anyhow!( _ => Err(anyhow!(

View File

@ -34,8 +34,5 @@ dwrote = "0.9"
winapi = "0.3" winapi = "0.3"
[target.'cfg(target_os = "macos")'.dependencies] [target.'cfg(target_os = "macos")'.dependencies]
core-foundation = "0.7" core-foundation = "0.9"
core-text = "15.0" core-text = "19.0"
# on linux, font-loader pulls in servo-font* crates which conflict with
# our newer font related deps, so we avoid it on linux
font-loader = { version = "0.8" }

View File

@ -0,0 +1,93 @@
#![cfg(target_os="macos")]
use crate::locator::{FontDataHandle, FontLocator};
use config::FontAttributes;
use core_foundation::base::{CFType, TCFType};
use core_foundation::dictionary::CFDictionary;
use core_foundation::number::CFNumber;
use core_foundation::string::CFString;
use core_foundation::url::CFURL;
use core_text::font_descriptor::*;
use std::collections::HashSet;
use std::path::PathBuf;
/// A FontLocator implemented using the system font loading
/// functions provided by the font-loader crate.
pub struct CoreTextFontLocator {}
fn descriptor_from_attr(attr: &FontAttributes) -> anyhow::Result<CTFontDescriptor> {
let family_name = attr
.family
.parse::<CFString>()
.map_err(|_| anyhow::anyhow!("failed to parse family name {} as CFString", attr.family))?;
let symbolic_traits: CTFontSymbolicTraits = kCTFontMonoSpaceTrait
| if attr.bold { kCTFontBoldTrait } else { 0 }
| if attr.italic { kCTFontItalicTrait } else { 0 };
let family_attr: CFString = unsafe { TCFType::wrap_under_get_rule(kCTFontFamilyNameAttribute) };
let traits_attr: CFString = unsafe { TCFType::wrap_under_get_rule(kCTFontTraitsAttribute) };
let symbolic_traits_attr: CFString =
unsafe { TCFType::wrap_under_get_rule(kCTFontSymbolicTrait) };
let traits = CFDictionary::from_CFType_pairs(&[(
symbolic_traits_attr.as_CFType(),
CFNumber::from(symbolic_traits as i32).as_CFType(),
)]);
let attributes = CFDictionary::from_CFType_pairs(&[
(traits_attr, traits.as_CFType()),
(family_attr, family_name.as_CFType()),
]);
Ok(core_text::font_descriptor::new_from_attributes(&attributes))
}
fn font_path_from_descriptor(descriptor: &CTFontDescriptor) -> anyhow::Result<PathBuf> {
let url: CFURL;
unsafe {
let value =
CTFontDescriptorCopyAttribute(descriptor.as_concrete_TypeRef(), kCTFontURLAttribute);
if value.is_null() {
return Err(anyhow::anyhow!("font descriptor has no URL"));
}
let value: CFType = TCFType::wrap_under_get_rule(value);
if !value.instance_of::<CFURL>() {
return Err(anyhow::anyhow!("font descriptor URL is not a CFURL"));
}
url = TCFType::wrap_under_get_rule(std::mem::transmute(value.as_CFTypeRef()));
}
if let Some(path) = url.to_path() {
Ok(path)
} else {
Err(anyhow::anyhow!("font descriptor URL is not a path"))
}
}
impl FontLocator for CoreTextFontLocator {
fn load_fonts(
&self,
fonts_selection: &[FontAttributes],
loaded: &mut HashSet<FontAttributes>,
) -> anyhow::Result<Vec<FontDataHandle>> {
let mut fonts = vec![];
for attr in fonts_selection {
if let Ok(descriptor) = descriptor_from_attr(attr) {
if let Ok(path) = font_path_from_descriptor(&descriptor) {
let handle = FontDataHandle::OnDisk { path, index: 0 };
if let Ok(parsed) = crate::parser::ParsedFont::from_locator(&handle) {
if crate::parser::font_info_matches(attr, parsed.names()) {
fonts.push(handle);
loaded.insert(attr.clone());
}
}
}
}
}
Ok(fonts)
}
}

View File

@ -16,7 +16,6 @@ impl FontLocator for FontConfigFontLocator {
loaded: &mut HashSet<FontAttributes>, loaded: &mut HashSet<FontAttributes>,
) -> anyhow::Result<Vec<FontDataHandle>> { ) -> anyhow::Result<Vec<FontDataHandle>> {
let mut fonts = vec![]; let mut fonts = vec![];
let mut fallback = vec![];
for attr in fonts_selection { for attr in fonts_selection {
let mut pattern = FontPattern::new()?; let mut pattern = FontPattern::new()?;
@ -55,8 +54,6 @@ impl FontLocator for FontConfigFontLocator {
} }
} }
fonts.append(&mut fallback);
Ok(fonts) Ok(fonts)
} }
} }

View File

@ -1,62 +0,0 @@
use crate::locator::{FontDataHandle, FontLocator};
use ::font_loader::system_fonts;
use config::FontAttributes;
use std::collections::HashSet;
/// 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],
loaded: &mut HashSet<FontAttributes>,
) -> anyhow::Result<Vec<FontDataHandle>> {
let mut fonts = Vec::new();
for font_attr in fonts_selection {
if cfg!(windows) && font_attr.family.len() > 31 {
// Avoid a super painful panic in the upstream library:
// https://github.com/MSleepyPanda/rust-font-loader/blob/2b264974fe080955d341ce8a163035bdce24ff2f/src/win32.rs#L87
log::error!(
"font-loader would panic for font family `{}`",
font_attr.family
);
continue;
}
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,
name: font_attr.family.clone(),
};
// The system may just decide to give us its fallback,
// eg: Consolas, so we need to parse the returned font
// here to see if we got what we asked for.
if let Ok(parsed) = crate::parser::ParsedFont::from_locator(&handle) {
if crate::parser::font_info_matches(font_attr, parsed.names()) {
fonts.push(handle);
loaded.insert(font_attr.clone());
}
}
}
}
Ok(fonts)
}
}

View File

@ -2,11 +2,10 @@ use config::FontAttributes;
use std::collections::HashSet; use std::collections::HashSet;
use std::path::PathBuf; use std::path::PathBuf;
pub mod core_text;
pub mod enum_font_families; pub mod enum_font_families;
#[cfg(all(unix, not(target_os = "macos")))] #[cfg(all(unix, not(target_os = "macos")))]
pub mod font_config; pub mod font_config;
#[cfg(target_os = "macos")]
pub mod font_loader;
/// Represents the data behind a font. /// Represents the data behind a font.
/// This may be a font file that we can read off disk, /// This may be a font file that we can read off disk,
@ -64,11 +63,11 @@ pub fn new_locator(locator: FontLocatorSelection) -> Box<dyn FontLocator> {
#[cfg(not(all(unix, not(target_os = "macos"))))] #[cfg(not(all(unix, not(target_os = "macos"))))]
panic!("fontconfig not compiled in"); panic!("fontconfig not compiled in");
} }
FontLocatorSelection::FontLoader => { FontLocatorSelection::CoreText => {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
return Box::new(font_loader::FontLoaderFontLocator {}); return Box::new(core_text::CoreTextFontLocator {});
#[cfg(not(target_os = "macos"))] #[cfg(not(target_os = "macos"))]
panic!("fontloader not compiled in"); panic!("CoreText not compiled in");
} }
FontLocatorSelection::EnumFontFamilies => { FontLocatorSelection::EnumFontFamilies => {
#[cfg(windows)] #[cfg(windows)]

View File

@ -551,7 +551,7 @@ pub fn font_info_matches(attr: &FontAttributes, names: &Names) -> bool {
Some("Italic") if attr.italic && !attr.bold => true, Some("Italic") if attr.italic && !attr.bold => true,
Some("Bold") if attr.bold && !attr.italic => true, Some("Bold") if attr.bold && !attr.italic => true,
Some("Bold Italic") if attr.bold && attr.italic => true, Some("Bold Italic") if attr.bold && attr.italic => true,
Some("Regular") | None if !attr.italic && !attr.bold => true, Some("Medium") | Some("Regular") | None if !attr.italic && !attr.bold => true,
_ => false, _ => false,
} }
} else { } else {