aboutsummaryrefslogtreecommitdiff
path: root/vendor/libghostty-vt/pkg/macos/graphics
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/graphics
parent55c138263e190a1e79d4b997bfb9397306c0ec1f (diff)
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/pkg/macos/graphics')
-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
9 files changed, 474 insertions, 0 deletions
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();
+}