summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Reiner <nathan@nathanreiner.xyz>2025-02-12 12:48:11 +0100
committerNathan Reiner <nathan@nathanreiner.xyz>2025-02-12 12:48:11 +0100
commit9fd81c0b38b2b843c24fb61bf8cb5b7873deaa72 (patch)
treea2d4d76a4fcc1334d83c5538e684061913be24d3
parentdae5bc02b1c934075e95694953b4330676e21611 (diff)
graphics: add line
-rw-r--r--build.zig106
-rw-r--r--src/estd/graphics/box.zig101
-rw-r--r--src/estd/graphics/canvas.zig13
-rw-r--r--src/estd/graphics/color.zig23
-rw-r--r--src/estd/graphics/curve.zig36
-rw-r--r--src/estd/graphics/line.zig76
-rw-r--r--src/estd/graphics/root.zig202
-rw-r--r--src/screen/drm/buffer/raw.zig2
-rw-r--r--src/screen/drm/buffer/root.zig2
-rw-r--r--src/screen/drm/pixel.zig18
-rw-r--r--src/screen/drm/request/frame-buffer.zig13
-rw-r--r--src/screen/drm/root.zig1
-rw-r--r--src/screen/main.zig47
13 files changed, 347 insertions, 293 deletions
diff --git a/build.zig b/build.zig
index 14f17d6..67df95b 100644
--- a/build.zig
+++ b/build.zig
@@ -1,72 +1,72 @@
const std = @import("std");
const Program = struct {
- name: []const u8,
- qemu: bool,
+ name: []const u8,
+ qemu: bool,
};
const programs = [_]Program {
- .{ .name = "shell", .qemu = false },
- .{ .name = "screen", .qemu = true },
+ .{ .name = "shell", .qemu = false },
+ .{ .name = "screen", .qemu = true },
};
pub fn build(b: *std.Build) void {
- const target = b.standardTargetOptions(.{});
- const optimize = b.standardOptimizeOption(.{});
+ const target = b.standardTargetOptions(.{});
+ const optimize = b.standardOptimizeOption(.{});
- const estd = b.createModule(.{
- .root_source_file = b.path("src/estd/root.zig"),
- });
+ const estd = b.createModule(.{
+ .root_source_file = b.path("src/estd/root.zig"),
+ });
- const init_exe = b.addExecutable(.{
- .name = "init",
- .root_source_file = b.path("src/init/main.zig"),
- .target = target,
- .optimize = optimize,
- });
- init_exe.root_module.addImport("estd", estd);
+ const init_exe = b.addExecutable(.{
+ .name = "init",
+ .root_source_file = b.path("src/init/main.zig"),
+ .target = target,
+ .optimize = optimize,
+ });
+ init_exe.root_module.addImport("estd", estd);
- const test_step = b.step("test", "Run tests");
+ const test_step = b.step("test", "Run tests");
- inline for (programs) |program| {
- const path = b.path("src/" ++ program.name ++ "/main.zig");
+ inline for (programs) |program| {
+ const path = b.path("src/" ++ program.name ++ "/main.zig");
- const exe = b.addExecutable(.{
- .name = program.name,
- .root_source_file = path,
- .target = target,
- .optimize = optimize
- });
- exe.root_module.addImport("estd", estd);
- b.installArtifact(exe);
+ const exe = b.addExecutable(.{
+ .name = program.name,
+ .root_source_file = path,
+ .target = target,
+ .optimize = optimize,
+ });
+ exe.root_module.addImport("estd", estd);
+ b.installArtifact(exe);
- const run = b.step("run-" ++ program.name, "Run " ++ program.name);
+ const run = b.step("run-" ++ program.name, "Run " ++ program.name);
- if (program.qemu) {
- const run_qemu = b.addSystemCommand(&.{ "./build/run-qemu" });
- run_qemu.addFileArg(init_exe.getEmittedBin());
- run_qemu.addFileArg(exe.getEmittedBin());
- run_qemu.step.dependOn(&exe.step);
- run_qemu.step.dependOn(&init_exe.step);
- run.dependOn(&run_qemu.step);
- } else {
- const run_artifact = b.addRunArtifact(exe);
- run.dependOn(&run_artifact.step);
- }
+ if (program.qemu) {
+ const run_qemu = b.addSystemCommand(&.{ "./build/run-qemu" });
+ run_qemu.addFileArg(init_exe.getEmittedBin());
+ run_qemu.addFileArg(exe.getEmittedBin());
+ run_qemu.step.dependOn(&exe.step);
+ run_qemu.step.dependOn(&init_exe.step);
+ run.dependOn(&run_qemu.step);
+ } else {
+ const run_artifact = b.addRunArtifact(exe);
+ run.dependOn(&run_artifact.step);
+ }
- const tests = b.addTest(.{
- .name = program.name,
- .root_source_file = path,
- });
- tests.root_module.addImport("estd", estd);
- const run_tests = b.addRunArtifact(tests);
- test_step.dependOn(&run_tests.step);
- }
+ const tests = b.addTest(.{
+ .name = program.name,
+ .root_source_file = path,
+ });
+ tests.root_module.addImport("estd", estd);
+ const run_tests = b.addRunArtifact(tests);
+ test_step.dependOn(&run_tests.step);
+ }
- const tests = b.addTest(.{
- .name = "estd",
- .root_source_file = b.path("src/estd/root.zig"),
- });
- const run_tests = b.addRunArtifact(tests);
- test_step.dependOn(&run_tests.step);
+ const tests = b.addTest(.{
+ .name = "estd",
+ .root_source_file = b.path("src/estd/root.zig"),
+ });
+ const run_tests = b.addRunArtifact(tests);
+ test_step.dependOn(&run_tests.step);
}
diff --git a/src/estd/graphics/box.zig b/src/estd/graphics/box.zig
new file mode 100644
index 0000000..83868aa
--- /dev/null
+++ b/src/estd/graphics/box.zig
@@ -0,0 +1,101 @@
+const std = @import("std");
+const graphics = @import("root.zig");
+
+pub const Box = struct {
+ const Self = @This();
+
+ x: u32,
+ y: u32,
+ width: u32,
+ height: u32,
+ color: graphics.Color,
+ radius: u32 = 0,
+
+ fn render_rect(
+ self: *const Self,
+ x: u32,
+ y: u32,
+ width: u32,
+ height: u32,
+ canvas: *const graphics.Canvas
+ ) void {
+ if (x >= canvas.width or y >= canvas.height) {
+ return;
+ }
+
+ const x_end = @min(x + width, canvas.width);
+ const y_end = @min(y + height, canvas.height);
+
+ for (y..y_end) |yp| {
+ const offset = yp * canvas.width;
+ @memset(
+ canvas.buffer[(offset + x)..(offset + x_end)],
+ self.color
+ );
+ }
+ }
+
+ pub fn render(self: *const Self, canvas: *const graphics.Canvas) void {
+ if (self.radius == 0) {
+ self.render_rect(self.x, self.y, self.width, self.height, canvas);
+ return;
+ }
+
+ const radius = @min(self.radius, self.width / 2, self.height / 2);
+ const core_width = self.width - 2 * radius;
+ const core_height = self.height - 2 * radius;
+
+ self.render_rect(
+ self.x + radius,
+ self.y,
+ core_width,
+ radius,
+ canvas
+ );
+
+ self.render_rect(
+ self.x + radius,
+ self.y + radius + core_height,
+ core_width,
+ radius,
+ canvas
+ );
+
+ self.render_rect(
+ self.x,
+ self.y + radius,
+ self.width,
+ core_height,
+ canvas
+ );
+
+ for (0..radius) |yp| {
+ const width: u32 = @intFromFloat(@round(std.math.sqrt(@as(f64, @floatFromInt(radius * radius - yp * yp)))));
+ const spacing = radius - width;
+
+ var offset = ((radius - yp) + self.y) * canvas.width + self.x + spacing;
+ @memset(
+ canvas.buffer[offset..offset + width],
+ self.color
+ );
+
+ offset = ((radius - yp) + self.y) * canvas.width + self.x + core_width + radius;
+ @memset(
+ canvas.buffer[offset..offset + width],
+ self.color
+ );
+
+ offset = (yp + self.y + radius + core_height) * canvas.width + self.x + spacing;
+ @memset(
+ canvas.buffer[offset..offset + width],
+ self.color
+ );
+
+ offset = (yp + self.y + radius + core_height) * canvas.width + self.x + core_width + radius;
+ @memset(
+ canvas.buffer[offset..offset + width],
+ self.color
+ );
+ }
+ }
+};
diff --git a/src/estd/graphics/canvas.zig b/src/estd/graphics/canvas.zig
new file mode 100644
index 0000000..35dba4b
--- /dev/null
+++ b/src/estd/graphics/canvas.zig
@@ -0,0 +1,13 @@
+const graphics = @import("root.zig");
+
+pub const Canvas = struct {
+ const Self = @This();
+
+ width: u32,
+ height: u32,
+ buffer: []volatile graphics.Color,
+
+ pub fn fill(self: *const Canvas, color: graphics.Color) void {
+ @memset(self.buffer, color);
+ }
+};
diff --git a/src/estd/graphics/color.zig b/src/estd/graphics/color.zig
new file mode 100644
index 0000000..b7fd97e
--- /dev/null
+++ b/src/estd/graphics/color.zig
@@ -0,0 +1,23 @@
+pub const Color = packed struct(u32) {
+ const Self = @This();
+
+ blue: u8,
+ green: u8,
+ red: u8,
+ _padding: u8 = 0x0,
+
+ pub fn mix(self: *const Self, other: *const Self, factor: f64) Self {
+ const inverse = 1 - factor;
+ return Self {
+ .red = @intFromFloat(
+ @as(f64, @floatFromInt(self.red)) * inverse + @as(f64, @floatFromInt(other.red)) * factor
+ ),
+ .green = @intFromFloat(
+ @as(f64, @floatFromInt(self.green)) * inverse + @as(f64, @floatFromInt(other.green)) * factor
+ ),
+ .blue = @intFromFloat(
+ @as(f64, @floatFromInt(self.blue)) * inverse + @as(f64, @floatFromInt(other.blue)) * factor
+ ),
+ };
+ }
+};
diff --git a/src/estd/graphics/curve.zig b/src/estd/graphics/curve.zig
new file mode 100644
index 0000000..d4be1d7
--- /dev/null
+++ b/src/estd/graphics/curve.zig
@@ -0,0 +1,36 @@
+const std = @import("std");
+const graphics = @import("root.zig");
+
+pub const Curve = struct {
+ const Self = @This();
+ const Point = struct {
+ x: u32,
+ y: u32,
+ };
+
+ start: Point,
+ middle: Point,
+ end: Point,
+
+ color: graphics.Color,
+
+ pub fn render(self: *const Self, canvas: *const graphics.Canvas) void {
+ const start_x: f64 = @floatFromInt(self.start.x);
+ const start_y: f64 = @floatFromInt(self.start.y);
+ const middle_x: f64 = @floatFromInt(self.middle.x);
+ const middle_y: f64 = @floatFromInt(self.middle.y);
+ const end_x: f64 = @floatFromInt(self.end.x);
+ const end_y: f64 = @floatFromInt(self.end.y);
+
+ for (0..100) |index| {
+ const t: f64 = @as(f64, @floatFromInt(index)) / 100;
+ const x: u32 = @intFromFloat(@round(
+ (1 - t) * ((1 - t) * start_x + t * middle_x) + t * ((1 - t) * middle_x + t * end_x)
+ ));
+ const y: u32 = @intFromFloat(@round(
+ (1 - t) * ((1 - t) * start_y + t * middle_y) + t * ((1 - t) * middle_y + t * end_y)
+ ));
+ canvas.buffer[x + canvas.width * y] = self.color;
+ }
+ }
+};
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;
+ }
+ }
+ }
+};
diff --git a/src/estd/graphics/root.zig b/src/estd/graphics/root.zig
index da09450..533d518 100644
--- a/src/estd/graphics/root.zig
+++ b/src/estd/graphics/root.zig
@@ -1,197 +1,5 @@
-const std = @import("std");
-
-pub const Pixel = packed struct(u32) {
- blue: u8,
- green: u8,
- red: u8,
- _padding: u8 = 0x0,
-};
-
-pub const Canvas = struct {
- const Self = @This();
-
- width: u32,
- height: u32,
- buffer: []volatile Pixel,
-
- pub fn fill(self: *const Canvas, pixel: Pixel) void {
- @memset(self.buffer, pixel);
- }
-
- fn gaussian_mean(values: [9]u32) u32 {
- return (values[0] + values[1] * 2 + values[2] +
- values[3] * 2 + values[4] * 8 + values[5] * 2 +
- values[6] + values[7] * 2 + values[8]) / 20;
- }
-
- pub fn set_with_anti_aliasing(self: *const Canvas, x: u32, y: u32) void {
- var neighbors_red: [9]u32 = undefined;
- var neighbors_green: [9]u32 = undefined;
- var neighbors_blue: [9]u32 = undefined;
-
- for (0..3) |h| {
- for (0..3) |w| {
- const pixel = self.buffer[(y + 1 - h) * self.width + x + 1 - w];
- neighbors_red[w + 3 * h] = pixel.red;
- neighbors_green[w + 3 * h] = pixel.green;
- neighbors_blue[w + 3 * h] = pixel.blue;
- }
- }
-
- self.buffer[x + (y * self.width)] = .{
- .red = @intCast(Self.gaussian_mean(neighbors_red)),
- .green = @intCast(Self.gaussian_mean(neighbors_green)),
- .blue = @intCast(Self.gaussian_mean(neighbors_blue)),
- };
- }
-};
-
-pub const Box = struct {
- const Self = @This();
-
- x: u32,
- y: u32,
- width: u32,
- height: u32,
- color: Pixel,
- radius: u32 = 0,
-
- fn render_rect(
- self: *const Self,
- x: u32,
- y: u32,
- width: u32,
- height: u32,
- canvas: *const Canvas
- ) void {
- if (x >= canvas.width or y >= canvas.height) {
- return;
- }
-
- const x_end = @min(x + width, canvas.width);
- const y_end = @min(y + height, canvas.height);
-
- for (y..y_end) |yp| {
- const offset = yp * canvas.width;
- @memset(
- canvas.buffer[(offset + x)..(offset + x_end)],
- self.color
- );
- }
- }
-
- pub fn render(self: *const Self, canvas: *const Canvas) void {
- if (self.radius == 0) {
- self.render_rect(self.x, self.y, self.width, self.height, canvas);
- return;
- }
-
- const radius = @min(self.radius, self.width / 2, self.height / 2);
- const core_width = self.width - 2 * radius;
- const core_height = self.height - 2 * radius;
-
- self.render_rect(
- self.x + radius,
- self.y,
- core_width,
- radius,
- canvas
- );
-
- self.render_rect(
- self.x + radius,
- self.y + radius + core_height,
- core_width,
- radius,
- canvas
- );
-
- self.render_rect(
- self.x,
- self.y + radius,
- self.width,
- core_height,
- canvas
- );
-
- for (0..radius) |yp| {
- const width: u32 = @intFromFloat(std.math.round(
- @as(f64, @floatFromInt(radius)) *
- @cos(std.math.asin(
- @as(f64, @floatFromInt(yp)) / @as(f64, @floatFromInt(radius))
- ))
- ));
- const spacing = radius - width;
-
- var offset = ((radius - yp) + self.y) * canvas.width + self.x + spacing;
- @memset(
- canvas.buffer[offset..offset + width],
- self.color
- );
-
- offset = ((radius - yp) + self.y) * canvas.width + self.x + core_width + radius;
- @memset(
- canvas.buffer[offset..offset + width],
- self.color
- );
-
- offset = (yp + self.y + radius + core_height) * canvas.width + self.x + spacing;
- @memset(
- canvas.buffer[offset..offset + width],
- self.color
- );
-
- offset = (yp + self.y + radius + core_height) * canvas.width + self.x + core_width + radius;
- @memset(
- canvas.buffer[offset..offset + width],
- self.color
- );
- }
-
- for (0..radius) |yp| {
- const width: u32 = @intFromFloat(std.math.round(
- @as(f64, @floatFromInt(radius)) *
- @cos(std.math.asin(
- @as(f64, @floatFromInt(yp)) / @as(f64, @floatFromInt(radius))
- ))
- ));
-
- const spacing = radius - width;
-
- canvas.set_with_anti_aliasing(
- self.x + spacing,
- @intCast(self.y + radius - yp),
- );
-
- canvas.set_with_anti_aliasing(
- self.x + spacing - 1,
- @intCast(self.y + radius - yp),
- );
-
- canvas.set_with_anti_aliasing(
- self.x + core_width + radius + width,
- @intCast(self.y + radius - yp),
- );
-
- canvas.set_with_anti_aliasing(
- self.x + spacing,
- @intCast(self.y + yp + radius + core_height),
- );
-
- canvas.set_with_anti_aliasing(
- self.x + core_width + radius + width,
- @intCast(self.y + yp + radius + core_height),
- );
- }
-
- for (0..core_width) |w| {
- canvas.set_with_anti_aliasing(@intCast(self.x + radius + w), self.y);
- canvas.set_with_anti_aliasing(@intCast(self.x + radius + w), self.y + self.height);
- }
-
- for (0..core_height) |h| {
- canvas.set_with_anti_aliasing(self.x, @intCast(self.y + radius + h));
- canvas.set_with_anti_aliasing(self.x + self.width, @intCast(self.y + radius + h));
- }
- }
-};
+pub const Canvas = @import("canvas.zig").Canvas;
+pub const Box = @import("box.zig").Box;
+pub const Color = @import("color.zig").Color;
+pub const Line = @import("line.zig").Line;
+pub const Curve = @import("curve.zig").Curve;
diff --git a/src/screen/drm/buffer/raw.zig b/src/screen/drm/buffer/raw.zig
index c5a04f3..12784de 100644
--- a/src/screen/drm/buffer/raw.zig
+++ b/src/screen/drm/buffer/raw.zig
@@ -40,7 +40,7 @@ pub const Raw = struct {
.id = 0,
.width = fb.width,
.height = fb.height,
- .pixel_format = drm.Pixel.Format.xrgb8888,
+ .pixel_format = .xrgb8888,
.flags = 0,
.handles = [_] u32 { fb.handle, 0, 0, 0 },
.pitches = [_] u32 { fb.stride, 0, 0, 0 },
diff --git a/src/screen/drm/buffer/root.zig b/src/screen/drm/buffer/root.zig
index f14ed66..30734f2 100644
--- a/src/screen/drm/buffer/root.zig
+++ b/src/screen/drm/buffer/root.zig
@@ -35,7 +35,7 @@ pub const Buffer = struct {
.width = self.current.width,
.height = self.current.height,
.buffer = @as(
- [*]volatile graphics.Pixel,
+ [*]volatile graphics.Color,
@ptrCast(@alignCast(self.current.bytes))
)[0..self.current.bytes.len / 4],
};
diff --git a/src/screen/drm/pixel.zig b/src/screen/drm/pixel.zig
index 7c99e52..8b13789 100644
--- a/src/screen/drm/pixel.zig
+++ b/src/screen/drm/pixel.zig
@@ -1,19 +1 @@
-fn pixel_format_code(comptime a: u8, comptime b: u8, comptime c: u8, comptime d: u8) u32 {
- return @as(u32, @intCast(a)) |
- (@as(u32, @intCast(b)) << 8) |
- (@as(u32, @intCast(c)) << 16) |
- (@as(u32, @intCast(d)) << 24);
-}
-
-pub const Pixel = packed struct(u32) {
- blue: u8,
- green: u8,
- red: u8,
- _padding: u8 = 0x0,
-
- pub const Format = enum(u32) {
- xrgb8888 = pixel_format_code('X', 'R', '2', '4'),
- };
-};
-
diff --git a/src/screen/drm/request/frame-buffer.zig b/src/screen/drm/request/frame-buffer.zig
index 8f93862..c9077e8 100644
--- a/src/screen/drm/request/frame-buffer.zig
+++ b/src/screen/drm/request/frame-buffer.zig
@@ -10,11 +10,22 @@ pub const CreateDumb = extern struct {
size: u32,
};
+fn pixel_format_code(comptime a: u8, comptime b: u8, comptime c: u8, comptime d: u8) u32 {
+ return @as(u32, @intCast(a)) |
+ (@as(u32, @intCast(b)) << 8) |
+ (@as(u32, @intCast(c)) << 16) |
+ (@as(u32, @intCast(d)) << 24);
+}
+
+pub const PixelFormat = enum(u32) {
+ xrgb8888 = pixel_format_code('X', 'R', '2', '4'),
+};
+
pub const FrameBufferCmd2 = extern struct {
id: u32,
width: u32,
height: u32,
- pixel_format: drm.Pixel.Format,
+ pixel_format: PixelFormat,
flags: u32,
handles: [4]u32,
pitches: [4]u32,
diff --git a/src/screen/drm/root.zig b/src/screen/drm/root.zig
index 5012743..2417463 100644
--- a/src/screen/drm/root.zig
+++ b/src/screen/drm/root.zig
@@ -6,4 +6,3 @@ pub const Event = @import("event.zig").Event;
pub const Connector = @import("connector/root.zig").Connector;
pub const Crtc = @import("crtc.zig").Crtc;
pub const Buffer = @import("buffer/root.zig").Buffer;
-pub const Pixel = @import("pixel.zig").Pixel;
diff --git a/src/screen/main.zig b/src/screen/main.zig
index 7b73450..2cb8c03 100644
--- a/src/screen/main.zig
+++ b/src/screen/main.zig
@@ -28,39 +28,44 @@ pub fn main() !void {
try crtc.attach(&buffer, &connector, mode);
- const center_x: i64 = @intCast(buffer.current.width / 2 - 100);
- const center_y: i64 = @intCast(buffer.current.height / 2 - 100);
+ const center_x = (buffer.current.width / 2);
+ const center_y = (buffer.current.height / 2);
- var box = graphics.Box {
- .x = @intCast(center_x),
- .y = @intCast(center_y),
- .width = 200,
- .height = 200,
- .color = .{ .red = 0xff, .green = 0x05, .blue = 0x07 },
- .radius = 0,
+ var line = graphics.Line {
+ .start = .{ .x = center_x, .y = center_y },
+ .end = .{ .x = center_x + 110 , .y = center_y + 100 },
+ .color = .{ .red = 0xff, .green = 0, .blue = 0 },
};
var last_duration: f64 = 0;
- var dir: f64 = 1;
var delta: f64 = 0;
- var radius: f64 = 0;
+ var angle: f64 = 0;
while (true) {
const start = try std.time.Instant.now();
const canvas = buffer.canvas();
+
canvas.fill(.{ .red = 0x25, .green = 0x25, .blue = 0x25 });
- box.render(&canvas);
- radius += delta * dir;
- if (radius > 100) {
- std.debug.print("HERE\n", .{});
- radius = 100;
- dir = -1;
- } else if (radius < 0) {
- radius = 0;
- dir = 1;
+ (graphics.Box {
+ .x = center_x - 100,
+ .y = center_y - 100,
+ .width = 200,
+ .height = 200,
+ .radius = 100,
+ .color = .{ .red = 0xff, .green = 0xff, .blue = 0xff },
+ }).render(&canvas);
+
+ line.render(&canvas);
+ const cos = @cos(std.math.degreesToRadians(angle));
+ const sin = @sin(std.math.degreesToRadians(angle));
+ line.end.x = @intCast(@as(i64, @intCast(center_x)) + @as(i64, @intFromFloat(100 * cos)));
+ line.end.y = @intCast(@as(i64, @intCast(center_y)) + @as(i64, @intFromFloat(100 * sin)));
+
+ angle += delta;
+ if (angle > 360) {
+ angle = 0;
}
- box.radius = @intFromFloat(radius);
const end = try std.time.Instant.now();
const duration: f64 = @floatFromInt(end.since(start));