feat(font): add the FreeType-only font backend (font-backend-freetype)

Ghostty can be built with -Dfont-backend=freetype, which uses FreeType
without any font discovery. The Rust port only had fontconfig+freetype
(default on Linux) and the CoreText variants. The new cargo feature
`font-backend-freetype` on ghostty-font (forwarded by ghostty-cli and
the root crate; non-Apple, non-wasm targets) behaves like Zig's mode:
font-family discovery, fallback search and codepoint-map overrides are
skipped (embedded fonts only); +list-fonts and +show-face print Zig's
"built without a font discovery mechanism" message and exit 1; +version
reports `.freetype`. The default backend is unchanged.

Also registers the Rust-only benchmark tooling extensions (--time,
--handler=full, ghostty-synthetic +sgr) in DEVIANT_FIXES.md.

Note: `--all-features` now selects this backend for the workspace.

Test Plan:
- cargo test -p ghostty-font --features font-backend-freetype (198)
- cargo build --features font-backend-freetype && ghostty +list-fonts
This commit is contained in:
ddidderr committed 2026-10-12 15:56:21 +02:00
1 parent ebd603f3da
commit ff1169abed
18 files changed
+327 -12

No files matched your search

+1 -1
View File
@@ -19,5 +19,5 @@ pub mod run;
pub mod web_canvas;
#[cfg(all(test, font_harfbuzz, font_fontconfig))]
#[cfg(all(test, font_harfbuzz))]
pub(crate) mod test_util;
+11 -1
View File
@@ -23,7 +23,6 @@ use crate::{
Style,
codepoint_resolver::CodepointResolver,
collection::{AddOptions, Collection, LoadOptions, SizeAdjustment},
discovery::{Descriptor, Fontconfig},
embedded,
face::{DesiredSize, FontData, Options as FaceOptions},
shape,
@@ -102,7 +101,18 @@ pub(crate) fn test_shaper_with_font(font_req: TestFont) -> TestShaper {
/// Returns None (the test is skipped, like `error.SkipZigTest`) if the font
/// can't be discovered.
#[cfg(not(font_fontconfig))]
pub(crate) fn test_shaper_with_discovered_font(_font_req: &str) -> Option<TestShaper> {
// No fontconfig discovery in this backend (for example `freetype`).
None
}
/// Returns None (the test is skipped, like `error.SkipZigTest`) if the font
/// can't be discovered.
#[cfg(font_fontconfig)]
pub(crate) fn test_shaper_with_discovered_font(font_req: &str) -> Option<TestShaper> {
use crate::discovery::{Descriptor, Fontconfig};
let lib = Library::init().unwrap();
let mut c = Collection::new();
c.load_options = Some(LoadOptions::new(lib.clone()));