summaryrefslogtreecommitdiff
path: root/src/estd/graphics/root.zig
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 /src/estd/graphics/root.zig
parentdae5bc02b1c934075e95694953b4330676e21611 (diff)
graphics: add line
Diffstat (limited to 'src/estd/graphics/root.zig')
-rw-r--r--src/estd/graphics/root.zig202
1 files changed, 5 insertions, 197 deletions
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;