libdraw

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

AuthorJakob Wakeling <[email protected]>
Date2024-03-15 22:36:25
Commit0c1b980371b5318e4b136d5a58328b17cf2b60c9
Parente9e986772888d197ec72f63cf80d0a7778702ca9

Implement a line drawing function

Diffstat

M src/draw.c | 27 +++++++++++++++++++++++++--
M src/draw.h | 2 ++
M src/x11/draw.c | 9 ++++++++-

3 files changed, 35 insertions, 3 deletions

diff --git a/src/draw.c b/src/draw.c
index 7e135fa..17455d4 100644
--- a/src/draw.c
+++ b/src/draw.c
@@ -6,7 +6,8 @@
 
 #include <stdlib.h>
 
-#define SET(B, X, Y, C) (B->buf[((Y) * B->bounds.w) + (X)] = C)
+#define PIXEL(B, X, Y) (B->buf[((Y) * B->bounds.w) + (X)])
+#define SET(B, X, Y, C) (PIXEL(B, X, Y) = C)
 #define IS_BOUND(B, X, Y) ((X) >= (B)->bounds.x && (X) < (B)->bounds.w && (Y) >= (B)->bounds.y && (Y) < (B)->bounds.h)
 #define SET_BOUND(B, X, Y, C) (IS_BOUND(B, X, Y) ? SET(B, X, Y, C) : 0)
 
@@ -25,7 +26,7 @@ void draw_buffer_free(draw_buffer **buf) {
 void draw_buffer_copy(draw_buffer *dst, draw_buffer *src, point dp, rect sr) {
 	for (int32_t x = 0; x < dst->bounds.w && x < (src->bounds.w - src->bounds.x); x += 1) {
 		for (int32_t y = 0; y < dst->bounds.h && y < (src->bounds.h - src->bounds.y); y += 1) {
-			dst->buf[((y + dp.y) * dst->bounds.w) + (x + dp.x)] = src->buf[((y + sr.y) * src->bounds.w) + (x + sr.x)];
+			PIXEL(dst, x + dp.x, y + dp.y) = PIXEL(src, x + sr.x, y + sr.y);
 		}
 	}
 }
@@ -37,7 +38,28 @@ void draw_buffer_clear(draw_buffer *buf, uint32_t colour) {
 void draw_buffer_rect(draw_buffer *buf, point p, rect r, uint32_t colour) {
 	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);
 	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);
-	for (; x0 < x1; x0 += 1) for (int32_t y = y0; y < y1; y += 1) { buf->buf[(y * buf->bounds.w) + x0] = colour; }
+	for (int32_t x = x0; x < x1; x += 1) for (int32_t y = y0; y < y1; y += 1) { SET(buf, x, y, colour); }
+}
+
+void draw_buffer_line(draw_buffer *buf, point p0, point p1, uint32_t colour) {
+	int32_t dx = abs(p1.x - p0.x);
+	int32_t dy = abs(p1.y - p0.y);
+
+	int32_t sx = p0.x < p1.x ? 1 : -1;
+	int32_t sy = p0.y < p1.y ? 1 : -1;
+
+	int32_t e = dx - dy;
+
+	for (;;) {
+		SET_BOUND(buf, p0.x, p0.y, colour);
+		if (p0.x == p1.x && p0.y == p1.y) { break; }
+
+		int32_t e2 = 2 * e;
+		if (e2 > -dy) { e -= dy; p0.x += sx; }
+		if (e2 < dx) { e += dx; p0.y += sy; }
+	}
+
+	SET_BOUND(buf, p0.x, p0.y, colour);
 }
 
 void draw_buffer_circle(draw_buffer *buf, point p, int32_t r, uint32_t colour, bool fill) {
diff --git a/src/draw.h b/src/draw.h
index 7adbe23..8bddd2b 100644
--- a/src/draw.h
+++ b/src/draw.h
@@ -72,6 +72,7 @@ extern int draw_window_init(draw_window **window, int32_t w, int32_t h, const ch
 extern void draw_window_free(draw_window **window);
 
 extern draw_event draw_window_event(draw_window *window);
+extern void draw_window_set_title(draw_window *window, const char *title);
 extern void draw_window_repaint(draw_window *window);
 
 extern int draw_window_draw(draw_window *w, point dp, draw_buffer *buf, rect br);
@@ -84,6 +85,7 @@ extern void draw_buffer_copy(draw_buffer *dst, draw_buffer *src, point dp, rect
 
 extern void draw_buffer_clear(draw_buffer *buf, uint32_t colour);
 extern void draw_buffer_rect(draw_buffer *buf, point p, rect r, uint32_t colour);
+extern void draw_buffer_line(draw_buffer *buf, point p0, point p1, uint32_t colour);
 extern void draw_buffer_circle(draw_buffer *buf, point p, int32_t r, uint32_t colour, bool fill);
 
 #endif // LIBDRAW_DRAW_H_RNC24Y6G
diff --git a/src/x11/draw.c b/src/x11/draw.c
index 6d52c17..d65ff0f 100644
--- a/src/x11/draw.c
+++ b/src/x11/draw.c
@@ -100,7 +100,7 @@ int draw_window_init(draw_window **window, int32_t w, int32_t h, const char *tit
 
 	xcb_change_property(
 		(*window)->connection, XCB_PROP_MODE_REPLACE, (*window)->window, XCB_ATOM_WM_CLASS, XCB_ATOM_STRING, 8,
-		strlen("libdraw"), "libdraw"
+		strlen(title), title
 	);
 
 	(*window)->symbols = xcb_key_symbols_alloc((*window)->connection);
@@ -222,6 +222,14 @@ draw_event draw_window_event(draw_window *window) {
 	free(_e); return event;
 }
 
+void draw_window_set_title(draw_window *window, const char *title) {
+	xcb_change_property(
+		window->connection, XCB_PROP_MODE_REPLACE, window->window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, strlen(title),
+		title
+	);
+	xcb_flush(window->connection);
+}
+
 void draw_window_repaint(draw_window *window) {
 	xcb_client_message_event_t e = {
 		.response_type = XCB_CLIENT_MESSAGE, .format = 32, .window = window->window, .type = ATOM_REPAINT,