From 4f1c6d1b5888a596eb90876554c7b1d025d8f2d6 Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Tue, 20 Jul 2021 21:00:05 -0700 Subject: [PATCH] glfw: add Image type Signed-off-by: Stephen Gutekanst --- glfw/src/Image.zig | 82 ++++++++++++++++++++++++++++++++++++++++++++++ glfw/src/main.zig | 2 ++ 2 files changed, 84 insertions(+) create mode 100644 glfw/src/Image.zig diff --git a/glfw/src/Image.zig b/glfw/src/Image.zig new file mode 100644 index 00000000..07aacccf --- /dev/null +++ b/glfw/src/Image.zig @@ -0,0 +1,82 @@ +//! Image data +//! +//! +//! This describes a single 2D image. See the documentation for each related function what the +//! expected pixel format is. +//! +//! see also: cursor_custom, window_icon +//! +//! It may be .owned (e.g. in the case of an image initialized by you for passing into glfw) or not +//! .owned (e.g. in the case of one gotten via glfw) If it is .owned, deinit should be called to +//! free the memory. It is safe to call deinit even if not .owned. + +const std = @import("std"); +const testing = std.testing; +const mem = std.mem; +const c = @import("c.zig").c; + +const Image = @This(); + +/// The width of this image, in pixels. +width: usize, + +/// The height of this image, in pixels. +height: usize, + +/// The pixel data of this image, arranged left-to-right, top-to-bottom. +pixels: []u8, + +/// Whether or not the pixels data is owned by you (true) or GLFW (false). +owned: bool, + +/// Initializes a new owned image with the given size and pixel_data_len of undefined .pixel values. +pub inline fn init(allocator: *mem.Allocator, width: usize, height: usize, pixel_data_len: usize) !Image { + const buf = try allocator.alloc(u8, pixel_data_len); + return Image{ + .width = width, + .height = height, + .pixels = buf, + .owned = true, + }; +} + +/// Turns a GLFW / C image into the nicer Zig type, and sets `.owned = false`. +/// +/// The length of pixel data must be supplied, as GLFW's image type does not itself describe the +/// number of bytes required per pixel / the length of the pixel data array. +/// +/// The returned memory is valid for as long as the GLFW C memory is valid. +pub inline fn fromC(native: c.GLFWimage, pixel_data_len: usize) Image { + return Image{ + .width = @intCast(usize, native.width), + .height = @intCast(usize, native.height), + .pixels = native.pixels[0..pixel_data_len], + .owned = false, + }; +} + +/// Turns the nicer Zig type into a GLFW / C image, for passing into GLFW C functions. +/// +/// The returned memory is valid for as long as the Zig memory is valid. +pub inline fn toC(self: Image) c.GLFWimage { + return c.GLFWimage{ + .width = @intCast(c_int, self.width), + .height = @intCast(c_int, self.height), + .pixels = &self.pixels[0], + }; +} + +/// Deinitializes the memory using the allocator iff `.owned = true`. +pub inline fn deinit(self: Image, allocator: *mem.Allocator) void { + if (self.owned) allocator.free(self.pixels); +} + +test "conversion" { + const allocator = testing.allocator; + + const image = try Image.init(allocator, 256, 256, 256 * 256 * 4); + defer image.deinit(allocator); + + const glfw = image.toC(); + _ = Image.fromC(glfw, image.width * image.height * 4); +} diff --git a/glfw/src/main.zig b/glfw/src/main.zig index 785ed0e9..43bb516d 100644 --- a/glfw/src/main.zig +++ b/glfw/src/main.zig @@ -12,6 +12,7 @@ pub const gamepad_axis = @import("gamepad_axis.zig"); pub const gamepad_button = @import("gamepad_button.zig"); pub const GammaRamp = @import("GammaRamp.zig"); pub const hat = @import("hat.zig"); +pub const Image = @import("Image.zig"); pub const joystick = @import("joystick.zig"); pub const key = @import("key.zig"); pub const mod = @import("mod.zig"); @@ -142,6 +143,7 @@ test "version" { // Reference these so the tests in these files get pulled in / ran. _ = Monitor; _ = GammaRamp; + _ = Image; _ = VideoMode; _ = Window;