diff --git a/pkg/macos/graphics.zig b/pkg/macos/graphics.zig index 56bdc776a..690d45e5b 100644 --- a/pkg/macos/graphics.zig +++ b/pkg/macos/graphics.zig @@ -1,4 +1,6 @@ pub const c = @import("graphics/c.zig"); +pub usingnamespace @import("graphics/affine_transform.zig"); +pub usingnamespace @import("graphics/bitmap_context.zig"); pub usingnamespace @import("graphics/color_space.zig"); pub usingnamespace @import("graphics/font.zig"); diff --git a/pkg/macos/graphics/affine_transform.zig b/pkg/macos/graphics/affine_transform.zig new file mode 100644 index 000000000..30528702e --- /dev/null +++ b/pkg/macos/graphics/affine_transform.zig @@ -0,0 +1,20 @@ +const std = @import("std"); +const assert = std.debug.assert; +const c = @import("c.zig"); + +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(AffineTransform, c.CGAffineTransformIdentity); + } + + pub fn cval(self: AffineTransform) c.struct_CGAffineTransform { + return @bitCast(c.struct_CGAffineTransform, self); + } +}; diff --git a/pkg/macos/graphics/bitmap_context.zig b/pkg/macos/graphics/bitmap_context.zig new file mode 100644 index 000000000..0516df417 --- /dev/null +++ b/pkg/macos/graphics/bitmap_context.zig @@ -0,0 +1,49 @@ +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"); + +pub const BitmapContext = opaque { + pub usingnamespace context.Context(BitmapContext); + + pub fn create( + data: ?[]u8, + width: usize, + height: usize, + bits_per_component: usize, + bytes_per_row: usize, + space: *graphics.ColorSpace, + ) Allocator.Error!*BitmapContext { + return @intToPtr( + ?*BitmapContext, + @ptrToInt(c.CGBitmapContextCreate( + @ptrCast(?*anyopaque, if (data) |d| d.ptr else null), + width, + height, + bits_per_component, + bytes_per_row, + @ptrCast(c.CGColorSpaceRef, space), + 0, + )), + ) 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); + defer ctx.release(); + + ctx.setShouldAntialias(true); + ctx.setShouldSmoothFonts(false); + ctx.setGrayFillColor(1, 1); + ctx.setGrayStrokeColor(1, 1); + ctx.setTextDrawingMode(.fill); + ctx.setTextMatrix(graphics.AffineTransform.identity()); + ctx.setTextPosition(0, 0); +} diff --git a/pkg/macos/graphics/context.zig b/pkg/macos/graphics/context.zig new file mode 100644 index 000000000..5a2f8dd3c --- /dev/null +++ b/pkg/macos/graphics/context.zig @@ -0,0 +1,85 @@ +const std = @import("std"); +const assert = std.debug.assert; +const Allocator = std.mem.Allocator; +const graphics = @import("../graphics.zig"); +const c = @import("c.zig"); + +/// Returns a struct that has all the shared context functions for the +/// given type. +pub fn Context(comptime T: type) type { + return struct { + pub fn release(self: *T) void { + c.CGContextRelease(@ptrCast(c.CGContextRef, self)); + } + + pub fn setLineWidth(self: *T, width: f64) void { + c.CGContextSetLineWidth( + @ptrCast(c.CGContextRef, self), + width, + ); + } + + pub fn setShouldAntialias(self: *T, v: bool) void { + c.CGContextSetShouldAntialias( + @ptrCast(c.CGContextRef, self), + v, + ); + } + + pub fn setShouldSmoothFonts(self: *T, v: bool) void { + c.CGContextSetShouldSmoothFonts( + @ptrCast(c.CGContextRef, self), + v, + ); + } + + pub fn setGrayFillColor(self: *T, gray: f64, alpha: f64) void { + c.CGContextSetGrayFillColor( + @ptrCast(c.CGContextRef, self), + gray, + alpha, + ); + } + + pub fn setGrayStrokeColor(self: *T, gray: f64, alpha: f64) void { + c.CGContextSetGrayStrokeColor( + @ptrCast(c.CGContextRef, self), + gray, + alpha, + ); + } + + pub fn setTextDrawingMode(self: *T, mode: TextDrawingMode) void { + c.CGContextSetTextDrawingMode( + @ptrCast(c.CGContextRef, self), + @enumToInt(mode), + ); + } + + pub fn setTextMatrix(self: *T, matrix: graphics.AffineTransform) void { + c.CGContextSetTextMatrix( + @ptrCast(c.CGContextRef, self), + matrix.cval(), + ); + } + + pub fn setTextPosition(self: *T, x: f64, y: f64) void { + c.CGContextSetTextPosition( + @ptrCast(c.CGContextRef, self), + x, + y, + ); + } + }; +} + +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, +};