diff --git a/flake.nix b/flake.nix index 73ffa36..bb5fab3 100644 --- a/flake.nix +++ b/flake.nix @@ -4,22 +4,26 @@ inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; outputs = { - self, - nixpkgs, - } : let system = "x86_64-linux"; - pkgs = import nixpkgs { inherit system; }; + self, + nixpkgs, + }: let + system = "x86_64-linux"; + pkgs = import nixpkgs {inherit system;}; in { devShells.${system}.default = pkgs.mkShell { - nativeBuildInputs = with pkgs; - [gcc clang - - tools lldb + nativeBuildInputs = with pkgs; [ + gcc + clang-tools + lldb - meson ninja pkg - - config + meson + ninja + pkg-config - gtk4 + gtk4 - gdb]; + gdb + ]; shellHook = ""; }; diff --git a/src/core/primitives.c b/src/core/primitives.c index a6a4eef..402b7cc 100644 --- a/src/core/primitives.c +++ b/src/core/primitives.c @@ -45,3 +45,13 @@ void vektor_polygon_free(VektorPolygon *pg) { free(pg->points); free(pg); } + +void vektor_primitivebuffer_add_primitive(VektorPrimitiveBuffer *buffer, + VektorPrimitive prim) { + if (buffer->count >= buffer->capacity) { + buffer->capacity = buffer->capacity ? buffer->capacity * 2 : 4; + buffer->primitives = + realloc(buffer->primitives, sizeof(VektorPrimitive) * buffer->capacity); + } + buffer->primitives[buffer->count++] = prim; +} diff --git a/src/core/primitives.h b/src/core/primitives.h index 2f9363a..8ad91bb 100644 --- a/src/core/primitives.h +++ b/src/core/primitives.h @@ -27,7 +27,12 @@ typedef struct { double radius; } VektorCircle; -typedef enum { LINE, POLYLINE, POLYGON, CIRCLE } VektorPrimitiveKind; +typedef enum { + VEKTOR_LINE, + VEKTOR_POLYLINE, + VEKTOR_POLYGON, + VEKTOR_CIRCLE +} VektorPrimitiveKind; typedef struct { VektorPrimitiveKind kind; @@ -39,7 +44,7 @@ typedef struct { }; } VektorPrimitive; -VektorPolyline* vektor_polyline_new(void); +VektorPolyline *vektor_polyline_new(void); void vektor_polyline_add_point(VektorPolyline *pl, V2 point); void vektor_polyline_free(VektorPolyline *pl); @@ -47,4 +52,13 @@ VektorPolygon *vektor_polygon_new(void); void vektor_polygon_add_point(VektorPolygon *pl, V2 point); void vektor_polygon_free(VektorPolygon *pl); +typedef struct { + VektorPrimitive *primitives; + size_t count; + size_t capacity; +} VektorPrimitiveBuffer; + +void vektor_primitivebuffer_add_primitive(VektorPrimitiveBuffer *edges, + VektorPrimitive edge); + #endif // PRIMITIVES_H_ diff --git a/src/core/raster.c b/src/core/raster.c index bc4b62e..ff4b0cb 100644 --- a/src/core/raster.c +++ b/src/core/raster.c @@ -1,6 +1,7 @@ #include "raster.h" #include "primitives.h" #include "stddef.h" +#include void vektor_edgebuffer_add_edge(EdgeBuffer *buffer, Edge edge) { if (buffer->count >= buffer->capacity) { @@ -10,17 +11,18 @@ void vektor_edgebuffer_add_edge(EdgeBuffer *buffer, Edge edge) { buffer->edges[buffer->count++] = edge; } -void vektor_edgebuffer_flatten_line(EdgeBuffer *buffer, VektorLine line) { +void vektor_line_flatten(EdgeBuffer *buffer, VektorLine line) { vektor_edgebuffer_add_edge(buffer, (Edge){line.p1, line.p2, 0}); } -void vektor_edgebuffer_flatten_polyline(EdgeBuffer *buffer, VektorPolyline *line) { +void vektor_polyline_flatten(EdgeBuffer *buffer, VektorPolyline *line) { for (size_t i = 0; i + 1 < line->count; i++) { - vektor_edgebuffer_add_edge(buffer, (Edge){line->points[i], line->points[i + 1], 0}); + vektor_edgebuffer_add_edge(buffer, + (Edge){line->points[i], line->points[i + 1], 0}); } } -void vektor_edgebuffer_flatten_polygon(EdgeBuffer *buffer, VektorPolygon *pg) { +void vektor_polygon_flatten(EdgeBuffer *buffer, VektorPolygon *pg) { size_t n = pg->count; if (n < 3) return; @@ -33,25 +35,27 @@ void vektor_edgebuffer_flatten_polygon(EdgeBuffer *buffer, VektorPolygon *pg) { } } -inline VektorFramebuffer vektor_framebuffer_new(unsigned int W, unsigned int H) { - VektorFramebuffer fb = {.width = W, .height = H, .pixels = calloc(W * H * 4, 1)}; +inline VektorFramebuffer vektor_framebuffer_new(unsigned int W, + unsigned int H) { + VektorFramebuffer fb = { + .width = W, .height = H, .pixels = calloc(W * H * 4, 1)}; return fb; } -inline void vektor_framebuffer_putpixel(VektorFramebuffer *fb, int x, int y, unsigned char r, - unsigned char g, unsigned char b) { +inline void vektor_framebuffer_putpixel(VektorFramebuffer *fb, int x, int y, + VektorColor color) { if ((unsigned)x >= fb->width || (unsigned)y >= fb->height) return; int i = (y * fb->width + x) * 4; - fb->pixels[i + 0] = r; - fb->pixels[i + 1] = g; - fb->pixels[i + 2] = b; - fb->pixels[i + 3] = 255; + fb->pixels[i + 0] = color.r; + fb->pixels[i + 1] = color.g; + fb->pixels[i + 2] = color.b; + fb->pixels[i + 3] = color.a; } -void vektor_framebuffer_drawline(VektorFramebuffer *fb, V2 a, V2 b, unsigned char r, unsigned char g, - unsigned char bl) { +void vektor_framebuffer_drawline(VektorFramebuffer *fb, V2 a, V2 b, + VektorColor color) { int x0 = (int)a.x; int y0 = (int)a.y; int x1 = (int)b.x; @@ -64,7 +68,7 @@ void vektor_framebuffer_drawline(VektorFramebuffer *fb, V2 a, V2 b, unsigned cha int err = dx + dy; for (;;) { - vektor_framebuffer_putpixel(fb, x0, y0, r, g, bl); + vektor_framebuffer_putpixel(fb, x0, y0, color); if (x0 == x1 && y0 == y1) break; @@ -80,15 +84,32 @@ void vektor_framebuffer_drawline(VektorFramebuffer *fb, V2 a, V2 b, unsigned cha } } -void vektor_framebuffer_drawto(VektorFramebuffer* fb, VektorCanvas* target) { - for(int x = 0; x < fb->width; x++) { - for(int y = 0; y < fb->height; y++) { +void rasterize(VektorFramebuffer *fb, VektorPrimitiveBuffer *prims) { + EdgeBuffer edges = {0}; + for (size_t i = 0; i < prims->count; i++) { + VektorPrimitive *p = &prims->primitives[i]; - int i = (y * fb->width + x) * 4; - target->canvasPixels[i+0] = (guchar)fb->pixels[i+0]; - target->canvasPixels[i+1] = (guchar)fb->pixels[i+1]; - target->canvasPixels[i+2] = (guchar)fb->pixels[i+2]; - target->canvasPixels[i+3] = (guchar)fb->pixels[i+3]; + switch (p->kind) { + case VEKTOR_LINE: + vektor_line_flatten(&edges, p->line); + break; + + case VEKTOR_POLYLINE: + vektor_polyline_flatten(&edges, p->polyline); + break; + + case VEKTOR_POLYGON: + vektor_polygon_flatten(&edges, p->polygon); + break; + + default: + // TODO fill in all primitives + break; } } + + for (size_t i = 0; i < edges.count; i++) { + vektor_framebuffer_drawline(fb, edges.edges[i].p1, edges.edges[i].p2, + vektor_color_solid(255, 0, 255)); + } } \ No newline at end of file diff --git a/src/core/raster.h b/src/core/raster.h index f747d1b..92aceaa 100644 --- a/src/core/raster.h +++ b/src/core/raster.h @@ -2,8 +2,8 @@ #define RASTER_H_ #include "primitives.h" -#include "../ui/vektorcanvas.h" +#include "src/util/color.h" #include "stddef.h" #include "vector.h" @@ -21,9 +21,9 @@ typedef struct { void vektor_edgebuffer_add_edge(EdgeBuffer *edges, Edge edge); -void vektor_edgebuffer_flatten_line(EdgeBuffer *edges, VektorLine line); -void vektor_edgebuffer_flatten_polyline(EdgeBuffer *edges, VektorPolyline *line); -void vektor_edgebuffer_flatten_polygon(EdgeBuffer *buffer, VektorPolygon *line); +void vektor_line_flatten(EdgeBuffer *edges, VektorLine line); +void vektor_polyline_flatten(EdgeBuffer *edges, VektorPolyline *line); +void vektor_polygon_flatten(EdgeBuffer *buffer, VektorPolygon *line); typedef struct { unsigned int width; @@ -31,14 +31,15 @@ typedef struct { unsigned char *pixels; // Flat RGBA8 array } VektorFramebuffer; -VektorFramebuffer vektor_framebuffer_new(unsigned int width, unsigned int height); +VektorFramebuffer vektor_framebuffer_new(unsigned int width, + unsigned int height); -void vektor_framebuffer_putpixel(VektorFramebuffer *fb, int x, int y, unsigned char r, unsigned char g, - unsigned char b); +void vektor_framebuffer_putpixel(VektorFramebuffer *fb, int x, int y, + VektorColor color); -void vektor_framebuffer_drawline(VektorFramebuffer *fb, V2 a, V2 b, unsigned char r, unsigned char g, - unsigned char bl); +void vektor_framebuffer_drawline(VektorFramebuffer *fb, V2 a, V2 b, + VektorColor color); -void vektor_framebuffer_drawto(VektorFramebuffer* fb, VektorCanvas* canvas); +void rasterize(VektorFramebuffer *fb, VektorPrimitiveBuffer *primitives); #endif // RASTER_H_ diff --git a/src/main.c b/src/main.c index a7eb5a4..a53ce02 100644 --- a/src/main.c +++ b/src/main.c @@ -1,10 +1,12 @@ #include "gtk/gtk.h" +#include "src/core/primitives.h" #include "stdio.h" #include "stdlib.h" #include "./core/raster.h" #include "./ui/uicontroller.h" #include "./ui/vektorcanvas.h" +#include "./util/color.h" static void on_map(GtkWidget *window, gpointer user_data) { vektor_uictrl_map((VektorWidgetState *)user_data); @@ -22,18 +24,31 @@ void write_ppm(const char *path, const VektorFramebuffer *fb) { static void activate(GtkApplication *app, gpointer user_data) { VektorFramebuffer fb = vektor_framebuffer_new(400, 400); - EdgeBuffer edges = {0}; - VektorPolygon pg = *vektor_polygon_new(); - vektor_polygon_add_point(&pg, (V2){50, 50}); - vektor_polygon_add_point(&pg, (V2){200, 80}); - vektor_polygon_add_point(&pg, (V2){120, 200}); + VektorPolygon triangle = *vektor_polygon_new(); + vektor_polygon_add_point(&triangle, (V2){50, 150}); + vektor_polygon_add_point(&triangle, (V2){200, 180}); + vektor_polygon_add_point(&triangle, (V2){120, 300}); - vektor_edgebuffer_flatten_polygon(&edges, &pg); + VektorPolygon star = *vektor_polygon_new(); + vektor_polygon_add_point(&star, (V2){150, 40}); + vektor_polygon_add_point(&star, (V2){180, 110}); + vektor_polygon_add_point(&star, (V2){260, 110}); + vektor_polygon_add_point(&star, (V2){200, 160}); + vektor_polygon_add_point(&star, (V2){220, 240}); + vektor_polygon_add_point(&star, (V2){150, 190}); + vektor_polygon_add_point(&star, (V2){80, 240}); + vektor_polygon_add_point(&star, (V2){100, 160}); + vektor_polygon_add_point(&star, (V2){40, 110}); + vektor_polygon_add_point(&star, (V2){120, 110}); - for (size_t i = 0; i < edges.count; i++) { - vektor_framebuffer_drawline(&fb, edges.edges[i].p1, edges.edges[i].p2, 0, 0, 0); - } + VektorPrimitiveBuffer prims = {0}; + vektor_primitivebuffer_add_primitive( + &prims, (VektorPrimitive){.kind = VEKTOR_POLYGON, .polygon = &triangle}); + vektor_primitivebuffer_add_primitive( + &prims, (VektorPrimitive){.kind = VEKTOR_POLYGON, .polygon = &star}); + + rasterize(&fb, &prims); VektorWidgetState *widget_state = (VektorWidgetState *)malloc(sizeof(VektorWidgetState)); @@ -41,8 +56,8 @@ static void activate(GtkApplication *app, gpointer user_data) { VektorCanvas *canvas = (VektorCanvas *)malloc(sizeof(VektorCanvas)); vektor_canvas_init(widget_state, canvas); - vektor_canvas_fill(canvas, vektor_color_new(0,0,0,255)); - vektor_framebuffer_drawto(&fb, canvas); + vektor_canvas_fill(canvas, vektor_color_new(255, 0, 0, 255)); + vektor_canvas_drawfrom(&fb, canvas); vektor_canvas_update(canvas); g_signal_connect(widget_state->window, "map", G_CALLBACK(on_map), diff --git a/src/ui/vektorcanvas.c b/src/ui/vektorcanvas.c index e59d012..e274c99 100644 --- a/src/ui/vektorcanvas.c +++ b/src/ui/vektorcanvas.c @@ -1,5 +1,6 @@ #include "gtk/gtk.h" +#include "../core/raster.h" #include "uicontroller.h" #include "vektorcanvas.h" @@ -40,7 +41,7 @@ void vektor_canvas_update(VektorCanvas *canvas) { GDK_PAINTABLE(canvas->canvasTexture)); } -void vektor_canvas_fill(VektorCanvas *canvas, VektorCanvasColor color) { +void vektor_canvas_fill(VektorCanvas *canvas, VektorColor color) { for (int x = 0; x < VKTR_CANVAS_WIDTH; x++) { for (int y = 0; y < VKTR_CANVAS_HEIGHT; y++) { int i = (y * VKTR_CANVAS_WIDTH + x) * 4; @@ -52,7 +53,15 @@ void vektor_canvas_fill(VektorCanvas *canvas, VektorCanvasColor color) { } } -VektorCanvasColor vektor_color_new(guchar cr, guchar cg, guchar cb, guchar ca) { - VektorCanvasColor c = {.r = cr, .g = cg, .b = cb, .a = ca}; - return c; +void vektor_canvas_drawfrom(VektorFramebuffer *fb, VektorCanvas *target) { + for (int x = 0; x < fb->width; x++) { + for (int y = 0; y < fb->height; y++) { + + int i = (y * fb->width + x) * 4; + target->canvasPixels[i + 0] = (guchar)fb->pixels[i + 0]; + target->canvasPixels[i + 1] = (guchar)fb->pixels[i + 1]; + target->canvasPixels[i + 2] = (guchar)fb->pixels[i + 2]; + target->canvasPixels[i + 3] = (guchar)fb->pixels[i + 3]; + } + } } \ No newline at end of file diff --git a/src/ui/vektorcanvas.h b/src/ui/vektorcanvas.h index 5e8edbb..bf6bad7 100644 --- a/src/ui/vektorcanvas.h +++ b/src/ui/vektorcanvas.h @@ -1,6 +1,8 @@ #ifndef VKTR_CANVAS_H #define VKTR_CANVAS_H +#include "../core/raster.h" +#include "../util/color.h" #include "uicontroller.h" typedef struct VektorCanvas { @@ -15,17 +17,9 @@ typedef struct VektorCanvas { int height; } VektorCanvas; -typedef struct VektorCanvasColor { - guchar r; - guchar g; - guchar b; - guchar a; -} VektorCanvasColor; - void vektor_canvas_init(VektorWidgetState *state, VektorCanvas *canvasOut); void vektor_canvas_update(VektorCanvas *canvas); -void vektor_canvas_fill(VektorCanvas *canvas, VektorCanvasColor color); - -VektorCanvasColor vektor_color_new(guchar r, guchar g, guchar b, guchar a); +void vektor_canvas_fill(VektorCanvas *canvas, VektorColor color); +void vektor_canvas_drawfrom(VektorFramebuffer *fb, VektorCanvas *canvas); #endif \ No newline at end of file diff --git a/src/util/color.h b/src/util/color.h new file mode 100644 index 0000000..176f4b7 --- /dev/null +++ b/src/util/color.h @@ -0,0 +1,23 @@ +#ifndef COLOR_H_ +#define COLOR_H_ + +typedef struct VektorColor { + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char a; +} VektorColor; + +static VektorColor vektor_color_blank = (VektorColor){0, 0, 0, 0}; + +static inline VektorColor vektor_color_new(unsigned char r, unsigned char g, + unsigned char b, unsigned char a) { + return (VektorColor){r, g, b, a}; +} + +static inline VektorColor vektor_color_solid(unsigned char r, unsigned char g, + unsigned char b) { + return (VektorColor){r, g, b, 255}; +} + +#endif // COLOR_H_