From 43129e95c73f0e6b3880c758a6fe89afbb9e9dd9 Mon Sep 17 00:00:00 2001 From: Paul Montag Date: Tue, 14 Apr 2026 06:26:38 -0500 Subject: [PATCH] fixing some things --- src/grome/matrix.zig | 51 +++++++++++++++++++++++++++++++------------- src/view/draw.zig | 44 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 15 deletions(-) create mode 100644 src/view/draw.zig diff --git a/src/grome/matrix.zig b/src/grome/matrix.zig index f945c0e..2019571 100644 --- a/src/grome/matrix.zig +++ b/src/grome/matrix.zig @@ -2,10 +2,31 @@ const std = @import("std"); const mem = std.mem; const Allocator = mem.Allocator; +/// Point is a location within the matrix, (x,y) +pub const Point = struct { + x: usize, + y: usize, +}; + +/// Rect is a rectangle +pub const Rect = struct { + width: usize, + height: usize, + + pub fn area(self: *const @This()) usize { + return self.width * self.height; + } +}; + +/// Area is the area +pub const Area = struct { + location: Point, + size: Rect, +}; + /// Matrix is a part of the game board -pub fn Matrix(comptime T: type, comptime width: usize, comptime height: usize) type { - const size = width * height; - const MatrixRowIterator = RowIterator(T, width); +pub fn Matrix(comptime T: type, size: Rect) type { + const MatrixRowIterator = RowIterator(T, size.width); return struct { /// data is the game board itself. @@ -13,14 +34,14 @@ pub fn Matrix(comptime T: type, comptime width: usize, comptime height: usize) t /// init creates the chunk, storing the bytes in memory. pub fn initZero(gpa: Allocator) !@This() { - const data = try gpa.alloc(T, size); + const data = try gpa.alloc(T, size.area()); @memset(data, mem.zeroes(T)); return .{ .data = data }; } /// init creates the chunk, storing the bytes in memory. pub fn init(gpa: Allocator, zero: T) !@This() { - const data = try gpa.alloc(T, size); + const data = try gpa.alloc(T, size.area()); @memset(data, zero); return .{ .data = data }; } @@ -31,14 +52,14 @@ pub fn Matrix(comptime T: type, comptime width: usize, comptime height: usize) t } // set sets the value of the specified location in memory - pub fn set(self: *@This(), x: usize, y: usize, val: T) void { - const index = (width * y) + x; + pub fn set(self: *@This(), loc: Point, val: T) void { + const index = (size.width * loc.y) + loc.x; self.data[index] = val; } // set sets the value of the specified location in memory - pub fn get(self: *const @This(), x: usize, y: usize) T { - const index = (width * y) + x; + pub fn get(self: *const @This(), loc: Point) T { + const index = (size.width * loc.y) + loc.x; return self.data[index]; } @@ -51,14 +72,14 @@ pub fn Matrix(comptime T: type, comptime width: usize, comptime height: usize) t test "TestMatrix" { const testing = std.testing; - var mat = try Matrix(u64, 10, 10).init(testing.allocator); + var mat = try Matrix(u64, Rect{ .width = 10, .height = 10 }).initZero(testing.allocator); defer mat.deinit(testing.allocator); - mat.set(1, 1, 100); - try testing.expectEqual(100, mat.get(1, 1)); + mat.set(Point{ .x = 1, .y = 1 }, 100); + try testing.expectEqual(100, mat.get(Point{ .x = 1, .y = 1 })); } -pub fn RowIterator(comptime T: type, comptime width: usize) type { +pub fn RowIterator(comptime T: type, width: usize) type { return struct { _index: usize, /// data is a reference to the board game data, now we will return it as @@ -88,11 +109,11 @@ pub fn RowIterator(comptime T: type, comptime width: usize) type { test "TestRowIterator" { const testing = std.testing; - var chunk = try Matrix(usize, 10, 10).init(testing.allocator); + var chunk = try Matrix(usize, Rect{ .height = 10, .width = 10 }).initZero(testing.allocator); defer chunk.deinit(testing.allocator); for (0..10) |x| { - chunk.set(x, x, x); + chunk.set(Point{ .x = x, .y = x }, x); } var iter = chunk.row_iterator(); diff --git a/src/view/draw.zig b/src/view/draw.zig new file mode 100644 index 0000000..5637b62 --- /dev/null +++ b/src/view/draw.zig @@ -0,0 +1,44 @@ +const std = @import("std"); +const mem = std.mem; + +const Allocator = mem.Allocator; +const Matrix = @import("../grome/matrix.zig").Matrix; + +/// DoubleBufferWriter manages two buffers for efficient rendering: a display buffer +/// showing the current screen state, and a write buffer for accumulating changes +/// that will be committed to the display on the next render cycle. This ABO +/// approach minimizes unnecessary updates by only diffing changed cells. +pub fn DoubleBufferWriter(width: usize, height: usize) type { + return struct { + // display holds the existing data. + display: Matrix(Cell, width, height), + // write is where we are writing the active changes which will be commited + // on the next rendering + write: Matrix(Cell, width, height), + + pub fn init(gpa: Allocator, len: usize) DoubleBufferWriter { + const display = gpa.alloc(Cell, len); + const write = gpa.alloc(Cell, len); + + return .{ + .display = display, + .write = write, + }; + } + + pub fn deinit(self: *@This(), gpa: Allocator) void { + gpa.free(self.display); + gpa.free(self.write); + } + }; +} + +pub const Cell = struct { + char: [8]u8, + width: usize, + + /// eql returns + pub fn eql(self: *const Cell, b: *const Cell) bool { + return mem.eql(u8, self.char, b.char) and self.width == b.width; + } +};