/* * gfx_16.c — 16-colour (mode 0x82) public drawing API. * * Raw primitives live in gfx_raw_16.c. Single-shot wrappers do one * W3-begin / one W3-end around their raw call; composites wrap many * raw calls in a single begin/end pair so the W3 dance is amortised. * * No vertical-accelerator path: in 16-colour mode each byte spans two * horizontal pixels, so a vertical Fill burst would also affect the * other column's nibble — vline16 falls back to per-row RMW. */ #include #include extern void _gfx_w3_video_begin(void); extern void _gfx_w3_video_end(void); extern void _gfx_putpixel16_raw(int x, int y, uint8_t color); extern void _gfx_hline16_raw (int x, int y, int len, uint8_t color); extern void _gfx_vline16_raw (int x, int y, int len, uint8_t color); extern void _gfx_clear16_raw (uint8_t color); void gfx_clear16(uint8_t color) { _gfx_w3_video_begin(); _gfx_clear16_raw(color); _gfx_w3_video_end(); } void gfx_putpixel16(int x, int y, uint8_t color) { if ((unsigned)x >= GFX_WIDTH_16 || (unsigned)y >= GFX_HEIGHT_16) return; _gfx_w3_video_begin(); _gfx_putpixel16_raw(x, y, color); _gfx_w3_video_end(); } void gfx_hline16(int x, int y, int len, uint8_t color) { _gfx_w3_video_begin(); _gfx_hline16_raw(x, y, len, color); _gfx_w3_video_end(); } void gfx_vline16(int x, int y, int len, uint8_t color) { _gfx_w3_video_begin(); _gfx_vline16_raw(x, y, len, color); _gfx_w3_video_end(); } void gfx_rect16(int x, int y, int w, int h, uint8_t color) { if (w <= 0 || h <= 0) return; _gfx_w3_video_begin(); _gfx_hline16_raw(x, y, w, color); _gfx_hline16_raw(x, y + h - 1, w, color); if (h > 2) { _gfx_vline16_raw(x, y + 1, h - 2, color); _gfx_vline16_raw(x + w - 1, y + 1, h - 2, color); } _gfx_w3_video_end(); } void gfx_fill_rect16(int x, int y, int w, int h, uint8_t color) { if (w <= 0 || h <= 0) return; /* Column-major vlines — user's earlier request: 16-color rect_fill * via vertical lines. Each column does its own per-row RMW; the * outer begin/end wraps the whole rect so W3 is mapped once. */ _gfx_w3_video_begin(); for (int xx = 0; xx < w; xx++) _gfx_vline16_raw(x + xx, y, h, color); _gfx_w3_video_end(); } void gfx_line16(int x0, int y0, int x1, int y1, uint8_t color) { if (y0 == y1) { int x = x0 <= x1 ? x0 : x1; int w = (x0 <= x1 ? x1 - x0 : x0 - x1) + 1; gfx_hline16(x, y0, w, color); return; } if (x0 == x1) { int y = y0 <= y1 ? y0 : y1; int h = (y0 <= y1 ? y1 - y0 : y0 - y1) + 1; gfx_vline16(x0, y, h, color); return; } /* Bresenham — single W3 setup around the whole loop. */ int dx = x1 - x0; int sx = dx < 0 ? -1 : 1; if (dx < 0) dx = -dx; int dy = y1 - y0; int sy = dy < 0 ? -1 : 1; if (dy < 0) dy = -dy; int err = (dx > dy ? dx : -dy) / 2; int x = x0, y = y0; _gfx_w3_video_begin(); for (;;) { _gfx_putpixel16_raw(x, y, color); if (x == x1 && y == y1) break; int e2 = err; if (e2 > -dx) { err -= dy; x += sx; } if (e2 < dy) { err += dx; y += sy; } } _gfx_w3_video_end(); }