aboutsummaryrefslogtreecommitdiff
path: root/vendor/libghostty-vt/src/font/discovery.zig
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-09-10 21:51:57 +0300
committerGitHub <noreply@github.com>2026-09-10 21:51:57 +0300
commit425c86179791cd32e2d4ce0ae7f269940b4b0663 (patch)
treee52c4383a6d69216cbe2a32638bf90841d7e2189 /vendor/libghostty-vt/src/font/discovery.zig
parent90e947a6e26e02f10ec7f1694c4eb5b78a86406b (diff)
chore: upgrade libghostty and preserve terminal behavior (#3906)
Diffstat (limited to 'vendor/libghostty-vt/src/font/discovery.zig')
-rw-r--r--vendor/libghostty-vt/src/font/discovery.zig85
1 files changed, 76 insertions, 9 deletions
diff --git a/vendor/libghostty-vt/src/font/discovery.zig b/vendor/libghostty-vt/src/font/discovery.zig
index b945aa01..1847693a 100644
--- a/vendor/libghostty-vt/src/font/discovery.zig
+++ b/vendor/libghostty-vt/src/font/discovery.zig
@@ -12,6 +12,7 @@ const Face = @import("main.zig").Face;
const Library = @import("main.zig").Library;
const Presentation = @import("main.zig").Presentation;
const Variation = @import("main.zig").face.Variation;
+const global = @import("../global.zig");
const log = std.log.scoped(.discovery);
@@ -349,6 +350,22 @@ pub const CoreText = struct {
_ = self;
}
+ /// Warm up the system font registry.
+ ///
+ /// The first CoreText query in a process initializes the system font
+ /// database, which takes multiple milliseconds, while subsequent
+ /// queries are microseconds.
+ pub fn warmup() void {
+ const name = macos.foundation.String.createWithBytes(
+ "AppleColorEmoji",
+ .utf8,
+ false,
+ ) catch return;
+ defer name.release();
+ const ct_font = macos.text.Font.createWithName(name, 12) catch return;
+ ct_font.release();
+ }
+
/// Discover fonts from a descriptor. This returns an iterator that can
/// be used to build up the deferred fonts.
pub fn discover(self: *const CoreText, alloc: Allocator, desc: Descriptor) !DiscoverIterator {
@@ -382,6 +399,54 @@ pub const CoreText = struct {
};
}
+ /// Discover a font by its exact name (family, full, or PostScript
+ /// name). This is significantly faster than `discover` because it
+ /// avoids the system-wide font matching that CTFontCollection does
+ /// (which takes multiple milliseconds). This should be preferred
+ /// when the desired font is known exactly, e.g. system fonts such
+ /// as Apple Color Emoji.
+ ///
+ /// Returns null if no font with this exact family name exists;
+ /// CoreText fallback fonts are never returned.
+ pub fn discoverExactFamily(
+ self: *const CoreText,
+ family: []const u8,
+ ) !?DeferredFace {
+ _ = self;
+
+ const family_str = try macos.foundation.String.createWithBytes(
+ family,
+ .utf8,
+ false,
+ );
+ defer family_str.release();
+
+ // Create our font. We need a size to initialize it so we use size
+ // 12 but we will alter the size later (same as DiscoverIterator).
+ const ct_font = try macos.text.Font.createWithName(family_str, 12);
+
+ // CTFontCreateWithName never returns null: if the requested font
+ // isn't installed it returns a substitute font. Verify we got
+ // the family we asked for, otherwise report not found.
+ const found: bool = found: {
+ const actual = ct_font.copyFamilyName();
+ defer actual.release();
+ var buf: [256]u8 = undefined;
+ const actual_slice = actual.cstring(&buf, .utf8) orelse
+ break :found false;
+ break :found std.mem.eql(u8, actual_slice, family);
+ };
+ if (!found) {
+ ct_font.release();
+ return null;
+ }
+
+ return .{ .ct = .{
+ .font = ct_font,
+ .variations = &.{},
+ } };
+ }
+
pub fn discoverFallback(
self: *const CoreText,
alloc: Allocator,
@@ -942,15 +1007,15 @@ pub const Windows = struct {
desc: Descriptor,
variations: []const Variation,
state: State,
- dir: ?std.fs.Dir,
- iter: ?std.fs.Dir.Iterator,
+ dir: ?std.Io.Dir,
+ iter: ?std.Io.Dir.Iterator,
system_path: ?[:0]const u8,
user_path: ?[:0]const u8,
const State = enum { system, user, done };
pub fn deinit(self: *DiscoverIterator) void {
- if (self.dir) |*d| d.close();
+ if (self.dir) |*d| d.close(global.io());
if (self.system_path) |p| self.alloc.free(p);
if (self.user_path) |p| self.alloc.free(p);
self.* = undefined;
@@ -967,7 +1032,8 @@ pub const Windows = struct {
continue;
};
self.system_path = path;
- self.dir = std.fs.openDirAbsoluteZ(
+ self.dir = std.Io.Dir.openDirAbsolute(
+ global.io(),
path,
.{ .iterate = true },
) catch {
@@ -982,7 +1048,8 @@ pub const Windows = struct {
continue;
};
self.user_path = path;
- self.dir = std.fs.openDirAbsoluteZ(
+ self.dir = std.Io.Dir.openDirAbsolute(
+ global.io(),
path,
.{ .iterate = true },
) catch {
@@ -995,9 +1062,9 @@ pub const Windows = struct {
}
}
- const entry = (self.iter.?.next() catch null) orelse {
+ const entry = (self.iter.?.next(global.io()) catch null) orelse {
// Finished this directory; advance state.
- if (self.dir) |*d| d.close();
+ if (self.dir) |*d| d.close(global.io());
self.dir = null;
self.iter = null;
self.state = switch (self.state) {
@@ -1020,7 +1087,7 @@ pub const Windows = struct {
/// Windows install but we just skip the directory rather than
/// falling back to a hardcoded drive letter.
fn systemFontsPath(self: *DiscoverIterator) ?[:0]const u8 {
- const systemroot = std.process.getEnvVarOwned(
+ const systemroot = global.environ().getAlloc(
self.alloc,
"SYSTEMROOT",
) catch return null;
@@ -1034,7 +1101,7 @@ pub const Windows = struct {
}
fn userFontsPath(self: *DiscoverIterator) ?[:0]const u8 {
- const local_appdata = std.process.getEnvVarOwned(
+ const local_appdata = global.environ().getAlloc(
self.alloc,
"LOCALAPPDATA",
) catch return null;