feat(font): port the Linux font engine
Ports the rest of ZIG/src/font for the freetype/fontconfig/harfbuzz backend: face loading and rasterization (synthetic bold/italic, color emoji bitmaps, glyph constraints for nerd font icons), fontconfig discovery, DeferredFace, Collection, CodepointResolver, CodepointMap, SharedGrid, opentype table parsers, the nerd font attribute table, and the harfbuzz shaper with feature parsing and shaping cache. Embedded fonts (JetBrains Mono 2.304 variable, Symbols Nerd Font 3.4.0, Noto emoji) and the test fonts from Ghostty live in res/ with their OFL/ MIT licenses. The crate opts into unsafe_code = "deny"; FFI is confined to ft.rs, fontconfig.rs and hb.rs with SAFETY comments. Glyph resampling uses an stb-style resampler that is not bit-identical to stb. Deferred to the next font pass (needs ghostty-terminal/config): shaper/run.zig, SharedGridSet.zig and the 23 terminal-driven shaper tests. Config-facing types are mirrored locally in config_types.rs. Test Plan: - cargo test -p ghostty-font (139 tests)
This commit is contained in:
1 parent
6cf16ed2e6
commit
25801765eb
64 files changed
+35316
-23
No files matched your search
@@ -0,0 +1,67 @@
|
||||
//! A library represents the shared state that the underlying font
|
||||
//! library implementation(s) require per-process. Port of `font/library.zig`
|
||||
//! (the `FreetypeLibrary` variant).
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use crate::face::freetype::ft;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum LibraryError {
|
||||
#[error("freetype error {0}")]
|
||||
Freetype(i32),
|
||||
}
|
||||
|
||||
/// Shared FreeType library state. Cheap to clone.
|
||||
#[derive(Clone)]
|
||||
pub struct Library {
|
||||
pub(crate) inner: Arc<LibraryInner>,
|
||||
}
|
||||
|
||||
pub(crate) struct LibraryInner {
|
||||
pub(crate) lib: ft::Lib,
|
||||
|
||||
/// Mutex to be held any time the library is
|
||||
/// being used to create or destroy a face.
|
||||
pub(crate) mutex: Mutex<()>,
|
||||
}
|
||||
|
||||
impl Library {
|
||||
pub fn init() -> Result<Library, LibraryError> {
|
||||
let lib = ft::Lib::new().map_err(LibraryError::Freetype)?;
|
||||
Ok(Library {
|
||||
inner: Arc::new(LibraryInner {
|
||||
lib,
|
||||
mutex: Mutex::new(()),
|
||||
}),
|
||||
})
|
||||
}
|
||||
|
||||
/// Lock the library mutex (poisoning is ignored: the guarded state is
|
||||
/// only FreeType's own).
|
||||
pub(crate) fn lock(&self) -> std::sync::MutexGuard<'_, ()> {
|
||||
self.inner
|
||||
.mutex
|
||||
.lock()
|
||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Library {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str("Library")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn init_and_clone() {
|
||||
let lib = Library::init().unwrap();
|
||||
let lib2 = lib.clone();
|
||||
drop(lib);
|
||||
drop(lib2.lock());
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user