diff options
| author | Can Celik <ogulcancelik@gmail.com> | 2026-04-04 19:22:04 +0300 |
|---|---|---|
| committer | Can Celik <ogulcancelik@gmail.com> | 2026-04-05 01:23:06 +0300 |
| commit | 41dd733ca7123c9ac4bfc6c781697a660e95b052 (patch) | |
| tree | 3fc91815ca139ef2e0b281bba0abda4ef15175f4 /vendor/libghostty-vt/pkg/macos/graphics | |
| parent | 55c138263e190a1e79d4b997bfb9397306c0ec1f (diff) | |
feat: finish ghostty pane backend integration
Diffstat (limited to 'vendor/libghostty-vt/pkg/macos/graphics')
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(); +} |
