ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
0
|
// Copyright (C) 2024, Jakob Wakeling |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
1
|
// All rights reserved. |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
2
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
3
|
#include "draw.h" |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
4
|
#include "util/util.h" |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
5
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
6
|
#include <stdlib.h> |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
7
|
|
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
8
|
#define PIXEL(B, X, Y) (B->buf[((Y) * B->bounds.w) + (X)]) |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
9
|
#define SET(B, X, Y, C) (PIXEL(B, X, Y) = C) |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
10
|
#define IS_BOUND(B, X, Y) ((X) >= (B)->bounds.x && (X) < (B)->bounds.w && (Y) >= (B)->bounds.y && (Y) < (B)->bounds.h) |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
11
|
#define SET_BOUND(B, X, Y, C) (IS_BOUND(B, X, Y) ? SET(B, X, Y, C) : 0) |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
12
|
|
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
13
|
bool draw_debug = false, draw_debug_verbose = false; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
14
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
15
|
draw_buffer *draw_buffer_init(int32_t w, int32_t h) { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
16
|
draw_buffer *buf = calloc(1, sizeof(draw_buffer)); if (buf == NULL) { return NULL; } |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
17
|
*buf = (draw_buffer){ .bounds = {0, 0, w, h}, .buf = malloc((w * h) * sizeof(uint32_t)) }; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
18
|
if (buf->buf == NULL) { free(buf); return NULL; } return buf; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
19
|
} |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
20
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
21
|
void draw_buffer_free(draw_buffer **buf) { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
22
|
free((*buf)->buf); free(*buf); *buf = NULL; |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
23
|
} |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
24
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
25
|
void draw_buffer_copy(draw_buffer *dst, draw_buffer *src, point dp, rect sr) { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
26
|
for (int32_t x = 0; x < dst->bounds.w && x < (src->bounds.w - src->bounds.x); x += 1) { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
27
|
for (int32_t y = 0; y < dst->bounds.h && y < (src->bounds.h - src->bounds.y); y += 1) { |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
28
|
PIXEL(dst, x + dp.x, y + dp.y) = PIXEL(src, x + sr.x, y + sr.y); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
29
|
} |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
30
|
} |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
31
|
} |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
32
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
33
|
void draw_buffer_clear(draw_buffer *buf, uint32_t colour) { |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
34
|
for (int64_t i = 0; i < buf->bounds.w * buf->bounds.h; i += 1) { buf->buf[i] = colour; } |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
35
|
} |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
36
|
|
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
37
|
void draw_buffer_rect(draw_buffer *buf, point p, rect r, uint32_t colour) { |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
38
|
int32_t x0 = CLAMP(p.x + r.x, buf->bounds.x, buf->bounds.w), y0 = CLAMP(p.y + r.y, buf->bounds.y, buf->bounds.h); |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
39
|
int32_t x1 = CLAMP(p.x + r.w, buf->bounds.x, buf->bounds.w), y1 = CLAMP(p.y + r.h, buf->bounds.y, buf->bounds.h); |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
40
|
for (int32_t x = x0; x < x1; x += 1) for (int32_t y = y0; y < y1; y += 1) { SET(buf, x, y, colour); } |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
41
|
} |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
42
|
|
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
43
|
void draw_buffer_line(draw_buffer *buf, point p0, point p1, uint32_t colour) { |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
44
|
int32_t dx = abs(p1.x - p0.x); |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
45
|
int32_t dy = abs(p1.y - p0.y); |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
46
|
|
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
47
|
int32_t sx = p0.x < p1.x ? 1 : -1; |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
48
|
int32_t sy = p0.y < p1.y ? 1 : -1; |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
49
|
|
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
50
|
int32_t e = dx - dy; |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
51
|
|
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
52
|
for (;;) { |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
53
|
SET_BOUND(buf, p0.x, p0.y, colour); |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
54
|
if (p0.x == p1.x && p0.y == p1.y) { break; } |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
55
|
|
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
56
|
int32_t e2 = 2 * e; |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
57
|
if (e2 > -dy) { e -= dy; p0.x += sx; } |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
58
|
if (e2 < dx) { e += dx; p0.y += sy; } |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
59
|
} |
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
60
|
|
0c1b980 |
Jakob Wakeling |
2024-03-16 11:36:25 |
61
|
SET_BOUND(buf, p0.x, p0.y, colour); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
62
|
} |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
63
|
|
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
64
|
void draw_buffer_circle(draw_buffer *buf, point p, int32_t r, uint32_t colour, bool fill) { |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
65
|
int32_t x = 0, y = r, d = 3 - (2 * r); |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
66
|
|
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
67
|
while (x <= y) { |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
68
|
if (fill) { |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
69
|
for (int32_t i = -x; i <= x; i++) { |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
70
|
SET_BOUND(buf, p.x + i, p.y + y, colour); |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
71
|
SET_BOUND(buf, p.x + i, p.y - y, colour); |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
72
|
} |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
73
|
|
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
74
|
for (int32_t i = -y; i <= y; i++) { |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
75
|
SET_BOUND(buf, p.x + i, p.y + x, colour); |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
76
|
SET_BOUND(buf, p.x + i, p.y - x, colour); |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
77
|
} |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
78
|
} |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
79
|
else { |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
80
|
SET_BOUND(buf, p.x + x, p.y + y, colour); |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
81
|
SET_BOUND(buf, p.x + x, p.y - y, colour); |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
82
|
SET_BOUND(buf, p.x - x, p.y + y, colour); |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
83
|
SET_BOUND(buf, p.x - x, p.y - y, colour); |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
84
|
SET_BOUND(buf, p.x + y, p.y + x, colour); |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
85
|
SET_BOUND(buf, p.x + y, p.y - x, colour); |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
86
|
SET_BOUND(buf, p.x - y, p.y + x, colour); |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
87
|
SET_BOUND(buf, p.x - y, p.y - x, colour); |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
88
|
} |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
89
|
|
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
90
|
x += 1; |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
91
|
if (d < 0) { d += (4 * x) + 6; } |
e9e9867 |
Jakob Wakeling |
2024-03-11 22:03:59 |
92
|
else { d += (4 * (x - y)) + 10; y -= 1; } |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
93
|
} |
ccd60e6 |
Jakob Wakeling |
2024-03-10 19:35:51 |
94
|
} |
|
|
|
95
|
|