mirror of
https://github.com/BoredDevNL/BoredOS.git
synced 2026-05-15 10:48:38 +00:00
checkpoint: BoredWord application
This commit is contained in:
parent
d824b4610a
commit
88f178e368
13 changed files with 1976 additions and 56 deletions
BIN
disk.img
BIN
disk.img
Binary file not shown.
|
|
@ -497,6 +497,83 @@ static uint64_t syscall_handler_inner(registers_t *regs) {
|
|||
}
|
||||
}
|
||||
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
}
|
||||
} else if (cmd == 18) { // GUI_CMD_DRAW_STRING_SCALED_SLOPED
|
||||
Window *win = (Window *)arg2;
|
||||
uint64_t coords = arg3;
|
||||
int ux = coords & 0xFFFFFFFF;
|
||||
int uy = coords >> 32;
|
||||
const char *user_str = (const char *)arg4;
|
||||
|
||||
// Unpack color, scale, slope from arg5
|
||||
uint64_t packed1 = arg5;
|
||||
uint32_t color = packed1 & 0xFFFFFFFF;
|
||||
uint32_t scale_bits = packed1 >> 32;
|
||||
float scale = *(float*)&scale_bits;
|
||||
|
||||
// Slope is passed via arg6 in the system call, but syscall5 only takes 5 args.
|
||||
// Oh right, we only have syscall5. Let's make a packed struct or just use a generic pointer for coords.
|
||||
// Even better, let's just make it a pointer to a struct.
|
||||
// Wait, I will just use `regs->r9` (arg6) directly since the syscall handler has access to all registers:
|
||||
uint64_t arg6 = regs->r9;
|
||||
uint32_t slope_bits = arg6 & 0xFFFFFFFF;
|
||||
float slope = *(float*)&slope_bits;
|
||||
|
||||
if (win && user_str) {
|
||||
extern void draw_string_scaled_sloped(int x, int y, const char *str, uint32_t color, float scale, float slope);
|
||||
extern void graphics_set_render_target(uint32_t *buffer, int w, int h);
|
||||
|
||||
// Copy string safely to kernel stack buffer
|
||||
char kernel_str[256];
|
||||
int i = 0;
|
||||
while (i < 255 && user_str[i]) {
|
||||
kernel_str[i] = user_str[i];
|
||||
i++;
|
||||
}
|
||||
kernel_str[i] = 0;
|
||||
|
||||
uint64_t rflags;
|
||||
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||
|
||||
ttf_font_t *font = win->font ? (ttf_font_t*)win->font : graphics_get_current_ttf();
|
||||
|
||||
if (win->pixels) {
|
||||
if (ux >= -100 && ux < win->w && uy >= -100 && uy < (win->h - 20)) {
|
||||
graphics_set_render_target(win->pixels, win->w, win->h - 20);
|
||||
if (font) {
|
||||
int baseline = uy + font_manager_get_font_ascent_scaled(font, scale) - 2;
|
||||
int cur_x = ux;
|
||||
const char *s = kernel_str;
|
||||
while (*s) {
|
||||
extern void font_manager_render_char_sloped(ttf_font_t *font, int x, int y, char c, uint32_t color, float scale, float slope, void (*put_pixel_fn)(int, int, uint32_t));
|
||||
font_manager_render_char_sloped(font, cur_x, baseline, *s, color, scale, slope, put_pixel);
|
||||
char buf[2] = {*s, 0};
|
||||
cur_x += font_manager_get_string_width_scaled(font, buf, scale);
|
||||
s++;
|
||||
}
|
||||
} else {
|
||||
draw_string_scaled_sloped(ux, uy, kernel_str, color, scale, slope);
|
||||
}
|
||||
graphics_set_render_target(NULL, 0, 0);
|
||||
}
|
||||
} else {
|
||||
if (font) {
|
||||
int baseline = win->y + uy + font_manager_get_font_ascent_scaled(font, scale) - 2;
|
||||
int cur_x = win->x + ux;
|
||||
const char *s = kernel_str;
|
||||
while (*s) {
|
||||
extern void font_manager_render_char_sloped(ttf_font_t *font, int x, int y, char c, uint32_t color, float scale, float slope, void (*put_pixel_fn)(int, int, uint32_t));
|
||||
font_manager_render_char_sloped(font, cur_x, baseline, *s, color, scale, slope, put_pixel);
|
||||
char buf[2] = {*s, 0};
|
||||
cur_x += font_manager_get_string_width_scaled(font, buf, scale);
|
||||
s++;
|
||||
}
|
||||
} else {
|
||||
draw_string_scaled_sloped(win->x + ux, win->y + uy, kernel_str, color, scale, slope);
|
||||
}
|
||||
}
|
||||
|
||||
asm volatile("push %0; popfq" : : "r"(rflags));
|
||||
}
|
||||
} else if (cmd == GUI_CMD_DRAW_IMAGE) {
|
||||
|
|
|
|||
1516
src/userland/gui/word.c
Normal file
1516
src/userland/gui/word.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -6,6 +6,7 @@
|
|||
extern uint64_t syscall3(uint64_t sys_num, uint64_t arg1, uint64_t arg2, uint64_t arg3);
|
||||
extern uint64_t syscall4(uint64_t sys_num, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4);
|
||||
extern uint64_t syscall5(uint64_t sys_num, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5);
|
||||
extern uint64_t syscall6(uint64_t sys_num, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6);
|
||||
|
||||
// sys_gui uses syscall #3
|
||||
#define SYS_GUI 3
|
||||
|
|
@ -71,6 +72,16 @@ void ui_draw_string_scaled(ui_window_t win, int x, int y, const char *str, uint3
|
|||
syscall5(SYS_GUI, GUI_CMD_DRAW_STRING_SCALED, (uint64_t)win, coords, (uint64_t)str, packed_arg5);
|
||||
}
|
||||
|
||||
void ui_draw_string_scaled_sloped(ui_window_t win, int x, int y, const char *str, uint32_t color, float scale, float slope) {
|
||||
uint64_t coords = ((uint64_t)x & 0xFFFFFFFF) | ((uint64_t)y << 32);
|
||||
// Pack color into lower 32, scale (as uint32_t representation) into upper 32
|
||||
uint32_t scale_bits = *(uint32_t*)&scale;
|
||||
uint32_t slope_bits = *(uint32_t*)&slope;
|
||||
uint64_t packed_arg5 = ((uint64_t)scale_bits << 32) | (color & 0xFFFFFFFF);
|
||||
|
||||
syscall6(SYS_GUI, GUI_CMD_DRAW_STRING_SCALED_SLOPED, (uint64_t)win, coords, (uint64_t)str, packed_arg5, (uint64_t)slope_bits);
|
||||
}
|
||||
|
||||
uint32_t ui_get_string_width_scaled(const char *str, float scale) {
|
||||
uint32_t scale_bits = *(uint32_t*)&scale;
|
||||
return (uint32_t)syscall4(SYS_GUI, GUI_CMD_GET_STRING_WIDTH_SCALED, (uint64_t)str, (uint64_t)scale_bits, 0);
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#define GUI_CMD_GET_FONT_HEIGHT_SCALED 13
|
||||
#define GUI_CMD_WINDOW_SET_TITLE 15
|
||||
#define GUI_CMD_SET_FONT 16
|
||||
#define GUI_CMD_DRAW_STRING_SCALED_SLOPED 18
|
||||
|
||||
// Event Types
|
||||
#define GUI_EVENT_NONE 0
|
||||
|
|
@ -62,6 +63,7 @@ void ui_get_screen_size(uint64_t *out_w, uint64_t *out_h);
|
|||
void ui_draw_string_bitmap(ui_window_t win, int x, int y, const char *str, uint32_t color);
|
||||
|
||||
void ui_draw_string_scaled(ui_window_t win, int x, int y, const char *str, uint32_t color, float scale);
|
||||
void ui_draw_string_scaled_sloped(ui_window_t win, int x, int y, const char *str, uint32_t color, float scale, float slope);
|
||||
uint32_t ui_get_string_width_scaled(const char *str, float scale);
|
||||
uint32_t ui_get_font_height_scaled(float scale);
|
||||
void ui_window_set_title(ui_window_t win, const char *title);
|
||||
|
|
|
|||
|
|
@ -59,6 +59,18 @@ uint64_t syscall5(uint64_t sys_num, uint64_t arg1, uint64_t arg2, uint64_t arg3,
|
|||
return ret;
|
||||
}
|
||||
|
||||
uint64_t syscall6(uint64_t sys_num, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4, uint64_t arg5, uint64_t arg6) {
|
||||
uint64_t ret;
|
||||
register uint64_t r10 asm("r10") = arg4;
|
||||
register uint64_t r8 asm("r8") = arg5;
|
||||
register uint64_t r9 asm("r9") = arg6;
|
||||
asm volatile("syscall"
|
||||
: "=a"(ret)
|
||||
: "a"(sys_num), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9)
|
||||
: "rcx", "r11", "memory");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void sys_exit(int status) {
|
||||
syscall1(SYS_EXIT, (uint64_t)status);
|
||||
|
|
|
|||
|
|
@ -750,6 +750,8 @@ static void explorer_open_target(const char *path) {
|
|||
} else {
|
||||
if (explorer_str_ends_with(path, ".elf")) {
|
||||
process_create_elf(path, NULL);
|
||||
} else if (explorer_str_ends_with(path, ".pdf")) {
|
||||
process_create_elf("A:/bin/word.elf", path);
|
||||
} else if (explorer_is_markdown_file(path)) {
|
||||
process_create_elf("A:/bin/markdown.elf", path);
|
||||
} else if (explorer_str_ends_with(path, ".pnt")) {
|
||||
|
|
@ -842,6 +844,8 @@ static void explorer_draw_file_icon(int x, int y, bool is_dir, uint32_t color, c
|
|||
if (full_path[explorer_strlen(full_path) - 1] != '/') explorer_strcat(full_path, "/");
|
||||
explorer_strcat(full_path, filename);
|
||||
draw_image_icon(x + 5, y + 5, full_path);
|
||||
} else if (explorer_str_ends_with(filename, ".pdf")) {
|
||||
draw_pdf_icon(x + 5, y + 5, "");
|
||||
} else if (explorer_str_ends_with(filename, ".elf")) {
|
||||
draw_elf_icon(x + 5, y + 5, "");
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -17,12 +17,10 @@ float kfabsf(float x) {
|
|||
}
|
||||
|
||||
float kpowf(float b, float e) {
|
||||
// Very simplified pow for stb_truetype's needs
|
||||
if (e == 0) return 1.0f;
|
||||
if (e == 1) return b;
|
||||
if (e == 0.5f) return ksqrtf(b);
|
||||
|
||||
// Fallback/log-based would be complex, let's see if this suffices
|
||||
float res = 1.0f;
|
||||
for (int i = 0; i < (int)e; i++) res *= b;
|
||||
return res;
|
||||
|
|
@ -33,13 +31,11 @@ float kfmodf(float x, float y) {
|
|||
}
|
||||
|
||||
float kcosf(float x) {
|
||||
// Taylor series for cos(x) around 0
|
||||
float x2 = x * x;
|
||||
return 1.0f - (x2 / 2.0f) + (x2 * x2 / 24.0f) - (x2 * x2 * x2 / 720.0f);
|
||||
}
|
||||
|
||||
float kacosf(float x) {
|
||||
// Very rough approximation for acos(x)
|
||||
if (x >= 1.0f) return 0;
|
||||
if (x <= -1.0f) return 3.14159f;
|
||||
return 1.57079f - x - (x*x*x)/6.0f;
|
||||
|
|
@ -59,6 +55,15 @@ static inline uint32_t alpha_blend(uint32_t bg, uint32_t fg, uint8_t alpha) {
|
|||
|
||||
static ttf_font_t *default_font = NULL;
|
||||
|
||||
#define MAX_LOADED_FONTS 8
|
||||
typedef struct {
|
||||
char path[128];
|
||||
ttf_font_t *font;
|
||||
} loaded_font_t;
|
||||
|
||||
static loaded_font_t loaded_fonts[MAX_LOADED_FONTS];
|
||||
static int loaded_font_count = 0;
|
||||
|
||||
#define FONT_CACHE_SIZE 2048
|
||||
typedef struct {
|
||||
char c;
|
||||
|
|
@ -67,15 +72,22 @@ typedef struct {
|
|||
unsigned char *bitmap;
|
||||
} font_cache_entry_t;
|
||||
|
||||
// Cache is disabled for now due to race conditions and collisions
|
||||
// static font_cache_entry_t g_font_cache[FONT_CACHE_SIZE];
|
||||
|
||||
bool font_manager_init(void) {
|
||||
// We'll load a default font later if available
|
||||
return true;
|
||||
}
|
||||
|
||||
ttf_font_t* font_manager_load(const char *path, float size) {
|
||||
(void)size;
|
||||
|
||||
for(int i=0; i<loaded_font_count; i++) {
|
||||
int match = 1;
|
||||
for(int j=0; path[j] || loaded_fonts[i].path[j]; j++) {
|
||||
if (path[j] != loaded_fonts[i].path[j]) { match = 0; break; }
|
||||
}
|
||||
if (match) return loaded_fonts[i].font;
|
||||
}
|
||||
|
||||
FAT32_FileHandle *fh = fat32_open(path, "r");
|
||||
if (!fh || !fh->valid) {
|
||||
serial_write("[FONT] Failed to open font file: ");
|
||||
|
|
@ -127,6 +139,13 @@ ttf_font_t* font_manager_load(const char *path, float size) {
|
|||
|
||||
if (!default_font) default_font = font;
|
||||
|
||||
if (loaded_font_count < MAX_LOADED_FONTS) {
|
||||
int i=0; while(path[i] && i<127) { loaded_fonts[loaded_font_count].path[i] = path[i]; i++; }
|
||||
loaded_fonts[loaded_font_count].path[i] = 0;
|
||||
loaded_fonts[loaded_font_count].font = font;
|
||||
loaded_font_count++;
|
||||
}
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
|
|
@ -145,16 +164,16 @@ void font_manager_render_char_scaled(ttf_font_t *font, int x, int y, char c, uin
|
|||
unsigned char *bitmap = NULL;
|
||||
int w, h, xoff, yoff;
|
||||
|
||||
float real_scale = stbtt_ScaleForPixelHeight(info, scale); // Convert pixel size back to stbtt scale
|
||||
float real_scale = stbtt_ScaleForPixelHeight(info, scale);
|
||||
|
||||
int codepoint = (unsigned char)c;
|
||||
if (codepoint == 128) codepoint = 0x2014; // — (—)
|
||||
if (codepoint == 129) codepoint = 0x2013; // – (–)
|
||||
if (codepoint == 130) codepoint = 0x2022; // • (•)
|
||||
if (codepoint == 131) codepoint = 0x2026; // … (…)
|
||||
if (codepoint == 132) codepoint = 0x2122; // ™ (™)
|
||||
if (codepoint == 133) codepoint = 0x20AC; // € (€)
|
||||
if (codepoint == 134) codepoint = 0x00B7; // · (·)
|
||||
if (codepoint == 128) codepoint = 0x2014;
|
||||
if (codepoint == 129) codepoint = 0x2013;
|
||||
if (codepoint == 130) codepoint = 0x2022;
|
||||
if (codepoint == 131) codepoint = 0x2026;
|
||||
if (codepoint == 132) codepoint = 0x2122;
|
||||
if (codepoint == 133) codepoint = 0x20AC;
|
||||
if (codepoint == 134) codepoint = 0x00B7;
|
||||
|
||||
bitmap = stbtt_GetCodepointBitmap(info, 0, real_scale, codepoint, &w, &h, &xoff, &yoff);
|
||||
|
||||
|
|
@ -174,6 +193,46 @@ void font_manager_render_char_scaled(ttf_font_t *font, int x, int y, char c, uin
|
|||
}
|
||||
}
|
||||
|
||||
void font_manager_render_char_sloped(ttf_font_t *font, int x, int y, char c, uint32_t color, float scale, float slope, void (*put_pixel_fn)(int, int, uint32_t)) {
|
||||
if (!font) font = default_font;
|
||||
if (!font) return;
|
||||
|
||||
stbtt_fontinfo *info = (stbtt_fontinfo *)font->info;
|
||||
|
||||
unsigned char *bitmap = NULL;
|
||||
int w, h, xoff, yoff;
|
||||
|
||||
float real_scale = stbtt_ScaleForPixelHeight(info, scale);
|
||||
|
||||
int codepoint = (unsigned char)c;
|
||||
if (codepoint == 128) codepoint = 0x2014;
|
||||
if (codepoint == 129) codepoint = 0x2013;
|
||||
if (codepoint == 130) codepoint = 0x2022;
|
||||
if (codepoint == 131) codepoint = 0x2026;
|
||||
if (codepoint == 132) codepoint = 0x2122;
|
||||
if (codepoint == 133) codepoint = 0x20AC;
|
||||
if (codepoint == 134) codepoint = 0x00B7;
|
||||
|
||||
bitmap = stbtt_GetCodepointBitmap(info, 0, real_scale, codepoint, &w, &h, &xoff, &yoff);
|
||||
|
||||
if (bitmap) {
|
||||
for (int row = 0; row < h; row++) {
|
||||
int slant_offset = (int)((h - row) * slope);
|
||||
|
||||
for (int col = 0; col < w; col++) {
|
||||
unsigned char alpha = bitmap[row * w + col];
|
||||
if (alpha > 0) {
|
||||
int px = x + col + xoff + slant_offset;
|
||||
int py = y + row + yoff;
|
||||
uint32_t bg = graphics_get_pixel(px, py);
|
||||
put_pixel_fn(px, py, alpha_blend(bg, color, alpha));
|
||||
}
|
||||
}
|
||||
}
|
||||
stbtt_FreeBitmap(bitmap, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
int font_manager_get_string_width(ttf_font_t *font, const char *s) {
|
||||
if (!font) font = default_font;
|
||||
if (!font) return 0;
|
||||
|
|
@ -211,15 +270,14 @@ int font_manager_get_string_width_scaled(ttf_font_t *font, const char *s, float
|
|||
while (*s) {
|
||||
int advance, lsb;
|
||||
int codepoint = (unsigned char)*s;
|
||||
if (codepoint == 128) codepoint = 0x2014; // — (—)
|
||||
if (codepoint == 129) codepoint = 0x2013; // – (–)
|
||||
if (codepoint == 130) codepoint = 0x2022; // • (•)
|
||||
if (codepoint == 131) codepoint = 0x2026; // … (…)
|
||||
if (codepoint == 132) codepoint = 0x2122; // ™ (™)
|
||||
if (codepoint == 133) codepoint = 0x20AC; // € (€)
|
||||
if (codepoint == 134) codepoint = 0x00B7; // · (·)
|
||||
if (codepoint == 128) codepoint = 0x2014;
|
||||
if (codepoint == 129) codepoint = 0x2013;
|
||||
if (codepoint == 130) codepoint = 0x2022;
|
||||
if (codepoint == 131) codepoint = 0x2026;
|
||||
if (codepoint == 132) codepoint = 0x2122;
|
||||
if (codepoint == 133) codepoint = 0x20AC;
|
||||
if (codepoint == 134) codepoint = 0x00B7;
|
||||
stbtt_GetCodepointHMetrics(info, codepoint, &advance, &lsb);
|
||||
// Round per-character to match draw_string's accumulation
|
||||
width += (int)(advance * real_scale + 0.5f);
|
||||
s++;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
// stb_truetype math stubs
|
||||
extern float ksqrtf(float x);
|
||||
extern float kpowf(float b, float e);
|
||||
extern float kfmodf(float x, float y);
|
||||
|
|
@ -24,21 +23,18 @@ extern float kfabsf(float x);
|
|||
|
||||
#define STBTT_assert(x) ((void)0)
|
||||
|
||||
// Memory management
|
||||
#define STBTT_malloc(x,u) kmalloc(x)
|
||||
#define STBTT_free(x,u) kfree(x)
|
||||
|
||||
// String functions
|
||||
#define STBTT_memcpy mem_memcpy
|
||||
#define STBTT_memset mem_memset
|
||||
|
||||
// Data types
|
||||
typedef uint64_t STBTT_ptrsize;
|
||||
|
||||
typedef struct {
|
||||
void *data;
|
||||
size_t size;
|
||||
void *info; // stbtt_fontinfo
|
||||
void *info;
|
||||
float scale;
|
||||
float pixel_height;
|
||||
int ascent;
|
||||
|
|
@ -50,6 +46,7 @@ bool font_manager_init(void);
|
|||
ttf_font_t* font_manager_load(const char *path, float size);
|
||||
void font_manager_render_char(ttf_font_t *font, int x, int y, char c, uint32_t color, void (*put_pixel_fn)(int, int, uint32_t));
|
||||
void font_manager_render_char_scaled(ttf_font_t *font, int x, int y, char c, uint32_t color, float scale, void (*put_pixel_fn)(int, int, uint32_t));
|
||||
void font_manager_render_char_sloped(ttf_font_t *font, int x, int y, char c, uint32_t color, float scale, float slope, void (*put_pixel_fn)(int, int, uint32_t));
|
||||
int font_manager_get_string_width(ttf_font_t *font, const char *s);
|
||||
int font_manager_get_string_width_scaled(ttf_font_t *font, const char *s, float scale);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "font.h"
|
||||
#include "io.h"
|
||||
#include "font_manager.h"
|
||||
#include "../mem/memory_manager.h"
|
||||
|
||||
static struct limine_framebuffer *g_fb = NULL;
|
||||
static uint32_t g_bg_color = 0xFF696969;
|
||||
|
|
@ -329,6 +330,128 @@ void draw_rounded_rect_filled(int x, int y, int w, int h, int radius, uint32_t c
|
|||
}
|
||||
}
|
||||
|
||||
static uint32_t blend_color_alpha(uint32_t bottom, uint32_t top, int alpha) {
|
||||
if (alpha <= 0) return bottom;
|
||||
if (alpha >= 255) return top;
|
||||
|
||||
int rb = (bottom >> 16) & 0xFF;
|
||||
int gb = (bottom >> 8) & 0xFF;
|
||||
int bb = bottom & 0xFF;
|
||||
|
||||
int rt = (top >> 16) & 0xFF;
|
||||
int gt = (top >> 8) & 0xFF;
|
||||
int bt = top & 0xFF;
|
||||
|
||||
int rr = rb + (((rt - rb) * alpha) >> 8);
|
||||
int gg = gb + (((gt - gb) * alpha) >> 8);
|
||||
int bb_new = bb + (((bt - bb) * alpha) >> 8);
|
||||
|
||||
return (rr << 16) | (gg << 8) | bb_new;
|
||||
}
|
||||
|
||||
void draw_rounded_rect_blurred(int x, int y, int w, int h, int radius, uint32_t tint_color, int blur_radius, int alpha) {
|
||||
if (!g_fb) return;
|
||||
int sw = get_screen_width();
|
||||
int sh = get_screen_height();
|
||||
|
||||
if (x < 0) { w += x; x = 0; }
|
||||
if (y < 0) { h += y; y = 0; }
|
||||
if (x + w > sw) w = sw - x;
|
||||
if (y + h > sh) h = sh - y;
|
||||
if (w <= 0 || h <= 0) return;
|
||||
|
||||
if (radius > w / 2) radius = w / 2;
|
||||
if (radius > h / 2) radius = h / 2;
|
||||
if (radius < 1) radius = 1;
|
||||
|
||||
uint32_t *tmp_buf = (uint32_t *)kmalloc(w * h * sizeof(uint32_t));
|
||||
if (!tmp_buf) {
|
||||
draw_rounded_rect_filled(x, y, w, h, radius, tint_color);
|
||||
return;
|
||||
}
|
||||
|
||||
for (int r = 0; r < h; r++) {
|
||||
int g_y = y + r;
|
||||
for (int c = 0; c < w; c++) {
|
||||
int g_x = x + c;
|
||||
|
||||
int r_sum = 0, g_sum = 0, b_sum = 0, count = 0;
|
||||
int start_kx = g_x - blur_radius;
|
||||
int end_kx = g_x + blur_radius;
|
||||
if (start_kx < 0) start_kx = 0;
|
||||
if (end_kx >= sw) end_kx = sw - 1;
|
||||
|
||||
for (int kx = start_kx; kx <= end_kx; kx++) {
|
||||
uint32_t pixel = g_back_buffer[g_y * sw + kx];
|
||||
r_sum += (pixel >> 16) & 0xFF;
|
||||
g_sum += (pixel >> 8) & 0xFF;
|
||||
b_sum += pixel & 0xFF;
|
||||
count++;
|
||||
}
|
||||
if(count == 0) count = 1;
|
||||
uint32_t out_pixel = ((r_sum / count) << 16) | ((g_sum / count) << 8) | (b_sum / count);
|
||||
tmp_buf[r * w + c] = out_pixel;
|
||||
}
|
||||
}
|
||||
|
||||
for (int c = 0; c < w; c++) {
|
||||
for (int r = 0; r < h; r++) {
|
||||
int g_y = y + r;
|
||||
int g_x = x + c;
|
||||
|
||||
if (g_clip_enabled) {
|
||||
if (g_x < g_clip_x || g_x >= g_clip_x + g_clip_w ||
|
||||
g_y < g_clip_y || g_y >= g_clip_y + g_clip_h) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
bool in_corner = false;
|
||||
int dx = 0, dy = 0;
|
||||
if (c < radius && r < radius) {
|
||||
dx = radius - c - 1; dy = radius - r - 1;
|
||||
in_corner = true;
|
||||
} else if (c >= w - radius && r < radius) {
|
||||
dx = c - (w - radius); dy = radius - r - 1;
|
||||
in_corner = true;
|
||||
} else if (c < radius && r >= h - radius) {
|
||||
dx = radius - c - 1; dy = r - (h - radius);
|
||||
in_corner = true;
|
||||
} else if (c >= w - radius && r >= h - radius) {
|
||||
dx = c - (w - radius); dy = r - (h - radius);
|
||||
in_corner = true;
|
||||
}
|
||||
|
||||
if (in_corner) {
|
||||
if (dx*dx + dy*dy >= radius*radius) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
int r_sum = 0, g_sum = 0, b_sum = 0, count = 0;
|
||||
int start_kr = r - blur_radius;
|
||||
int end_kr = r + blur_radius;
|
||||
if (start_kr < 0) start_kr = 0;
|
||||
if (end_kr >= h) end_kr = h - 1;
|
||||
|
||||
for (int kr = start_kr; kr <= end_kr; kr++) {
|
||||
uint32_t pixel = tmp_buf[kr * w + c];
|
||||
r_sum += (pixel >> 16) & 0xFF;
|
||||
g_sum += (pixel >> 8) & 0xFF;
|
||||
b_sum += pixel & 0xFF;
|
||||
count++;
|
||||
}
|
||||
if(count == 0) count = 1;
|
||||
uint32_t blurred_pixel = ((r_sum / count) << 16) | ((g_sum / count) << 8) | (b_sum / count);
|
||||
|
||||
uint32_t final_pixel = blend_color_alpha(blurred_pixel, tint_color, alpha);
|
||||
g_back_buffer[g_y * sw + g_x] = final_pixel;
|
||||
}
|
||||
}
|
||||
|
||||
kfree(tmp_buf);
|
||||
}
|
||||
|
||||
void draw_char(int x, int y, char c, uint32_t color) {
|
||||
if (g_current_ttf) {
|
||||
font_manager_render_char(g_current_ttf, x, y, c, color, put_pixel);
|
||||
|
|
@ -463,6 +586,37 @@ void draw_string_scaled(int x, int y, const char *s, uint32_t color, float scale
|
|||
}
|
||||
}
|
||||
|
||||
void draw_string_sloped(int x, int y, const char *s, uint32_t color, float slope) {
|
||||
if (g_current_ttf) draw_string_scaled_sloped(x, y, s, color, g_current_ttf->pixel_height, slope);
|
||||
else draw_string_scaled(x, y, s, color, 15.0f); // Fast fallback if no ttf
|
||||
}
|
||||
|
||||
void draw_string_scaled_sloped(int x, int y, const char *s, uint32_t color, float scale, float slope) {
|
||||
if (!s) return;
|
||||
int cur_x = x;
|
||||
|
||||
if (g_current_ttf) {
|
||||
int baseline = y + font_manager_get_font_ascent_scaled(g_current_ttf, scale) - 2;
|
||||
int line_height = font_manager_get_font_line_height_scaled(g_current_ttf, scale);
|
||||
|
||||
while (*s) {
|
||||
if (*s == '\n') {
|
||||
cur_x = x;
|
||||
baseline += line_height;
|
||||
} else {
|
||||
font_manager_render_char_sloped(g_current_ttf, cur_x, baseline, *s, color, scale, slope, put_pixel);
|
||||
char buf[2] = {*s, 0};
|
||||
cur_x += font_manager_get_string_width_scaled(g_current_ttf, buf, scale);
|
||||
}
|
||||
s++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback to normal draw_string_scaled if no TTF
|
||||
draw_string_scaled(x, y, s, color, scale);
|
||||
}
|
||||
|
||||
void draw_desktop_background(void) {
|
||||
if (!g_fb) return;
|
||||
|
||||
|
|
|
|||
|
|
@ -21,10 +21,13 @@ uint32_t graphics_get_pixel(int x, int y);
|
|||
void draw_rect(int x, int y, int w, int h, uint32_t color);
|
||||
void draw_rounded_rect(int x, int y, int w, int h, int radius, uint32_t color);
|
||||
void draw_rounded_rect_filled(int x, int y, int w, int h, int radius, uint32_t color);
|
||||
void draw_rounded_rect_blurred(int x, int y, int w, int h, int radius, uint32_t tint_color, int blur_radius, int alpha);
|
||||
void draw_char(int x, int y, char c, uint32_t color);
|
||||
void draw_char_bitmap(int x, int y, char c, uint32_t color);
|
||||
void draw_string(int x, int y, const char *s, uint32_t color);
|
||||
void draw_string_scaled(int x, int y, const char *s, uint32_t color, float scale);
|
||||
void draw_string_sloped(int x, int y, const char *s, uint32_t color, float slope);
|
||||
void draw_string_scaled_sloped(int x, int y, const char *s, uint32_t color, float scale, float slope);
|
||||
void draw_desktop_background(void);
|
||||
void graphics_set_bg_color(uint32_t color);
|
||||
void graphics_set_bg_pattern(const uint32_t *pattern); // 128x128 pattern
|
||||
|
|
|
|||
119
src/wm/wm.c
119
src/wm/wm.c
|
|
@ -129,6 +129,7 @@ int desktop_max_cols = 23;
|
|||
int mouse_speed = 10;
|
||||
static int mouse_accum_x = 0;
|
||||
static int mouse_accum_y = 0;
|
||||
Window *active_mouse_capture_win = NULL;
|
||||
|
||||
// Helper to check if string ends with suffix
|
||||
static bool str_ends_with(const char *str, const char *suffix) {
|
||||
|
|
@ -508,6 +509,33 @@ void draw_document_icon(int x, int y, const char *label) {
|
|||
draw_icon_label(x, y, label);
|
||||
}
|
||||
|
||||
void draw_pdf_icon(int x, int y, const char *label) {
|
||||
uint32_t icon_buf[48 * 48];
|
||||
for (int i = 0; i < 48 * 48; i++) icon_buf[i] = 0xFFFF00FF;
|
||||
graphics_set_render_target(icon_buf, 48, 48);
|
||||
|
||||
// Document shape
|
||||
draw_rounded_rect_filled(4, 4, 40, 40, 8, 0xFFFFFFFF);
|
||||
// Red banner
|
||||
draw_rounded_rect_filled(8, 8, 32, 14, 4, 0xFFDF2020);
|
||||
// PDF text roughly (simplified to lines for now)
|
||||
draw_rect(14, 25, 20, 2, 0xFFBBBBBB);
|
||||
draw_rect(14, 33, 14, 2, 0xFFBBBBBB);
|
||||
|
||||
graphics_set_render_target(NULL, 0, 0);
|
||||
int dx = x + 24, dy = y + 12;
|
||||
for (int ty = 0; ty < 32; ty++) {
|
||||
for (int tx = 0; tx < 32; tx++) {
|
||||
int src_x = tx * 48 / 32;
|
||||
int src_y = ty * 48 / 32;
|
||||
uint32_t c1 = icon_buf[src_y * 48 + src_x];
|
||||
if (c1 != 0xFFFF00FF) put_pixel(dx + tx, dy + ty, c1);
|
||||
}
|
||||
}
|
||||
|
||||
draw_icon_label(x, y, label);
|
||||
}
|
||||
|
||||
void draw_elf_icon(int x, int y, const char *label) {
|
||||
uint32_t icon_buf[48 * 48];
|
||||
for (int i = 0; i < 48 * 48; i++) icon_buf[i] = 0xFFFF00FF;
|
||||
|
|
@ -912,6 +940,23 @@ static long long isqrt(long long n) {
|
|||
return x;
|
||||
}
|
||||
|
||||
static void draw_dock_word(int x, int y) {
|
||||
// Rich blue document style
|
||||
draw_rounded_rect_filled(x, y, 48, 48, 10, 0xFF4A90E2);
|
||||
draw_rounded_rect_filled(x + 1, y + 1, 46, 28, 9, 0xFF5D9CE6);
|
||||
draw_rounded_rect_filled(x + 1, y + 24, 46, 23, 9, 0xFF3A80D2);
|
||||
|
||||
// White document page in center
|
||||
draw_rounded_rect_filled(x + 8, y + 8, 32, 32, 4, 0xFFFFFFFF);
|
||||
// Blue header edge
|
||||
draw_rounded_rect_filled(x + 8, y + 8, 32, 8, 4, 0xFF2868B8);
|
||||
|
||||
// Text lines using dark grey
|
||||
draw_rect(x + 14, y + 22, 20, 2, 0xFF666666);
|
||||
draw_rect(x + 14, y + 27, 20, 2, 0xFF666666);
|
||||
draw_rect(x + 14, y + 32, 14, 2, 0xFF666666);
|
||||
}
|
||||
|
||||
static void draw_dock_notepad(int x, int y) {
|
||||
draw_rounded_rect_filled(x, y, 48, 48, 10, 0xFFCC9A00);
|
||||
draw_rounded_rect_filled(x + 1, y + 1, 46, 28, 9, 0xFFFFD700);
|
||||
|
|
@ -1225,7 +1270,21 @@ void wm_paint(void) {
|
|||
asm volatile("pushfq; pop %0; cli" : "=r"(rflags));
|
||||
|
||||
DirtyRect dirty = graphics_get_dirty_rect();
|
||||
|
||||
if (dirty.active) {
|
||||
int d_h = 60;
|
||||
int d_y = sh - d_h - 6;
|
||||
int d_item_sz = 48;
|
||||
int d_space = 10;
|
||||
int d_tw = 10 * (d_item_sz + d_space);
|
||||
int d_bg_x = (sw - d_tw) / 2 - 12;
|
||||
int d_bg_w = d_tw + 24;
|
||||
|
||||
if (!(dirty.x >= d_bg_x + d_bg_w || dirty.x + dirty.w <= d_bg_x ||
|
||||
dirty.y >= d_y + d_h || dirty.y + dirty.h <= d_y)) {
|
||||
graphics_mark_dirty(d_bg_x - 10, d_y - 10, d_bg_w + 20, d_h + 20);
|
||||
dirty = graphics_get_dirty_rect();
|
||||
}
|
||||
graphics_set_clipping(dirty.x, dirty.y, dirty.w, dirty.h);
|
||||
} else {
|
||||
graphics_clear_clipping();
|
||||
|
|
@ -1274,6 +1333,7 @@ void wm_paint(void) {
|
|||
draw_image_icon(icon->x, icon->y, full_path);
|
||||
draw_icon_label(icon->x, icon->y, icon->name);
|
||||
}
|
||||
else if (str_ends_with(icon->name, ".pdf")) draw_pdf_icon(icon->x, icon->y, icon->name);
|
||||
else draw_document_icon(icon->x, icon->y, icon->name);
|
||||
}
|
||||
}
|
||||
|
|
@ -1324,10 +1384,12 @@ void wm_paint(void) {
|
|||
int dock_y = sh - dock_h - 6;
|
||||
int dock_item_size = 48;
|
||||
int dock_spacing = 10;
|
||||
int total_dock_width = 10 * (dock_item_size + dock_spacing);
|
||||
int total_dock_width = 11 * (dock_item_size + dock_spacing);
|
||||
int dock_bg_x = (sw - total_dock_width) / 2 - 12;
|
||||
int dock_bg_w = total_dock_width + 24;
|
||||
draw_rounded_rect_filled(dock_bg_x, dock_y, dock_bg_w, dock_h, 18, COLOR_DOCK_BG);
|
||||
|
||||
// Draw blurred dock background with reduced radius and tint
|
||||
draw_rounded_rect_blurred(dock_bg_x, dock_y, dock_bg_w, dock_h, 18, COLOR_DOCK_BG, 5, 140);
|
||||
|
||||
int dock_x = (sw - total_dock_width) / 2;
|
||||
int dock_item_y = dock_y + 6;
|
||||
|
|
@ -1351,7 +1413,8 @@ void wm_paint(void) {
|
|||
draw_dock_taskman(dock_x, dock_item_y);
|
||||
dock_x += dock_item_size + dock_spacing;
|
||||
draw_dock_clock(dock_x, dock_item_y);
|
||||
// Editor removed from dock
|
||||
dock_x += dock_item_size + dock_spacing;
|
||||
draw_dock_word(dock_x, dock_item_y);
|
||||
|
||||
// Desktop Context Menu (with rounded corners)
|
||||
if (desktop_menu_visible) {
|
||||
|
|
@ -1533,6 +1596,10 @@ void wm_remove_window(Window *win) {
|
|||
}
|
||||
window_count--;
|
||||
|
||||
if (active_mouse_capture_win == win) {
|
||||
active_mouse_capture_win = NULL;
|
||||
}
|
||||
|
||||
// Mark for redraw while protected
|
||||
force_redraw = true;
|
||||
} else {
|
||||
|
|
@ -1905,7 +1972,7 @@ void wm_handle_right_click(int x, int y) {
|
|||
int dock_y = sh - dock_h - 6;
|
||||
int dock_item_size = 48;
|
||||
int dock_spacing = 10;
|
||||
int total_dock_width = 10 * (dock_item_size + dock_spacing);
|
||||
int total_dock_width = 11 * (dock_item_size + dock_spacing);
|
||||
int dock_bg_x = (sw - total_dock_width) / 2 - 12;
|
||||
int dock_bg_w = total_dock_width + 24;
|
||||
|
||||
|
|
@ -1926,6 +1993,7 @@ void wm_handle_right_click(int x, int y) {
|
|||
else if (item == 7) start_menu_pending_app = "Browser";
|
||||
else if (item == 8) start_menu_pending_app = "Task Manager";
|
||||
else if (item == 9) start_menu_pending_app = "Clock";
|
||||
else if (item == 10) start_menu_pending_app = "Word Processor";
|
||||
}
|
||||
} else {
|
||||
wm_handle_click(mx, my);
|
||||
|
|
@ -2048,6 +2116,10 @@ void wm_handle_right_click(int x, int y) {
|
|||
Window *existing = wm_find_window_by_title("Txtedit");
|
||||
if (existing) wm_bring_to_front(existing);
|
||||
else process_create_elf("/bin/txtedit.elf", NULL);
|
||||
} else if (str_starts_with(start_menu_pending_app, "Word Processor")) {
|
||||
Window *existing = wm_find_window_by_title("Word Processor");
|
||||
if (existing) wm_bring_to_front(existing);
|
||||
else process_create_elf("/bin/word.elf", NULL);
|
||||
} else if (str_starts_with(start_menu_pending_app, "Terminal")) {
|
||||
cmd_reset(); wm_bring_to_front(&win_cmd);
|
||||
} else if (str_starts_with(start_menu_pending_app, "Calculator")) {
|
||||
|
|
@ -2160,6 +2232,8 @@ void wm_handle_right_click(int x, int y) {
|
|||
process_create_elf("/bin/paint.elf", path);
|
||||
} else if (str_ends_with(icon->name, ".md")) {
|
||||
process_create_elf("/bin/markdown.elf", path);
|
||||
} else if (str_ends_with(icon->name, ".pdf")) {
|
||||
process_create_elf("/bin/word.elf", path);
|
||||
} else if (is_image_file(icon->name)) {
|
||||
process_create_elf("/bin/viewer.elf", path);
|
||||
} else {
|
||||
|
|
@ -2385,46 +2459,57 @@ void wm_handle_right_click(int x, int y) {
|
|||
}
|
||||
}
|
||||
if (topmost && topmost->data) {
|
||||
active_mouse_capture_win = topmost;
|
||||
if (my >= topmost->y + 20)
|
||||
syscall_send_mouse_down_event(topmost, mx - topmost->x, my - topmost->y - 20);
|
||||
} else {
|
||||
active_mouse_capture_win = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!left && prev_left) {
|
||||
// Left button released - send MOUSE_UP event to topmost window
|
||||
Window *topmost = NULL;
|
||||
// Left button released - send MOUSE_UP event to captured or topmost window
|
||||
Window *target = active_mouse_capture_win;
|
||||
if (!target) {
|
||||
int topmost_z = -1;
|
||||
for (int w = 0; w < window_count; w++) {
|
||||
Window *win = all_windows[w];
|
||||
if (win->visible && rect_contains(win->x, win->y, win->w, win->h, mx, my)) {
|
||||
if (win->z_index > topmost_z) {
|
||||
topmost = win;
|
||||
target = win;
|
||||
topmost_z = win->z_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (topmost && topmost->data) {
|
||||
if (my >= topmost->y + 20)
|
||||
syscall_send_mouse_up_event(topmost, mx - topmost->x, my - topmost->y - 20);
|
||||
}
|
||||
}
|
||||
|
||||
if (target && target->data) {
|
||||
int rel_y = my - target->y - 20;
|
||||
// Provide coordinates clamped if escaping bounds slightly on UP? Usually raw is fine.
|
||||
syscall_send_mouse_up_event(target, mx - target->x, rel_y);
|
||||
}
|
||||
active_mouse_capture_win = NULL;
|
||||
}
|
||||
|
||||
if (dx != 0 || dy != 0) {
|
||||
// Mouse moved - send MOUSE_MOVE event to topmost window
|
||||
Window *topmost = NULL;
|
||||
// Mouse moved - send MOUSE_MOVE event to captured window (if dragging) or topmost
|
||||
Window *target = active_mouse_capture_win;
|
||||
if (!target) {
|
||||
int topmost_z = -1;
|
||||
for (int w = 0; w < window_count; w++) {
|
||||
Window *win = all_windows[w];
|
||||
if (win->visible && rect_contains(win->x, win->y, win->w, win->h, mx, my)) {
|
||||
if (win->z_index > topmost_z) {
|
||||
topmost = win;
|
||||
target = win;
|
||||
topmost_z = win->z_index;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (topmost && topmost->data) {
|
||||
if (my >= topmost->y + 20)
|
||||
syscall_send_mouse_move_event(topmost, mx - topmost->x, my - topmost->y - 20, buttons);
|
||||
}
|
||||
|
||||
if (target && target->data) {
|
||||
int rel_y = my - target->y - 20;
|
||||
syscall_send_mouse_move_event(target, mx - target->x, rel_y, buttons);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ void draw_traffic_light(int x, int y);
|
|||
void draw_icon(int x, int y, const char *label);
|
||||
void draw_folder_icon(int x, int y, const char *label);
|
||||
void draw_document_icon(int x, int y, const char *label);
|
||||
void draw_pdf_icon(int x, int y, const char *label);
|
||||
void draw_elf_icon(int x, int y, const char *label);
|
||||
void draw_image_icon(int x, int y, const char *label);
|
||||
void draw_notepad_icon(int x, int y, const char *label);
|
||||
|
|
|
|||
Loading…
Reference in a new issue