mirror of
https://github.com/subhobhai943/SUB-OS.git
synced 2026-10-25 16:52:29 +00:00
- Create separate feature branch 'feat/gui-desktop' - Implement double-buffered 2D graphics engine with alpha blending, gradients, rounded rects, and font rasterization in gui/gui_gfx.c and include/gui/gui_gfx.h - Implement alpha-blended mouse pointer overlay in gui/gui_cursor.c and include/gui/gui_cursor.h - Implement SUB-WM Window Manager with draggable titlebars, close/minimize buttons, drop shadows, and event routing in gui/gui_wm.c and include/gui/gui_wm.h - Implement Cyberpunk/Nord desktop environment with wallpaper, taskbar, start menu popup, and system tray in gui/gui_desktop.c and include/gui/gui_desktop.h - Implement built-in GUI apps: System Performance Monitor, GUI Terminal Emulator, File Explorer, Calculator, Paint Studio, and About dialog in gui/gui_apps.c and include/gui/gui_apps.h - Add 'startx', 'gui', and 'desktop' applets in LazyBox suite - Verified multi-architecture compilation across x86_64, AArch64, and ARMv8i
306 lines
12 KiB
C
306 lines
12 KiB
C
// High-Performance 2D Graphics Engine & Software Compositor for SUB-OS
|
|
#include <gui/gui_gfx.h>
|
|
#include <mm/kmalloc.h>
|
|
#include <lib/string.h>
|
|
|
|
static uint32_t* g_frontbuffer = NULL;
|
|
static uint32_t* g_backbuffer = NULL;
|
|
static int g_width = 320;
|
|
static int g_height = 200;
|
|
|
|
// Standard 8x8 font bitmap table for printable ASCII characters (32..126)
|
|
static const uint8_t font8x8[96][8] = {
|
|
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space
|
|
{0x18,0x3c,0x3c,0x18,0x18,0x00,0x18,0x00}, // !
|
|
{0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00}, // "
|
|
{0x6c,0x6c,0xfe,0x6c,0xfe,0x6c,0x6c,0x00}, // #
|
|
{0x18,0x3e,0x60,0x3c,0x06,0x7c,0x18,0x00}, // $
|
|
{0x00,0x63,0x66,0x0c,0x18,0x33,0x63,0x00}, // %
|
|
{0x38,0x6c,0x38,0x76,0xdc,0xcc,0x76,0x00}, // &
|
|
{0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00}, // '
|
|
{0x0c,0x18,0x30,0x30,0x30,0x18,0x0c,0x00}, // (
|
|
{0x30,0x18,0x0c,0x0c,0x0c,0x18,0x30,0x00}, // )
|
|
{0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00}, // *
|
|
{0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00}, // +
|
|
{0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30}, // ,
|
|
{0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00}, // -
|
|
{0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00}, // .
|
|
{0x06,0x0c,0x18,0x30,0x60,0xc0,0x80,0x00}, // /
|
|
{0x7c,0xc6,0xce,0xd6,0xe6,0xc6,0x7c,0x00}, // 0
|
|
{0x18,0x38,0x18,0x18,0x18,0x18,0x7e,0x00}, // 1
|
|
{0x7c,0xc6,0x06,0x1c,0x30,0x66,0xfe,0x00}, // 2
|
|
{0x7c,0xc6,0x06,0x3c,0x06,0xc6,0x7c,0x00}, // 3
|
|
{0x1c,0x3c,0x6c,0xcc,0xfe,0x0c,0x1e,0x00}, // 4
|
|
{0xfe,0xc0,0xfc,0x06,0x06,0xc6,0x7c,0x00}, // 5
|
|
{0x7c,0xc6,0xc0,0xfc,0xc6,0xc6,0x7c,0x00}, // 6
|
|
{0xfe,0x06,0x0c,0x18,0x30,0x30,0x30,0x00}, // 7
|
|
{0x7c,0xc6,0xc6,0x7c,0xc6,0xc6,0x7c,0x00}, // 8
|
|
{0x7c,0xc6,0xc6,0x7e,0x06,0xc6,0x7c,0x00}, // 9
|
|
{0x00,0x18,0x18,0x00,0x18,0x18,0x00,0x00}, // :
|
|
{0x00,0x18,0x18,0x00,0x18,0x18,0x30,0x00}, // ;
|
|
{0x06,0x0c,0x18,0x30,0x18,0x0c,0x06,0x00}, // <
|
|
{0x00,0x00,0x7e,0x00,0x7e,0x00,0x00,0x00}, // =
|
|
{0x60,0x30,0x18,0x0c,0x18,0x30,0x60,0x00}, // >
|
|
{0x7c,0xc6,0x0c,0x18,0x18,0x00,0x18,0x00}, // ?
|
|
{0x7c,0xc6,0xde,0xde,0xdc,0xc0,0x7c,0x00}, // @
|
|
{0x38,0x6c,0xc6,0xfe,0xc6,0xc6,0xc6,0x00}, // A
|
|
{0xfc,0x66,0x66,0x7c,0x66,0x66,0xfc,0x00}, // B
|
|
{0x3c,0x66,0xc0,0xc0,0xc0,0x66,0x3c,0x00}, // C
|
|
{0xf8,0x6c,0x66,0x66,0x66,0x6c,0xf8,0x00}, // D
|
|
{0xfe,0x62,0x68,0x78,0x68,0x62,0xfe,0x00}, // E
|
|
{0xfe,0x62,0x68,0x78,0x68,0x60,0xf0,0x00}, // F
|
|
{0x3c,0x66,0xc0,0xc0,0xce,0x66,0x3e,0x00}, // G
|
|
{0xc6,0xc6,0xc6,0xfe,0xc6,0xc6,0xc6,0x00}, // H
|
|
{0x3c,0x18,0x18,0x18,0x18,0x18,0x3c,0x00}, // I
|
|
{0x1e,0x0c,0x0c,0x0c,0xcc,0xcc,0x78,0x00}, // J
|
|
{0xe6,0x66,0x6c,0x78,0x6c,0x66,0xe6,0x00}, // K
|
|
{0xf0,0x60,0x60,0x60,0x62,0x66,0xfe,0x00}, // L
|
|
{0xc6,0xee,0xfe,0xd6,0xc6,0xc6,0xc6,0x00}, // M
|
|
{0xc6,0xe6,0xf6,0xde,0xce,0xc6,0xc6,0x00}, // N
|
|
{0x7c,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00}, // O
|
|
{0xfc,0x66,0x66,0x7c,0x60,0x60,0xf0,0x00}, // P
|
|
{0x7c,0xc6,0xc6,0xc6,0xd6,0xde,0x7c,0x06}, // Q
|
|
{0xfc,0x66,0x66,0x7c,0x6c,0x66,0xe6,0x00}, // R
|
|
{0x7c,0xc6,0x60,0x38,0x0c,0xc6,0x7c,0x00}, // S
|
|
{0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x00}, // T
|
|
{0xc6,0xc6,0xc6,0xc6,0xc6,0xc6,0x7c,0x00}, // U
|
|
{0xc6,0xc6,0xc6,0xc6,0xc6,0x6c,0x38,0x00}, // V
|
|
{0xc6,0xc6,0xc6,0xd6,0xfe,0xee,0xc6,0x00}, // W
|
|
{0xc6,0xc6,0x6c,0x38,0x6c,0xc6,0xc6,0x00}, // X
|
|
{0x66,0x66,0x66,0x3c,0x18,0x18,0x18,0x00}, // Y
|
|
{0xfe,0x06,0x0c,0x18,0x30,0x60,0xfe,0x00}, // Z
|
|
{0x3c,0x30,0x30,0x30,0x30,0x30,0x3c,0x00}, // [
|
|
{0xc0,0x60,0x30,0x18,0x0c,0x06,0x02,0x00}, // \
|
|
{0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00}, // ]
|
|
{0x10,0x38,0x6c,0xc6,0x00,0x00,0x00,0x00}, // ^
|
|
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff}, // _
|
|
{0x30,0x18,0x0c,0x00,0x00,0x00,0x00,0x00}, // `
|
|
{0x00,0x00,0x78,0x0c,0x7c,0xcc,0x76,0x00}, // a
|
|
{0xe0,0x60,0x7c,0x66,0x66,0x66,0xdc,0x00}, // b
|
|
{0x00,0x00,0x78,0xcc,0xc0,0xcc,0x78,0x00}, // c
|
|
{0x1c,0x0c,0x7c,0xcc,0xcc,0xcc,0x76,0x00}, // d
|
|
{0x00,0x00,0x78,0xcc,0xfc,0xc0,0x78,0x00}, // e
|
|
{0x38,0x6c,0x60,0xf0,0x60,0x60,0xf0,0x00}, // f
|
|
{0x00,0x00,0x76,0xcc,0xcc,0x7c,0x0c,0xf8}, // g
|
|
{0xe0,0x60,0x6c,0x76,0x66,0x66,0xe6,0x00}, // h
|
|
{0x18,0x00,0x38,0x18,0x18,0x18,0x3c,0x00}, // i
|
|
{0x0c,0x00,0x1c,0x0c,0x0c,0xcc,0xcc,0x78}, // j
|
|
{0xe0,0x60,0x66,0x6c,0x78,0x6c,0xe6,0x00}, // k
|
|
{0x38,0x18,0x18,0x18,0x18,0x18,0x3c,0x00}, // l
|
|
{0x00,0x00,0xec,0xfe,0xd6,0xc6,0xc6,0x00}, // m
|
|
{0x00,0x00,0xdc,0x66,0x66,0x66,0x66,0x00}, // n
|
|
{0x00,0x00,0x7c,0xc6,0xc6,0xc6,0x7c,0x00}, // o
|
|
{0x00,0x00,0xdc,0x66,0x66,0x7c,0x60,0xf0}, // p
|
|
{0x00,0x00,0x76,0xcc,0xcc,0x7c,0x0c,0x1e}, // q
|
|
{0x00,0x00,0xdc,0x76,0x60,0x60,0xf0,0x00}, // r
|
|
{0x00,0x00,0x7c,0xc0,0x78,0x0c,0xf8,0x00}, // s
|
|
{0x10,0x30,0x7c,0x30,0x30,0x34,0x18,0x00}, // t
|
|
{0x00,0x00,0xcc,0xcc,0xcc,0xcc,0x76,0x00}, // u
|
|
{0x00,0x00,0xc6,0xc6,0xc6,0x6c,0x38,0x00}, // v
|
|
{0x00,0x00,0xc6,0xc6,0xd6,0xfe,0x6c,0x00}, // w
|
|
{0x00,0x00,0xc6,0x6c,0x38,0x6c,0xc6,0x00}, // x
|
|
{0x00,0x00,0xcc,0xcc,0xcc,0x7c,0x0c,0xf8}, // y
|
|
{0x00,0x00,0xfc,0x18,0x30,0x60,0xfc,0x00}, // z
|
|
{0x0e,0x18,0x18,0x70,0x18,0x18,0x0e,0x00}, // {
|
|
{0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x00}, // |
|
|
{0x70,0x18,0x18,0x0e,0x18,0x18,0x70,0x00}, // }
|
|
{0x76,0xdc,0x00,0x00,0x00,0x00,0x00,0x00}, // ~
|
|
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} // DEL
|
|
};
|
|
|
|
void gui_gfx_init(uint32_t* fb, int width, int height) {
|
|
g_frontbuffer = fb;
|
|
g_width = (width > 0) ? width : 320;
|
|
g_height = (height > 0) ? height : 200;
|
|
|
|
if (!g_backbuffer) {
|
|
g_backbuffer = (uint32_t*)kzalloc(g_width * g_height * sizeof(uint32_t));
|
|
}
|
|
}
|
|
|
|
int gui_gfx_get_width(void) { return g_width; }
|
|
int gui_gfx_get_height(void) { return g_height; }
|
|
uint32_t* gui_gfx_get_backbuffer(void) { return g_backbuffer; }
|
|
|
|
void gui_gfx_clear(uint32_t color) {
|
|
if (!g_backbuffer) return;
|
|
size_t count = g_width * g_height;
|
|
for (size_t i = 0; i < count; i++) {
|
|
g_backbuffer[i] = color;
|
|
}
|
|
}
|
|
|
|
void gui_gfx_draw_pixel(int x, int y, uint32_t color) {
|
|
if (!g_backbuffer || x < 0 || y < 0 || x >= g_width || y >= g_height) return;
|
|
g_backbuffer[y * g_width + x] = color;
|
|
}
|
|
|
|
void gui_gfx_draw_pixel_blend(int x, int y, uint32_t color, uint8_t alpha) {
|
|
if (!g_backbuffer || x < 0 || y < 0 || x >= g_width || y >= g_height) return;
|
|
uint32_t bg = g_backbuffer[y * g_width + x];
|
|
g_backbuffer[y * g_width + x] = gui_color_alpha_blend(bg, color, alpha);
|
|
}
|
|
|
|
void gui_gfx_draw_line(int x0, int y0, int x1, int y1, uint32_t color) {
|
|
int dx = (x1 > x0) ? (x1 - x0) : (x0 - x1);
|
|
int dy = (y1 > y0) ? (y1 - y0) : (y0 - y1);
|
|
int sx = (x0 < x1) ? 1 : -1;
|
|
int sy = (y0 < y1) ? 1 : -1;
|
|
int err = dx - dy;
|
|
|
|
while (1) {
|
|
gui_gfx_draw_pixel(x0, y0, color);
|
|
if (x0 == x1 && y0 == y1) break;
|
|
int e2 = 2 * err;
|
|
if (e2 > -dy) { err -= dy; x0 += sx; }
|
|
if (e2 < dx) { err += dx; y0 += sy; }
|
|
}
|
|
}
|
|
|
|
void gui_gfx_draw_rect(int x, int y, int w, int h, uint32_t color) {
|
|
gui_gfx_draw_line(x, y, x + w - 1, y, color);
|
|
gui_gfx_draw_line(x, y + h - 1, x + w - 1, y + h - 1, color);
|
|
gui_gfx_draw_line(x, y, x, y + h - 1, color);
|
|
gui_gfx_draw_line(x + w - 1, y, x + w - 1, y + h - 1, color);
|
|
}
|
|
|
|
void gui_gfx_fill_rect(int x, int y, int w, int h, uint32_t color) {
|
|
if (!g_backbuffer) return;
|
|
if (x < 0) { w += x; x = 0; }
|
|
if (y < 0) { h += y; y = 0; }
|
|
if (x + w > g_width) w = g_width - x;
|
|
if (y + h > g_height) h = g_height - y;
|
|
if (w <= 0 || h <= 0) return;
|
|
|
|
for (int j = y; j < y + h; j++) {
|
|
uint32_t* row = &g_backbuffer[j * g_width + x];
|
|
for (int i = 0; i < w; i++) {
|
|
row[i] = color;
|
|
}
|
|
}
|
|
}
|
|
|
|
void gui_gfx_fill_rect_blend(int x, int y, int w, int h, uint32_t color, uint8_t alpha) {
|
|
if (!g_backbuffer) return;
|
|
if (x < 0) { w += x; x = 0; }
|
|
if (y < 0) { h += y; y = 0; }
|
|
if (x + w > g_width) w = g_width - x;
|
|
if (y + h > g_height) h = g_height - y;
|
|
if (w <= 0 || h <= 0) return;
|
|
|
|
for (int j = y; j < y + h; j++) {
|
|
uint32_t* row = &g_backbuffer[j * g_width + x];
|
|
for (int i = 0; i < w; i++) {
|
|
row[i] = gui_color_alpha_blend(row[i], color, alpha);
|
|
}
|
|
}
|
|
}
|
|
|
|
void gui_gfx_draw_rounded_rect(int x, int y, int w, int h, int r, uint32_t color, bool filled) {
|
|
if (r <= 0) {
|
|
if (filled) gui_gfx_fill_rect(x, y, w, h, color);
|
|
else gui_gfx_draw_rect(x, y, w, h, color);
|
|
return;
|
|
}
|
|
|
|
if (filled) {
|
|
gui_gfx_fill_rect(x + r, y, w - 2 * r, h, color);
|
|
gui_gfx_fill_rect(x, y + r, r, h - 2 * r, color);
|
|
gui_gfx_fill_rect(x + w - r, y + r, r, h - 2 * r, color);
|
|
} else {
|
|
gui_gfx_draw_line(x + r, y, x + w - r, y, color);
|
|
gui_gfx_draw_line(x + r, y + h - 1, x + w - r, y + h - 1, color);
|
|
gui_gfx_draw_line(x, y + r, x, y + h - r, color);
|
|
gui_gfx_draw_line(x + w - 1, y + r, x + w - 1, y + h - r, color);
|
|
}
|
|
}
|
|
|
|
void gui_gfx_draw_gradient_v(int x, int y, int w, int h, uint32_t top_col, uint32_t bot_col) {
|
|
if (h <= 0 || w <= 0) return;
|
|
for (int j = 0; j < h; j++) {
|
|
uint8_t factor = (uint8_t)((j * 255) / h);
|
|
uint32_t row_col = gui_color_alpha_blend(top_col, bot_col, factor);
|
|
gui_gfx_fill_rect(x, y + j, w, 1, row_col);
|
|
}
|
|
}
|
|
|
|
void gui_gfx_draw_gradient_h(int x, int y, int w, int h, uint32_t left_col, uint32_t right_col) {
|
|
if (w <= 0 || h <= 0) return;
|
|
for (int i = 0; i < w; i++) {
|
|
uint8_t factor = (uint8_t)((i * 255) / w);
|
|
uint32_t col = gui_color_alpha_blend(left_col, right_col, factor);
|
|
gui_gfx_fill_rect(x + i, y, 1, h, col);
|
|
}
|
|
}
|
|
|
|
void gui_gfx_draw_char(int x, int y, char c, uint32_t fg, uint32_t bg, bool transparent_bg) {
|
|
if (c < 32 || c > 126) c = '?';
|
|
const uint8_t* glyph = font8x8[c - 32];
|
|
|
|
for (int row = 0; row < 8; row++) {
|
|
uint8_t bits = glyph[row];
|
|
for (int col = 0; col < 8; col++) {
|
|
if (bits & (1 << (7 - col))) {
|
|
gui_gfx_draw_pixel(x + col, y + row, fg);
|
|
} else if (!transparent_bg) {
|
|
gui_gfx_draw_pixel(x + col, y + row, bg);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void gui_gfx_draw_string(int x, int y, const char* str, uint32_t fg) {
|
|
if (!str) return;
|
|
int cx = x;
|
|
while (*str) {
|
|
gui_gfx_draw_char(cx, y, *str, fg, 0, true);
|
|
cx += 8;
|
|
str++;
|
|
}
|
|
}
|
|
|
|
void gui_gfx_draw_string_bg(int x, int y, const char* str, uint32_t fg, uint32_t bg) {
|
|
if (!str) return;
|
|
int cx = x;
|
|
while (*str) {
|
|
gui_gfx_draw_char(cx, y, *str, fg, bg, false);
|
|
cx += 8;
|
|
str++;
|
|
}
|
|
}
|
|
|
|
void gui_gfx_draw_string_shadow(int x, int y, const char* str, uint32_t fg, uint32_t shadow) {
|
|
gui_gfx_draw_string(x + 1, y + 1, str, shadow);
|
|
gui_gfx_draw_string(x, y, str, fg);
|
|
}
|
|
|
|
void gui_gfx_draw_shadow(int x, int y, int w, int h, int blur) {
|
|
for (int r = 1; r <= blur; r++) {
|
|
uint8_t alpha = (uint8_t)(60 / r);
|
|
gui_gfx_fill_rect_blend(x + r, y + h, w, r, GUI_COLOR_BLACK, alpha);
|
|
gui_gfx_fill_rect_blend(x + w, y + r, r, h, GUI_COLOR_BLACK, alpha);
|
|
}
|
|
}
|
|
|
|
void gui_gfx_blit(int dx, int dy, int w, int h, const uint32_t* src_buf) {
|
|
if (!g_backbuffer || !src_buf) return;
|
|
for (int j = 0; j < h; j++) {
|
|
int py = dy + j;
|
|
if (py < 0 || py >= g_height) continue;
|
|
for (int i = 0; i < w; i++) {
|
|
int px = dx + i;
|
|
if (px < 0 || px >= g_width) continue;
|
|
uint32_t pixel = src_buf[j * w + i];
|
|
if ((pixel >> 24) > 0) {
|
|
g_backbuffer[py * g_width + px] = pixel;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void gui_gfx_present(void) {
|
|
if (g_frontbuffer && g_backbuffer) {
|
|
memcpy(g_frontbuffer, g_backbuffer, g_width * g_height * sizeof(uint32_t));
|
|
}
|
|
}
|