aboutsummaryrefslogtreecommitdiff
path: root/draw.c
diff options
context:
space:
mode:
authorLena <lena@omega>2026-01-01 00:00:00 +0000
committerLena <lena@omega>2026-01-01 00:00:00 +0000
commit2fa72ee0dc67d973330aec4ba98260e9f57f7821 (patch)
treee6a25c07c8da61d29e4e1f8a72436565e63c5777 /draw.c
downloadmouseboard-0.1.tar.gz
Enter mouseboardHEADv0.1master
Keyboard-only pointing: a labelled grid over every monitor, type a label to jump to a cell, bisect it by quadrant until the crosshair is exact, then one key clicks. The coarse grid keeps labels short and bisection keeps precision unlimited, so a hotkey and a few keystrokes replace the mouse. The core talks only to the backend interface in platform.h; wlroots Wayland and Win32 backends supply the overlay, keyboard grab and pointer.
Diffstat (limited to 'draw.c')
-rw-r--r--draw.c111
1 files changed, 111 insertions, 0 deletions
diff --git a/draw.c b/draw.c
new file mode 100644
index 0000000..297f5d0
--- /dev/null
+++ b/draw.c
@@ -0,0 +1,111 @@
+/* draw.c - software rendering onto an ARGB8888 mb_buffer. */
+#include "draw.h"
+#include "font.h"
+
+#include <stddef.h>
+
+/* wl_shm ARGB8888 and Win32 layered windows both hold premultiplied alpha. */
+static uint32_t premul(uint32_t argb)
+{
+ uint32_t a = argb >> 24;
+ uint32_t r = (argb >> 16) & 0xff;
+ uint32_t g = (argb >> 8) & 0xff;
+ uint32_t b = argb & 0xff;
+ r = r * a / 255;
+ g = g * a / 255;
+ b = b * a / 255;
+ return (a << 24) | (r << 16) | (g << 8) | b;
+}
+
+/* Fill a logical rectangle, expanding each logical pixel to a scale*scale block
+ * of device pixels. Clipping is in logical space; scale=1 is the identity. */
+static void fill_premul(struct mb_buffer *b, int x, int y, int w, int h,
+ uint32_t pm)
+{
+ int s = b->scale;
+ int x1 = x + w, y1 = y + h;
+ if (x < 0)
+ x = 0;
+ if (y < 0)
+ y = 0;
+ if (x1 > b->w)
+ x1 = b->w;
+ if (y1 > b->h)
+ y1 = b->h;
+ int n = (x1 - x) * s;
+ for (int row = y; row < y1; row++) {
+ for (int sy = 0; sy < s; sy++) {
+ uint32_t *p = b->px +
+ (size_t)(row * s + sy) * b->stride +
+ (size_t)x * s;
+ for (int i = 0; i < n; i++)
+ p[i] = pm;
+ }
+ }
+}
+
+void draw_fill(struct mb_buffer *b, int x, int y, int w, int h, uint32_t argb)
+{
+ fill_premul(b, x, y, w, h, premul(argb));
+}
+
+void draw_hline(struct mb_buffer *b, int x, int y, int len, int thick,
+ uint32_t argb)
+{
+ fill_premul(b, x, y, len, thick, premul(argb));
+}
+
+void draw_vline(struct mb_buffer *b, int x, int y, int len, int thick,
+ uint32_t argb)
+{
+ fill_premul(b, x, y, thick, len, premul(argb));
+}
+
+void draw_rect(struct mb_buffer *b, int x, int y, int w, int h, int thick,
+ uint32_t argb)
+{
+ uint32_t pm = premul(argb);
+ fill_premul(b, x, y, w, thick, pm); /* top */
+ fill_premul(b, x, y + h - thick, w, thick, pm); /* bottom */
+ fill_premul(b, x, y, thick, h, pm); /* left */
+ fill_premul(b, x + w - thick, y, thick, h, pm); /* right */
+}
+
+int text_height(int scale)
+{
+ return FONT_H * scale;
+}
+
+int text_width(const char *s, int scale)
+{
+ int n = 0;
+ while (s[n])
+ n++;
+ if (n == 0)
+ return 0;
+ return n * (FONT_W * scale) + (n - 1) * scale; /* scale-px gaps */
+}
+
+int draw_text(struct mb_buffer *b, int x, int y, const char *s, int scale,
+ uint32_t fg)
+{
+ int advance = FONT_W * scale + scale;
+ int w = text_width(s, scale);
+
+ uint32_t fpm = premul(fg);
+ int pen = x;
+ for (const char *c = s; *c; c++) {
+ const unsigned char *g = font_glyph(*c);
+ for (int gy = 0; gy < FONT_H; gy++) {
+ unsigned char bits = g[gy];
+ for (int gx = 0; gx < FONT_W; gx++) {
+ if (!(bits & (1u << gx)))
+ continue;
+ fill_premul(b, pen + gx * scale,
+ y + gy * scale, scale, scale, fpm);
+ }
+ }
+ pen += advance;
+ }
+ return w;
+}