master hovercats/oakiss / pkg / wld / patch / 0002-renderer-add-circle-and-line-primitives.patch
  1From c4801596c8ecc0f6476d0bf14582d2086f531853 Mon Sep 17 00:00:00 2001
  2From: dalem <lain@dalem.foo>
  3Date: Sat, 14 Mar 2026 19:30:03 +0100
  4Subject: [PATCH] renderer: add circle and line primitives
  5
  6---
  7 interface/renderer.h |  2 +
  8 renderer.c           | 95 ++++++++++++++++++++++++++++++++++++++++++++
  9 wld-private.h        |  4 ++
 10 wld.h                |  6 +++
 11 4 files changed, 107 insertions(+)
 12
 13diff --git a/interface/renderer.h b/interface/renderer.h
 14index 021aea1..0dabbfd 100644
 15--- a/interface/renderer.h
 16+++ b/interface/renderer.h
 17@@ -61,6 +61,8 @@ static const struct wld_renderer_impl wld_renderer_impl = {
 18 	.fill_region = &default_fill_region,
 19 	.copy_region = &default_copy_region,
 20 #endif
 21+	.draw_circle = &wld_draw_circle,
 22+	.draw_line = &wld_draw_line,
 23 	.draw_text = &renderer_draw_text,
 24 	.flush = &renderer_flush,
 25 	.destroy = &renderer_destroy
 26diff --git a/renderer.c b/renderer.c
 27index 569d6ba..e8a59c9 100644
 28--- a/renderer.c
 29+++ b/renderer.c
 30@@ -139,6 +139,101 @@ wld_copy_region(struct wld_renderer *renderer,
 31 	                            dst_x, dst_y, region);
 32 }
 33 
 34+static void
 35+circle_points(struct wld_renderer *renderer, uint32_t color, 
 36+              int32_t x1, int32_t y1, 
 37+              int32_t x2, int32_t y2, bool fill)
 38+{
 39+	if (fill) {
 40+		renderer->impl->fill_rectangle(renderer, color, x1-x2, y1+y2,
 41+				                       2*x2+1, 1);
 42+		renderer->impl->fill_rectangle(renderer, color, x1-x2, y1-y2,
 43+				                       2*x2+1, 1);
 44+		renderer->impl->fill_rectangle(renderer, color, x1-y2, y1+x2,
 45+				                       2*y2+1, 1);
 46+		renderer->impl->fill_rectangle(renderer, color, x1-y2, y1-x2,
 47+				                       2*y2+1, 1);
 48+	} else {
 49+		renderer->impl->fill_rectangle(renderer, color, x1+x2, y1+y2, 1, 1);
 50+		renderer->impl->fill_rectangle(renderer, color, x1-x2, y1+y2, 1, 1);
 51+		renderer->impl->fill_rectangle(renderer, color, x1+x2, y1-y2, 1, 1);
 52+		renderer->impl->fill_rectangle(renderer, color, x1-x2, y1-y2, 1, 1);
 53+		renderer->impl->fill_rectangle(renderer, color, x1+y2, y1+x2, 1, 1);
 54+		renderer->impl->fill_rectangle(renderer, color, x1-y2, y1+x2, 1, 1);
 55+		renderer->impl->fill_rectangle(renderer, color, x1+y2, y1-x2, 1, 1);
 56+		renderer->impl->fill_rectangle(renderer, color, x1-y2, y1-x2, 1, 1);
 57+	}
 58+}
 59+
 60+EXPORT
 61+void
 62+wld_draw_circle(struct wld_renderer *renderer, uint32_t color,
 63+                int32_t x1, int32_t y1, 
 64+                uint32_t r, bool fill)
 65+{
 66+	int32_t x2 = 0, y2 = r;
 67+	int32_t d = 3 - (2*r);
 68+
 69+	circle_points(renderer, color, x1, y1, x2, y2, fill);
 70+
 71+	while (y2 >= x2) {
 72+		if (d > 0) {
 73+			y2--;
 74+			d = d + 4*(x2-y2) + 10;
 75+		}
 76+		else
 77+			d = d + 4*x2 + 6;
 78+
 79+		x2++;
 80+
 81+		circle_points(renderer, color, x1, y1, x2, y2, fill);
 82+	}
 83+}
 84+
 85+
 86+EXPORT
 87+void
 88+wld_draw_line(struct wld_renderer *renderer, uint32_t color,
 89+              int32_t x1, int32_t y1,
 90+              int32_t x2, int32_t y2)
 91+{
 92+	int32_t dx = abs(x2-x1),  sx = x1 < x2 ? 1 : -1;
 93+	int32_t dy = -abs(y2-y1), sy = y1 < y2 ? 1 : -1;
 94+	int32_t err = dx + dy, e2;
 95+
 96+	/* just use fill_rectangle for purely vertical and horizontal line */
 97+	if (y1 == y2) {
 98+		int32_t lx = sx > 0 ? x1 : x2;
 99+		renderer->impl->fill_rectangle(renderer, color, lx, y1, dx + 1, 1);
100+		return;
101+	}
102+
103+	if (x1 == x2) {
104+		int32_t ly = sy > 0 ? y1 : y2;
105+		renderer->impl->fill_rectangle(renderer, color, x1, ly, 1, -dy + 1);
106+		return;
107+	}
108+
109+	while (true) {
110+		renderer->impl->fill_rectangle(renderer, color, x1, y1, 1, 1);
111+
112+		if (x1 == x2 && y1 == y2)
113+			break;
114+
115+		e2 = 2 * err;
116+
117+		if (e2 >= dy) {
118+			err += dy;
119+			x1 += sx;
120+		}
121+
122+		if (e2 <= dx) {
123+			err += dx;
124+			y1 += sy;
125+		}
126+	}
127+}
128+
129 EXPORT
130 void
131 wld_draw_text(struct wld_renderer *renderer,
132diff --git a/wld-private.h b/wld-private.h
133index 5bdaed3..0953edb 100644
134--- a/wld-private.h
135+++ b/wld-private.h
136@@ -108,6 +108,10 @@ struct wld_renderer_impl {
137 	void (*copy_region)(struct wld_renderer *renderer, struct buffer *src,
138 	                    int32_t dst_x, int32_t dst_y,
139 	                    pixman_region32_t *region);
140+	void (*draw_circle)(struct wld_renderer *renderer, uint32_t color,
141+                        int32_t x1, int32_t y1, uint32_t r, bool fill);
142+	void (*draw_line)(struct wld_renderer *renderer, uint32_t color,
143+                      int32_t x1, int32_t y1, int32_t x2, int32_t y2);
144 	void (*draw_text)(struct wld_renderer *renderer,
145 	                  struct font *font, uint32_t color,
146 	                  int32_t x, int32_t y, const char *text, uint32_t length,
147diff --git a/wld.h b/wld.h
148index 9eabdd6..b1c53c6 100644
149--- a/wld.h
150+++ b/wld.h
151@@ -249,6 +249,12 @@ void wld_copy_rectangle(struct wld_renderer *renderer,
152                         int32_t src_x, int32_t src_y,
153                         uint32_t width, uint32_t height);
154 
155+void wld_draw_circle(struct wld_renderer *renderer, uint32_t color,
156+                     int32_t x1, int32_t y1, uint32_t r, bool fill);
157+
158+void wld_draw_line(struct wld_renderer *renderer, uint32_t color,
159+                   int32_t x1, int32_t y1, int32_t x2, int32_t y2);
160+
161 void wld_copy_region(struct wld_renderer *renderer,
162                      struct wld_buffer *buffer,
163                      int32_t dst_x, int32_t dst_y, pixman_region32_t *region);
164-- 
1652.49.0
166