Author | Jakob Wakeling <[email protected]> |
Date | 2024-03-15 22:36:25 |
Commit | 0c1b980371b5318e4b136d5a58328b17cf2b60c9 |
Parent | e9e986772888d197ec72f63cf80d0a7778702ca9 |
Implement a line drawing function
Diffstat
M | src/draw.c | | | 28 | +++++++++++++++++++++++++--- |
M | src/draw.h | | | 2 | ++ |
M | src/x11/draw.c | | | 10 | +++++++++- |
3 files changed, 36 insertions, 4 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,