diff --git a/pkg/pixman/build.zig b/pkg/pixman/build.zig index 2ec6a0da6..6f5d35648 100644 --- a/pkg/pixman/build.zig +++ b/pkg/pixman/build.zig @@ -87,6 +87,10 @@ pub fn buildPixman( "-DSIZEOF_LONG=8", "-DPACKAGE=foo", + + // There is ubsan + "-fno-sanitize=undefined", + "-fno-sanitize-trap=undefined", }); if (!target.isWindows()) { diff --git a/pkg/pixman/error.zig b/pkg/pixman/error.zig new file mode 100644 index 000000000..2fa569aed --- /dev/null +++ b/pkg/pixman/error.zig @@ -0,0 +1,4 @@ +pub const Error = error{ + // Pixman doesn't really have errors so we just have a single error. + PixmanFailure, +}; diff --git a/pkg/pixman/image.zig b/pkg/pixman/image.zig index 967701e17..9dc9d8118 100644 --- a/pkg/pixman/image.zig +++ b/pkg/pixman/image.zig @@ -3,36 +3,86 @@ const c = @import("c.zig"); const pixman = @import("main.zig"); pub const Image = opaque { - pub inline fn createBitsNoClear( + pub fn createBitsNoClear( format: pixman.FormatCode, width: c_int, height: c_int, bits: [*]u32, stride: c_int, - ) ?*Image { + ) pixman.Error!*Image { return @ptrCast(?*Image, c.pixman_image_create_bits_no_clear( @enumToInt(format), width, height, bits, stride, - )); + )) orelse return pixman.Error.PixmanFailure; } - pub inline fn unref(self: *Image) bool { + pub fn unref(self: *Image) bool { return c.pixman_image_unref(@ptrCast(*c.pixman_image_t, self)) == 1; } + + pub fn fillBoxes( + self: *Image, + op: pixman.Op, + color: pixman.Color, + boxes: []const pixman.Box32, + ) pixman.Error!void { + if (c.pixman_image_fill_boxes( + @enumToInt(op), + @ptrCast(*c.pixman_image_t, self), + @ptrCast(*const c.pixman_color_t, &color), + @intCast(c_int, boxes.len), + @ptrCast([*c]const c.pixman_box32_t, boxes.ptr), + ) == 0) return pixman.Error.PixmanFailure; + } }; test "create and destroy" { const testing = std.testing; + const alloc = testing.allocator; const width = 10; const height = 10; const format: pixman.FormatCode = .g1; const stride = format.strideForWidth(width); - var bits: [width * height]u32 = undefined; - const img = Image.createBitsNoClear(.g1, width, height, &bits, stride); - try testing.expect(img != null); - try testing.expect(img.?.unref()); + + const len = height * @intCast(usize, stride); + var data = try alloc.alloc(u32, len); + defer alloc.free(data); + std.mem.set(u32, data, 0); + const img = try Image.createBitsNoClear(.g1, width, height, data.ptr, stride); + try testing.expect(img.unref()); +} + +test "fill boxes" { + const testing = std.testing; + const alloc = testing.allocator; + + // Dimensions + const width = 100; + const height = 100; + const format: pixman.FormatCode = .a1; + const stride = format.strideForWidth(width); + + // Image + const len = height * @intCast(usize, stride); + var data = try alloc.alloc(u32, len); + defer alloc.free(data); + std.mem.set(u32, data, 0); + const img = try Image.createBitsNoClear(format, width, height, data.ptr, stride); + defer _ = img.unref(); + + // Fill + const color: pixman.Color = .{ .red = 0xFFFF, .green = 0xFFFF, .blue = 0xFFFF, .alpha = 0xFFFF }; + const boxes = &[_]pixman.Box32{ + .{ + .x1 = 0, + .y1 = 0, + .x2 = width, + .y2 = height, + }, + }; + try img.fillBoxes(.src, color, boxes); } diff --git a/pkg/pixman/main.zig b/pkg/pixman/main.zig index c14cb5c6c..864736b2c 100644 --- a/pkg/pixman/main.zig +++ b/pkg/pixman/main.zig @@ -1,7 +1,9 @@ const std = @import("std"); pub const c = @import("c.zig"); +pub usingnamespace @import("error.zig"); pub usingnamespace @import("format.zig"); pub usingnamespace @import("image.zig"); +pub usingnamespace @import("types.zig"); test { std.testing.refAllDecls(@This()); diff --git a/pkg/pixman/types.zig b/pkg/pixman/types.zig new file mode 100644 index 000000000..fef250f25 --- /dev/null +++ b/pkg/pixman/types.zig @@ -0,0 +1,76 @@ +const std = @import("std"); +const c = @import("c.zig"); +const pixman = @import("main.zig"); + +pub const Op = enum(c_uint) { + clear = 0x00, + src = 0x01, + dst = 0x02, + over = 0x03, + over_reverse = 0x04, + in = 0x05, + in_reverse = 0x06, + out = 0x07, + out_reverse = 0x08, + atop = 0x09, + atop_reverse = 0x0a, + xor = 0x0b, + add = 0x0c, + saturate = 0x0d, + + disjoint_clear = 0x10, + disjoint_src = 0x11, + disjoint_dst = 0x12, + disjoint_over = 0x13, + disjoint_over_reverse = 0x14, + disjoint_in = 0x15, + disjoint_in_reverse = 0x16, + disjoint_out = 0x17, + disjoint_out_reverse = 0x18, + disjoint_atop = 0x19, + disjoint_atop_reverse = 0x1a, + disjoint_xor = 0x1b, + + conjoint_clear = 0x20, + conjoint_src = 0x21, + conjoint_dst = 0x22, + conjoint_over = 0x23, + conjoint_over_reverse = 0x24, + conjoint_in = 0x25, + conjoint_in_reverse = 0x26, + conjoint_out = 0x27, + conjoint_out_reverse = 0x28, + conjoint_atop = 0x29, + conjoint_atop_reverse = 0x2a, + conjoint_xor = 0x2b, + + multiply = 0x30, + screen = 0x31, + overlay = 0x32, + darken = 0x33, + lighten = 0x34, + color_dodge = 0x35, + color_burn = 0x36, + hard_light = 0x37, + soft_light = 0x38, + difference = 0x39, + exclusion = 0x3a, + hsl_hue = 0x3b, + hsl_saturation = 0x3c, + hsl_color = 0x3d, + hsl_luminosity = 0x3e, +}; + +pub const Color = extern struct { + red: u16, + green: u16, + blue: u16, + alpha: u16, +}; + +pub const Box32 = extern struct { + x1: i32, + y1: i32, + x2: i32, + y2: i32, +};