libdraw

Minimal window and drawing library
git clone http://git.omkov.net/libdraw
Log | Tree | Refs | Download

libdraw/src/draw.c (96 lines, 3.1 KiB) -rw-r--r-- file download

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