aboutsummaryrefslogtreecommitdiff
path: root/vendor/libghostty-vt/pkg/macos
diff options
context:
space:
mode:
authorCan Celik <ogulcancelik@gmail.com>2026-04-04 19:22:04 +0300
committerCan Celik <ogulcancelik@gmail.com>2026-04-05 01:23:06 +0300
commit41dd733ca7123c9ac4bfc6c781697a660e95b052 (patch)
tree3fc91815ca139ef2e0b281bba0abda4ef15175f4 /vendor/libghostty-vt/pkg/macos
parent55c138263e190a1e79d4b997bfb9397306c0ec1f (diff)
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/pkg/macos')
-rw-r--r--vendor/libghostty-vt/pkg/macos/animation.zig10
-rw-r--r--vendor/libghostty-vt/pkg/macos/animation/c.zig1
-rw-r--r--vendor/libghostty-vt/pkg/macos/build.zig82
-rw-r--r--vendor/libghostty-vt/pkg/macos/build.zig.zon9
-rw-r--r--vendor/libghostty-vt/pkg/macos/carbon.zig5
-rw-r--r--vendor/libghostty-vt/pkg/macos/carbon/c.zig1
-rw-r--r--vendor/libghostty-vt/pkg/macos/dispatch.zig18
-rw-r--r--vendor/libghostty-vt/pkg/macos/dispatch/c.zig1
-rw-r--r--vendor/libghostty-vt/pkg/macos/dispatch/data.zig31
-rw-r--r--vendor/libghostty-vt/pkg/macos/dispatch/queue.zig8
-rw-r--r--vendor/libghostty-vt/pkg/macos/foundation.zig37
-rw-r--r--vendor/libghostty-vt/pkg/macos/foundation/array.zig176
-rw-r--r--vendor/libghostty-vt/pkg/macos/foundation/attributed_string.zig103
-rw-r--r--vendor/libghostty-vt/pkg/macos/foundation/base.zig35
-rw-r--r--vendor/libghostty-vt/pkg/macos/foundation/c.zig1
-rw-r--r--vendor/libghostty-vt/pkg/macos/foundation/character_set.zig49
-rw-r--r--vendor/libghostty-vt/pkg/macos/foundation/data.zig38
-rw-r--r--vendor/libghostty-vt/pkg/macos/foundation/dictionary.zig125
-rw-r--r--vendor/libghostty-vt/pkg/macos/foundation/number.zig79
-rw-r--r--vendor/libghostty-vt/pkg/macos/foundation/string.zig174
-rw-r--r--vendor/libghostty-vt/pkg/macos/foundation/type.zig2
-rw-r--r--vendor/libghostty-vt/pkg/macos/foundation/url.zig104
-rw-r--r--vendor/libghostty-vt/pkg/macos/graphics.zig24
-rw-r--r--vendor/libghostty-vt/pkg/macos/graphics/affine_transform.zig16
-rw-r--r--vendor/libghostty-vt/pkg/macos/graphics/bitmap_context.zig50
-rw-r--r--vendor/libghostty-vt/pkg/macos/graphics/c.zig1
-rw-r--r--vendor/libghostty-vt/pkg/macos/graphics/color_space.zig99
-rw-r--r--vendor/libghostty-vt/pkg/macos/graphics/context.zig172
-rw-r--r--vendor/libghostty-vt/pkg/macos/graphics/font.zig3
-rw-r--r--vendor/libghostty-vt/pkg/macos/graphics/geometry.zig34
-rw-r--r--vendor/libghostty-vt/pkg/macos/graphics/image.zig31
-rw-r--r--vendor/libghostty-vt/pkg/macos/graphics/path.zig68
-rw-r--r--vendor/libghostty-vt/pkg/macos/iosurface.zig8
-rw-r--r--vendor/libghostty-vt/pkg/macos/iosurface/c.zig1
-rw-r--r--vendor/libghostty-vt/pkg/macos/iosurface/iosurface.zig136
-rw-r--r--vendor/libghostty-vt/pkg/macos/main.zig35
-rw-r--r--vendor/libghostty-vt/pkg/macos/os.zig10
-rw-r--r--vendor/libghostty-vt/pkg/macos/os/c.zig1
-rw-r--r--vendor/libghostty-vt/pkg/macos/os/log.zig65
-rw-r--r--vendor/libghostty-vt/pkg/macos/os/signpost.zig214
-rw-r--r--vendor/libghostty-vt/pkg/macos/os/zig_macos.c11
-rw-r--r--vendor/libghostty-vt/pkg/macos/text.zig38
-rw-r--r--vendor/libghostty-vt/pkg/macos/text/c.zig1
-rw-r--r--vendor/libghostty-vt/pkg/macos/text/ext.c10
-rw-r--r--vendor/libghostty-vt/pkg/macos/text/font.zig306
-rw-r--r--vendor/libghostty-vt/pkg/macos/text/font_collection.zig139
-rw-r--r--vendor/libghostty-vt/pkg/macos/text/font_descriptor.zig287
-rw-r--r--vendor/libghostty-vt/pkg/macos/text/font_manager.zig23
-rw-r--r--vendor/libghostty-vt/pkg/macos/text/frame.zig33
-rw-r--r--vendor/libghostty-vt/pkg/macos/text/framesetter.zig66
-rw-r--r--vendor/libghostty-vt/pkg/macos/text/line.zig123
-rw-r--r--vendor/libghostty-vt/pkg/macos/text/paragraph_style.zig49
-rw-r--r--vendor/libghostty-vt/pkg/macos/text/run.zig117
-rw-r--r--vendor/libghostty-vt/pkg/macos/text/stylized_strings.zig16
-rw-r--r--vendor/libghostty-vt/pkg/macos/text/typesetter.zig36
-rw-r--r--vendor/libghostty-vt/pkg/macos/video.zig10
-rw-r--r--vendor/libghostty-vt/pkg/macos/video/c.zig1
-rw-r--r--vendor/libghostty-vt/pkg/macos/video/display_link.zig86
-rw-r--r--vendor/libghostty-vt/pkg/macos/video/pixel_format.zig171
59 files changed, 3580 insertions, 0 deletions
diff --git a/vendor/libghostty-vt/pkg/macos/animation.zig b/vendor/libghostty-vt/pkg/macos/animation.zig
new file mode 100644
index 00000000..247f9760
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/animation.zig
@@ -0,0 +1,10 @@
+pub const c = @import("animation/c.zig").c;
+
+/// https://developer.apple.com/documentation/quartzcore/calayer/contents_gravity_values?language=objc
+pub extern "c" const kCAGravityTopLeft: *anyopaque;
+pub extern "c" const kCAGravityBottomLeft: *anyopaque;
+pub extern "c" const kCAGravityCenter: *anyopaque;
+
+test {
+ @import("std").testing.refAllDecls(@This());
+}
diff --git a/vendor/libghostty-vt/pkg/macos/animation/c.zig b/vendor/libghostty-vt/pkg/macos/animation/c.zig
new file mode 100644
index 00000000..1a7d1627
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/animation/c.zig
@@ -0,0 +1 @@
+pub const c = @import("../main.zig").c;
diff --git a/vendor/libghostty-vt/pkg/macos/build.zig b/vendor/libghostty-vt/pkg/macos/build.zig
new file mode 100644
index 00000000..0525e481
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/build.zig
@@ -0,0 +1,82 @@
+const std = @import("std");
+const builtin = @import("builtin");
+const apple_sdk = @import("apple_sdk");
+
+pub fn build(b: *std.Build) !void {
+ const target = b.standardTargetOptions(.{});
+ const optimize = b.standardOptimizeOption(.{});
+
+ const module = b.addModule("macos", .{
+ .root_source_file = b.path("main.zig"),
+ .target = target,
+ .optimize = optimize,
+ });
+
+ const lib = b.addLibrary(.{
+ .name = "macos",
+ .root_module = b.createModule(.{
+ .target = target,
+ .optimize = optimize,
+ }),
+ .linkage = .static,
+ });
+
+ lib.addCSourceFile(.{
+ .file = b.path("os/zig_macos.c"),
+ .flags = &.{"-std=c99"},
+ });
+ lib.addCSourceFile(.{
+ .file = b.path("text/ext.c"),
+ });
+ lib.linkFramework("CoreFoundation");
+ lib.linkFramework("CoreGraphics");
+ lib.linkFramework("CoreText");
+ lib.linkFramework("CoreVideo");
+ lib.linkFramework("QuartzCore");
+ lib.linkFramework("IOSurface");
+ if (target.result.os.tag == .macos) {
+ lib.linkFramework("Carbon");
+ module.linkFramework("Carbon", .{});
+ }
+
+ if (target.result.os.tag.isDarwin()) {
+ module.linkFramework("CoreFoundation", .{});
+ module.linkFramework("CoreGraphics", .{});
+ module.linkFramework("CoreText", .{});
+ module.linkFramework("CoreVideo", .{});
+ module.linkFramework("QuartzCore", .{});
+ module.linkFramework("IOSurface", .{});
+
+ try apple_sdk.addPaths(b, lib);
+ }
+ b.installArtifact(lib);
+
+ {
+ const test_exe = b.addTest(.{
+ .name = "test",
+ .root_module = b.createModule(.{
+ .root_source_file = b.path("main.zig"),
+ .target = target,
+ .optimize = optimize,
+ }),
+ });
+ if (target.result.os.tag.isDarwin()) {
+ try apple_sdk.addPaths(b, test_exe);
+ }
+ test_exe.linkLibrary(lib);
+
+ var it = module.import_table.iterator();
+ while (it.next()) |entry| {
+ test_exe.root_module.addImport(
+ entry.key_ptr.*,
+ entry.value_ptr.*,
+ );
+ }
+
+ b.installArtifact(test_exe);
+
+ const tests_run = b.addRunArtifact(test_exe);
+ const test_step = b.step("test", "Run tests");
+ test_step.dependOn(&tests_run.step);
+ }
+}
diff --git a/vendor/libghostty-vt/pkg/macos/build.zig.zon b/vendor/libghostty-vt/pkg/macos/build.zig.zon
new file mode 100644
index 00000000..4c22ad7c
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/build.zig.zon
@@ -0,0 +1,9 @@
+.{
+ .name = .macos,
+ .version = "0.1.0",
+ .fingerprint = 0x45e2f6107d5b2b2c,
+ .paths = .{""},
+ .dependencies = .{
+ .apple_sdk = .{ .path = "../apple-sdk" },
+ },
+}
diff --git a/vendor/libghostty-vt/pkg/macos/carbon.zig b/vendor/libghostty-vt/pkg/macos/carbon.zig
new file mode 100644
index 00000000..8eafaffe
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/carbon.zig
@@ -0,0 +1,5 @@
+pub const c = @import("carbon/c.zig").c;
+
+test {
+ @import("std").testing.refAllDecls(@This());
+}
diff --git a/vendor/libghostty-vt/pkg/macos/carbon/c.zig b/vendor/libghostty-vt/pkg/macos/carbon/c.zig
new file mode 100644
index 00000000..1a7d1627
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/carbon/c.zig
@@ -0,0 +1 @@
+pub const c = @import("../main.zig").c;
diff --git a/vendor/libghostty-vt/pkg/macos/dispatch.zig b/vendor/libghostty-vt/pkg/macos/dispatch.zig
new file mode 100644
index 00000000..3add9c0e
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/dispatch.zig
@@ -0,0 +1,18 @@
+pub const c = @import("dispatch/c.zig").c;
+pub const data = @import("dispatch/data.zig");
+pub const queue = @import("dispatch/queue.zig");
+pub const Data = data.Data;
+
+pub extern "c" fn dispatch_sync(
+ queue: *anyopaque,
+ block: *anyopaque,
+) void;
+
+pub extern "c" fn dispatch_async(
+ queue: *anyopaque,
+ block: *anyopaque,
+) void;
+
+test {
+ @import("std").testing.refAllDecls(@This());
+}
diff --git a/vendor/libghostty-vt/pkg/macos/dispatch/c.zig b/vendor/libghostty-vt/pkg/macos/dispatch/c.zig
new file mode 100644
index 00000000..1a7d1627
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/dispatch/c.zig
@@ -0,0 +1 @@
+pub const c = @import("../main.zig").c;
diff --git a/vendor/libghostty-vt/pkg/macos/dispatch/data.zig b/vendor/libghostty-vt/pkg/macos/dispatch/data.zig
new file mode 100644
index 00000000..28df24b7
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/dispatch/data.zig
@@ -0,0 +1,31 @@
+const std = @import("std");
+const foundation = @import("../foundation.zig");
+const c = @import("c.zig").c;
+
+pub const Data = opaque {
+ pub const DESTRUCTOR_DEFAULT = c.DISPATCH_DATA_DESTRUCTOR_DEFAULT;
+
+ pub fn create(
+ data: []const u8,
+ queue: ?*anyopaque,
+ destructor: ?*anyopaque,
+ ) !*Data {
+ return dispatch_data_create(
+ data.ptr,
+ data.len,
+ queue,
+ destructor,
+ ) orelse return error.OutOfMemory;
+ }
+
+ pub fn release(data: *Data) void {
+ foundation.c.CFRelease(data);
+ }
+};
+
+extern "c" fn dispatch_data_create(
+ data: [*]const u8,
+ len: usize,
+ queue: ?*anyopaque,
+ destructor: ?*anyopaque,
+) ?*Data;
diff --git a/vendor/libghostty-vt/pkg/macos/dispatch/queue.zig b/vendor/libghostty-vt/pkg/macos/dispatch/queue.zig
new file mode 100644
index 00000000..cb2ca01c
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/dispatch/queue.zig
@@ -0,0 +1,8 @@
+const std = @import("std");
+const c = @import("c.zig").c;
+
+pub const Queue = *anyopaque; // dispatch_queue_t
+
+pub fn getMain() Queue {
+ return c.dispatch_get_main_queue().?;
+}
diff --git a/vendor/libghostty-vt/pkg/macos/foundation.zig b/vendor/libghostty-vt/pkg/macos/foundation.zig
new file mode 100644
index 00000000..d4f63409
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/foundation.zig
@@ -0,0 +1,37 @@
+const array = @import("foundation/array.zig");
+const attributed_string = @import("foundation/attributed_string.zig");
+const base = @import("foundation/base.zig");
+const character_set = @import("foundation/character_set.zig");
+const data = @import("foundation/data.zig");
+const dictionary = @import("foundation/dictionary.zig");
+const number = @import("foundation/number.zig");
+const string = @import("foundation/string.zig");
+const typepkg = @import("foundation/type.zig");
+const url = @import("foundation/url.zig");
+
+pub const c = @import("foundation/c.zig").c;
+pub const Array = array.Array;
+pub const MutableArray = array.MutableArray;
+pub const AttributedString = attributed_string.AttributedString;
+pub const MutableAttributedString = attributed_string.MutableAttributedString;
+pub const ComparisonResult = base.ComparisonResult;
+pub const Range = base.Range;
+pub const FourCharCode = base.FourCharCode;
+pub const CharacterSet = character_set.CharacterSet;
+pub const Data = data.Data;
+pub const Dictionary = dictionary.Dictionary;
+pub const MutableDictionary = dictionary.MutableDictionary;
+pub const Number = number.Number;
+pub const String = string.String;
+pub const MutableString = string.MutableString;
+pub const StringComparison = string.StringComparison;
+pub const StringEncoding = string.StringEncoding;
+pub const stringGetSurrogatePairForLongCharacter = string.stringGetSurrogatePairForLongCharacter;
+pub const URL = url.URL;
+pub const URLPathStyle = url.URLPathStyle;
+pub const CFRelease = typepkg.CFRelease;
+pub const CFRetain = typepkg.CFRetain;
+
+test {
+ @import("std").testing.refAllDecls(@This());
+}
diff --git a/vendor/libghostty-vt/pkg/macos/foundation/array.zig b/vendor/libghostty-vt/pkg/macos/foundation/array.zig
new file mode 100644
index 00000000..7b580eb0
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/foundation/array.zig
@@ -0,0 +1,176 @@
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+const base = @import("base.zig");
+const c = @import("c.zig").c;
+const cftype = @import("type.zig");
+const ComparisonResult = base.ComparisonResult;
+const Range = base.Range;
+
+pub const Array = opaque {
+ pub fn create(comptime T: type, values: []*const T) Allocator.Error!*Array {
+ return CFArrayCreate(
+ null,
+ @ptrCast(values.ptr),
+ @intCast(values.len),
+ null,
+ ) orelse error.OutOfMemory;
+ }
+
+ pub fn release(self: *Array) void {
+ cftype.CFRelease(self);
+ }
+
+ pub fn getCount(self: *Array) usize {
+ return CFArrayGetCount(self);
+ }
+
+ /// Note the return type is actually a `*const T` but we strip the
+ /// constness so that further API calls work correctly. The Foundation
+ /// API doesn't properly mark things const/non-const.
+ pub fn getValueAtIndex(self: *Array, comptime T: type, idx: usize) *T {
+ return @ptrCast(@alignCast(CFArrayGetValueAtIndex(self, idx)));
+ }
+
+ pub extern "c" fn CFArrayCreate(
+ allocator: ?*anyopaque,
+ values: [*]*const anyopaque,
+ num_values: usize,
+ callbacks: ?*const anyopaque,
+ ) ?*Array;
+ pub extern "c" fn CFArrayGetCount(*Array) usize;
+ pub extern "c" fn CFArrayGetValueAtIndex(*Array, usize) *anyopaque;
+ extern "c" var kCFTypeArrayCallBacks: anyopaque;
+};
+
+pub const MutableArray = opaque {
+ pub fn create() Allocator.Error!*MutableArray {
+ return CFArrayCreateMutable(
+ null,
+ 0,
+ &c.kCFTypeArrayCallBacks,
+ ) orelse error.OutOfMemory;
+ }
+
+ pub fn createCopy(array: *Array) Allocator.Error!*MutableArray {
+ return CFArrayCreateMutableCopy(
+ null,
+ 0,
+ array,
+ ) orelse error.OutOfMemory;
+ }
+
+ pub fn release(self: *MutableArray) void {
+ cftype.CFRelease(self);
+ }
+
+ pub fn appendValue(
+ self: *MutableArray,
+ comptime Elem: type,
+ value: *const Elem,
+ ) void {
+ CFArrayAppendValue(self, @ptrCast(@constCast(value)));
+ }
+
+ pub fn removeValue(self: *MutableArray, idx: usize) void {
+ CFArrayRemoveValueAtIndex(self, idx);
+ }
+
+ pub fn sortValues(
+ self: *MutableArray,
+ comptime Elem: type,
+ comptime Context: type,
+ context: ?*Context,
+ comptime comparator: ?*const fn (
+ a: *const Elem,
+ b: *const Elem,
+ context: ?*Context,
+ ) callconv(.c) ComparisonResult,
+ ) void {
+ CFArraySortValues(
+ self,
+ Range.init(0, Array.CFArrayGetCount(@ptrCast(self))),
+ comparator,
+ context,
+ );
+ }
+
+ extern "c" fn CFArrayCreateMutable(
+ allocator: ?*anyopaque,
+ capacity: usize,
+ callbacks: ?*const anyopaque,
+ ) ?*MutableArray;
+ extern "c" fn CFArrayCreateMutableCopy(
+ allocator: ?*anyopaque,
+ capacity: usize,
+ array: *Array,
+ ) ?*MutableArray;
+ extern "c" fn CFArrayAppendValue(
+ *MutableArray,
+ *anyopaque,
+ ) void;
+ extern "c" fn CFArrayRemoveValueAtIndex(
+ *MutableArray,
+ usize,
+ ) void;
+ extern "c" fn CFArraySortValues(
+ array: *MutableArray,
+ range: Range,
+ comparator: ?*const anyopaque,
+ context: ?*anyopaque,
+ ) void;
+};
+
+test "array" {
+ const testing = std.testing;
+
+ const str = "hello";
+ var values = [_]*const u8{ &str[0], &str[1] };
+ const arr = try Array.create(u8, &values);
+ defer arr.release();
+
+ try testing.expectEqual(@as(usize, 2), arr.getCount());
+
+ {
+ const ch = arr.getValueAtIndex(u8, 0);
+ try testing.expectEqual(@as(u8, 'h'), ch.*);
+ }
+
+ // Can make it mutable
+ var mut = try MutableArray.createCopy(arr);
+ defer mut.release();
+}
+
+test "array sorting" {
+ const testing = std.testing;
+
+ const str = "hello";
+ var values = [_]*const u8{ &str[0], &str[1] };
+ const arr = try Array.create(u8, &values);
+ defer arr.release();
+ const mut = try MutableArray.createCopy(arr);
+ defer mut.release();
+
+ mut.sortValues(
+ u8,
+ void,
+ null,
+ struct {
+ fn compare(a: *const u8, b: *const u8, _: ?*void) callconv(.c) ComparisonResult {
+ if (a.* > b.*) return .greater;
+ if (a.* == b.*) return .equal;
+ return .less;
+ }
+ }.compare,
+ );
+
+ {
+ const mutarr: *Array = @ptrCast(mut);
+ const ch = mutarr.getValueAtIndex(u8, 0);
+ try testing.expectEqual(@as(u8, 'e'), ch.*);
+ }
+ {
+ const mutarr: *Array = @ptrCast(mut);
+ const ch = mutarr.getValueAtIndex(u8, 1);
+ try testing.expectEqual(@as(u8, 'h'), ch.*);
+ }
+}
diff --git a/vendor/libghostty-vt/pkg/macos/foundation/attributed_string.zig b/vendor/libghostty-vt/pkg/macos/foundation/attributed_string.zig
new file mode 100644
index 00000000..c7f27d7d
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/foundation/attributed_string.zig
@@ -0,0 +1,103 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const Allocator = std.mem.Allocator;
+const foundation = @import("../foundation.zig");
+const text = @import("../text.zig");
+const c = @import("c.zig").c;
+
+pub const AttributedString = opaque {
+ pub fn create(
+ str: *foundation.String,
+ attributes: *foundation.Dictionary,
+ ) Allocator.Error!*AttributedString {
+ return @ptrCast(@constCast(c.CFAttributedStringCreate(
+ null,
+ @ptrCast(str),
+ @ptrCast(attributes),
+ ) orelse return Allocator.Error.OutOfMemory));
+ }
+
+ pub fn release(self: *AttributedString) void {
+ foundation.CFRelease(self);
+ }
+
+ pub fn getLength(self: *AttributedString) usize {
+ return @intCast(c.CFAttributedStringGetLength(@ptrCast(self)));
+ }
+
+ pub fn getString(self: *AttributedString) *foundation.String {
+ return @ptrFromInt(@intFromPtr(
+ c.CFAttributedStringGetString(@ptrCast(self)),
+ ));
+ }
+};
+
+pub const MutableAttributedString = opaque {
+ pub fn create(cap: usize) Allocator.Error!*MutableAttributedString {
+ return @as(
+ ?*MutableAttributedString,
+ @ptrFromInt(@intFromPtr(c.CFAttributedStringCreateMutable(
+ null,
+ @intCast(cap),
+ ))),
+ ) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn release(self: *MutableAttributedString) void {
+ foundation.CFRelease(self);
+ }
+
+ pub fn replaceString(
+ self: *MutableAttributedString,
+ range: foundation.Range,
+ replacement: *foundation.String,
+ ) void {
+ c.CFAttributedStringReplaceString(
+ @ptrCast(self),
+ @bitCast(range),
+ @ptrCast(replacement),
+ );
+ }
+
+ pub fn setAttribute(
+ self: *MutableAttributedString,
+ range: foundation.Range,
+ key: anytype,
+ value: ?*anyopaque,
+ ) void {
+ const T = @TypeOf(key);
+ const info = @typeInfo(T);
+ const Key = if (info != .pointer) T else info.pointer.child;
+ const key_arg = if (@hasDecl(Key, "key"))
+ key.key()
+ else
+ key;
+
+ c.CFAttributedStringSetAttribute(
+ @ptrCast(self),
+ @bitCast(range),
+ @ptrCast(key_arg),
+ value,
+ );
+ }
+
+ pub fn getLength(self: *MutableAttributedString) usize {
+ return @intCast(c.CFAttributedStringGetLength(@ptrCast(self)));
+ }
+};
+
+test "mutable attributed string" {
+ //const testing = std.testing;
+
+ const str = try MutableAttributedString.create(0);
+ defer str.release();
+
+ {
+ const rep = try foundation.String.createWithBytes("hello", .utf8, false);
+ defer rep.release();
+ str.replaceString(foundation.Range.init(0, 0), rep);
+ }
+
+ str.setAttribute(foundation.Range.init(0, 0), text.FontAttribute.url, null);
+ str.setAttribute(foundation.Range.init(0, 0), text.FontAttribute.name.key(), null);
+}
diff --git a/vendor/libghostty-vt/pkg/macos/foundation/base.zig b/vendor/libghostty-vt/pkg/macos/foundation/base.zig
new file mode 100644
index 00000000..b926523f
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/foundation/base.zig
@@ -0,0 +1,35 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const c = @import("c.zig").c;
+
+pub const ComparisonResult = enum(c_int) {
+ less = -1,
+ equal = 0,
+ greater = 1,
+};
+
+pub const Range = extern struct {
+ location: c.CFIndex,
+ length: c.CFIndex,
+
+ pub fn init(loc: usize, len: usize) Range {
+ return @bitCast(c.CFRangeMake(@intCast(loc), @intCast(len)));
+ }
+};
+
+pub const FourCharCode = packed struct(u32) {
+ d: u8,
+ c: u8,
+ b: u8,
+ a: u8,
+
+ pub fn init(v: *const [4]u8) FourCharCode {
+ return .{ .a = v[0], .b = v[1], .c = v[2], .d = v[3] };
+ }
+
+ /// Converts the ID to a string. The return value is only valid
+ /// for the lifetime of the self pointer.
+ pub fn str(self: FourCharCode) [4]u8 {
+ return .{ self.a, self.b, self.c, self.d };
+ }
+};
diff --git a/vendor/libghostty-vt/pkg/macos/foundation/c.zig b/vendor/libghostty-vt/pkg/macos/foundation/c.zig
new file mode 100644
index 00000000..1a7d1627
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/foundation/c.zig
@@ -0,0 +1 @@
+pub const c = @import("../main.zig").c;
diff --git a/vendor/libghostty-vt/pkg/macos/foundation/character_set.zig b/vendor/libghostty-vt/pkg/macos/foundation/character_set.zig
new file mode 100644
index 00000000..d80ca45d
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/foundation/character_set.zig
@@ -0,0 +1,49 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const Allocator = std.mem.Allocator;
+const foundation = @import("../foundation.zig");
+const c = @import("c.zig").c;
+
+pub const CharacterSet = opaque {
+ pub fn createWithCharactersInString(
+ str: *foundation.String,
+ ) Allocator.Error!*CharacterSet {
+ return @as(?*CharacterSet, @ptrFromInt(@intFromPtr(c.CFCharacterSetCreateWithCharactersInString(
+ null,
+ @ptrCast(str),
+ )))) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn createWithCharactersInRange(
+ range: foundation.Range,
+ ) Allocator.Error!*CharacterSet {
+ return @as(?*CharacterSet, @ptrFromInt(@intFromPtr(c.CFCharacterSetCreateWithCharactersInRange(
+ null,
+ @bitCast(range),
+ )))) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn release(self: *CharacterSet) void {
+ c.CFRelease(self);
+ }
+};
+
+test "character set" {
+ //const testing = std.testing;
+
+ const str = try foundation.String.createWithBytes("hello world", .ascii, false);
+ defer str.release();
+
+ const cs = try CharacterSet.createWithCharactersInString(str);
+ defer cs.release();
+}
+
+test "character set range" {
+ //const testing = std.testing;
+
+ const cs = try CharacterSet.createWithCharactersInRange(.{
+ .location = 'A',
+ .length = 1,
+ });
+ defer cs.release();
+}
diff --git a/vendor/libghostty-vt/pkg/macos/foundation/data.zig b/vendor/libghostty-vt/pkg/macos/foundation/data.zig
new file mode 100644
index 00000000..c06da65b
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/foundation/data.zig
@@ -0,0 +1,38 @@
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+const foundation = @import("../foundation.zig");
+const c = @import("c.zig").c;
+
+pub const Data = opaque {
+ pub fn createWithBytesNoCopy(data: []const u8) Allocator.Error!*Data {
+ return @as(
+ ?*Data,
+ @ptrFromInt(@intFromPtr(c.CFDataCreateWithBytesNoCopy(
+ null,
+ data.ptr,
+ @intCast(data.len),
+ c.kCFAllocatorNull,
+ ))),
+ ) orelse error.OutOfMemory;
+ }
+
+ pub fn release(self: *Data) void {
+ foundation.CFRelease(self);
+ }
+
+ pub fn getPointer(self: *Data) [*]const u8 {
+ return @ptrCast(c.CFDataGetBytePtr(@ptrCast(self)));
+ }
+
+ pub fn getLength(self: *Data) usize {
+ return @intCast(c.CFDataGetLength(@ptrCast(self)));
+ }
+};
+
+test {
+ //const testing = std.testing;
+
+ const raw = "hello world";
+ const data = try Data.createWithBytesNoCopy(raw);
+ defer data.release();
+}
diff --git a/vendor/libghostty-vt/pkg/macos/foundation/dictionary.zig b/vendor/libghostty-vt/pkg/macos/foundation/dictionary.zig
new file mode 100644
index 00000000..a529442a
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/foundation/dictionary.zig
@@ -0,0 +1,125 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const Allocator = std.mem.Allocator;
+const foundation = @import("../foundation.zig");
+const c = @import("c.zig").c;
+
+pub const Dictionary = opaque {
+ pub fn create(
+ keys: ?[]const ?*const anyopaque,
+ values: ?[]const ?*const anyopaque,
+ ) Allocator.Error!*Dictionary {
+ if (keys != null or values != null) {
+ assert(keys != null);
+ assert(values != null);
+ assert(keys.?.len == values.?.len);
+ }
+
+ return @as(?*Dictionary, @ptrFromInt(@intFromPtr(c.CFDictionaryCreate(
+ null,
+ @ptrCast(@constCast(if (keys) |slice| slice.ptr else null)),
+ @ptrCast(@constCast(if (values) |slice| slice.ptr else null)),
+ @intCast(if (keys) |slice| slice.len else 0),
+ &c.kCFTypeDictionaryKeyCallBacks,
+ &c.kCFTypeDictionaryValueCallBacks,
+ )))) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn release(self: *Dictionary) void {
+ foundation.CFRelease(self);
+ }
+
+ pub fn getCount(self: *Dictionary) usize {
+ return @intCast(c.CFDictionaryGetCount(@ptrCast(self)));
+ }
+
+ pub fn getValue(self: *Dictionary, comptime V: type, key: ?*const anyopaque) ?*V {
+ return @ptrFromInt(@intFromPtr(c.CFDictionaryGetValue(
+ @ptrCast(self),
+ key,
+ )));
+ }
+
+ pub fn getKeysAndValues(self: *Dictionary, alloc: Allocator) !struct {
+ keys: []?*const anyopaque,
+ values: []?*const anyopaque,
+ } {
+ const count = self.getCount();
+ const keys = try alloc.alloc(?*const anyopaque, count);
+ errdefer alloc.free(keys);
+ const values = try alloc.alloc(?*const anyopaque, count);
+ errdefer alloc.free(values);
+ c.CFDictionaryGetKeysAndValues(
+ @ptrCast(self),
+ @ptrCast(keys.ptr),
+ @ptrCast(values.ptr),
+ );
+ return .{ .keys = keys, .values = values };
+ }
+};
+
+pub const MutableDictionary = opaque {
+ pub fn create(cap: usize) Allocator.Error!*MutableDictionary {
+ return @as(?*MutableDictionary, @ptrFromInt(@intFromPtr(c.CFDictionaryCreateMutable(
+ null,
+ @intCast(cap),
+ &c.kCFTypeDictionaryKeyCallBacks,
+ &c.kCFTypeDictionaryValueCallBacks,
+ )))) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn createMutableCopy(cap: usize, src: *Dictionary) Allocator.Error!*MutableDictionary {
+ return @as(?*MutableDictionary, @ptrFromInt(@intFromPtr(c.CFDictionaryCreateMutableCopy(
+ null,
+ @intCast(cap),
+ @ptrCast(src),
+ )))) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn release(self: *MutableDictionary) void {
+ foundation.CFRelease(self);
+ }
+
+ pub fn setValue(self: *MutableDictionary, key: ?*const anyopaque, value: ?*const anyopaque) void {
+ c.CFDictionarySetValue(
+ @ptrCast(self),
+ key,
+ value,
+ );
+ }
+};
+
+test "dictionary" {
+ const testing = std.testing;
+
+ const str = try foundation.String.createWithBytes("hello", .unicode, false);
+ defer str.release();
+
+ var keys = [_]?*const anyopaque{c.kCFURLIsPurgeableKey};
+ var values = [_]?*const anyopaque{str};
+ const dict = try Dictionary.create(&keys, &values);
+ defer dict.release();
+
+ try testing.expectEqual(@as(usize, 1), dict.getCount());
+ try testing.expect(dict.getValue(foundation.String, c.kCFURLIsPurgeableKey) != null);
+ try testing.expect(dict.getValue(foundation.String, c.kCFURLIsVolumeKey) == null);
+}
+
+test "mutable dictionary" {
+ const testing = std.testing;
+
+ const dict = try MutableDictionary.create(0);
+ defer dict.release();
+
+ const str = try foundation.String.createWithBytes("hello", .unicode, false);
+ defer str.release();
+
+ dict.setValue(c.kCFURLIsPurgeableKey, str);
+
+ {
+ const imm = @as(*Dictionary, @ptrCast(dict));
+ try testing.expectEqual(@as(usize, 1), imm.getCount());
+ try testing.expect(imm.getValue(foundation.String, c.kCFURLIsPurgeableKey) != null);
+ try testing.expect(imm.getValue(foundation.String, c.kCFURLIsVolumeKey) == null);
+ }
+}
diff --git a/vendor/libghostty-vt/pkg/macos/foundation/number.zig b/vendor/libghostty-vt/pkg/macos/foundation/number.zig
new file mode 100644
index 00000000..88bf9edf
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/foundation/number.zig
@@ -0,0 +1,79 @@
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+const foundation = @import("../foundation.zig");
+const c = @import("c.zig").c;
+
+pub const Number = opaque {
+ pub fn create(
+ comptime type_: NumberType,
+ value: *const type_.ValueType(),
+ ) Allocator.Error!*Number {
+ return @as(?*Number, @ptrFromInt(@intFromPtr(c.CFNumberCreate(
+ null,
+ @intFromEnum(type_),
+ value,
+ )))) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn getValue(self: *const Number, comptime t: NumberType, ptr: *t.ValueType()) bool {
+ return c.CFNumberGetValue(
+ @ptrCast(self),
+ @intFromEnum(t),
+ ptr,
+ ) == 1;
+ }
+
+ pub fn release(self: *Number) void {
+ c.CFRelease(self);
+ }
+};
+
+pub const NumberType = enum(c.CFNumberType) {
+ sint8 = c.kCFNumberSInt8Type,
+ sint16 = c.kCFNumberSInt16Type,
+ sint32 = c.kCFNumberSInt32Type,
+ sint64 = c.kCFNumberSInt64Type,
+ float32 = c.kCFNumberFloat32Type,
+ float64 = c.kCFNumberFloat64Type,
+ char = c.kCFNumberCharType,
+ short = c.kCFNumberShortType,
+ int = c.kCFNumberIntType,
+ long = c.kCFNumberLongType,
+ long_long = c.kCFNumberLongLongType,
+ float = c.kCFNumberFloatType,
+ double = c.kCFNumberDoubleType,
+ cf_index = c.kCFNumberCFIndexType,
+ ns_integer = c.kCFNumberNSIntegerType,
+ cg_float = c.kCFNumberCGFloatType,
+
+ pub fn ValueType(comptime self: NumberType) type {
+ return switch (self) {
+ .sint8 => i8,
+ .sint16 => i16,
+ .sint32 => i32,
+ .sint64 => i64,
+ .float32 => f32,
+ .float64 => f64,
+ .char => u8,
+ .short => c_short,
+ .int => c_int,
+ .long => c_long,
+ .long_long => c_longlong,
+ .float => f32,
+ .double => f64,
+ else => unreachable, // TODO
+ };
+ }
+};
+
+test {
+ const testing = std.testing;
+
+ const inner: i8 = 42;
+ const v = try Number.create(.sint8, &inner);
+ defer v.release();
+
+ var result: i8 = undefined;
+ try testing.expect(v.getValue(.sint8, &result));
+ try testing.expectEqual(result, inner);
+}
diff --git a/vendor/libghostty-vt/pkg/macos/foundation/string.zig b/vendor/libghostty-vt/pkg/macos/foundation/string.zig
new file mode 100644
index 00000000..2f679fef
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/foundation/string.zig
@@ -0,0 +1,174 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const Allocator = std.mem.Allocator;
+const foundation = @import("../foundation.zig");
+const c = @import("c.zig").c;
+
+pub const String = opaque {
+ pub fn createWithBytes(
+ bs: []const u8,
+ encoding: StringEncoding,
+ external: bool,
+ ) Allocator.Error!*String {
+ return @as(?*String, @ptrFromInt(@intFromPtr(c.CFStringCreateWithBytes(
+ null,
+ bs.ptr,
+ @intCast(bs.len),
+ @intFromEnum(encoding),
+ @intFromBool(external),
+ )))) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn createWithCharactersNoCopy(
+ unichars: []const u16,
+ ) *String {
+ return @as(*String, @ptrFromInt(@intFromPtr(c.CFStringCreateWithCharactersNoCopy(
+ null,
+ @ptrCast(unichars.ptr),
+ @intCast(unichars.len),
+ foundation.c.kCFAllocatorNull,
+ ))));
+ }
+
+ pub fn release(self: *String) void {
+ c.CFRelease(self);
+ }
+
+ pub fn getLength(self: *String) usize {
+ return @intCast(c.CFStringGetLength(@ptrCast(self)));
+ }
+
+ pub fn hasPrefix(self: *String, prefix: *String) bool {
+ return c.CFStringHasPrefix(
+ @ptrCast(self),
+ @ptrCast(prefix),
+ ) == 1;
+ }
+
+ pub fn compare(
+ self: *String,
+ other: *String,
+ options: StringComparison,
+ ) foundation.ComparisonResult {
+ return @enumFromInt(c.CFStringCompare(
+ @ptrCast(self),
+ @ptrCast(other),
+ @intCast(@as(c_int, @bitCast(options))),
+ ));
+ }
+
+ pub fn cstring(self: *String, buf: []u8, encoding: StringEncoding) ?[]const u8 {
+ if (c.CFStringGetCString(
+ @ptrCast(self),
+ buf.ptr,
+ @intCast(buf.len),
+ @intFromEnum(encoding),
+ ) == 0) return null;
+ return std.mem.sliceTo(buf, 0);
+ }
+
+ pub fn cstringPtr(self: *String, encoding: StringEncoding) ?[:0]const u8 {
+ const ptr = c.CFStringGetCStringPtr(
+ @ptrCast(self),
+ @intFromEnum(encoding),
+ );
+ if (ptr == null) return null;
+ return std.mem.sliceTo(ptr, 0);
+ }
+};
+
+pub const MutableString = opaque {
+ pub fn create(cap: usize) !*MutableString {
+ return @ptrCast(c.CFStringCreateMutable(
+ null,
+ @intCast(cap),
+ ) orelse return Allocator.Error.OutOfMemory);
+ }
+
+ pub fn release(self: *MutableString) void {
+ foundation.CFRelease(self);
+ }
+
+ pub fn string(self: *MutableString) *String {
+ return @ptrCast(self);
+ }
+
+ pub fn appendCharacters(self: *MutableString, chars: []const u16) void {
+ c.CFStringAppendCharacters(
+ @ptrCast(self),
+ chars.ptr,
+ @intCast(chars.len),
+ );
+ }
+};
+
+pub const StringComparison = packed struct {
+ case_insensitive: bool = false,
+ _unused_2: bool = false,
+ backwards: bool = false,
+ anchored: bool = false,
+ nonliteral: bool = false,
+ localized: bool = false,
+ numerically: bool = false,
+ diacritic_insensitive: bool = false,
+ width_insensitive: bool = false,
+ forced_ordering: bool = false,
+ _padding: u22 = 0,
+
+ test {
+ try std.testing.expectEqual(@bitSizeOf(c_int), @bitSizeOf(StringComparison));
+ }
+};
+
+/// https://developer.apple.com/documentation/corefoundation/cfstringencoding?language=objc
+pub const StringEncoding = enum(u32) {
+ invalid = 0xffffffff,
+ mac_roman = 0,
+ windows_latin1 = 0x0500,
+ iso_latin1 = 0x0201,
+ nextstep_latin = 0x0B01,
+ ascii = 0x0600,
+ unicode = 0x0100,
+ utf8 = 0x08000100,
+ non_lossy_ascii = 0x0BFF,
+ utf16_be = 0x10000100,
+ utf16_le = 0x14000100,
+ utf32 = 0x0c000100,
+ utf32_be = 0x18000100,
+ utf32_le = 0x1c000100,
+};
+
+pub fn stringGetSurrogatePairForLongCharacter(
+ ch: u32,
+ surrogates: []u16,
+) bool {
+ assert(surrogates.len >= 2);
+ return c.CFStringGetSurrogatePairForLongCharacter(ch, surrogates.ptr) == 1;
+}
+
+test "string" {
+ const testing = std.testing;
+
+ const str = try String.createWithBytes("hello world", .ascii, false);
+ defer str.release();
+
+ const prefix = try String.createWithBytes("hello", .ascii, false);
+ defer prefix.release();
+
+ try testing.expect(str.hasPrefix(prefix));
+ try testing.expectEqual(foundation.ComparisonResult.equal, str.compare(str, .{}));
+ try testing.expectEqualStrings("hello world", str.cstringPtr(.ascii).?);
+
+ {
+ var buf: [128]u8 = undefined;
+ const cstr = str.cstring(&buf, .ascii).?;
+ try testing.expectEqualStrings("hello world", cstr);
+ }
+}
+
+test "unichar" {
+ const testing = std.testing;
+
+ var unichars: [2]u16 = undefined;
+ try testing.expect(!stringGetSurrogatePairForLongCharacter('A', &unichars));
+}
diff --git a/vendor/libghostty-vt/pkg/macos/foundation/type.zig b/vendor/libghostty-vt/pkg/macos/foundation/type.zig
new file mode 100644
index 00000000..45bd0905
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/foundation/type.zig
@@ -0,0 +1,2 @@
+pub extern "c" fn CFRelease(*anyopaque) void;
+pub extern "c" fn CFRetain(*anyopaque) void;
diff --git a/vendor/libghostty-vt/pkg/macos/foundation/url.zig b/vendor/libghostty-vt/pkg/macos/foundation/url.zig
new file mode 100644
index 00000000..b48a7181
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/foundation/url.zig
@@ -0,0 +1,104 @@
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+const foundation = @import("../foundation.zig");
+const c = @import("c.zig").c;
+
+pub const URL = opaque {
+ pub fn createWithString(str: *foundation.String, base: ?*URL) Allocator.Error!*URL {
+ return CFURLCreateWithString(
+ null,
+ str,
+ base,
+ ) orelse error.OutOfMemory;
+ }
+
+ pub fn createWithFileSystemPath(
+ path: *foundation.String,
+ style: URLPathStyle,
+ dir: bool,
+ ) Allocator.Error!*URL {
+ return @as(
+ ?*URL,
+ @ptrFromInt(@intFromPtr(c.CFURLCreateWithFileSystemPath(
+ null,
+ @ptrCast(path),
+ @intFromEnum(style),
+ if (dir) 1 else 0,
+ ))),
+ ) orelse error.OutOfMemory;
+ }
+
+ pub fn createStringByReplacingPercentEscapes(
+ str: *foundation.String,
+ escape: *foundation.String,
+ ) Allocator.Error!*foundation.String {
+ return CFURLCreateStringByReplacingPercentEscapes(
+ null,
+ str,
+ escape,
+ ) orelse return error.OutOfMemory;
+ }
+
+ pub fn release(self: *URL) void {
+ foundation.CFRelease(self);
+ }
+
+ pub fn copyPath(self: *URL) ?*foundation.String {
+ return CFURLCopyPath(self);
+ }
+
+ pub extern "c" fn CFURLCreateWithString(
+ allocator: ?*anyopaque,
+ url_string: *const anyopaque,
+ base_url: ?*const anyopaque,
+ ) ?*URL;
+ pub extern "c" fn CFURLCopyPath(*URL) ?*foundation.String;
+ pub extern "c" fn CFURLCreateStringByReplacingPercentEscapes(
+ allocator: ?*anyopaque,
+ original: *const anyopaque,
+ escape: *const anyopaque,
+ ) ?*foundation.String;
+};
+
+pub const URLPathStyle = enum(c_int) {
+ posix = c.kCFURLPOSIXPathStyle,
+ windows = c.kCFURLWindowsPathStyle,
+};
+
+test {
+ const testing = std.testing;
+
+ const str = try foundation.String.createWithBytes("http://www.example.com/foo", .utf8, false);
+ defer str.release();
+
+ const url = try URL.createWithString(str, null);
+ defer url.release();
+
+ {
+ const path = url.copyPath().?;
+ defer path.release();
+
+ var buf: [128]u8 = undefined;
+ const cstr = path.cstring(&buf, .utf8).?;
+ try testing.expectEqualStrings("/foo", cstr);
+ }
+}
+
+test "path" {
+ const testing = std.testing;
+
+ const str = try foundation.String.createWithBytes("foo/bar.ttf", .utf8, false);
+ defer str.release();
+
+ const url = try URL.createWithFileSystemPath(str, .posix, false);
+ defer url.release();
+
+ {
+ const path = url.copyPath().?;
+ defer path.release();
+
+ var buf: [128]u8 = undefined;
+ const cstr = path.cstring(&buf, .utf8).?;
+ try testing.expectEqualStrings("foo/bar.ttf", cstr);
+ }
+}
diff --git a/vendor/libghostty-vt/pkg/macos/graphics.zig b/vendor/libghostty-vt/pkg/macos/graphics.zig
new file mode 100644
index 00000000..5195da4a
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/graphics.zig
@@ -0,0 +1,24 @@
+const affine_transform = @import("graphics/affine_transform.zig");
+const bitmap_context = @import("graphics/bitmap_context.zig");
+const color_space = @import("graphics/color_space.zig");
+const font = @import("graphics/font.zig");
+const geometry = @import("graphics/geometry.zig");
+const image = @import("graphics/image.zig");
+const path = @import("graphics/path.zig");
+
+pub const c = @import("graphics/c.zig").c;
+pub const AffineTransform = affine_transform.AffineTransform;
+pub const BitmapContext = bitmap_context.BitmapContext;
+pub const ColorSpace = color_space.ColorSpace;
+pub const Glyph = font.Glyph;
+pub const Point = geometry.Point;
+pub const Rect = geometry.Rect;
+pub const Size = geometry.Size;
+pub const ImageAlphaInfo = image.ImageAlphaInfo;
+pub const BitmapInfo = image.BitmapInfo;
+pub const Path = path.Path;
+pub const MutablePath = path.MutablePath;
+
+test {
+ @import("std").testing.refAllDecls(@This());
+}
diff --git a/vendor/libghostty-vt/pkg/macos/graphics/affine_transform.zig b/vendor/libghostty-vt/pkg/macos/graphics/affine_transform.zig
new file mode 100644
index 00000000..e649e7a1
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/graphics/affine_transform.zig
@@ -0,0 +1,16 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const c = @import("c.zig").c;
+
+pub const AffineTransform = extern struct {
+ a: c.CGFloat,
+ b: c.CGFloat,
+ c: c.CGFloat,
+ d: c.CGFloat,
+ tx: c.CGFloat,
+ ty: c.CGFloat,
+
+ pub fn identity() AffineTransform {
+ return @bitCast(c.CGAffineTransformIdentity);
+ }
+};
diff --git a/vendor/libghostty-vt/pkg/macos/graphics/bitmap_context.zig b/vendor/libghostty-vt/pkg/macos/graphics/bitmap_context.zig
new file mode 100644
index 00000000..7db5577f
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/graphics/bitmap_context.zig
@@ -0,0 +1,50 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const Allocator = std.mem.Allocator;
+const graphics = @import("../graphics.zig");
+const Context = @import("context.zig").Context;
+const c = @import("c.zig").c;
+
+pub const BitmapContext = opaque {
+ pub const context = Context(BitmapContext);
+
+ pub fn create(
+ data: ?[]u8,
+ width: usize,
+ height: usize,
+ bits_per_component: usize,
+ bytes_per_row: usize,
+ space: *graphics.ColorSpace,
+ opts: c_uint,
+ ) Allocator.Error!*BitmapContext {
+ return @as(
+ ?*BitmapContext,
+ @ptrFromInt(@intFromPtr(c.CGBitmapContextCreate(
+ @ptrCast(if (data) |d| d.ptr else null),
+ width,
+ height,
+ bits_per_component,
+ bytes_per_row,
+ @ptrCast(space),
+ opts,
+ ))),
+ ) orelse Allocator.Error.OutOfMemory;
+ }
+};
+
+test {
+ //const testing = std.testing;
+
+ const cs = try graphics.ColorSpace.createDeviceGray();
+ defer cs.release();
+ const ctx = try BitmapContext.create(null, 80, 80, 8, 80, cs, 0);
+ const context = BitmapContext.context;
+ defer context.release(ctx);
+ context.setShouldAntialias(ctx, true);
+ context.setShouldSmoothFonts(ctx, false);
+ context.setGrayFillColor(ctx, 1, 1);
+ context.setGrayStrokeColor(ctx, 1, 1);
+ context.setTextDrawingMode(ctx, .fill);
+ context.setTextMatrix(ctx, graphics.AffineTransform.identity());
+ context.setTextPosition(ctx, 0, 0);
+}
diff --git a/vendor/libghostty-vt/pkg/macos/graphics/c.zig b/vendor/libghostty-vt/pkg/macos/graphics/c.zig
new file mode 100644
index 00000000..1a7d1627
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/graphics/c.zig
@@ -0,0 +1 @@
+pub const c = @import("../main.zig").c;
diff --git a/vendor/libghostty-vt/pkg/macos/graphics/color_space.zig b/vendor/libghostty-vt/pkg/macos/graphics/color_space.zig
new file mode 100644
index 00000000..16960591
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/graphics/color_space.zig
@@ -0,0 +1,99 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const Allocator = std.mem.Allocator;
+const c = @import("c.zig").c;
+
+pub const ColorSpace = opaque {
+ pub fn createDeviceGray() Allocator.Error!*ColorSpace {
+ return @as(
+ ?*ColorSpace,
+ @ptrFromInt(@intFromPtr(c.CGColorSpaceCreateDeviceGray())),
+ ) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn createDeviceRGB() Allocator.Error!*ColorSpace {
+ return @as(
+ ?*ColorSpace,
+ @ptrFromInt(@intFromPtr(c.CGColorSpaceCreateDeviceRGB())),
+ ) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn createNamed(name: Name) Allocator.Error!*ColorSpace {
+ return @as(
+ ?*ColorSpace,
+ @ptrFromInt(@intFromPtr(c.CGColorSpaceCreateWithName(name.cfstring()))),
+ ) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn release(self: *ColorSpace) void {
+ c.CGColorSpaceRelease(@ptrCast(self));
+ }
+
+ pub const Name = enum {
+ /// This color space uses the DCI P3 primaries, a D65 white point, and
+ /// the sRGB transfer function.
+ displayP3,
+ /// The Display P3 color space with a linear transfer function and
+ /// extended-range values.
+ extendedLinearDisplayP3,
+ /// The sRGB colorimetry and non-linear transfer function are specified
+ /// in IEC 61966-2-1.
+ sRGB,
+ /// This color space has the same colorimetry as `sRGB`, but uses a
+ /// linear transfer function.
+ linearSRGB,
+ /// This color space has the same colorimetry as `sRGB`, but you can
+ /// encode component values below `0.0` and above `1.0`. Negative values
+ /// are encoded as the signed reflection of the original encoding
+ /// function, as shown in the formula below:
+ /// ```
+ /// extendedTransferFunction(x) = sign(x) * sRGBTransferFunction(abs(x))
+ /// ```
+ extendedSRGB,
+ /// This color space has the same colorimetry as `sRGB`; in addition,
+ /// you may encode component values below `0.0` and above `1.0`.
+ extendedLinearSRGB,
+ /// ...
+ genericGrayGamma2_2,
+ /// ...
+ linearGray,
+ /// This color space has the same colorimetry as `genericGrayGamma2_2`,
+ /// but you can encode component values below `0.0` and above `1.0`.
+ /// Negative values are encoded as the signed reflection of the
+ /// original encoding function, as shown in the formula below:
+ /// ```
+ /// extendedGrayTransferFunction(x) = sign(x) * gamma22Function(abs(x))
+ /// ```
+ extendedGray,
+ /// This color space has the same colorimetry as `linearGray`; in
+ /// addition, you may encode component values below `0.0` and above `1.0`.
+ extendedLinearGray,
+
+ fn cfstring(self: Name) c.CFStringRef {
+ return switch (self) {
+ .displayP3 => c.kCGColorSpaceDisplayP3,
+ .extendedLinearDisplayP3 => c.kCGColorSpaceExtendedLinearDisplayP3,
+ .sRGB => c.kCGColorSpaceSRGB,
+ .extendedSRGB => c.kCGColorSpaceExtendedSRGB,
+ .linearSRGB => c.kCGColorSpaceLinearSRGB,
+ .extendedLinearSRGB => c.kCGColorSpaceExtendedLinearSRGB,
+ .genericGrayGamma2_2 => c.kCGColorSpaceGenericGrayGamma2_2,
+ .extendedGray => c.kCGColorSpaceExtendedGray,
+ .linearGray => c.kCGColorSpaceLinearGray,
+ .extendedLinearGray => c.kCGColorSpaceExtendedLinearGray,
+ };
+ }
+ };
+};
+
+test {
+ //const testing = std.testing;
+
+ const space = try ColorSpace.createDeviceGray();
+ defer space.release();
+}
+
+test {
+ const space = try ColorSpace.createDeviceRGB();
+ defer space.release();
+}
diff --git a/vendor/libghostty-vt/pkg/macos/graphics/context.zig b/vendor/libghostty-vt/pkg/macos/graphics/context.zig
new file mode 100644
index 00000000..77e4344e
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/graphics/context.zig
@@ -0,0 +1,172 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const Allocator = std.mem.Allocator;
+const graphics = @import("../graphics.zig");
+const c = @import("c.zig").c;
+
+/// Returns a struct that has all the shared context functions for the
+/// given type.
+pub fn Context(comptime T: type) type {
+ return struct {
+ value: *T,
+
+ pub fn release(self: *T) void {
+ c.CGContextRelease(@ptrCast(self));
+ }
+
+ pub fn setLineWidth(self: *T, width: f64) void {
+ c.CGContextSetLineWidth(
+ @ptrCast(self),
+ width,
+ );
+ }
+
+ pub fn setAllowsAntialiasing(self: *T, v: bool) void {
+ c.CGContextSetAllowsAntialiasing(
+ @ptrCast(self),
+ v,
+ );
+ }
+
+ pub fn setAllowsFontSmoothing(self: *T, v: bool) void {
+ c.CGContextSetAllowsFontSmoothing(
+ @ptrCast(self),
+ v,
+ );
+ }
+
+ pub fn setAllowsFontSubpixelPositioning(self: *T, v: bool) void {
+ c.CGContextSetAllowsFontSubpixelPositioning(
+ @ptrCast(self),
+ v,
+ );
+ }
+
+ pub fn setAllowsFontSubpixelQuantization(self: *T, v: bool) void {
+ c.CGContextSetAllowsFontSubpixelQuantization(
+ @ptrCast(self),
+ v,
+ );
+ }
+
+ pub fn setShouldAntialias(self: *T, v: bool) void {
+ c.CGContextSetShouldAntialias(
+ @ptrCast(self),
+ v,
+ );
+ }
+
+ pub fn setShouldSmoothFonts(self: *T, v: bool) void {
+ c.CGContextSetShouldSmoothFonts(
+ @ptrCast(self),
+ v,
+ );
+ }
+
+ pub fn setShouldSubpixelPositionFonts(self: *T, v: bool) void {
+ c.CGContextSetShouldSubpixelPositionFonts(
+ @ptrCast(self),
+ v,
+ );
+ }
+
+ pub fn setShouldSubpixelQuantizeFonts(self: *T, v: bool) void {
+ c.CGContextSetShouldSubpixelQuantizeFonts(
+ @ptrCast(self),
+ v,
+ );
+ }
+
+ pub fn setGrayFillColor(self: *T, gray: f64, alpha: f64) void {
+ c.CGContextSetGrayFillColor(
+ @ptrCast(self),
+ gray,
+ alpha,
+ );
+ }
+
+ pub fn setGrayStrokeColor(self: *T, gray: f64, alpha: f64) void {
+ c.CGContextSetGrayStrokeColor(
+ @ptrCast(self),
+ gray,
+ alpha,
+ );
+ }
+
+ pub fn setRGBFillColor(self: *T, r: f64, g: f64, b: f64, alpha: f64) void {
+ c.CGContextSetRGBFillColor(
+ @ptrCast(self),
+ r,
+ g,
+ b,
+ alpha,
+ );
+ }
+
+ pub fn setRGBStrokeColor(self: *T, r: f64, g: f64, b: f64, alpha: f64) void {
+ c.CGContextSetRGBStrokeColor(
+ @ptrCast(self),
+ r,
+ g,
+ b,
+ alpha,
+ );
+ }
+
+ pub fn setTextDrawingMode(self: *T, mode: TextDrawingMode) void {
+ c.CGContextSetTextDrawingMode(
+ @ptrCast(self),
+ @intFromEnum(mode),
+ );
+ }
+
+ pub fn setTextMatrix(self: *T, matrix: graphics.AffineTransform) void {
+ c.CGContextSetTextMatrix(
+ @ptrCast(self),
+ @bitCast(matrix),
+ );
+ }
+
+ pub fn setTextPosition(self: *T, x: f64, y: f64) void {
+ c.CGContextSetTextPosition(
+ @ptrCast(self),
+ x,
+ y,
+ );
+ }
+
+ pub fn fillRect(self: *T, rect: graphics.Rect) void {
+ c.CGContextFillRect(
+ @ptrCast(self),
+ @bitCast(rect),
+ );
+ }
+
+ pub fn scaleCTM(self: *T, sx: c.CGFloat, sy: c.CGFloat) void {
+ c.CGContextScaleCTM(
+ @ptrCast(self),
+ sx,
+ sy,
+ );
+ }
+
+ pub fn translateCTM(self: *T, tx: c.CGFloat, ty: c.CGFloat) void {
+ c.CGContextTranslateCTM(
+ @ptrCast(self),
+ tx,
+ ty,
+ );
+ }
+ };
+}
+
+pub const TextDrawingMode = enum(c_int) {
+ fill = c.kCGTextFill,
+ stroke = c.kCGTextStroke,
+ fill_stroke = c.kCGTextFillStroke,
+ invisible = c.kCGTextInvisible,
+ fill_clip = c.kCGTextFillClip,
+ stroke_clip = c.kCGTextStrokeClip,
+ fill_stroke_clip = c.kCGTextFillStrokeClip,
+ clip = c.kCGTextClip,
+};
diff --git a/vendor/libghostty-vt/pkg/macos/graphics/font.zig b/vendor/libghostty-vt/pkg/macos/graphics/font.zig
new file mode 100644
index 00000000..c310c62a
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/graphics/font.zig
@@ -0,0 +1,3 @@
+const c = @import("c.zig").c;
+
+pub const Glyph = c.CGGlyph;
diff --git a/vendor/libghostty-vt/pkg/macos/graphics/geometry.zig b/vendor/libghostty-vt/pkg/macos/graphics/geometry.zig
new file mode 100644
index 00000000..66937403
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/graphics/geometry.zig
@@ -0,0 +1,34 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const c = @import("c.zig").c;
+
+pub const Point = extern struct {
+ x: c.CGFloat,
+ y: c.CGFloat,
+};
+
+pub const Rect = extern struct {
+ origin: Point,
+ size: Size,
+
+ pub fn init(x: f64, y: f64, width: f64, height: f64) Rect {
+ return @bitCast(c.CGRectMake(x, y, width, height));
+ }
+
+ pub fn isNull(self: Rect) bool {
+ return c.CGRectIsNull(@bitCast(self));
+ }
+
+ pub fn getHeight(self: Rect) c.CGFloat {
+ return c.CGRectGetHeight(@bitCast(self));
+ }
+
+ pub fn getWidth(self: Rect) c.CGFloat {
+ return c.CGRectGetWidth(@bitCast(self));
+ }
+};
+
+pub const Size = extern struct {
+ width: c.CGFloat,
+ height: c.CGFloat,
+};
diff --git a/vendor/libghostty-vt/pkg/macos/graphics/image.zig b/vendor/libghostty-vt/pkg/macos/graphics/image.zig
new file mode 100644
index 00000000..879384b1
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/graphics/image.zig
@@ -0,0 +1,31 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const Allocator = std.mem.Allocator;
+const graphics = @import("../graphics.zig");
+const context = @import("context.zig");
+const c = @import("c.zig").c;
+
+pub const ImageAlphaInfo = enum(c_uint) {
+ none = c.kCGImageAlphaNone,
+ premultiplied_last = c.kCGImageAlphaPremultipliedLast,
+ premultiplied_first = c.kCGImageAlphaPremultipliedFirst,
+ last = c.kCGImageAlphaLast,
+ first = c.kCGImageAlphaFirst,
+ none_skip_last = c.kCGImageAlphaNoneSkipLast,
+ none_skip_first = c.kCGImageAlphaNoneSkipFirst,
+ only = c.kCGImageAlphaOnly,
+};
+
+pub const BitmapInfo = enum(c_uint) {
+ alpha_mask = c.kCGBitmapAlphaInfoMask,
+ float_mask = c.kCGBitmapFloatInfoMask,
+ float_components = c.kCGBitmapFloatComponents,
+ byte_order_mask = c.kCGBitmapByteOrderMask,
+ byte_order_default = c.kCGBitmapByteOrderDefault,
+ byte_order_16_little = c.kCGBitmapByteOrder16Little,
+ byte_order_32_little = c.kCGBitmapByteOrder32Little,
+ byte_order_16_big = c.kCGBitmapByteOrder16Big,
+ byte_order_32_big = c.kCGBitmapByteOrder32Big,
+
+ _,
+};
diff --git a/vendor/libghostty-vt/pkg/macos/graphics/path.zig b/vendor/libghostty-vt/pkg/macos/graphics/path.zig
new file mode 100644
index 00000000..7f549709
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/graphics/path.zig
@@ -0,0 +1,68 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const Allocator = std.mem.Allocator;
+const foundation = @import("../foundation.zig");
+const graphics = @import("../graphics.zig");
+const c = @import("c.zig").c;
+
+pub const Path = opaque {
+ pub fn createWithRect(
+ rect: graphics.Rect,
+ transform: ?*const graphics.AffineTransform,
+ ) Allocator.Error!*Path {
+ return @as(
+ ?*Path,
+ @ptrFromInt(@intFromPtr(c.CGPathCreateWithRect(
+ @bitCast(rect),
+ @ptrCast(transform),
+ ))),
+ ) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn release(self: *Path) void {
+ foundation.CFRelease(self);
+ }
+};
+
+pub const MutablePath = opaque {
+ pub fn create() Allocator.Error!*MutablePath {
+ return @as(
+ ?*MutablePath,
+ @ptrFromInt(@intFromPtr(c.CGPathCreateMutable())),
+ ) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn release(self: *MutablePath) void {
+ foundation.CFRelease(self);
+ }
+
+ pub fn addRect(
+ self: *MutablePath,
+ transform: ?*const graphics.AffineTransform,
+ rect: graphics.Rect,
+ ) void {
+ c.CGPathAddRect(
+ @ptrCast(self),
+ @ptrCast(transform),
+ @bitCast(rect),
+ );
+ }
+
+ pub fn getBoundingBox(self: *MutablePath) graphics.Rect {
+ return @bitCast(c.CGPathGetBoundingBox(@ptrCast(self)));
+ }
+};
+
+test "mutable path" {
+ //const testing = std.testing;
+
+ const path = try MutablePath.create();
+ defer path.release();
+
+ path.addRect(null, graphics.Rect.init(0, 0, 100, 200));
+}
+
+test "path from rect" {
+ const path = try Path.createWithRect(graphics.Rect.init(0, 0, 100, 200), null);
+ defer path.release();
+}
diff --git a/vendor/libghostty-vt/pkg/macos/iosurface.zig b/vendor/libghostty-vt/pkg/macos/iosurface.zig
new file mode 100644
index 00000000..9d2e750c
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/iosurface.zig
@@ -0,0 +1,8 @@
+const iosurface = @import("iosurface/iosurface.zig");
+
+pub const c = @import("iosurface/c.zig").c;
+pub const IOSurface = iosurface.IOSurface;
+
+test {
+ @import("std").testing.refAllDecls(@This());
+}
diff --git a/vendor/libghostty-vt/pkg/macos/iosurface/c.zig b/vendor/libghostty-vt/pkg/macos/iosurface/c.zig
new file mode 100644
index 00000000..1a7d1627
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/iosurface/c.zig
@@ -0,0 +1 @@
+pub const c = @import("../main.zig").c;
diff --git a/vendor/libghostty-vt/pkg/macos/iosurface/iosurface.zig b/vendor/libghostty-vt/pkg/macos/iosurface/iosurface.zig
new file mode 100644
index 00000000..37f8712b
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/iosurface/iosurface.zig
@@ -0,0 +1,136 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const Allocator = std.mem.Allocator;
+const c = @import("c.zig").c;
+const foundation = @import("../foundation.zig");
+const graphics = @import("../graphics.zig");
+const video = @import("../video.zig");
+
+pub const IOSurface = opaque {
+ pub const Error = error{
+ InvalidOperation,
+ };
+
+ pub const Properties = struct {
+ width: c_int,
+ height: c_int,
+ pixel_format: video.PixelFormat,
+ bytes_per_element: c_int,
+ colorspace: ?*graphics.ColorSpace,
+ };
+
+ pub fn init(properties: Properties) Allocator.Error!*IOSurface {
+ var w = try foundation.Number.create(.int, &properties.width);
+ defer w.release();
+ var h = try foundation.Number.create(.int, &properties.height);
+ defer h.release();
+ var pf = try foundation.Number.create(.int, &@as(c_int, @intFromEnum(properties.pixel_format)));
+ defer pf.release();
+ var bpe = try foundation.Number.create(.int, &properties.bytes_per_element);
+ defer bpe.release();
+
+ var properties_dict = try foundation.Dictionary.create(
+ &[_]?*const anyopaque{
+ c.kIOSurfaceWidth,
+ c.kIOSurfaceHeight,
+ c.kIOSurfacePixelFormat,
+ c.kIOSurfaceBytesPerElement,
+ },
+ &[_]?*const anyopaque{ w, h, pf, bpe },
+ );
+ defer properties_dict.release();
+
+ var surface = @as(?*IOSurface, @ptrFromInt(@intFromPtr(
+ c.IOSurfaceCreate(@ptrCast(properties_dict)),
+ ))) orelse return error.OutOfMemory;
+
+ if (properties.colorspace) |space| {
+ surface.setColorSpace(space);
+ }
+
+ return surface;
+ }
+
+ pub fn deinit(self: *IOSurface) void {
+ // We mark it purgeable so that it is immediately unloaded, so that we
+ // don't have to wait for CoreFoundation garbage collection to trigger.
+ _ = c.IOSurfaceSetPurgeable(
+ @ptrCast(self),
+ c.kIOSurfacePurgeableEmpty,
+ null,
+ );
+ foundation.CFRelease(self);
+ }
+
+ pub fn retain(self: *IOSurface) void {
+ foundation.CFRetain(self);
+ }
+
+ pub fn release(self: *IOSurface) void {
+ foundation.CFRelease(self);
+ }
+
+ pub fn setColorSpace(self: *IOSurface, colorspace: *graphics.ColorSpace) void {
+ const serialized_colorspace = graphics.c.CGColorSpaceCopyPropertyList(
+ @ptrCast(colorspace),
+ ).?;
+ defer foundation.CFRelease(@constCast(serialized_colorspace));
+
+ c.IOSurfaceSetValue(
+ @ptrCast(self),
+ c.kIOSurfaceColorSpace,
+ @ptrCast(serialized_colorspace),
+ );
+ }
+
+ pub inline fn lock(self: *IOSurface) void {
+ c.IOSurfaceLock(
+ @ptrCast(self),
+ 0,
+ null,
+ );
+ }
+ pub inline fn unlock(self: *IOSurface) void {
+ c.IOSurfaceUnlock(
+ @ptrCast(self),
+ 0,
+ null,
+ );
+ }
+
+ pub inline fn getAllocSize(self: *IOSurface) usize {
+ return c.IOSurfaceGetAllocSize(@ptrCast(self));
+ }
+
+ pub inline fn getWidth(self: *IOSurface) usize {
+ return c.IOSurfaceGetWidth(@ptrCast(self));
+ }
+
+ pub inline fn getHeight(self: *IOSurface) usize {
+ return c.IOSurfaceGetHeight(@ptrCast(self));
+ }
+
+ pub inline fn getBytesPerElement(self: *IOSurface) usize {
+ return c.IOSurfaceGetBytesPerElement(@ptrCast(self));
+ }
+
+ pub inline fn getBytesPerRow(self: *IOSurface) usize {
+ return c.IOSurfaceGetBytesPerRow(@ptrCast(self));
+ }
+
+ pub inline fn getBaseAddress(self: *IOSurface) ?[*]u8 {
+ return @ptrCast(c.IOSurfaceGetBaseAddress(@ptrCast(self)));
+ }
+
+ pub inline fn getElementWidth(self: *IOSurface) usize {
+ return c.IOSurfaceGetElementWidth(@ptrCast(self));
+ }
+
+ pub inline fn getElementHeight(self: *IOSurface) usize {
+ return c.IOSurfaceGetElementHeight(@ptrCast(self));
+ }
+
+ pub inline fn getPixelFormat(self: *IOSurface) video.PixelFormat {
+ return @enumFromInt(c.IOSurfaceGetPixelFormat(@ptrCast(self)));
+ }
+};
diff --git a/vendor/libghostty-vt/pkg/macos/main.zig b/vendor/libghostty-vt/pkg/macos/main.zig
new file mode 100644
index 00000000..e4f4b950
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/main.zig
@@ -0,0 +1,35 @@
+const builtin = @import("builtin");
+
+pub const carbon = @import("carbon.zig");
+pub const foundation = @import("foundation.zig");
+pub const animation = @import("animation.zig");
+pub const dispatch = @import("dispatch.zig");
+pub const graphics = @import("graphics.zig");
+pub const os = @import("os.zig");
+pub const text = @import("text.zig");
+pub const video = @import("video.zig");
+pub const iosurface = @import("iosurface.zig");
+
+// All of our C imports consolidated into one place. We used to
+// import them one by one in each package but Zig 0.14 has some
+// kind of issue with that I wasn't able to minimize.
+pub const c = @cImport({
+ @cInclude("CoreFoundation/CoreFoundation.h");
+ @cInclude("CoreGraphics/CoreGraphics.h");
+ @cInclude("CoreText/CoreText.h");
+ @cInclude("CoreVideo/CoreVideo.h");
+ @cInclude("CoreVideo/CVPixelBuffer.h");
+ @cInclude("QuartzCore/CALayer.h");
+ @cInclude("IOSurface/IOSurfaceRef.h");
+ @cInclude("dispatch/dispatch.h");
+ @cInclude("os/log.h");
+ @cInclude("os/signpost.h");
+
+ if (builtin.os.tag == .macos) {
+ @cInclude("Carbon/Carbon.h");
+ }
+});
+
+test {
+ @import("std").testing.refAllDecls(@This());
+}
diff --git a/vendor/libghostty-vt/pkg/macos/os.zig b/vendor/libghostty-vt/pkg/macos/os.zig
new file mode 100644
index 00000000..9716a9ab
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/os.zig
@@ -0,0 +1,10 @@
+const log = @import("os/log.zig");
+
+pub const c = @import("os/c.zig");
+pub const signpost = @import("os/signpost.zig");
+pub const Log = log.Log;
+pub const LogType = log.LogType;
+
+test {
+ @import("std").testing.refAllDecls(@This());
+}
diff --git a/vendor/libghostty-vt/pkg/macos/os/c.zig b/vendor/libghostty-vt/pkg/macos/os/c.zig
new file mode 100644
index 00000000..1a7d1627
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/os/c.zig
@@ -0,0 +1 @@
+pub const c = @import("../main.zig").c;
diff --git a/vendor/libghostty-vt/pkg/macos/os/log.zig b/vendor/libghostty-vt/pkg/macos/os/log.zig
new file mode 100644
index 00000000..219c914d
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/os/log.zig
@@ -0,0 +1,65 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const Allocator = std.mem.Allocator;
+const c = @import("c.zig").c;
+
+pub const Log = opaque {
+ pub fn create(
+ subsystem: [:0]const u8,
+ category: [:0]const u8,
+ ) *Log {
+ return @ptrCast(c.os_log_create(
+ subsystem.ptr,
+ category.ptr,
+ ).?);
+ }
+
+ pub fn release(self: *Log) void {
+ c.os_release(self);
+ }
+
+ pub fn typeEnabled(self: *Log, typ: LogType) bool {
+ return c.os_log_type_enabled(
+ @ptrCast(self),
+ @intFromEnum(typ),
+ );
+ }
+
+ pub fn log(
+ self: *Log,
+ alloc: Allocator,
+ typ: LogType,
+ comptime format: []const u8,
+ args: anytype,
+ ) void {
+ const str = nosuspend std.fmt.allocPrintSentinel(
+ alloc,
+ format,
+ args,
+ 0,
+ ) catch return;
+ defer alloc.free(str);
+ zig_os_log_with_type(self, typ, str.ptr);
+ }
+
+ extern "c" fn zig_os_log_with_type(*Log, LogType, [*c]const u8) void;
+};
+
+/// https://developer.apple.com/documentation/os/os_log_type_t?language=objc
+pub const LogType = enum(c.os_log_type_t) {
+ default = c.OS_LOG_TYPE_DEFAULT,
+ debug = c.OS_LOG_TYPE_DEBUG,
+ info = c.OS_LOG_TYPE_INFO,
+ err = c.OS_LOG_TYPE_ERROR,
+ fault = c.OS_LOG_TYPE_FAULT,
+};
+
+test {
+ const testing = std.testing;
+
+ const log = Log.create("com.mitchellh.ghostty", "test");
+ defer log.release();
+
+ try testing.expect(log.typeEnabled(.fault));
+ log.log(testing.allocator, .default, "hello {d}", .{12});
+}
diff --git a/vendor/libghostty-vt/pkg/macos/os/signpost.zig b/vendor/libghostty-vt/pkg/macos/os/signpost.zig
new file mode 100644
index 00000000..2bd12566
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/os/signpost.zig
@@ -0,0 +1,214 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const Allocator = std.mem.Allocator;
+const c = @import("c.zig").c;
+const logpkg = @import("log.zig");
+const Log = logpkg.Log;
+
+/// This should be called once at the start of the program to intialize
+/// some required state for signpost logging.
+///
+/// This is all to workaround a Zig bug:
+/// https://github.com/ziglang/zig/issues/24370
+pub fn init() void {
+ if (__dso_handle != null) return;
+
+ const sym = comptime sym: {
+ const root = @import("root");
+
+ // If we have a main function, use that as the symbol.
+ if (@hasDecl(root, "main")) break :sym root.main;
+
+ // Otherwise, we're in a library, so we just use the first
+ // function in our root module. I actually don't know if this is
+ // all required or if we can just use the real `__dso_handle` symbol,
+ // but this seems to work for now.
+ for (@typeInfo(root).@"struct".decls) |decl_info| {
+ const decl = @field(root, decl_info.name);
+ if (@typeInfo(@TypeOf(decl)) == .@"fn") break :sym decl;
+ }
+
+ @compileError("no functions found in root module");
+ };
+
+ // Since __dso_handle is not automatically populated by the linker,
+ // we populate it by looking up the main function's module address
+ // which should be a mach-o header.
+ var info: DlInfo = undefined;
+ const result = dladdr(sym, &info);
+ assert(result != 0);
+ __dso_handle = @ptrCast(@alignCast(info.dli_fbase));
+}
+
+/// This should REALLY be an extern var that is populated by the linker,
+/// but there is a Zig bug: https://github.com/ziglang/zig/issues/24370
+var __dso_handle: ?*c.mach_header = null;
+
+// Import the necessary C functions and types
+extern "c" fn dladdr(addr: ?*const anyopaque, info: *DlInfo) c_int;
+
+// Define the Dl_info structure
+const DlInfo = extern struct {
+ dli_fname: [*:0]const u8, // Pathname of shared object
+ dli_fbase: ?*anyopaque, // Base address of shared object
+ dli_sname: [*:0]const u8, // Name of nearest symbol
+ dli_saddr: ?*anyopaque, // Address of nearest symbol
+};
+
+/// Checks whether signpost logging is enabled for the given log handle.
+/// Returns true if signposts will be recorded for this log, false otherwise.
+/// This can be used to avoid expensive operations when signpost logging is disabled.
+///
+/// https://developer.apple.com/documentation/os/os_signpost_enabled?language=objc
+pub fn enabled(log: *Log) bool {
+ return c.os_signpost_enabled(@ptrCast(log));
+}
+
+/// Emits a signpost event - a single point in time marker.
+/// Events are useful for marking when specific actions occur, such as
+/// user interactions, state changes, or other discrete occurrences.
+/// The event will appear as a vertical line in Instruments.
+///
+/// https://developer.apple.com/documentation/os/os_signpost_event_emit?language=objc
+pub fn emitEvent(
+ log: *Log,
+ id: Id,
+ comptime name: [:0]const u8,
+) void {
+ emitWithName(log, id, .event, name);
+}
+
+/// Marks the beginning of a time interval.
+/// Use this with intervalEnd to measure the duration of operations.
+/// The same ID must be used for both the begin and end calls.
+/// Intervals appear as horizontal bars in Instruments timeline.
+///
+/// https://developer.apple.com/documentation/os/os_signpost_interval_begin?language=objc
+pub fn intervalBegin(log: *Log, id: Id, comptime name: [:0]const u8) void {
+ emitWithName(log, id, .interval_begin, name);
+}
+
+/// Marks the end of a time interval.
+/// Must be paired with a prior intervalBegin call using the same ID.
+/// The name should match the name used in intervalBegin.
+/// Instruments will calculate and display the duration between begin and end.
+///
+/// https://developer.apple.com/documentation/os/os_signpost_interval_end?language=objc
+pub fn intervalEnd(log: *Log, id: Id, comptime name: [:0]const u8) void {
+ emitWithName(log, id, .interval_end, name);
+}
+
+/// The internal function to emit a signpost with a specific name.
+fn emitWithName(
+ log: *Log,
+ id: Id,
+ typ: Type,
+ comptime name: [:0]const u8,
+) void {
+ // Init must be called by this point.
+ assert(__dso_handle != null);
+
+ var buf: [2]u8 = @splat(0);
+ c._os_signpost_emit_with_name_impl(
+ __dso_handle,
+ @ptrCast(log),
+ @intFromEnum(typ),
+ @intFromEnum(id),
+ name.ptr,
+ "".ptr,
+ &buf,
+ buf.len,
+ );
+}
+
+/// https://developer.apple.com/documentation/os/os_signpost_id_t?language=objc
+pub const Id = enum(u64) {
+ null = 0, // OS_SIGNPOST_ID_NULL
+ invalid = 0xFFFFFFFFFFFFFFFF, // OS_SIGNPOST_ID_INVALID
+ exclusive = 0xEEEEB0B5B2B2EEEE, // OS_SIGNPOST_ID_EXCLUSIVE
+ _,
+
+ /// Generates a new signpost ID for use with signpost operations.
+ /// The ID is unique for the given log handle and can be used to track
+ /// asynchronous operations or mark specific points of interest in the code.
+ /// Returns a unique signpost ID that can be used with os_signpost functions.
+ ///
+ /// https://developer.apple.com/documentation/os/os_signpost_id_generate?language=objc
+ pub fn generate(log: *Log) Id {
+ return @enumFromInt(c.os_signpost_id_generate(@ptrCast(log)));
+ }
+
+ /// Creates a signpost ID based on a pointer value.
+ /// This is useful for tracking operations associated with a specific object
+ /// or memory location. The same pointer will always generate the same ID
+ /// for a given log handle, allowing correlation of signpost events.
+ /// Pass null to get the null signpost ID.
+ ///
+ /// https://developer.apple.com/documentation/os/os_signpost_id_for_pointer?language=objc
+ pub fn forPointer(log: *Log, ptr: ?*anyopaque) Id {
+ return @enumFromInt(c.os_signpost_id_make_with_pointer(
+ @ptrCast(log),
+ @ptrCast(ptr),
+ ));
+ }
+
+ test "generate ID" {
+ // We can't really test the return value because it may return null
+ // if signposts are disabled.
+ const id: Id = .generate(Log.create("com.mitchellh.ghostty", "test"));
+ try std.testing.expect(id != .invalid);
+ }
+
+ test "generate ID for pointer" {
+ var foo: usize = 0x1234;
+ const id: Id = .forPointer(Log.create("com.mitchellh.ghostty", "test"), &foo);
+ try std.testing.expect(id != .null);
+ }
+};
+
+/// https://developer.apple.com/documentation/os/ossignposttype?language=objc
+pub const Type = enum(u8) {
+ event = 0, // OS_SIGNPOST_EVENT
+ interval_begin = 1, // OS_SIGNPOST_INTERVAL_BEGIN
+ interval_end = 2, // OS_SIGNPOST_INTERVAL_END
+
+ pub const mask: u8 = 0x03; // OS_SIGNPOST_TYPE_MASK
+};
+
+/// Special os_log category values that surface in Instruments and other
+/// tooling.
+pub const Category = struct {
+ /// Points of Interest appear as a dedicated track in Instruments.
+ /// Use this for high-level application events that help understand
+ /// the flow of your application.
+ pub const points_of_interest: [:0]const u8 = "PointsOfInterest";
+
+ /// Dynamic Tracing category enables runtime-configurable logging.
+ /// Signposts in this category can be enabled/disabled dynamically
+ /// without recompiling.
+ pub const dynamic_tracing: [:0]const u8 = "DynamicTracing";
+
+ /// Dynamic Stack Tracing category captures call stacks at signpost
+ /// events. This provides deeper debugging information but has higher
+ /// performance overhead.
+ pub const dynamic_stack_tracing: [:0]const u8 = "DynamicStackTracing";
+};
+
+test {
+ _ = Id;
+}
+
+test enabled {
+ _ = enabled(Log.create("com.mitchellh.ghostty", "test"));
+}
+
+test "intervals" {
+ init();
+
+ const log = Log.create("com.mitchellh.ghostty", "test");
+ defer log.release();
+
+ // Test that we can begin and end an interval
+ const id = Id.generate(log);
+ intervalBegin(log, id, "Test Interval");
+}
diff --git a/vendor/libghostty-vt/pkg/macos/os/zig_macos.c b/vendor/libghostty-vt/pkg/macos/os/zig_macos.c
new file mode 100644
index 00000000..1c4f0698
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/os/zig_macos.c
@@ -0,0 +1,11 @@
+#include <os/log.h>
+#include <os/signpost.h>
+
+// A wrapper so we can use the os_log_with_type macro.
+void zig_os_log_with_type(
+ os_log_t log,
+ os_log_type_t type,
+ const char *message
+) {
+ os_log_with_type(log, type, "%{public}s", message);
+}
diff --git a/vendor/libghostty-vt/pkg/macos/text.zig b/vendor/libghostty-vt/pkg/macos/text.zig
new file mode 100644
index 00000000..bfaa388b
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/text.zig
@@ -0,0 +1,38 @@
+const font = @import("text/font.zig");
+const font_collection = @import("text/font_collection.zig");
+const font_descriptor = @import("text/font_descriptor.zig");
+const font_manager = @import("text/font_manager.zig");
+const frame = @import("text/frame.zig");
+const framesetter = @import("text/framesetter.zig");
+const typesetter = @import("text/typesetter.zig");
+const line = @import("text/line.zig");
+const paragraph_style = @import("text/paragraph_style.zig");
+const run = @import("text/run.zig");
+const stylized_strings = @import("text/stylized_strings.zig");
+
+pub const c = @import("text/c.zig").c;
+pub const Font = font.Font;
+pub const FontTableTag = font.FontTableTag;
+pub const FontCollection = font_collection.FontCollection;
+pub const FontDescriptor = font_descriptor.FontDescriptor;
+pub const FontAttribute = font_descriptor.FontAttribute;
+pub const FontTraitKey = font_descriptor.FontTraitKey;
+pub const FontVariationAxisKey = font_descriptor.FontVariationAxisKey;
+pub const FontSymbolicTraits = font_descriptor.FontSymbolicTraits;
+pub const createFontDescriptorsFromURL = font_manager.createFontDescriptorsFromURL;
+pub const createFontDescriptorsFromData = font_manager.createFontDescriptorsFromData;
+pub const createFontDescriptorFromData = font_manager.createFontDescriptorFromData;
+pub const Frame = frame.Frame;
+pub const Framesetter = framesetter.Framesetter;
+pub const Typesetter = typesetter.Typesetter;
+pub const Line = line.Line;
+pub const ParagraphStyle = paragraph_style.ParagraphStyle;
+pub const ParagraphStyleSetting = paragraph_style.ParagraphStyleSetting;
+pub const ParagraphStyleSpecifier = paragraph_style.ParagraphStyleSpecifier;
+pub const WritingDirection = paragraph_style.WritingDirection;
+pub const Run = run.Run;
+pub const StringAttribute = stylized_strings.StringAttribute;
+
+test {
+ @import("std").testing.refAllDecls(@This());
+}
diff --git a/vendor/libghostty-vt/pkg/macos/text/c.zig b/vendor/libghostty-vt/pkg/macos/text/c.zig
new file mode 100644
index 00000000..1a7d1627
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/text/c.zig
@@ -0,0 +1 @@
+pub const c = @import("../main.zig").c;
diff --git a/vendor/libghostty-vt/pkg/macos/text/ext.c b/vendor/libghostty-vt/pkg/macos/text/ext.c
new file mode 100644
index 00000000..55bff8a6
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/text/ext.c
@@ -0,0 +1,10 @@
+#include <CoreText/CoreText.h>
+
+// A wrapper to fix a Zig C ABI issue.
+void zig_cabi_CTLineGetBoundsWithOptions(
+ CTLineRef line,
+ CTLineBoundsOptions options,
+ CGRect *result
+) {
+ *result = CTLineGetBoundsWithOptions(line, options);
+}
diff --git a/vendor/libghostty-vt/pkg/macos/text/font.zig b/vendor/libghostty-vt/pkg/macos/text/font.zig
new file mode 100644
index 00000000..ea37891f
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/text/font.zig
@@ -0,0 +1,306 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const Allocator = std.mem.Allocator;
+const foundation = @import("../foundation.zig");
+const graphics = @import("../graphics.zig");
+const text = @import("../text.zig");
+const c = @import("c.zig").c;
+
+pub const Font = opaque {
+ pub fn createWithFontDescriptor(desc: *const text.FontDescriptor, size: f32) Allocator.Error!*Font {
+ return @as(
+ ?*Font,
+ @ptrFromInt(@intFromPtr(c.CTFontCreateWithFontDescriptor(
+ @ptrCast(desc),
+ size,
+ null,
+ ))),
+ ) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn createForString(
+ self: *Font,
+ str: *foundation.String,
+ range: foundation.Range,
+ ) ?*Font {
+ return @ptrCast(@constCast(c.CTFontCreateForString(
+ @ptrCast(self),
+ @ptrCast(str),
+ @bitCast(range),
+ )));
+ }
+
+ pub fn copyWithAttributes(
+ self: *Font,
+ size: f32,
+ matrix: ?*const graphics.AffineTransform,
+ attrs: ?*text.FontDescriptor,
+ ) Allocator.Error!*Font {
+ return @as(
+ ?*Font,
+ @ptrFromInt(@intFromPtr(c.CTFontCreateCopyWithAttributes(
+ @ptrCast(self),
+ size,
+ @ptrCast(matrix),
+ @ptrCast(attrs),
+ ))),
+ ) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn release(self: *Font) void {
+ c.CFRelease(self);
+ }
+
+ pub fn retain(self: *Font) void {
+ _ = c.CFRetain(self);
+ }
+
+ pub fn copyDescriptor(self: *Font) *text.FontDescriptor {
+ return @ptrCast(@constCast(c.CTFontCopyFontDescriptor(@ptrCast(self))));
+ }
+
+ pub fn copyFeatures(self: *Font) *foundation.Array {
+ return @ptrCast(@constCast(c.CTFontCopyFeatures(@ptrCast(self))));
+ }
+
+ pub fn copyDefaultCascadeListForLanguages(self: *Font) *foundation.Array {
+ return @ptrCast(@constCast(c.CTFontCopyDefaultCascadeListForLanguages(@ptrCast(self), null)));
+ }
+
+ pub fn copyTable(self: *Font, tag: FontTableTag) ?*foundation.Data {
+ return @ptrCast(@constCast(c.CTFontCopyTable(
+ @ptrCast(self),
+ @intFromEnum(tag),
+ c.kCTFontTableOptionNoOptions,
+ )));
+ }
+
+ pub fn getGlyphCount(self: *Font) usize {
+ return @intCast(c.CTFontGetGlyphCount(@ptrCast(self)));
+ }
+
+ pub fn getGlyphsForCharacters(self: *Font, chars: []const u16, glyphs: []graphics.Glyph) bool {
+ assert(chars.len == glyphs.len);
+ return c.CTFontGetGlyphsForCharacters(
+ @ptrCast(self),
+ chars.ptr,
+ glyphs.ptr,
+ @intCast(chars.len),
+ );
+ }
+
+ pub fn createPathForGlyph(self: *Font, glyph: graphics.Glyph) ?*graphics.Path {
+ return @ptrCast(@constCast(c.CTFontCreatePathForGlyph(
+ @ptrCast(self),
+ glyph,
+ null,
+ )));
+ }
+
+ pub fn drawGlyphs(
+ self: *Font,
+ glyphs: []const graphics.Glyph,
+ positions: []const graphics.Point,
+ context: anytype, // Must be some context type from graphics
+ ) void {
+ assert(positions.len == glyphs.len);
+ c.CTFontDrawGlyphs(
+ @ptrCast(self),
+ glyphs.ptr,
+ @ptrCast(positions.ptr),
+ glyphs.len,
+ @ptrCast(context),
+ );
+ }
+
+ pub fn getBoundingRectsForGlyphs(
+ self: *Font,
+ orientation: FontOrientation,
+ glyphs: []const graphics.Glyph,
+ rects: ?[]graphics.Rect,
+ ) graphics.Rect {
+ if (rects) |s| assert(glyphs.len == s.len);
+ return @bitCast(c.CTFontGetBoundingRectsForGlyphs(
+ @ptrCast(self),
+ @intFromEnum(orientation),
+ glyphs.ptr,
+ @ptrCast(if (rects) |s| s.ptr else null),
+ @intCast(glyphs.len),
+ ));
+ }
+
+ pub fn getAdvancesForGlyphs(
+ self: *Font,
+ orientation: FontOrientation,
+ glyphs: []const graphics.Glyph,
+ advances: ?[]graphics.Size,
+ ) f64 {
+ if (advances) |s| assert(glyphs.len == s.len);
+ return c.CTFontGetAdvancesForGlyphs(
+ @ptrCast(self),
+ @intFromEnum(orientation),
+ glyphs.ptr,
+ @ptrCast(if (advances) |s| s.ptr else null),
+ @intCast(glyphs.len),
+ );
+ }
+
+ pub fn copyAttribute(self: *Font, comptime attr: text.FontAttribute) ?attr.Value() {
+ return @ptrFromInt(@intFromPtr(c.CTFontCopyAttribute(
+ @ptrCast(self),
+ @ptrCast(attr.key()),
+ )));
+ }
+
+ pub fn copyFamilyName(self: *Font) *foundation.String {
+ return @ptrFromInt(@intFromPtr(c.CTFontCopyFamilyName(@ptrCast(self))));
+ }
+
+ pub fn copyDisplayName(self: *Font) *foundation.String {
+ return @ptrFromInt(@intFromPtr(c.CTFontCopyDisplayName(@ptrCast(self))));
+ }
+
+ pub fn copyPostScriptName(self: *Font) *foundation.String {
+ return @ptrFromInt(@intFromPtr(c.CTFontCopyPostScriptName(@ptrCast(self))));
+ }
+
+ pub fn getSymbolicTraits(self: *Font) text.FontSymbolicTraits {
+ return @bitCast(c.CTFontGetSymbolicTraits(@ptrCast(self)));
+ }
+
+ pub fn getAscent(self: *Font) f64 {
+ return c.CTFontGetAscent(@ptrCast(self));
+ }
+
+ pub fn getDescent(self: *Font) f64 {
+ return c.CTFontGetDescent(@ptrCast(self));
+ }
+
+ pub fn getLeading(self: *Font) f64 {
+ return c.CTFontGetLeading(@ptrCast(self));
+ }
+
+ pub fn getBoundingBox(self: *Font) graphics.Rect {
+ return @bitCast(c.CTFontGetBoundingBox(@ptrCast(self)));
+ }
+
+ pub fn getUnderlinePosition(self: *Font) f64 {
+ return c.CTFontGetUnderlinePosition(@ptrCast(self));
+ }
+
+ pub fn getUnderlineThickness(self: *Font) f64 {
+ return c.CTFontGetUnderlineThickness(@ptrCast(self));
+ }
+
+ pub fn getCapHeight(self: *Font) f64 {
+ return c.CTFontGetCapHeight(@ptrCast(self));
+ }
+
+ pub fn getXHeight(self: *Font) f64 {
+ return c.CTFontGetXHeight(@ptrCast(self));
+ }
+
+ pub fn getUnitsPerEm(self: *Font) u32 {
+ return c.CTFontGetUnitsPerEm(@ptrCast(self));
+ }
+
+ pub fn getSize(self: *Font) f64 {
+ return c.CTFontGetSize(@ptrCast(self));
+ }
+};
+
+pub const FontOrientation = enum(c_uint) {
+ default = c.kCTFontOrientationDefault,
+ horizontal = c.kCTFontOrientationHorizontal,
+ vertical = c.kCTFontOrientationVertical,
+};
+
+pub const FontTableTag = enum(u32) {
+ svg = c.kCTFontTableSVG,
+ os2 = c.kCTFontTableOS2,
+ head = c.kCTFontTableHead,
+ hhea = c.kCTFontTableHhea,
+ post = c.kCTFontTablePost,
+ _,
+
+ pub fn init(v: *const [4]u8) FontTableTag {
+ const raw: u32 = @bitCast(foundation.FourCharCode.init(v));
+ return @enumFromInt(raw);
+ }
+};
+
+test {
+ const testing = std.testing;
+
+ const name = try foundation.String.createWithBytes("Monaco", .utf8, false);
+ defer name.release();
+ const desc = try text.FontDescriptor.createWithNameAndSize(name, 12);
+ defer desc.release();
+
+ const font = try Font.createWithFontDescriptor(desc, 12);
+ defer font.release();
+
+ // Traits
+ {
+ const traits = font.getSymbolicTraits();
+ try testing.expect(!traits.color_glyphs);
+ }
+
+ var glyphs = [1]graphics.Glyph{0};
+ try testing.expect(font.getGlyphsForCharacters(
+ &[_]u16{'A'},
+ &glyphs,
+ ));
+ try testing.expect(glyphs[0] > 0);
+
+ // Bounding rect
+ {
+ var rect = font.getBoundingRectsForGlyphs(.horizontal, &glyphs, null);
+ try testing.expect(rect.size.width > 0);
+
+ var singles: [1]graphics.Rect = undefined;
+ rect = font.getBoundingRectsForGlyphs(.horizontal, &glyphs, &singles);
+ try testing.expect(rect.size.width > 0);
+ try testing.expect(singles[0].size.width > 0);
+ }
+
+ // Advances
+ {
+ var advance = font.getAdvancesForGlyphs(.horizontal, &glyphs, null);
+ try testing.expect(advance > 0);
+
+ var singles: [1]graphics.Size = undefined;
+ advance = font.getAdvancesForGlyphs(.horizontal, &glyphs, &singles);
+ try testing.expect(advance > 0);
+ try testing.expect(singles[0].width > 0);
+ }
+
+ // Draw
+ {
+ const cs = try graphics.ColorSpace.createDeviceGray();
+ defer cs.release();
+ const ctx = try graphics.BitmapContext.create(null, 80, 80, 8, 80, cs, 0);
+ const context = graphics.BitmapContext.context;
+ defer context.release(ctx);
+
+ var pos = [_]graphics.Point{.{ .x = 0, .y = 0 }};
+ font.drawGlyphs(
+ &glyphs,
+ &pos,
+ ctx,
+ );
+ }
+}
+
+test "copy" {
+ const name = try foundation.String.createWithBytes("Monaco", .utf8, false);
+ defer name.release();
+ const desc = try text.FontDescriptor.createWithNameAndSize(name, 12);
+ defer desc.release();
+
+ const font = try Font.createWithFontDescriptor(desc, 12);
+ defer font.release();
+
+ const f2 = try font.copyWithAttributes(14, null, null);
+ defer f2.release();
+}
diff --git a/vendor/libghostty-vt/pkg/macos/text/font_collection.zig b/vendor/libghostty-vt/pkg/macos/text/font_collection.zig
new file mode 100644
index 00000000..8b4a86a6
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/text/font_collection.zig
@@ -0,0 +1,139 @@
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+const foundation = @import("../foundation.zig");
+const text = @import("../text.zig");
+const c = @import("c.zig").c;
+
+pub const FontCollection = opaque {
+ pub fn createFromAvailableFonts() Allocator.Error!*FontCollection {
+ return @as(
+ ?*FontCollection,
+ @ptrFromInt(@intFromPtr(c.CTFontCollectionCreateFromAvailableFonts(null))),
+ ) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn createWithFontDescriptors(descs: *foundation.Array) Allocator.Error!*FontCollection {
+ return @as(
+ ?*FontCollection,
+ @ptrFromInt(@intFromPtr(c.CTFontCollectionCreateWithFontDescriptors(
+ @ptrCast(descs),
+ null,
+ ))),
+ ) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn release(self: *FontCollection) void {
+ c.CFRelease(self);
+ }
+
+ pub fn createMatchingFontDescriptors(self: *FontCollection) *foundation.Array {
+ const result = c.CTFontCollectionCreateMatchingFontDescriptors(@ptrCast(self));
+ if (result) |ptr| return @ptrFromInt(@intFromPtr(ptr));
+
+ // If we have no results, we create an empty array. This is not
+ // exactly matching the Mac API. We can fix this later if we want
+ // but I chose this to make it slightly more Zig-like at the cost
+ // of some memory in the rare case.
+ return foundation.Array.create(anyopaque, &[_]*const anyopaque{}) catch unreachable;
+ }
+};
+
+fn debugDumpList(list: *foundation.Array) !void {
+ var i: usize = 0;
+ while (i < list.getCount()) : (i += 1) {
+ const desc = list.getValueAtIndex(text.FontDescriptor, i);
+ {
+ var buf: [128]u8 = undefined;
+ const name = desc.copyAttribute(.name);
+ defer name.release();
+ const cstr = name.cstring(&buf, .utf8).?;
+
+ var family_buf: [128]u8 = undefined;
+ const family = desc.copyAttribute(.family_name);
+ defer family.release();
+ const family_cstr = family.cstring(&family_buf, .utf8).?;
+
+ var buf2: [128]u8 = undefined;
+ const url = desc.copyAttribute(.url);
+ defer url.release();
+ const path = path: {
+ const blank = try foundation.String.createWithBytes("", .utf8, false);
+ defer blank.release();
+
+ const path = url.copyPath() orelse break :path "<no path>";
+ defer path.release();
+
+ const decoded = try foundation.URL.createStringByReplacingPercentEscapes(
+ path,
+ blank,
+ );
+ defer decoded.release();
+
+ break :path decoded.cstring(&buf2, .utf8) orelse
+ "<path cannot be converted to string>";
+ };
+
+ std.log.warn("i={d} name={s} family={s} path={s}", .{ i, cstr, family_cstr, path });
+ }
+ }
+}
+
+test "collection" {
+ const testing = std.testing;
+
+ const v = try FontCollection.createFromAvailableFonts();
+ defer v.release();
+
+ const list = v.createMatchingFontDescriptors();
+ defer list.release();
+
+ try testing.expect(list.getCount() > 0);
+}
+
+test "from descriptors" {
+ const testing = std.testing;
+
+ const name = try foundation.String.createWithBytes("AppleColorEmoji", .utf8, false);
+ defer name.release();
+
+ const desc = try text.FontDescriptor.createWithNameAndSize(name, 12);
+ defer desc.release();
+
+ var desc_arr = [_]*const text.FontDescriptor{desc};
+ const arr = try foundation.Array.create(text.FontDescriptor, &desc_arr);
+ defer arr.release();
+
+ const v = try FontCollection.createWithFontDescriptors(arr);
+ defer v.release();
+
+ const list = v.createMatchingFontDescriptors();
+ defer list.release();
+
+ try testing.expect(list.getCount() > 0);
+
+ // try debugDumpList(list);
+}
+
+test "from descriptors no match" {
+ const testing = std.testing;
+
+ const name = try foundation.String.createWithBytes("ThisShouldNeverExist", .utf8, false);
+ defer name.release();
+
+ const desc = try text.FontDescriptor.createWithNameAndSize(name, 12);
+ defer desc.release();
+
+ var desc_arr = [_]*const text.FontDescriptor{desc};
+ const arr = try foundation.Array.create(text.FontDescriptor, &desc_arr);
+ defer arr.release();
+
+ const v = try FontCollection.createWithFontDescriptors(arr);
+ defer v.release();
+
+ const list = v.createMatchingFontDescriptors();
+ defer list.release();
+
+ try testing.expect(list.getCount() == 0);
+
+ //try debugDumpList(list);
+}
diff --git a/vendor/libghostty-vt/pkg/macos/text/font_descriptor.zig b/vendor/libghostty-vt/pkg/macos/text/font_descriptor.zig
new file mode 100644
index 00000000..563165bc
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/text/font_descriptor.zig
@@ -0,0 +1,287 @@
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+const foundation = @import("../foundation.zig");
+const c = @import("c.zig").c;
+
+pub const FontDescriptor = opaque {
+ pub fn createWithNameAndSize(name: *foundation.String, size: f64) Allocator.Error!*FontDescriptor {
+ return @as(
+ ?*FontDescriptor,
+ @ptrFromInt(@intFromPtr(c.CTFontDescriptorCreateWithNameAndSize(@ptrCast(name), size))),
+ ) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn createWithAttributes(dict: *foundation.Dictionary) Allocator.Error!*FontDescriptor {
+ return @as(
+ ?*FontDescriptor,
+ @ptrFromInt(@intFromPtr(c.CTFontDescriptorCreateWithAttributes(@ptrCast(dict)))),
+ ) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn createCopyWithAttributes(
+ original: *FontDescriptor,
+ dict: *foundation.Dictionary,
+ ) Allocator.Error!*FontDescriptor {
+ return @as(
+ ?*FontDescriptor,
+ @ptrFromInt(@intFromPtr(c.CTFontDescriptorCreateCopyWithAttributes(
+ @ptrCast(original),
+ @ptrCast(dict),
+ ))),
+ ) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn createCopyWithVariation(
+ original: *FontDescriptor,
+ id: *foundation.Number,
+ value: f64,
+ ) Allocator.Error!*FontDescriptor {
+ return @as(
+ ?*FontDescriptor,
+ @ptrCast(@constCast(c.CTFontDescriptorCreateCopyWithVariation(
+ @ptrCast(original),
+ @ptrCast(id),
+ value,
+ ))),
+ ) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn retain(self: *FontDescriptor) void {
+ _ = c.CFRetain(self);
+ }
+
+ pub fn release(self: *FontDescriptor) void {
+ c.CFRelease(self);
+ }
+
+ pub fn copyAttribute(self: *const FontDescriptor, comptime attr: FontAttribute) ?attr.Value() {
+ return @ptrFromInt(@intFromPtr(c.CTFontDescriptorCopyAttribute(
+ @ptrCast(self),
+ @ptrCast(attr.key()),
+ )));
+ }
+
+ pub fn copyAttributes(self: *const FontDescriptor) *foundation.Dictionary {
+ return @ptrFromInt(@intFromPtr(c.CTFontDescriptorCopyAttributes(
+ @ptrCast(self),
+ )));
+ }
+};
+
+pub const FontAttribute = enum {
+ url,
+ name,
+ display_name,
+ family_name,
+ style_name,
+ traits,
+ variation,
+ size,
+ matrix,
+ cascade_list,
+ character_set,
+ languages,
+ baseline_adjust,
+ macintosh_encodings,
+ features,
+ feature_settings,
+ fixed_advance,
+ orientation,
+ format,
+ registration_scope,
+ priority,
+ enabled,
+ downloadable,
+ downloaded,
+
+ // https://developer.apple.com/documentation/coretext/core_text_constants?language=objc
+ variation_axes,
+
+ pub fn key(self: FontAttribute) *foundation.String {
+ return @as(*foundation.String, @ptrFromInt(@intFromPtr(switch (self) {
+ .url => c.kCTFontURLAttribute,
+ .name => c.kCTFontNameAttribute,
+ .display_name => c.kCTFontDisplayNameAttribute,
+ .family_name => c.kCTFontFamilyNameAttribute,
+ .style_name => c.kCTFontStyleNameAttribute,
+ .traits => c.kCTFontTraitsAttribute,
+ .variation => c.kCTFontVariationAttribute,
+ .size => c.kCTFontSizeAttribute,
+ .matrix => c.kCTFontMatrixAttribute,
+ .cascade_list => c.kCTFontCascadeListAttribute,
+ .character_set => c.kCTFontCharacterSetAttribute,
+ .languages => c.kCTFontLanguagesAttribute,
+ .baseline_adjust => c.kCTFontBaselineAdjustAttribute,
+ .macintosh_encodings => c.kCTFontMacintoshEncodingsAttribute,
+ .features => c.kCTFontFeaturesAttribute,
+ .feature_settings => c.kCTFontFeatureSettingsAttribute,
+ .fixed_advance => c.kCTFontFixedAdvanceAttribute,
+ .orientation => c.kCTFontOrientationAttribute,
+ .format => c.kCTFontFormatAttribute,
+ .registration_scope => c.kCTFontRegistrationScopeAttribute,
+ .priority => c.kCTFontPriorityAttribute,
+ .enabled => c.kCTFontEnabledAttribute,
+ .downloadable => c.kCTFontDownloadableAttribute,
+ .downloaded => c.kCTFontDownloadedAttribute,
+ .variation_axes => c.kCTFontVariationAxesAttribute,
+ })));
+ }
+
+ pub fn Value(comptime self: FontAttribute) type {
+ return switch (self) {
+ .url => *foundation.URL,
+ .name => *foundation.String,
+ .display_name => *foundation.String,
+ .family_name => *foundation.String,
+ .style_name => *foundation.String,
+ .traits => *foundation.Dictionary,
+ .variation => *foundation.Dictionary,
+ .size => *foundation.Number,
+ .matrix => *anyopaque, // CFDataRef
+ .cascade_list => *foundation.Array,
+ .character_set => *anyopaque, // CFCharacterSetRef
+ .languages => *foundation.Array,
+ .baseline_adjust => *foundation.Number,
+ .macintosh_encodings => *foundation.Number,
+ .features => *foundation.Array,
+ .feature_settings => *foundation.Array,
+ .fixed_advance => *foundation.Number,
+ .orientation => *foundation.Number,
+ .format => *foundation.Number,
+ .registration_scope => *foundation.Number,
+ .priority => *foundation.Number,
+ .enabled => *foundation.Number,
+ .downloadable => *anyopaque, // CFBoolean
+ .downloaded => *anyopaque, // CFBoolean
+ .variation_axes => *foundation.Array,
+ };
+ }
+};
+
+pub const FontTraitKey = enum {
+ symbolic,
+ weight,
+ width,
+ slant,
+
+ pub fn key(self: FontTraitKey) *foundation.String {
+ return @as(*foundation.String, @ptrFromInt(@intFromPtr(switch (self) {
+ .symbolic => c.kCTFontSymbolicTrait,
+ .weight => c.kCTFontWeightTrait,
+ .width => c.kCTFontWidthTrait,
+ .slant => c.kCTFontSlantTrait,
+ })));
+ }
+
+ pub fn Value(self: FontTraitKey) type {
+ return switch (self) {
+ .symbolic => *foundation.Number,
+ .weight => *foundation.Number,
+ .width => *foundation.Number,
+ .slant => *foundation.Number,
+ };
+ }
+};
+
+// https://developer.apple.com/documentation/coretext/ctfont/font_variation_axis_dictionary_keys?language=objc
+pub const FontVariationAxisKey = enum {
+ identifier,
+ minimum_value,
+ maximum_value,
+ default_value,
+ name,
+ hidden,
+
+ pub fn key(self: FontVariationAxisKey) *foundation.String {
+ return @as(*foundation.String, @ptrFromInt(@intFromPtr(switch (self) {
+ .identifier => c.kCTFontVariationAxisIdentifierKey,
+ .minimum_value => c.kCTFontVariationAxisMinimumValueKey,
+ .maximum_value => c.kCTFontVariationAxisMaximumValueKey,
+ .default_value => c.kCTFontVariationAxisDefaultValueKey,
+ .name => c.kCTFontVariationAxisNameKey,
+ .hidden => c.kCTFontVariationAxisHiddenKey,
+ })));
+ }
+
+ pub fn Value(comptime self: FontVariationAxisKey) type {
+ return switch (self) {
+ .identifier => foundation.Number,
+ .minimum_value => foundation.Number,
+ .maximum_value => foundation.Number,
+ .default_value => foundation.Number,
+ .name => foundation.String,
+ .hidden => foundation.Number,
+ };
+ }
+};
+
+pub const FontSymbolicTraits = packed struct(u32) {
+ italic: bool = false,
+ bold: bool = false,
+ _unused1: u3 = 0,
+ expanded: bool = false,
+ condensed: bool = false,
+ _unused2: u3 = 0,
+ monospace: bool = false,
+ vertical: bool = false,
+ ui_optimized: bool = false,
+ color_glyphs: bool = false,
+ composite: bool = false,
+ _padding: u17 = 0,
+
+ pub fn init(num: *foundation.Number) FontSymbolicTraits {
+ var raw: i32 = undefined;
+ _ = num.getValue(.sint32, &raw);
+ return @as(FontSymbolicTraits, @bitCast(raw));
+ }
+
+ test {
+ try std.testing.expectEqual(
+ @bitSizeOf(c.CTFontSymbolicTraits),
+ @bitSizeOf(FontSymbolicTraits),
+ );
+ }
+
+ test "bitcast" {
+ const actual: c.CTFontSymbolicTraits = c.kCTFontTraitMonoSpace | c.kCTFontTraitExpanded;
+ const expected: FontSymbolicTraits = .{
+ .monospace = true,
+ .expanded = true,
+ };
+
+ try std.testing.expectEqual(actual, @as(c.CTFontSymbolicTraits, @bitCast(expected)));
+ }
+
+ test "number" {
+ const raw: i32 = c.kCTFontTraitMonoSpace | c.kCTFontTraitExpanded;
+ const num = try foundation.Number.create(.sint32, &raw);
+ defer num.release();
+
+ const expected: FontSymbolicTraits = .{ .monospace = true, .expanded = true };
+ const actual = FontSymbolicTraits.init(num);
+ try std.testing.expect(std.meta.eql(expected, actual));
+ }
+};
+
+test {
+ @import("std").testing.refAllDecls(@This());
+}
+
+test "descriptor" {
+ const testing = std.testing;
+
+ const name = try foundation.String.createWithBytes("foo", .utf8, false);
+ defer name.release();
+
+ const v = try FontDescriptor.createWithNameAndSize(name, 12);
+ defer v.release();
+
+ const copy_name = v.copyAttribute(.name).?;
+ defer copy_name.release();
+
+ {
+ var buf: [128]u8 = undefined;
+ const cstr = copy_name.cstring(&buf, .utf8).?;
+ try testing.expectEqualStrings("foo", cstr);
+ }
+}
diff --git a/vendor/libghostty-vt/pkg/macos/text/font_manager.zig b/vendor/libghostty-vt/pkg/macos/text/font_manager.zig
new file mode 100644
index 00000000..988da122
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/text/font_manager.zig
@@ -0,0 +1,23 @@
+const std = @import("std");
+const Allocator = std.mem.Allocator;
+const foundation = @import("../foundation.zig");
+const FontDescriptor = @import("./font_descriptor.zig").FontDescriptor;
+const c = @import("c.zig").c;
+
+pub fn createFontDescriptorsFromURL(url: *foundation.URL) ?*foundation.Array {
+ return @ptrFromInt(@intFromPtr(c.CTFontManagerCreateFontDescriptorsFromURL(
+ @ptrCast(url),
+ )));
+}
+
+pub fn createFontDescriptorsFromData(data: *foundation.Data) ?*foundation.Array {
+ return @ptrFromInt(@intFromPtr(c.CTFontManagerCreateFontDescriptorsFromData(
+ @ptrCast(data),
+ )));
+}
+
+pub fn createFontDescriptorFromData(data: *foundation.Data) ?*FontDescriptor {
+ return @ptrFromInt(@intFromPtr(c.CTFontManagerCreateFontDescriptorFromData(
+ @ptrCast(data),
+ )));
+}
diff --git a/vendor/libghostty-vt/pkg/macos/text/frame.zig b/vendor/libghostty-vt/pkg/macos/text/frame.zig
new file mode 100644
index 00000000..979134a1
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/text/frame.zig
@@ -0,0 +1,33 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const Allocator = std.mem.Allocator;
+const foundation = @import("../foundation.zig");
+const graphics = @import("../graphics.zig");
+const text = @import("../text.zig");
+const c = @import("c.zig").c;
+
+pub const Frame = opaque {
+ pub fn release(self: *Frame) void {
+ foundation.CFRelease(self);
+ }
+
+ pub fn getLineOrigins(
+ self: *Frame,
+ range: foundation.Range,
+ points: []graphics.Point,
+ ) void {
+ c.CTFrameGetLineOrigins(
+ @ptrCast(self),
+ @bitCast(range),
+ @ptrCast(points.ptr),
+ );
+ }
+
+ pub fn getLines(self: *Frame) *foundation.Array {
+ return @ptrFromInt(@intFromPtr(c.CTFrameGetLines(@ptrCast(self))));
+ }
+};
+
+test {
+ // See framesetter tests...
+}
diff --git a/vendor/libghostty-vt/pkg/macos/text/framesetter.zig b/vendor/libghostty-vt/pkg/macos/text/framesetter.zig
new file mode 100644
index 00000000..dbd82762
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/text/framesetter.zig
@@ -0,0 +1,66 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const Allocator = std.mem.Allocator;
+const foundation = @import("../foundation.zig");
+const graphics = @import("../graphics.zig");
+const text = @import("../text.zig");
+const c = @import("c.zig").c;
+
+pub const Framesetter = opaque {
+ pub fn createWithAttributedString(str: *foundation.AttributedString) Allocator.Error!*Framesetter {
+ return @as(
+ ?*Framesetter,
+ @ptrFromInt(@intFromPtr(c.CTFramesetterCreateWithAttributedString(
+ @ptrCast(str),
+ ))),
+ ) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn release(self: *Framesetter) void {
+ foundation.CFRelease(self);
+ }
+
+ pub fn createFrame(
+ self: *Framesetter,
+ range: foundation.Range,
+ path: *graphics.Path,
+ attrs: ?*foundation.Dictionary,
+ ) !*text.Frame {
+ return @as(
+ ?*text.Frame,
+ @ptrFromInt(@intFromPtr(c.CTFramesetterCreateFrame(
+ @ptrCast(self),
+ @bitCast(range),
+ @ptrCast(path),
+ @ptrCast(attrs),
+ ))),
+ ) orelse error.FrameCreateFailed;
+ }
+};
+
+test {
+ const str = try foundation.MutableAttributedString.create(0);
+ defer str.release();
+ {
+ const rep = try foundation.String.createWithBytes("hello", .utf8, false);
+ defer rep.release();
+ str.replaceString(foundation.Range.init(0, 0), rep);
+ }
+
+ const fs = try Framesetter.createWithAttributedString(@ptrCast(str));
+ defer fs.release();
+
+ const path = try graphics.Path.createWithRect(graphics.Rect.init(0, 0, 100, 200), null);
+ defer path.release();
+ const frame = try fs.createFrame(
+ foundation.Range.init(0, 0),
+ path,
+ null,
+ );
+ defer frame.release();
+
+ {
+ var points: [1]graphics.Point = undefined;
+ frame.getLineOrigins(foundation.Range.init(0, 1), &points);
+ }
+}
diff --git a/vendor/libghostty-vt/pkg/macos/text/line.zig b/vendor/libghostty-vt/pkg/macos/text/line.zig
new file mode 100644
index 00000000..248f8e64
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/text/line.zig
@@ -0,0 +1,123 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const Allocator = std.mem.Allocator;
+const foundation = @import("../foundation.zig");
+const graphics = @import("../graphics.zig");
+const text = @import("../text.zig");
+const c = @import("c.zig").c;
+
+pub const Line = opaque {
+ pub fn createWithAttributedString(str: *foundation.AttributedString) Allocator.Error!*Line {
+ return @as(
+ ?*Line,
+ @ptrFromInt(@intFromPtr(c.CTLineCreateWithAttributedString(
+ @ptrCast(str),
+ ))),
+ ) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn release(self: *Line) void {
+ foundation.CFRelease(self);
+ }
+
+ pub fn getGlyphCount(self: *Line) usize {
+ return @intCast(c.CTLineGetGlyphCount(
+ @ptrCast(self),
+ ));
+ }
+
+ pub fn getBoundsWithOptions(
+ self: *Line,
+ opts: LineBoundsOptions,
+ ) graphics.Rect {
+ return @bitCast(c.CTLineGetBoundsWithOptions(
+ @ptrCast(self),
+ @bitCast(opts),
+ ));
+ }
+
+ pub fn getTypographicBounds(
+ self: *Line,
+ ascent: ?*f64,
+ descent: ?*f64,
+ leading: ?*f64,
+ ) f64 {
+ return c.CTLineGetTypographicBounds(
+ @ptrCast(self),
+ ascent,
+ descent,
+ leading,
+ );
+ }
+
+ pub fn getGlyphRuns(self: *Line) *foundation.Array {
+ return @ptrCast(@constCast(c.CTLineGetGlyphRuns(@ptrCast(self))));
+ }
+};
+
+pub const LineBoundsOptions = packed struct {
+ exclude_leading: bool = false,
+ exclude_shifts: bool = false,
+ hanging_punctuation: bool = false,
+ glyph_path_bounds: bool = false,
+ use_optical_bounds: bool = false,
+ language_extents: bool = false,
+ _padding: u58 = 0,
+
+ test {
+ try std.testing.expectEqual(
+ @bitSizeOf(c.CTLineBoundsOptions),
+ @bitSizeOf(LineBoundsOptions),
+ );
+ }
+
+ test "bitcast" {
+ const actual: c.CTLineBoundsOptions = c.kCTLineBoundsExcludeTypographicShifts |
+ c.kCTLineBoundsUseOpticalBounds;
+ const expected: LineBoundsOptions = .{
+ .exclude_shifts = true,
+ .use_optical_bounds = true,
+ };
+
+ try std.testing.expectEqual(actual, @as(c.CTLineBoundsOptions, @bitCast(expected)));
+ }
+};
+
+test {
+ @import("std").testing.refAllDecls(@This());
+}
+
+test "line" {
+ const testing = std.testing;
+
+ const font = font: {
+ const name = try foundation.String.createWithBytes("Monaco", .utf8, false);
+ defer name.release();
+ const desc = try text.FontDescriptor.createWithNameAndSize(name, 12);
+ defer desc.release();
+
+ break :font try text.Font.createWithFontDescriptor(desc, 12);
+ };
+ defer font.release();
+
+ const rep = try foundation.String.createWithBytes("hello", .utf8, false);
+ defer rep.release();
+ const str = try foundation.MutableAttributedString.create(rep.getLength());
+ defer str.release();
+ str.replaceString(foundation.Range.init(0, 0), rep);
+ str.setAttribute(
+ foundation.Range.init(0, rep.getLength()),
+ text.StringAttribute.font,
+ font,
+ );
+
+ const line = try Line.createWithAttributedString(@as(*foundation.AttributedString, @ptrCast(str)));
+ defer line.release();
+
+ try testing.expectEqual(@as(usize, 5), line.getGlyphCount());
+
+ // TODO: this is a garbage value but should work...
+ const bounds = line.getBoundsWithOptions(.{});
+ _ = bounds;
+ //std.log.warn("bounds={}", .{bounds});
+}
diff --git a/vendor/libghostty-vt/pkg/macos/text/paragraph_style.zig b/vendor/libghostty-vt/pkg/macos/text/paragraph_style.zig
new file mode 100644
index 00000000..f1d7fe95
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/text/paragraph_style.zig
@@ -0,0 +1,49 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const Allocator = std.mem.Allocator;
+const foundation = @import("../foundation.zig");
+const graphics = @import("../graphics.zig");
+const text = @import("../text.zig");
+const c = @import("c.zig").c;
+
+// https://developer.apple.com/documentation/coretext/ctparagraphstyle?language=objc
+pub const ParagraphStyle = opaque {
+ pub fn create(
+ settings: []const ParagraphStyleSetting,
+ ) Allocator.Error!*ParagraphStyle {
+ return @ptrCast(@constCast(c.CTParagraphStyleCreate(
+ @ptrCast(settings.ptr),
+ settings.len,
+ )));
+ }
+
+ pub fn release(self: *ParagraphStyle) void {
+ foundation.CFRelease(self);
+ }
+};
+
+/// https://developer.apple.com/documentation/coretext/ctparagraphstylesetting?language=objc
+pub const ParagraphStyleSetting = extern struct {
+ spec: ParagraphStyleSpecifier,
+ value_size: usize,
+ value: *const anyopaque,
+};
+
+/// https://developer.apple.com/documentation/coretext/ctparagraphstylespecifier?language=objc
+pub const ParagraphStyleSpecifier = enum(c_uint) {
+ base_writing_direction = 13,
+};
+
+/// https://developer.apple.com/documentation/uikit/nswritingdirectionattributename?language=objc
+pub const WritingDirection = enum(c_int) {
+ natural = -1,
+ ltr = 0,
+ rtl = 1,
+ lro = 2,
+ rlo = 3,
+};
+
+test ParagraphStyle {
+ const p = try ParagraphStyle.create(&.{});
+ defer p.release();
+}
diff --git a/vendor/libghostty-vt/pkg/macos/text/run.zig b/vendor/libghostty-vt/pkg/macos/text/run.zig
new file mode 100644
index 00000000..2895bfe3
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/text/run.zig
@@ -0,0 +1,117 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const Allocator = std.mem.Allocator;
+const foundation = @import("../foundation.zig");
+const graphics = @import("../graphics.zig");
+const text = @import("../text.zig");
+const c = @import("c.zig").c;
+
+pub const Run = opaque {
+ pub fn release(self: *Run) void {
+ foundation.CFRelease(self);
+ }
+
+ pub fn getGlyphCount(self: *Run) usize {
+ return @intCast(c.CTRunGetGlyphCount(@ptrCast(self)));
+ }
+
+ pub fn getGlyphsPtr(self: *Run) ?[]const graphics.Glyph {
+ const len = self.getGlyphCount();
+ if (len == 0) return &.{};
+ const ptr: [*c]const graphics.Glyph = @ptrCast(
+ c.CTRunGetGlyphsPtr(@ptrCast(self)),
+ );
+ if (ptr == null) return null;
+ return ptr[0..len];
+ }
+
+ pub fn getGlyphs(self: *Run, alloc: Allocator) ![]const graphics.Glyph {
+ const len = self.getGlyphCount();
+ const ptr = try alloc.alloc(graphics.Glyph, len);
+ errdefer alloc.free(ptr);
+ c.CTRunGetGlyphs(
+ @ptrCast(self),
+ .{ .location = 0, .length = 0 },
+ @ptrCast(ptr.ptr),
+ );
+ return ptr;
+ }
+
+ pub fn getPositionsPtr(self: *Run) ?[]const graphics.Point {
+ const len = self.getGlyphCount();
+ if (len == 0) return &.{};
+ const ptr: [*c]const graphics.Point = @ptrCast(
+ c.CTRunGetPositionsPtr(@ptrCast(self)),
+ );
+ if (ptr == null) return null;
+ return ptr[0..len];
+ }
+
+ pub fn getPositions(self: *Run, alloc: Allocator) ![]const graphics.Point {
+ const len = self.getGlyphCount();
+ const ptr = try alloc.alloc(graphics.Point, len);
+ errdefer alloc.free(ptr);
+ c.CTRunGetPositions(
+ @ptrCast(self),
+ .{ .location = 0, .length = 0 },
+ @ptrCast(ptr.ptr),
+ );
+ return ptr;
+ }
+
+ pub fn getAdvancesPtr(self: *Run) ?[]const graphics.Size {
+ const len = self.getGlyphCount();
+ if (len == 0) return &.{};
+ const ptr: [*c]const graphics.Size = @ptrCast(
+ c.CTRunGetAdvancesPtr(@ptrCast(self)),
+ );
+ if (ptr == null) return null;
+ return ptr[0..len];
+ }
+
+ pub fn getAdvances(self: *Run, alloc: Allocator) ![]const graphics.Size {
+ const len = self.getGlyphCount();
+ const ptr = try alloc.alloc(graphics.Size, len);
+ errdefer alloc.free(ptr);
+ c.CTRunGetAdvances(
+ @ptrCast(self),
+ .{ .location = 0, .length = 0 },
+ @ptrCast(ptr.ptr),
+ );
+ return ptr;
+ }
+
+ pub fn getStringIndicesPtr(self: *Run) ?[]const usize {
+ const len = self.getGlyphCount();
+ if (len == 0) return &.{};
+ const ptr: [*c]const usize = @ptrCast(
+ c.CTRunGetStringIndicesPtr(@ptrCast(self)),
+ );
+ if (ptr == null) return null;
+ return ptr[0..len];
+ }
+
+ pub fn getStringIndices(self: *Run, alloc: Allocator) ![]const usize {
+ const len = self.getGlyphCount();
+ const ptr = try alloc.alloc(usize, len);
+ errdefer alloc.free(ptr);
+ c.CTRunGetStringIndices(
+ @ptrCast(self),
+ .{ .location = 0, .length = 0 },
+ @ptrCast(ptr.ptr),
+ );
+ return ptr;
+ }
+
+ pub fn getStatus(self: *Run) Status {
+ return @bitCast(c.CTRunGetStatus(@ptrCast(self)));
+ }
+};
+
+/// https://developer.apple.com/documentation/coretext/ctrunstatus?language=objc
+pub const Status = packed struct(u32) {
+ right_to_left: bool,
+ non_monotonic: bool,
+ has_non_identity_matrix: bool,
+ _pad: u29 = 0,
+};
diff --git a/vendor/libghostty-vt/pkg/macos/text/stylized_strings.zig b/vendor/libghostty-vt/pkg/macos/text/stylized_strings.zig
new file mode 100644
index 00000000..8e262f9a
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/text/stylized_strings.zig
@@ -0,0 +1,16 @@
+const foundation = @import("../foundation.zig");
+const c = @import("c.zig").c;
+
+pub const StringAttribute = enum {
+ font,
+ paragraph_style,
+ writing_direction,
+
+ pub fn key(self: StringAttribute) *foundation.String {
+ return @ptrFromInt(@intFromPtr(switch (self) {
+ .font => c.kCTFontAttributeName,
+ .paragraph_style => c.kCTParagraphStyleAttributeName,
+ .writing_direction => c.kCTWritingDirectionAttributeName,
+ }));
+ }
+};
diff --git a/vendor/libghostty-vt/pkg/macos/text/typesetter.zig b/vendor/libghostty-vt/pkg/macos/text/typesetter.zig
new file mode 100644
index 00000000..dc07df98
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/text/typesetter.zig
@@ -0,0 +1,36 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const Allocator = std.mem.Allocator;
+const foundation = @import("../foundation.zig");
+const graphics = @import("../graphics.zig");
+const text = @import("../text.zig");
+const c = @import("c.zig").c;
+
+pub const Typesetter = opaque {
+ pub fn createWithAttributedStringAndOptions(
+ str: *foundation.AttributedString,
+ opts: *foundation.Dictionary,
+ ) Allocator.Error!*Typesetter {
+ return @as(
+ ?*Typesetter,
+ @ptrFromInt(@intFromPtr(c.CTTypesetterCreateWithAttributedStringAndOptions(
+ @ptrCast(str),
+ @ptrCast(opts),
+ ))),
+ ) orelse Allocator.Error.OutOfMemory;
+ }
+
+ pub fn release(self: *Typesetter) void {
+ foundation.CFRelease(self);
+ }
+
+ pub fn createLine(
+ self: *Typesetter,
+ range: foundation.c.CFRange,
+ ) *text.Line {
+ return @ptrFromInt(@intFromPtr(c.CTTypesetterCreateLine(
+ @ptrCast(self),
+ range,
+ )));
+ }
+};
diff --git a/vendor/libghostty-vt/pkg/macos/video.zig b/vendor/libghostty-vt/pkg/macos/video.zig
new file mode 100644
index 00000000..d0b1125a
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/video.zig
@@ -0,0 +1,10 @@
+const display_link = @import("video/display_link.zig");
+const pixel_format = @import("video/pixel_format.zig");
+
+pub const c = @import("video/c.zig").c;
+pub const DisplayLink = display_link.DisplayLink;
+pub const PixelFormat = pixel_format.PixelFormat;
+
+test {
+ @import("std").testing.refAllDecls(@This());
+}
diff --git a/vendor/libghostty-vt/pkg/macos/video/c.zig b/vendor/libghostty-vt/pkg/macos/video/c.zig
new file mode 100644
index 00000000..1a7d1627
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/video/c.zig
@@ -0,0 +1 @@
+pub const c = @import("../main.zig").c;
diff --git a/vendor/libghostty-vt/pkg/macos/video/display_link.zig b/vendor/libghostty-vt/pkg/macos/video/display_link.zig
new file mode 100644
index 00000000..7d6b437f
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/video/display_link.zig
@@ -0,0 +1,86 @@
+const std = @import("std");
+const assert = std.debug.assert;
+const Allocator = std.mem.Allocator;
+const c = @import("c.zig").c;
+
+pub const DisplayLink = opaque {
+ pub const Error = error{
+ InvalidOperation,
+ };
+
+ pub fn createWithActiveCGDisplays() Allocator.Error!*DisplayLink {
+ var result: ?*DisplayLink = null;
+ if (c.CVDisplayLinkCreateWithActiveCGDisplays(
+ @ptrCast(&result),
+ ) != c.kCVReturnSuccess)
+ return error.OutOfMemory;
+
+ return result orelse error.OutOfMemory;
+ }
+
+ pub fn release(self: *DisplayLink) void {
+ c.CVDisplayLinkRelease(@ptrCast(self));
+ }
+
+ pub fn start(self: *DisplayLink) Error!void {
+ if (c.CVDisplayLinkStart(@ptrCast(self)) != c.kCVReturnSuccess)
+ return error.InvalidOperation;
+ }
+
+ pub fn stop(self: *DisplayLink) Error!void {
+ if (c.CVDisplayLinkStop(@ptrCast(self)) != c.kCVReturnSuccess)
+ return error.InvalidOperation;
+ }
+
+ pub fn isRunning(self: *DisplayLink) bool {
+ return c.CVDisplayLinkIsRunning(@ptrCast(self)) != 0;
+ }
+
+ pub fn setCurrentCGDisplay(
+ self: *DisplayLink,
+ display_id: c.CGDirectDisplayID,
+ ) Error!void {
+ if (c.CVDisplayLinkSetCurrentCGDisplay(
+ @ptrCast(self),
+ display_id,
+ ) != c.kCVReturnSuccess)
+ return error.InvalidOperation;
+ }
+
+ // Note: this purposely throws away a ton of arguments I didn't need.
+ // It would be trivial to refactor this into Zig types and properly
+ // pass this through.
+ pub fn setOutputCallback(
+ self: *DisplayLink,
+ comptime Userdata: type,
+ comptime callbackFn: *const fn (*DisplayLink, ?*Userdata) void,
+ userinfo: ?*Userdata,
+ ) Error!void {
+ if (c.CVDisplayLinkSetOutputCallback(
+ @ptrCast(self),
+ @ptrCast(&(struct {
+ fn callback(
+ displayLink: *DisplayLink,
+ inNow: *const c.CVTimeStamp,
+ inOutputTime: *const c.CVTimeStamp,
+ flagsIn: c.CVOptionFlags,
+ flagsOut: *c.CVOptionFlags,
+ inner_userinfo: ?*anyopaque,
+ ) callconv(.c) c.CVReturn {
+ _ = inNow;
+ _ = inOutputTime;
+ _ = flagsIn;
+ _ = flagsOut;
+
+ callbackFn(
+ displayLink,
+ @ptrCast(@alignCast(inner_userinfo)),
+ );
+ return c.kCVReturnSuccess;
+ }
+ }).callback),
+ userinfo,
+ ) != c.kCVReturnSuccess)
+ return error.InvalidOperation;
+ }
+};
diff --git a/vendor/libghostty-vt/pkg/macos/video/pixel_format.zig b/vendor/libghostty-vt/pkg/macos/video/pixel_format.zig
new file mode 100644
index 00000000..78091daa
--- /dev/null
+++ b/vendor/libghostty-vt/pkg/macos/video/pixel_format.zig
@@ -0,0 +1,171 @@
+const c = @import("c.zig").c;
+
+pub const PixelFormat = enum(c_int) {
+ /// 1 bit indexed
+ @"1Monochrome" = c.kCVPixelFormatType_1Monochrome,
+ /// 2 bit indexed
+ @"2Indexed" = c.kCVPixelFormatType_2Indexed,
+ /// 4 bit indexed
+ @"4Indexed" = c.kCVPixelFormatType_4Indexed,
+ /// 8 bit indexed
+ @"8Indexed" = c.kCVPixelFormatType_8Indexed,
+ /// 1 bit indexed gray, white is zero
+ @"1IndexedGray_WhiteIsZero" = c.kCVPixelFormatType_1IndexedGray_WhiteIsZero,
+ /// 2 bit indexed gray, white is zero
+ @"2IndexedGray_WhiteIsZero" = c.kCVPixelFormatType_2IndexedGray_WhiteIsZero,
+ /// 4 bit indexed gray, white is zero
+ @"4IndexedGray_WhiteIsZero" = c.kCVPixelFormatType_4IndexedGray_WhiteIsZero,
+ /// 8 bit indexed gray, white is zero
+ @"8IndexedGray_WhiteIsZero" = c.kCVPixelFormatType_8IndexedGray_WhiteIsZero,
+ /// 16 bit BE RGB 555
+ @"16BE555" = c.kCVPixelFormatType_16BE555,
+ /// 16 bit LE RGB 555
+ @"16LE555" = c.kCVPixelFormatType_16LE555,
+ /// 16 bit LE RGB 5551
+ @"16LE5551" = c.kCVPixelFormatType_16LE5551,
+ /// 16 bit BE RGB 565
+ @"16BE565" = c.kCVPixelFormatType_16BE565,
+ /// 16 bit LE RGB 565
+ @"16LE565" = c.kCVPixelFormatType_16LE565,
+ /// 24 bit RGB
+ @"24RGB" = c.kCVPixelFormatType_24RGB,
+ /// 24 bit BGR
+ @"24BGR" = c.kCVPixelFormatType_24BGR,
+ /// 32 bit ARGB
+ @"32ARGB" = c.kCVPixelFormatType_32ARGB,
+ /// 32 bit BGRA
+ @"32BGRA" = c.kCVPixelFormatType_32BGRA,
+ /// 32 bit ABGR
+ @"32ABGR" = c.kCVPixelFormatType_32ABGR,
+ /// 32 bit RGBA
+ @"32RGBA" = c.kCVPixelFormatType_32RGBA,
+ /// 64 bit ARGB, 16-bit big-endian samples
+ @"64ARGB" = c.kCVPixelFormatType_64ARGB,
+ /// 64 bit RGBA, 16-bit little-endian full-range (0-65535) samples
+ @"64RGBALE" = c.kCVPixelFormatType_64RGBALE,
+ /// 48 bit RGB, 16-bit big-endian samples
+ @"48RGB" = c.kCVPixelFormatType_48RGB,
+ /// 32 bit AlphaGray, 16-bit big-endian samples, black is zero
+ @"32AlphaGray" = c.kCVPixelFormatType_32AlphaGray,
+ /// 16 bit Grayscale, 16-bit big-endian samples, black is zero
+ @"16Gray" = c.kCVPixelFormatType_16Gray,
+ /// 30 bit RGB, 10-bit big-endian samples, 2 unused padding bits (at least significant end).
+ @"30RGB" = c.kCVPixelFormatType_30RGB,
+ /// 30 bit RGB, 10-bit big-endian samples, 2 unused padding bits (at most significant end), video-range (64-940).
+ @"30RGB_r210" = c.kCVPixelFormatType_30RGB_r210,
+ /// Component Y'CbCr 8-bit 4:2:2, ordered Cb Y'0 Cr Y'1
+ @"422YpCbCr8" = c.kCVPixelFormatType_422YpCbCr8,
+ /// Component Y'CbCrA 8-bit 4:4:4:4, ordered Cb Y' Cr A
+ @"4444YpCbCrA8" = c.kCVPixelFormatType_4444YpCbCrA8,
+ /// Component Y'CbCrA 8-bit 4:4:4:4, rendering format. full range alpha, zero biased YUV, ordered A Y' Cb Cr
+ @"4444YpCbCrA8R" = c.kCVPixelFormatType_4444YpCbCrA8R,
+ /// Component Y'CbCrA 8-bit 4:4:4:4, ordered A Y' Cb Cr, full range alpha, video range Y'CbCr.
+ @"4444AYpCbCr8" = c.kCVPixelFormatType_4444AYpCbCr8,
+ /// Component Y'CbCrA 16-bit 4:4:4:4, ordered A Y' Cb Cr, full range alpha, video range Y'CbCr, 16-bit little-endian samples.
+ @"4444AYpCbCr16" = c.kCVPixelFormatType_4444AYpCbCr16,
+ /// Component AY'CbCr single precision floating-point 4:4:4:4
+ @"4444AYpCbCrFloat" = c.kCVPixelFormatType_4444AYpCbCrFloat,
+ /// Component Y'CbCr 8-bit 4:4:4, ordered Cr Y' Cb, video range Y'CbCr
+ @"444YpCbCr8" = c.kCVPixelFormatType_444YpCbCr8,
+ /// Component Y'CbCr 10,12,14,16-bit 4:2:2
+ @"422YpCbCr16" = c.kCVPixelFormatType_422YpCbCr16,
+ /// Component Y'CbCr 10-bit 4:2:2
+ @"422YpCbCr10" = c.kCVPixelFormatType_422YpCbCr10,
+ /// Component Y'CbCr 10-bit 4:4:4
+ @"444YpCbCr10" = c.kCVPixelFormatType_444YpCbCr10,
+ /// Planar Component Y'CbCr 8-bit 4:2:0. baseAddr points to a big-endian CVPlanarPixelBufferInfo_YCbCrPlanar struct
+ @"420YpCbCr8Planar" = c.kCVPixelFormatType_420YpCbCr8Planar,
+ /// Planar Component Y'CbCr 8-bit 4:2:0, full range. baseAddr points to a big-endian CVPlanarPixelBufferInfo_YCbCrPlanar struct
+ @"420YpCbCr8PlanarFullRange" = c.kCVPixelFormatType_420YpCbCr8PlanarFullRange,
+ /// First plane: Video-range Component Y'CbCr 8-bit 4:2:2, ordered Cb Y'0 Cr Y'1; second plane: alpha 8-bit 0-255
+ @"422YpCbCr_4A_8BiPlanar" = c.kCVPixelFormatType_422YpCbCr_4A_8BiPlanar,
+ /// Bi-Planar Component Y'CbCr 8-bit 4:2:0, video-range (luma=[16,235] chroma=[16,240]). baseAddr points to a big-endian CVPlanarPixelBufferInfo_YCbCrBiPlanar struct
+ @"420YpCbCr8BiPlanarVideoRange" = c.kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange,
+ /// Bi-Planar Component Y'CbCr 8-bit 4:2:0, full-range (luma=[0,255] chroma=[1,255]). baseAddr points to a big-endian CVPlanarPixelBufferInfo_YCbCrBiPlanar struct
+ @"420YpCbCr8BiPlanarFullRange" = c.kCVPixelFormatType_420YpCbCr8BiPlanarFullRange,
+ /// Bi-Planar Component Y'CbCr 8-bit 4:2:2, video-range (luma=[16,235] chroma=[16,240]). baseAddr points to a big-endian CVPlanarPixelBufferInfo_YCbCrBiPlanar struct
+ @"422YpCbCr8BiPlanarVideoRange" = c.kCVPixelFormatType_422YpCbCr8BiPlanarVideoRange,
+ /// Bi-Planar Component Y'CbCr 8-bit 4:2:2, full-range (luma=[0,255] chroma=[1,255]). baseAddr points to a big-endian CVPlanarPixelBufferInfo_YCbCrBiPlanar struct
+ @"422YpCbCr8BiPlanarFullRange" = c.kCVPixelFormatType_422YpCbCr8BiPlanarFullRange,
+ /// Bi-Planar Component Y'CbCr 8-bit 4:4:4, video-range (luma=[16,235] chroma=[16,240]). baseAddr points to a big-endian CVPlanarPixelBufferInfo_YCbCrBiPlanar struct
+ @"444YpCbCr8BiPlanarVideoRange" = c.kCVPixelFormatType_444YpCbCr8BiPlanarVideoRange,
+ /// Bi-Planar Component Y'CbCr 8-bit 4:4:4, full-range (luma=[0,255] chroma=[1,255]). baseAddr points to a big-endian CVPlanarPixelBufferInfo_YCbCrBiPlanar struct
+ @"444YpCbCr8BiPlanarFullRange" = c.kCVPixelFormatType_444YpCbCr8BiPlanarFullRange,
+ /// Component Y'CbCr 8-bit 4:2:2, ordered Y'0 Cb Y'1 Cr
+ @"422YpCbCr8_yuvs" = c.kCVPixelFormatType_422YpCbCr8_yuvs,
+ /// Component Y'CbCr 8-bit 4:2:2, full range, ordered Y'0 Cb Y'1 Cr
+ @"422YpCbCr8FullRange" = c.kCVPixelFormatType_422YpCbCr8FullRange,
+ /// 8 bit one component, black is zero
+ OneComponent8 = c.kCVPixelFormatType_OneComponent8,
+ /// 8 bit two component, black is zero
+ TwoComponent8 = c.kCVPixelFormatType_TwoComponent8,
+ /// little-endian RGB101010, 2 MSB are ignored, wide-gamut (384-895)
+ @"30RGBLEPackedWideGamut" = c.kCVPixelFormatType_30RGBLEPackedWideGamut,
+ /// little-endian ARGB2101010 full-range ARGB
+ ARGB2101010LEPacked = c.kCVPixelFormatType_ARGB2101010LEPacked,
+ /// little-endian ARGB10101010, each 10 bits in the MSBs of 16bits, wide-gamut (384-895, including alpha)
+ @"40ARGBLEWideGamut" = c.kCVPixelFormatType_40ARGBLEWideGamut,
+ /// little-endian ARGB10101010, each 10 bits in the MSBs of 16bits, wide-gamut (384-895, including alpha). Alpha premultiplied
+ @"40ARGBLEWideGamutPremultiplied" = c.kCVPixelFormatType_40ARGBLEWideGamutPremultiplied,
+ /// 10 bit little-endian one component, stored as 10 MSBs of 16 bits, black is zero
+ OneComponent10 = c.kCVPixelFormatType_OneComponent10,
+ /// 12 bit little-endian one component, stored as 12 MSBs of 16 bits, black is zero
+ OneComponent12 = c.kCVPixelFormatType_OneComponent12,
+ /// 16 bit little-endian one component, black is zero
+ OneComponent16 = c.kCVPixelFormatType_OneComponent16,
+ /// 16 bit little-endian two component, black is zero
+ TwoComponent16 = c.kCVPixelFormatType_TwoComponent16,
+ /// 16 bit one component IEEE half-precision float, 16-bit little-endian samples
+ OneComponent16Half = c.kCVPixelFormatType_OneComponent16Half,
+ /// 32 bit one component IEEE float, 32-bit little-endian samples
+ OneComponent32Float = c.kCVPixelFormatType_OneComponent32Float,
+ /// 16 bit two component IEEE half-precision float, 16-bit little-endian samples
+ TwoComponent16Half = c.kCVPixelFormatType_TwoComponent16Half,
+ /// 32 bit two component IEEE float, 32-bit little-endian samples
+ TwoComponent32Float = c.kCVPixelFormatType_TwoComponent32Float,
+ /// 64 bit RGBA IEEE half-precision float, 16-bit little-endian samples
+ @"64RGBAHalf" = c.kCVPixelFormatType_64RGBAHalf,
+ /// 128 bit RGBA IEEE float, 32-bit little-endian samples
+ @"128RGBAFloat" = c.kCVPixelFormatType_128RGBAFloat,
+ /// Bayer 14-bit Little-Endian, packed in 16-bits, ordered G R G R... alternating with B G B G...
+ @"14Bayer_GRBG" = c.kCVPixelFormatType_14Bayer_GRBG,
+ /// Bayer 14-bit Little-Endian, packed in 16-bits, ordered R G R G... alternating with G B G B...
+ @"14Bayer_RGGB" = c.kCVPixelFormatType_14Bayer_RGGB,
+ /// Bayer 14-bit Little-Endian, packed in 16-bits, ordered B G B G... alternating with G R G R...
+ @"14Bayer_BGGR" = c.kCVPixelFormatType_14Bayer_BGGR,
+ /// Bayer 14-bit Little-Endian, packed in 16-bits, ordered G B G B... alternating with R G R G...
+ @"14Bayer_GBRG" = c.kCVPixelFormatType_14Bayer_GBRG,
+ /// IEEE754-2008 binary16 (half float), describing the normalized shift when comparing two images. Units are 1/meters: ( pixelShift / (pixelFocalLength * baselineInMeters) )
+ DisparityFloat16 = c.kCVPixelFormatType_DisparityFloat16,
+ /// IEEE754-2008 binary32 float, describing the normalized shift when comparing two images. Units are 1/meters: ( pixelShift / (pixelFocalLength * baselineInMeters) )
+ DisparityFloat32 = c.kCVPixelFormatType_DisparityFloat32,
+ /// IEEE754-2008 binary16 (half float), describing the depth (distance to an object) in meters
+ DepthFloat16 = c.kCVPixelFormatType_DepthFloat16,
+ /// IEEE754-2008 binary32 float, describing the depth (distance to an object) in meters
+ DepthFloat32 = c.kCVPixelFormatType_DepthFloat32,
+ /// 2 plane YCbCr10 4:2:0, each 10 bits in the MSBs of 16bits, video-range (luma=[64,940] chroma=[64,960])
+ @"420YpCbCr10BiPlanarVideoRange" = c.kCVPixelFormatType_420YpCbCr10BiPlanarVideoRange,
+ /// 2 plane YCbCr10 4:2:2, each 10 bits in the MSBs of 16bits, video-range (luma=[64,940] chroma=[64,960])
+ @"422YpCbCr10BiPlanarVideoRange" = c.kCVPixelFormatType_422YpCbCr10BiPlanarVideoRange,
+ /// 2 plane YCbCr10 4:4:4, each 10 bits in the MSBs of 16bits, video-range (luma=[64,940] chroma=[64,960])
+ @"444YpCbCr10BiPlanarVideoRange" = c.kCVPixelFormatType_444YpCbCr10BiPlanarVideoRange,
+ /// 2 plane YCbCr10 4:2:0, each 10 bits in the MSBs of 16bits, full-range (Y range 0-1023)
+ @"420YpCbCr10BiPlanarFullRange" = c.kCVPixelFormatType_420YpCbCr10BiPlanarFullRange,
+ /// 2 plane YCbCr10 4:2:2, each 10 bits in the MSBs of 16bits, full-range (Y range 0-1023)
+ @"422YpCbCr10BiPlanarFullRange" = c.kCVPixelFormatType_422YpCbCr10BiPlanarFullRange,
+ /// 2 plane YCbCr10 4:4:4, each 10 bits in the MSBs of 16bits, full-range (Y range 0-1023)
+ @"444YpCbCr10BiPlanarFullRange" = c.kCVPixelFormatType_444YpCbCr10BiPlanarFullRange,
+ /// first and second planes as per 420YpCbCr8BiPlanarVideoRange (420v), alpha 8 bits in third plane full-range. No CVPlanarPixelBufferInfo struct.
+ @"420YpCbCr8VideoRange_8A_TriPlanar" = c.kCVPixelFormatType_420YpCbCr8VideoRange_8A_TriPlanar,
+ /// Single plane Bayer 16-bit little-endian sensor element ("sensel".*) samples from full-size decoding of ProRes RAW images; Bayer pattern (sensel ordering) and other raw conversion information is described via buffer attachments
+ @"16VersatileBayer" = c.kCVPixelFormatType_16VersatileBayer,
+ /// Single plane 64-bit RGBA (16-bit little-endian samples) from downscaled decoding of ProRes RAW images; components--which may not be co-sited with one another--are sensel values and require raw conversion, information for which is described via buffer attachments
+ @"64RGBA_DownscaledProResRAW" = c.kCVPixelFormatType_64RGBA_DownscaledProResRAW,
+ /// 2 plane YCbCr16 4:2:2, video-range (luma=[4096,60160] chroma=[4096,61440])
+ @"422YpCbCr16BiPlanarVideoRange" = c.kCVPixelFormatType_422YpCbCr16BiPlanarVideoRange,
+ /// 2 plane YCbCr16 4:4:4, video-range (luma=[4096,60160] chroma=[4096,61440])
+ @"444YpCbCr16BiPlanarVideoRange" = c.kCVPixelFormatType_444YpCbCr16BiPlanarVideoRange,
+ /// 3 plane video-range YCbCr16 4:4:4 with 16-bit full-range alpha (luma=[4096,60160] chroma=[4096,61440] alpha=[0,65535]). No CVPlanarPixelBufferInfo struct.
+ @"444YpCbCr16VideoRange_16A_TriPlanar" = c.kCVPixelFormatType_444YpCbCr16VideoRange_16A_TriPlanar,
+ _,
+};