diff options
| author | Lena <lena@omega> | 2026-01-01 00:00:00 +0000 |
|---|---|---|
| committer | Lena <lena@omega> | 2026-01-01 00:00:00 +0000 |
| commit | 2fa72ee0dc67d973330aec4ba98260e9f57f7821 (patch) | |
| tree | e6a25c07c8da61d29e4e1f8a72436565e63c5777 /draw.c | |
| download | mouseboard-0.1.tar.gz | |
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.c | 111 |
1 files changed, 111 insertions, 0 deletions
@@ -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; +} |