feat: add rasterization primitives
This commit is contained in:
5
.clang-format
Normal file
5
.clang-format
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
BasedOnStyle: LLVM
|
||||||
|
ColumnLimit: 80
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
IndentWidth: 2
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,7 +1,9 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
|
.vscode
|
||||||
.idea
|
.idea
|
||||||
*.log
|
*.log
|
||||||
tmp/
|
tmp/
|
||||||
.cache/
|
.cache/
|
||||||
build/
|
build/
|
||||||
.direnv/
|
.direnv/
|
||||||
|
*.ppm
|
||||||
19
.vscode/c_cpp_properties.json
vendored
19
.vscode/c_cpp_properties.json
vendored
@@ -1,19 +0,0 @@
|
|||||||
{
|
|
||||||
"configurations": [
|
|
||||||
{
|
|
||||||
"name": "Linux",
|
|
||||||
"includePath": [
|
|
||||||
"${workspaceFolder}/**"
|
|
||||||
],
|
|
||||||
"defines": [],
|
|
||||||
"compilerPath": "/usr/bin/gcc",
|
|
||||||
"cStandard": "c17",
|
|
||||||
"cppStandard": "gnu++17",
|
|
||||||
"intelliSenseMode": "linux-gcc-x64",
|
|
||||||
"compileCommands": [
|
|
||||||
"${workspaceFolder}/build/compile_commands.json"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"version": 4
|
|
||||||
}
|
|
||||||
38
flake.lock
generated
38
flake.lock
generated
@@ -1,27 +1,23 @@
|
|||||||
{
|
{
|
||||||
"nodes": {
|
"nodes" : {
|
||||||
"nixpkgs": {
|
"nixpkgs" : {
|
||||||
"locked": {
|
"locked" : {
|
||||||
"lastModified": 1772433332,
|
"lastModified" : 1772433332,
|
||||||
"narHash": "sha256-izhTDFKsg6KeVBxJS9EblGeQ8y+O8eCa6RcW874vxEc=",
|
"narHash" : "sha256-izhTDFKsg6KeVBxJS9EblGeQ8y+O8eCa6RcW874vxEc=",
|
||||||
"owner": "NixOS",
|
"owner" : "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo" : "nixpkgs",
|
||||||
"rev": "cf59864ef8aa2e178cccedbe2c178185b0365705",
|
"rev" : "cf59864ef8aa2e178cccedbe2c178185b0365705",
|
||||||
"type": "github"
|
"type" : "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original" : {
|
||||||
"owner": "NixOS",
|
"owner" : "NixOS",
|
||||||
"ref": "nixos-unstable",
|
"ref" : "nixos-unstable",
|
||||||
"repo": "nixpkgs",
|
"repo" : "nixpkgs",
|
||||||
"type": "github"
|
"type" : "github"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"root": {
|
"root" : {"inputs" : {"nixpkgs" : "nixpkgs"}}
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": "nixpkgs"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"root": "root",
|
"root" : "root",
|
||||||
"version": 7
|
"version" : 7
|
||||||
}
|
}
|
||||||
|
|||||||
25
flake.nix
25
flake.nix
@@ -3,30 +3,23 @@
|
|||||||
|
|
||||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
|
||||||
outputs =
|
outputs = {
|
||||||
{
|
|
||||||
self,
|
self,
|
||||||
nixpkgs,
|
nixpkgs,
|
||||||
}:
|
} : let system = "x86_64-linux";
|
||||||
let
|
|
||||||
system = "x86_64-linux";
|
|
||||||
pkgs = import nixpkgs { inherit system; };
|
pkgs = import nixpkgs { inherit system; };
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
devShells.${system}.default = pkgs.mkShell {
|
devShells.${system}.default = pkgs.mkShell {
|
||||||
nativeBuildInputs = with pkgs; [
|
nativeBuildInputs = with pkgs;
|
||||||
gcc
|
[gcc clang -
|
||||||
clang-tools
|
tools lldb
|
||||||
lldb
|
|
||||||
|
|
||||||
meson
|
meson ninja pkg -
|
||||||
ninja
|
config
|
||||||
pkg-config
|
|
||||||
|
|
||||||
gtk4
|
gtk4
|
||||||
|
|
||||||
gdb
|
gdb];
|
||||||
];
|
|
||||||
|
|
||||||
shellHook = "";
|
shellHook = "";
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ gtk = dependency('gtk4', required: true)
|
|||||||
|
|
||||||
src = files(
|
src = files(
|
||||||
'src/main.c',
|
'src/main.c',
|
||||||
'src/matrix.c',
|
'src/core/matrix.c',
|
||||||
|
'src/core/primitives.c',
|
||||||
|
'src/core/raster.c',
|
||||||
'src/ui/uicontroller.c',
|
'src/ui/uicontroller.c',
|
||||||
'src/ui/vektorcanvas.c'
|
'src/ui/vektorcanvas.c'
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "matrix.h"
|
#include "matrix.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
|
inline M33 m33_zero(void) { return (M33){{{0, 0, 0}, {0, 0, 0}, {0, 0, 0}}}; }
|
||||||
|
|
||||||
inline M33 m33_identity(void) {
|
inline M33 m33_identity(void) {
|
||||||
return (M33){{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}};
|
return (M33){{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}};
|
||||||
}
|
}
|
||||||
@@ -18,6 +20,10 @@ inline M33 m33_rotate(double theta) {
|
|||||||
{{cos(theta), -sin(theta), 0}, {sin(theta), cos(theta), 0}, {0, 0, 1}}};
|
{{cos(theta), -sin(theta), 0}, {sin(theta), cos(theta), 0}, {0, 0, 1}}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline M33 m33_shear(double theta_x, double theta_y) {
|
||||||
|
return (M33){{{1, tan(theta_x), 0}, {tan(theta_y), 1, 0}, {0, 0, 0}}};
|
||||||
|
}
|
||||||
|
|
||||||
M33 m33_add(const M33 m1, const M33 m2) {
|
M33 m33_add(const M33 m1, const M33 m2) {
|
||||||
M33 res;
|
M33 res;
|
||||||
for (int i = 0; i < 3; ++i)
|
for (int i = 0; i < 3; ++i)
|
||||||
@@ -12,6 +12,7 @@ M33 m33_identity(void);
|
|||||||
M33 m33_translate(double tx, double ty);
|
M33 m33_translate(double tx, double ty);
|
||||||
M33 m33_scale(double sx, double sy);
|
M33 m33_scale(double sx, double sy);
|
||||||
M33 m33_rotate(double rad);
|
M33 m33_rotate(double rad);
|
||||||
|
M33 m33_shear(double theta_x, double theta_y);
|
||||||
|
|
||||||
M33 m33_add(const M33 m1, const M33 m2);
|
M33 m33_add(const M33 m1, const M33 m2);
|
||||||
M33 m33_sub(const M33 m1, const M33 m2);
|
M33 m33_sub(const M33 m1, const M33 m2);
|
||||||
47
src/core/primitives.c
Normal file
47
src/core/primitives.c
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#include "primitives.h"
|
||||||
|
|
||||||
|
Polyline *mk_polyline(void) {
|
||||||
|
Polyline *pl = malloc(sizeof(Polyline));
|
||||||
|
pl->count = 0;
|
||||||
|
pl->capacity = 4;
|
||||||
|
pl->points = malloc(sizeof(V2) * pl->capacity);
|
||||||
|
return pl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_point_polyline(Polyline *pl, V2 point) {
|
||||||
|
if (pl->count >= pl->capacity) {
|
||||||
|
pl->capacity *= 2;
|
||||||
|
pl->points = realloc(pl->points, sizeof(V2) * pl->capacity);
|
||||||
|
}
|
||||||
|
pl->points[pl->count++] = point;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_polyline(Polyline *pl) {
|
||||||
|
if (!pl)
|
||||||
|
return;
|
||||||
|
free(pl->points);
|
||||||
|
free(pl);
|
||||||
|
}
|
||||||
|
|
||||||
|
Polygon *mk_polygon(void) {
|
||||||
|
Polygon *pg = malloc(sizeof(Polygon));
|
||||||
|
pg->count = 0;
|
||||||
|
pg->capacity = 4;
|
||||||
|
pg->points = malloc(sizeof(V2) * pg->capacity);
|
||||||
|
return pg;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_point_polygon(Polygon *pg, V2 point) {
|
||||||
|
if (pg->count >= pg->capacity) {
|
||||||
|
pg->capacity *= 2;
|
||||||
|
pg->points = realloc(pg->points, sizeof(V2) * pg->capacity);
|
||||||
|
}
|
||||||
|
pg->points[pg->count++] = point;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free_polygon(Polygon *pg) {
|
||||||
|
if (!pg)
|
||||||
|
return;
|
||||||
|
free(pg->points);
|
||||||
|
free(pg);
|
||||||
|
}
|
||||||
50
src/core/primitives.h
Normal file
50
src/core/primitives.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
#ifndef PRIMITIVES_H_
|
||||||
|
#define PRIMITIVES_H_
|
||||||
|
|
||||||
|
#include "stddef.h"
|
||||||
|
#include "stdlib.h"
|
||||||
|
#include "vector.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
V2 p1;
|
||||||
|
V2 p2;
|
||||||
|
} Line;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
V2 *points;
|
||||||
|
size_t count;
|
||||||
|
size_t capacity;
|
||||||
|
} Polyline;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
V2 *points;
|
||||||
|
size_t count;
|
||||||
|
size_t capacity;
|
||||||
|
} Polygon;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
V2 center;
|
||||||
|
double radius;
|
||||||
|
} Circle;
|
||||||
|
|
||||||
|
typedef enum { LINE, POLYLINE, POLYGON, CIRCLE } PrimitiveKind;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PrimitiveKind kind;
|
||||||
|
union {
|
||||||
|
Line line;
|
||||||
|
Polyline *polyline;
|
||||||
|
Polygon *polygon;
|
||||||
|
Circle circle;
|
||||||
|
};
|
||||||
|
} Primitive;
|
||||||
|
|
||||||
|
Polyline *mk_polyline(void);
|
||||||
|
void add_point_polyline(Polyline *pl, V2 point);
|
||||||
|
void free_polyline(Polyline *pl);
|
||||||
|
|
||||||
|
Polygon *mk_polygon(void);
|
||||||
|
void add_point_polygon(Polygon *pl, V2 point);
|
||||||
|
void free_polygon(Polygon *pl);
|
||||||
|
|
||||||
|
#endif // PRIMITIVES_H_
|
||||||
80
src/core/raster.c
Normal file
80
src/core/raster.c
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
#include "raster.h"
|
||||||
|
#include "primitives.h"
|
||||||
|
#include "stddef.h"
|
||||||
|
|
||||||
|
void add_edge(EdgeBuffer *buffer, Edge edge) {
|
||||||
|
if (buffer->count >= buffer->capacity) {
|
||||||
|
buffer->capacity = buffer->capacity ? buffer->capacity * 2 : 4;
|
||||||
|
buffer->edges = realloc(buffer->edges, sizeof(Edge) * buffer->capacity);
|
||||||
|
}
|
||||||
|
buffer->edges[buffer->count++] = edge;
|
||||||
|
}
|
||||||
|
|
||||||
|
void flatten_line(EdgeBuffer *buffer, Line line) {
|
||||||
|
add_edge(buffer, (Edge){line.p1, line.p2, 0});
|
||||||
|
}
|
||||||
|
|
||||||
|
void flatten_polyline(EdgeBuffer *buffer, Polyline *line) {
|
||||||
|
for (size_t i = 0; i + 1 < line->count; i++) {
|
||||||
|
add_edge(buffer, (Edge){line->points[i], line->points[i + 1], 0});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void flatten_polygon(EdgeBuffer *buffer, Polygon *pg) {
|
||||||
|
size_t n = pg->count;
|
||||||
|
if (n < 3)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < n; i++) {
|
||||||
|
V2 p1 = pg->points[i];
|
||||||
|
V2 p2 = pg->points[(i + 1) % n];
|
||||||
|
int winding = (p1.y < p2.y) ? +1 : -1;
|
||||||
|
add_edge(buffer, (Edge){p1, p2, winding});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Framebuffer mk_framebuffer(unsigned int W, unsigned int H) {
|
||||||
|
Framebuffer fb = {.width = W, .height = H, .pixels = calloc(W * H * 3, 1)};
|
||||||
|
return fb;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void put_pixel(Framebuffer *fb, int x, int y, unsigned char r,
|
||||||
|
unsigned char g, unsigned char b) {
|
||||||
|
if ((unsigned)x >= fb->width || (unsigned)y >= fb->height)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int i = (y * fb->width + x) * 3;
|
||||||
|
fb->pixels[i + 0] = r;
|
||||||
|
fb->pixels[i + 1] = g;
|
||||||
|
fb->pixels[i + 2] = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_line(Framebuffer *fb, V2 a, V2 b, unsigned char r, unsigned char g,
|
||||||
|
unsigned char bl) {
|
||||||
|
int x0 = (int)a.x;
|
||||||
|
int y0 = (int)a.y;
|
||||||
|
int x1 = (int)b.x;
|
||||||
|
int y1 = (int)b.y;
|
||||||
|
|
||||||
|
int dx = abs(x1 - x0);
|
||||||
|
int sx = x0 < x1 ? 1 : -1;
|
||||||
|
int dy = -abs(y1 - y0);
|
||||||
|
int sy = y0 < y1 ? 1 : -1;
|
||||||
|
int err = dx + dy;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
put_pixel(fb, x0, y0, r, g, bl);
|
||||||
|
if (x0 == x1 && y0 == y1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
int e2 = 2 * err;
|
||||||
|
if (e2 >= dy) {
|
||||||
|
err += dy;
|
||||||
|
x0 += sx;
|
||||||
|
}
|
||||||
|
if (e2 <= dx) {
|
||||||
|
err += dx;
|
||||||
|
y0 += sy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
40
src/core/raster.h
Normal file
40
src/core/raster.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#ifndef RASTER_H_
|
||||||
|
#define RASTER_H_
|
||||||
|
|
||||||
|
#include "primitives.h"
|
||||||
|
#include "stddef.h"
|
||||||
|
#include "vector.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
V2 p1;
|
||||||
|
V2 p2;
|
||||||
|
int winding;
|
||||||
|
} Edge;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Edge *edges;
|
||||||
|
size_t count;
|
||||||
|
size_t capacity;
|
||||||
|
} EdgeBuffer;
|
||||||
|
|
||||||
|
void add_edge(EdgeBuffer *edges, Edge edge);
|
||||||
|
|
||||||
|
void flatten_line(EdgeBuffer *edges, Line line);
|
||||||
|
void flatten_polyline(EdgeBuffer *edges, Polyline *line);
|
||||||
|
void flatten_polygon(EdgeBuffer *buffer, Polygon *line);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int width;
|
||||||
|
unsigned int height;
|
||||||
|
unsigned char *pixels; // Flat RGB8 array
|
||||||
|
} Framebuffer;
|
||||||
|
|
||||||
|
Framebuffer mk_framebuffer(unsigned int width, unsigned int height);
|
||||||
|
|
||||||
|
void put_pixel(Framebuffer *fb, int x, int y, unsigned char r, unsigned char g,
|
||||||
|
unsigned char b);
|
||||||
|
|
||||||
|
void draw_line(Framebuffer *fb, V2 a, V2 b, unsigned char r, unsigned char g,
|
||||||
|
unsigned char bl);
|
||||||
|
|
||||||
|
#endif // RASTER_H_
|
||||||
@@ -8,6 +8,16 @@ typedef struct {
|
|||||||
double y;
|
double y;
|
||||||
} V2;
|
} V2;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
} V3;
|
||||||
|
|
||||||
|
static inline V3 vec2_vector(const V2 v) { return (V3){v.x, v.y, 0}; }
|
||||||
|
|
||||||
|
static inline V3 vec2_point(const V2 v) { return (V3){v.x, v.y, 1}; }
|
||||||
|
|
||||||
static inline V2 vec2_add(const V2 v1, const V2 v2) {
|
static inline V2 vec2_add(const V2 v1, const V2 v2) {
|
||||||
return (V2){v1.x + v2.x, v1.y + v2.y};
|
return (V2){v1.x + v2.x, v1.y + v2.y};
|
||||||
}
|
}
|
||||||
39
src/main.c
39
src/main.c
@@ -2,31 +2,58 @@
|
|||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
#include "stdlib.h"
|
#include "stdlib.h"
|
||||||
|
|
||||||
|
#include "./core/raster.h"
|
||||||
#include "./ui/uicontroller.h"
|
#include "./ui/uicontroller.h"
|
||||||
#include "./ui/vektorcanvas.h"
|
#include "./ui/vektorcanvas.h"
|
||||||
|
|
||||||
|
static void on_map(GtkWidget *window, gpointer user_data) {
|
||||||
static void on_map(GtkWidget* window, gpointer user_data) {
|
vektor_uictrl_map((VektorWidgetState *)user_data);
|
||||||
vektor_uictrl_map((VektorWidgetState*)user_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void activate(GtkApplication *app, gpointer user_data) {
|
static void activate(GtkApplication *app, gpointer user_data) {
|
||||||
|
|
||||||
VektorWidgetState* widget_state = (VektorWidgetState*)malloc(sizeof(VektorWidgetState));
|
VektorWidgetState *widget_state =
|
||||||
|
(VektorWidgetState *)malloc(sizeof(VektorWidgetState));
|
||||||
vektor_uictrl_init(app, widget_state);
|
vektor_uictrl_init(app, widget_state);
|
||||||
|
|
||||||
VektorCanvas* canvas = (VektorCanvas*)malloc(sizeof(VektorCanvas));
|
VektorCanvas *canvas = (VektorCanvas *)malloc(sizeof(VektorCanvas));
|
||||||
vektor_canvas_init(widget_state, canvas);
|
vektor_canvas_init(widget_state, canvas);
|
||||||
VektorCanvasColor red = vektor_color_new(255, 0, 0, 255);
|
VektorCanvasColor red = vektor_color_new(255, 0, 0, 255);
|
||||||
vektor_canvas_fill(canvas, &red);
|
vektor_canvas_fill(canvas, &red);
|
||||||
vektor_canvas_update(canvas);
|
vektor_canvas_update(canvas);
|
||||||
|
|
||||||
g_signal_connect(widget_state->window, "map", G_CALLBACK(on_map), widget_state);
|
g_signal_connect(widget_state->window, "map", G_CALLBACK(on_map),
|
||||||
|
widget_state);
|
||||||
|
|
||||||
gtk_window_present(widget_state->window);
|
gtk_window_present(widget_state->window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void write_ppm(const char *path, const Framebuffer *fb) {
|
||||||
|
FILE *f = fopen(path, "wb");
|
||||||
|
if (!f)
|
||||||
|
abort();
|
||||||
|
|
||||||
|
fprintf(f, "P6\n%d %d\n255\n", fb->width, fb->height);
|
||||||
|
fwrite(fb->pixels, 1, fb->width * fb->height * 3, f);
|
||||||
|
fclose(f);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
Framebuffer fb = mk_framebuffer(256, 256);
|
||||||
|
EdgeBuffer edges = {0};
|
||||||
|
|
||||||
|
Polygon pg = *mk_polygon();
|
||||||
|
add_point_polygon(&pg, (V2){50, 50});
|
||||||
|
add_point_polygon(&pg, (V2){200, 80});
|
||||||
|
add_point_polygon(&pg, (V2){120, 200});
|
||||||
|
|
||||||
|
flatten_polygon(&edges, &pg);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < edges.count; i++) {
|
||||||
|
draw_line(&fb, edges.edges[i].p1, edges.edges[i].p2, 255, 255, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
write_ppm("out.ppm", &fb);
|
||||||
|
|
||||||
GtkApplication *app;
|
GtkApplication *app;
|
||||||
int status;
|
int status;
|
||||||
|
|||||||
@@ -1,20 +1,22 @@
|
|||||||
#include "uicontroller.h"
|
#include "uicontroller.h"
|
||||||
#include "gtk/gtk.h"
|
#include "gtk/gtk.h"
|
||||||
|
|
||||||
void vektor_uictrl_init(GtkApplication* app, VektorWidgetState* stateOut) {
|
void vektor_uictrl_init(GtkApplication *app, VektorWidgetState *stateOut) {
|
||||||
GtkBuilder* builder = gtk_builder_new();
|
GtkBuilder *builder = gtk_builder_new();
|
||||||
GError* error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
g_print("%s\n", g_get_current_dir());
|
g_print("%s\n", g_get_current_dir());
|
||||||
|
|
||||||
// TODO: .ui files as resources instead of sketchy relative paths
|
// TODO: .ui files as resources instead of sketchy relative paths
|
||||||
if(!gtk_builder_add_from_file(builder, "./ui/main.ui", &error)) {
|
if (!gtk_builder_add_from_file(builder, "./ui/main.ui", &error)) {
|
||||||
g_error("Fatal: %s", error->message);
|
g_error("Fatal: %s", error->message);
|
||||||
}
|
}
|
||||||
|
|
||||||
stateOut->window = GTK_WINDOW(gtk_builder_get_object(builder, "main_window"));
|
stateOut->window = GTK_WINDOW(gtk_builder_get_object(builder, "main_window"));
|
||||||
stateOut->workspacePaned = GTK_PANED(gtk_builder_get_object(builder, "workspace_paned"));
|
stateOut->workspacePaned =
|
||||||
stateOut->workspaceCanvas = GTK_PICTURE(gtk_builder_get_object(builder, "workspace"));
|
GTK_PANED(gtk_builder_get_object(builder, "workspace_paned"));
|
||||||
|
stateOut->workspaceCanvas =
|
||||||
|
GTK_PICTURE(gtk_builder_get_object(builder, "workspace"));
|
||||||
|
|
||||||
gtk_window_set_application(stateOut->window, app);
|
gtk_window_set_application(stateOut->window, app);
|
||||||
gtk_window_set_title(stateOut->window, "Vektor");
|
gtk_window_set_title(stateOut->window, "Vektor");
|
||||||
@@ -23,7 +25,7 @@ void vektor_uictrl_init(GtkApplication* app, VektorWidgetState* stateOut) {
|
|||||||
g_object_unref(builder);
|
g_object_unref(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vektor_uictrl_map(VektorWidgetState* state) {
|
void vektor_uictrl_map(VektorWidgetState *state) {
|
||||||
|
|
||||||
// set the workspace divider to 7:3 ratio
|
// set the workspace divider to 7:3 ratio
|
||||||
int window_width = gtk_widget_get_width(GTK_WIDGET(state->window));
|
int window_width = gtk_widget_get_width(GTK_WIDGET(state->window));
|
||||||
|
|||||||
@@ -8,14 +8,14 @@ Global application widget state, holding references to
|
|||||||
all the widgets used in internal logic of the program
|
all the widgets used in internal logic of the program
|
||||||
*/
|
*/
|
||||||
typedef struct VektorWidgetState {
|
typedef struct VektorWidgetState {
|
||||||
GtkWindow* window;
|
GtkWindow *window;
|
||||||
GtkPaned* workspacePaned;
|
GtkPaned *workspacePaned;
|
||||||
GtkPicture* workspaceCanvas;
|
GtkPicture *workspaceCanvas;
|
||||||
|
|
||||||
//GtkWidget* Workspace
|
// GtkWidget* Workspace
|
||||||
} VektorWidgetState;
|
} VektorWidgetState;
|
||||||
|
|
||||||
void vektor_uictrl_init(GtkApplication* app, VektorWidgetState* stateOut);
|
void vektor_uictrl_init(GtkApplication *app, VektorWidgetState *stateOut);
|
||||||
void vektor_uictrl_map(VektorWidgetState* state);
|
void vektor_uictrl_map(VektorWidgetState *state);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,65 +1,57 @@
|
|||||||
#include "gtk/gtk.h"
|
#include "gtk/gtk.h"
|
||||||
|
|
||||||
#include "vektorcanvas.h"
|
|
||||||
#include "uicontroller.h"
|
#include "uicontroller.h"
|
||||||
|
#include "vektorcanvas.h"
|
||||||
|
|
||||||
#define VKTR_CANVAS_WIDTH 400
|
#define VKTR_CANVAS_WIDTH 400
|
||||||
#define VKTR_CANVAS_HEIGHT 400
|
#define VKTR_CANVAS_HEIGHT 400
|
||||||
#define VKTR_CANVAS_SIZE (VKTR_CANVAS_WIDTH * VKTR_CANVAS_HEIGHT * 4)
|
#define VKTR_CANVAS_SIZE (VKTR_CANVAS_WIDTH * VKTR_CANVAS_HEIGHT * 4)
|
||||||
|
|
||||||
void vektor_canvas_init(VektorWidgetState* state, VektorCanvas* canvasOut) {
|
void vektor_canvas_init(VektorWidgetState *state, VektorCanvas *canvasOut) {
|
||||||
canvasOut->canvasWidget = state->workspaceCanvas;
|
canvasOut->canvasWidget = state->workspaceCanvas;
|
||||||
canvasOut->width = VKTR_CANVAS_WIDTH;
|
canvasOut->width = VKTR_CANVAS_WIDTH;
|
||||||
canvasOut->height = VKTR_CANVAS_HEIGHT;
|
canvasOut->height = VKTR_CANVAS_HEIGHT;
|
||||||
canvasOut->canvasPixels = g_malloc0(VKTR_CANVAS_SIZE);
|
canvasOut->canvasPixels = g_malloc0(VKTR_CANVAS_SIZE);
|
||||||
|
|
||||||
canvasOut->canvasPixelBytes = g_bytes_new(canvasOut->canvasPixels, VKTR_CANVAS_SIZE);
|
canvasOut->canvasPixelBytes =
|
||||||
|
g_bytes_new(canvasOut->canvasPixels, VKTR_CANVAS_SIZE);
|
||||||
canvasOut->canvasTexture = gdk_memory_texture_new(
|
canvasOut->canvasTexture = gdk_memory_texture_new(
|
||||||
VKTR_CANVAS_WIDTH,
|
VKTR_CANVAS_WIDTH, VKTR_CANVAS_HEIGHT, GDK_MEMORY_R8G8B8A8,
|
||||||
VKTR_CANVAS_HEIGHT,
|
canvasOut->canvasPixelBytes, VKTR_CANVAS_WIDTH * 4);
|
||||||
GDK_MEMORY_R8G8B8A8,
|
|
||||||
canvasOut->canvasPixelBytes,
|
|
||||||
VKTR_CANVAS_WIDTH * 4
|
|
||||||
);
|
|
||||||
|
|
||||||
gtk_picture_set_paintable(canvasOut->canvasWidget, GDK_PAINTABLE(canvasOut->canvasTexture));
|
gtk_picture_set_paintable(canvasOut->canvasWidget,
|
||||||
|
GDK_PAINTABLE(canvasOut->canvasTexture));
|
||||||
|
|
||||||
//g_object_unref(bytes);
|
// g_object_unref(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vektor_canvas_update(VektorCanvas* canvas) {
|
void vektor_canvas_update(VektorCanvas *canvas) {
|
||||||
g_bytes_unref(canvas->canvasPixelBytes);
|
g_bytes_unref(canvas->canvasPixelBytes);
|
||||||
canvas->canvasPixelBytes = g_bytes_new(canvas->canvasPixels, VKTR_CANVAS_SIZE);
|
canvas->canvasPixelBytes =
|
||||||
|
g_bytes_new(canvas->canvasPixels, VKTR_CANVAS_SIZE);
|
||||||
|
|
||||||
g_object_unref(canvas->canvasTexture);
|
g_object_unref(canvas->canvasTexture);
|
||||||
canvas->canvasTexture = gdk_memory_texture_new(
|
canvas->canvasTexture =
|
||||||
canvas->width, canvas->height,
|
gdk_memory_texture_new(canvas->width, canvas->height, GDK_MEMORY_R8G8B8A8,
|
||||||
GDK_MEMORY_R8G8B8A8,
|
canvas->canvasPixelBytes, canvas->width * 4);
|
||||||
canvas->canvasPixelBytes,
|
|
||||||
canvas->width * 4
|
|
||||||
);
|
|
||||||
|
|
||||||
gtk_picture_set_paintable(canvas->canvasWidget, GDK_PAINTABLE(canvas->canvasTexture));
|
gtk_picture_set_paintable(canvas->canvasWidget,
|
||||||
|
GDK_PAINTABLE(canvas->canvasTexture));
|
||||||
}
|
}
|
||||||
|
|
||||||
void vektor_canvas_fill(VektorCanvas* canvas, VektorCanvasColor* color) {
|
void vektor_canvas_fill(VektorCanvas *canvas, VektorCanvasColor *color) {
|
||||||
for(int x = 0; x < VKTR_CANVAS_WIDTH; x++) {
|
for (int x = 0; x < VKTR_CANVAS_WIDTH; x++) {
|
||||||
for(int y = 0; y < VKTR_CANVAS_HEIGHT; y++) {
|
for (int y = 0; y < VKTR_CANVAS_HEIGHT; y++) {
|
||||||
int i = (y * VKTR_CANVAS_WIDTH + x) * 4;
|
int i = (y * VKTR_CANVAS_WIDTH + x) * 4;
|
||||||
canvas->canvasPixels[i+0] = color->r;
|
canvas->canvasPixels[i + 0] = color->r;
|
||||||
canvas->canvasPixels[i+1] = color->g;
|
canvas->canvasPixels[i + 1] = color->g;
|
||||||
canvas->canvasPixels[i+2] = color->b;
|
canvas->canvasPixels[i + 2] = color->b;
|
||||||
canvas->canvasPixels[i+3] = color->a;
|
canvas->canvasPixels[i + 3] = color->a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VektorCanvasColor vektor_color_new(guchar cr, guchar cg, guchar cb, guchar ca) {
|
VektorCanvasColor vektor_color_new(guchar cr, guchar cg, guchar cb, guchar ca) {
|
||||||
VektorCanvasColor c = {
|
VektorCanvasColor c = {.r = cr, .g = cg, .b = cb, .a = ca};
|
||||||
.r = cr,
|
|
||||||
.g = cg,
|
|
||||||
.b = cb,
|
|
||||||
.a = ca
|
|
||||||
};
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@@ -4,12 +4,12 @@
|
|||||||
#include "uicontroller.h"
|
#include "uicontroller.h"
|
||||||
|
|
||||||
typedef struct VektorCanvas {
|
typedef struct VektorCanvas {
|
||||||
GtkPicture* canvasWidget;
|
GtkPicture *canvasWidget;
|
||||||
|
|
||||||
// texture related stuff
|
// texture related stuff
|
||||||
guchar* canvasPixels;
|
guchar *canvasPixels;
|
||||||
GdkTexture* canvasTexture;
|
GdkTexture *canvasTexture;
|
||||||
GBytes* canvasPixelBytes;
|
GBytes *canvasPixelBytes;
|
||||||
|
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
@@ -22,9 +22,9 @@ typedef struct VektorCanvasColor {
|
|||||||
guchar a;
|
guchar a;
|
||||||
} VektorCanvasColor;
|
} VektorCanvasColor;
|
||||||
|
|
||||||
void vektor_canvas_init(VektorWidgetState* state, VektorCanvas* canvasOut);
|
void vektor_canvas_init(VektorWidgetState *state, VektorCanvas *canvasOut);
|
||||||
void vektor_canvas_update(VektorCanvas* canvas);
|
void vektor_canvas_update(VektorCanvas *canvas);
|
||||||
void vektor_canvas_fill(VektorCanvas* canvas, VektorCanvasColor* color);
|
void vektor_canvas_fill(VektorCanvas *canvas, VektorCanvasColor *color);
|
||||||
|
|
||||||
VektorCanvasColor vektor_color_new(guchar r, guchar g, guchar b, guchar a);
|
VektorCanvasColor vektor_color_new(guchar r, guchar g, guchar b, guchar a);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user