summaryrefslogtreecommitdiff
path: root/src/estd/graphics/line.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/estd/graphics/line.zig')
-rw-r--r--src/estd/graphics/line.zig76
1 files changed, 76 insertions, 0 deletions
diff --git a/src/estd/graphics/line.zig b/src/estd/graphics/line.zig
new file mode 100644
index 0000000..93f17ff
--- /dev/null
+++ b/src/estd/graphics/line.zig
@@ -0,0 +1,76 @@
+const std = @import("std");
+const graphics = @import("root.zig");
+
+pub const Line = struct {
+ const Self = @This();
+ const Point = struct {
+ x: u32,
+ y: u32,
+ };
+
+ start: Point,
+ end: Point,
+
+ color: graphics.Color,
+
+ fn distance(a: u32, b: u32) u32 {
+ if (a < b) {
+ return b - a;
+ } else {
+ return a - b;
+ }
+ }
+
+ pub fn render(self: *const Self, canvas: *const graphics.Canvas) void {
+ var start = self.start;
+ var end = self.end;
+ const steep = distance(start.y, end.y) > distance(start.x, end.x);
+
+ if (steep) {
+ std.mem.swap(u32, &start.x, &start.y);
+ std.mem.swap(u32, &end.x, &end.y);
+ }
+
+ if (start.x > end.x) {
+ std.mem.swap(Point, &start, &end);
+ }
+
+ const dx: f64 = @floatFromInt(end.x - start.x);
+ const dy: f64 = @floatFromInt(@as(i64, @intCast(end.y)) - @as(i64, @intCast(start.y)));
+ var gradient: f64 = dy / dx;
+ if (dx == 0) {
+ gradient = 1;
+ }
+
+
+ var intersect_y: f64 = @floatFromInt(start.y);
+
+ if (steep) {
+ for (start.x..end.x + 1) |x| {
+ const y: usize = @intFromFloat(intersect_y);
+ const factor = intersect_y - @as(f64, @floatFromInt(y));
+
+ var previous_color = canvas.buffer[canvas.width * x + y];
+ canvas.buffer[x * canvas.width + y] = previous_color.mix(&self.color, factor);
+
+ previous_color = canvas.buffer[x * canvas.width + y - 1];
+ canvas.buffer[x * canvas.width + y - 1] = self.color.mix(&previous_color, factor);
+
+ intersect_y += gradient;
+ }
+ } else {
+ for (start.x..end.x + 1) |x| {
+ const y: u32 = @intFromFloat(intersect_y);
+ const factor = intersect_y - @as(f64, @floatFromInt(y));
+
+ var previous_color = canvas.buffer[x + canvas.width * y];
+ canvas.buffer[x + canvas.width * y] = previous_color.mix(&self.color, factor);
+
+ previous_color = canvas.buffer[x + canvas.width * (y - 1)];
+ canvas.buffer[x + canvas.width * (y - 1)] = self.color.mix(&previous_color, factor);
+
+ intersect_y += gradient;
+ }
+ }
+ }
+};