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