diff --git a/boredos.iso b/boredos.iso index 7b88230..07ab20a 100644 Binary files a/boredos.iso and b/boredos.iso differ diff --git a/build/cmd.o b/build/cmd.o index a50b6e4..c94019f 100644 Binary files a/build/cmd.o and b/build/cmd.o differ diff --git a/build/explorer.o b/build/explorer.o index a1344a7..5399762 100644 Binary files a/build/explorer.o and b/build/explorer.o differ diff --git a/build/graphics.o b/build/graphics.o index b341032..f484a9d 100644 Binary files a/build/graphics.o and b/build/graphics.o differ diff --git a/python_http.log b/python_http.log new file mode 100644 index 0000000..0cfb1d1 --- /dev/null +++ b/python_http.log @@ -0,0 +1,28 @@ +Traceback (most recent call last): + File "", line 198, in _run_module_as_main + File "", line 88, in _run_code + File "/opt/homebrew/Cellar/python@3.14/3.14.2/Frameworks/Python.framework/Versions/3.14/lib/python3.14/http/server.py", line 1432, in + test( + ~~~~^ + HandlerClass=handler_class, + ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ...<6 lines>... + tls_password=tls_key_password, + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + ) + ^ + File "/opt/homebrew/Cellar/python@3.14/3.14.2/Frameworks/Python.framework/Versions/3.14/lib/python3.14/http/server.py", line 1348, in test + server = ServerClass(addr, HandlerClass) + File "/opt/homebrew/Cellar/python@3.14/3.14.2/Frameworks/Python.framework/Versions/3.14/lib/python3.14/socketserver.py", line 457, in __init__ + self.server_bind() + ~~~~~~~~~~~~~~~~^^ + File "/opt/homebrew/Cellar/python@3.14/3.14.2/Frameworks/Python.framework/Versions/3.14/lib/python3.14/http/server.py", line 1419, in server_bind + return super().server_bind() + ~~~~~~~~~~~~~~~~~~~^^ + File "/opt/homebrew/Cellar/python@3.14/3.14.2/Frameworks/Python.framework/Versions/3.14/lib/python3.14/http/server.py", line 148, in server_bind + socketserver.TCPServer.server_bind(self) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^ + File "/opt/homebrew/Cellar/python@3.14/3.14.2/Frameworks/Python.framework/Versions/3.14/lib/python3.14/socketserver.py", line 478, in server_bind + self.socket.bind(self.server_address) + ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^ +OSError: [Errno 48] Address already in use diff --git a/src/kernel/font_manager.c b/src/kernel/font_manager.c index fb654ce..174545a 100644 --- a/src/kernel/font_manager.c +++ b/src/kernel/font_manager.c @@ -109,6 +109,7 @@ ttf_font_t* font_manager_load(const char *path, float size) { font->data = buffer; font->size = fsize; font->info = info; + font->pixel_height = size; font->scale = stbtt_ScaleForPixelHeight(info, size); stbtt_GetFontVMetrics(info, &font->ascent, &font->descent, &font->line_gap); @@ -121,10 +122,17 @@ 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)) { if (!font) font = default_font; if (!font) return; + font_manager_render_char_scaled(font, x, y, c, color, font->pixel_height, put_pixel_fn); +} + +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)) { + if (!font) font = default_font; + if (!font) return; stbtt_fontinfo *info = (stbtt_fontinfo *)font->info; int w, h, xoff, yoff; - unsigned char *bitmap = stbtt_GetCodepointBitmap(info, 0, font->scale, c, &w, &h, &xoff, &yoff); + float real_scale = stbtt_ScaleForPixelHeight(info, scale); // Convert pixel size back to stbtt scale + unsigned char *bitmap = stbtt_GetCodepointBitmap(info, 0, real_scale, c, &w, &h, &xoff, &yoff); if (bitmap) { for (int row = 0; row < h; row++) { @@ -143,16 +151,44 @@ void font_manager_render_char(ttf_font_t *font, int x, int y, char c, uint32_t c } int font_manager_get_string_width(ttf_font_t *font, const char *s) { + if (!font) font = default_font; + if (!font) return 0; + return font_manager_get_string_width_scaled(font, s, font->pixel_height); +} + +int font_manager_get_font_height_scaled(ttf_font_t *font, float scale) { + if (!font) font = default_font; + if (!font) return 0; + float real_scale = stbtt_ScaleForPixelHeight((stbtt_fontinfo *)font->info, scale); + return (int)((font->ascent - font->descent) * real_scale); +} + +int font_manager_get_font_ascent_scaled(ttf_font_t *font, float scale) { + if (!font) font = default_font; + if (!font) return 0; + float real_scale = stbtt_ScaleForPixelHeight((stbtt_fontinfo *)font->info, scale); + return (int)(font->ascent * real_scale); +} + +int font_manager_get_font_line_height_scaled(ttf_font_t *font, float scale) { + if (!font) font = default_font; + if (!font) return 0; + float real_scale = stbtt_ScaleForPixelHeight((stbtt_fontinfo *)font->info, scale); + return (int)((font->ascent - font->descent + font->line_gap) * real_scale); +} + +int font_manager_get_string_width_scaled(ttf_font_t *font, const char *s, float scale) { if (!font) font = default_font; if (!font || !s) return 0; stbtt_fontinfo *info = (stbtt_fontinfo *)font->info; + float real_scale = stbtt_ScaleForPixelHeight(info, scale); int width = 0; while (*s) { int advance, lsb; stbtt_GetCodepointHMetrics(info, *s, &advance, &lsb); // Round per-character to match draw_string's accumulation - width += (int)(advance * font->scale + 0.5f); + width += (int)(advance * real_scale + 0.5f); s++; } return width; diff --git a/src/kernel/font_manager.h b/src/kernel/font_manager.h index 7ca2645..b96a74d 100644 --- a/src/kernel/font_manager.h +++ b/src/kernel/font_manager.h @@ -40,6 +40,7 @@ typedef struct { size_t size; void *info; // stbtt_fontinfo float scale; + float pixel_height; int ascent; int descent; int line_gap; @@ -48,6 +49,12 @@ typedef struct { 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)); 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); + +int font_manager_get_font_height_scaled(ttf_font_t *font, float scale); +int font_manager_get_font_ascent_scaled(ttf_font_t *font, float scale); +int font_manager_get_font_line_height_scaled(ttf_font_t *font, float scale); #endif diff --git a/src/kernel/graphics.c b/src/kernel/graphics.c index 9a4218a..43160cf 100644 --- a/src/kernel/graphics.c +++ b/src/kernel/graphics.c @@ -379,25 +379,45 @@ int graphics_get_font_height(void) { return 10; // Fallback bitmap height } +int graphics_get_font_height_scaled(float scale) { + if (g_current_ttf) { + return font_manager_get_font_height_scaled(g_current_ttf, scale); + } + return 10; // Fallback bitmap height +} + +int graphics_get_string_width_scaled(const char *s, float scale) { + if (g_current_ttf) { + return font_manager_get_string_width_scaled(g_current_ttf, s, scale); + } + int len = 0; + while (s && s[len]) len++; + return len * 8; // Fallback bitmap width +} + void draw_string(int x, int y, const char *s, uint32_t color) { + if (g_current_ttf) draw_string_scaled(x, y, s, color, g_current_ttf->pixel_height); + else draw_string_scaled(x, y, s, color, 15.0f); +} + +void draw_string_scaled(int x, int y, const char *s, uint32_t color, float scale) { if (!s) return; int cur_x = x; if (g_current_ttf) { - float scale = g_current_ttf->scale; - // Shift baseline up by roughly 2 pixels for better vertical centering in bars/inputs - int baseline = y + (int)(g_current_ttf->ascent * scale) - 2; - int line_height = (int)((g_current_ttf->ascent - g_current_ttf->descent + g_current_ttf->line_gap) * scale); + // We let the font manager handle the stbtt scale internally to avoid bringing stb_truetype into graphics.c + 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(g_current_ttf, cur_x, baseline, *s, color, put_pixel); + font_manager_render_char_scaled(g_current_ttf, cur_x, baseline, *s, color, scale, put_pixel); // Advance by same rounded width that font_manager_get_string_width uses char buf[2] = {*s, 0}; - cur_x += font_manager_get_string_width(g_current_ttf, buf); + cur_x += font_manager_get_string_width_scaled(g_current_ttf, buf, scale); } s++; } diff --git a/src/kernel/graphics.h b/src/kernel/graphics.h index 9180ba6..8d40fb2 100644 --- a/src/kernel/graphics.h +++ b/src/kernel/graphics.h @@ -24,6 +24,7 @@ void draw_rounded_rect_filled(int x, int y, int w, int h, int radius, uint32_t c 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_desktop_background(void); void graphics_set_bg_color(uint32_t color); void graphics_set_bg_pattern(const uint32_t *pattern); // 128x128 pattern @@ -56,6 +57,8 @@ void graphics_clear_clipping(void); #include "font_manager.h" ttf_font_t *graphics_get_current_ttf(void); int graphics_get_font_height(void); +int graphics_get_font_height_scaled(float scale); +int graphics_get_string_width_scaled(const char *s, float scale); void graphics_set_font(const char *path); #endif diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index 4744184..0cf22f4 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -385,6 +385,45 @@ static uint64_t syscall_handler_inner(uint64_t syscall_num, uint64_t arg1, uint6 draw_string_bitmap(win->x + ux, win->y + uy, kernel_str, color); } + asm volatile("push %0; popfq" : : "r"(rflags)); + } + } else if (cmd == 11) { // GUI_CMD_DRAW_STRING_SCALED + Window *win = (Window *)arg2; + uint64_t coords = arg3; + int ux = coords & 0xFFFFFFFF; + int uy = coords >> 32; + const char *user_str = (const char *)arg4; + uint64_t packed = arg5; + uint32_t color = packed & 0xFFFFFFFF; + uint32_t scale_bits = packed >> 32; + float scale = *(float*)&scale_bits; + + if (win && user_str) { + extern void draw_string_scaled(int x, int y, const char *str, uint32_t color, float scale); + 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)); + + 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); + draw_string_scaled(ux, uy, kernel_str, color, scale); + graphics_set_render_target(NULL, 0, 0); + } + } else { + draw_string_scaled(win->x + ux, win->y + uy, kernel_str, color, scale); + } + asm volatile("push %0; popfq" : : "r"(rflags)); } } else if (cmd == GUI_CMD_DRAW_IMAGE) { @@ -464,9 +503,31 @@ static uint64_t syscall_handler_inner(uint64_t syscall_num, uint64_t arg1, uint6 } else { return (uint64_t)i * 8; // Fallback bitmap width } + } else if (cmd == 12) { // GUI_CMD_GET_STRING_WIDTH_SCALED + const char *user_str = (const char *)arg2; + uint32_t scale_bits = (uint32_t)arg3; + float scale = *(float*)&scale_bits; + + if (!user_str) return 0; + + char kernel_str[256]; + int i = 0; + while (i < 255 && user_str[i]) { + kernel_str[i] = user_str[i]; + i++; + } + kernel_str[i] = 0; + + extern int graphics_get_string_width_scaled(const char *s, float scale); + return (uint64_t)graphics_get_string_width_scaled(kernel_str, scale); } else if (cmd == GUI_CMD_GET_FONT_HEIGHT) { extern int graphics_get_font_height(void); return (uint64_t)graphics_get_font_height(); + } else if (cmd == 13) { // GUI_CMD_GET_FONT_HEIGHT_SCALED + uint32_t scale_bits = (uint32_t)arg2; + float scale = *(float*)&scale_bits; + extern int graphics_get_font_height_scaled(float scale); + return (uint64_t)graphics_get_font_height_scaled(scale); } } else if (syscall_num == SYS_FS) { int cmd = (int)arg1; diff --git a/src/kernel/userland/browser.c b/src/kernel/userland/browser.c index f32be3d..8486f84 100644 --- a/src/kernel/userland/browser.c +++ b/src/kernel/userland/browser.c @@ -72,12 +72,16 @@ static long strtol(const char* nptr, char** endptr, int base) { return neg ? -res : res; } -typedef enum { TAG_NONE, TAG_IMG, TAG_INPUT, TAG_BUTTON } HTMLTag; +#define TAG_NONE 0 +#define TAG_IMG 1 +#define TAG_INPUT 2 +#define TAG_BUTTON 3 +#define TAG_HR 4 typedef struct { char content[1024]; int x, y, w, h; - HTMLTag tag; + int tag; // Changed from HTMLTag enum to int char link_url[256]; char attr_value[256]; uint32_t color; @@ -90,6 +94,7 @@ typedef struct { int form_id; int input_cursor; int input_scroll; + float scale; } RenderElement; #define MAX_ELEMENTS 65536 @@ -325,14 +330,36 @@ static void flush_line(bool centered) { if (offset_x < 10) offset_x = 10; int max_h = 16; + int max_baseline = 16; + + // First pass: find maximum height and maximum baseline + for (int i = 0; i < line_element_count; i++) { + RenderElement *el = &elements[line_elements[i]]; + if (el->tag == TAG_IMG && el->img_h + 10 > max_h) max_h = el->img_h + 10; + if ((el->tag == TAG_INPUT || el->tag == TAG_BUTTON) && 20 + 10 > max_h) max_h = 20 + 10; + if (el->tag == TAG_NONE) { + int fh = ui_get_font_height_scaled(el->scale); + if (fh + 4 > max_h) max_h = fh + 4; + if (fh > max_baseline) max_baseline = fh; + } + } + + // Second pass: apply coordinates with baseline alignment for (int i = 0; i < line_element_count; i++) { RenderElement *el = &elements[line_elements[i]]; el->x = offset_x; - el->y = cur_line_y; + + // Align text to the baseline of the largest text on this line + if (el->tag == TAG_NONE) { + int fh = ui_get_font_height_scaled(el->scale); + el->y = cur_line_y + (max_baseline - fh); + } else { + el->y = cur_line_y; // Keep images/inputs at the top for now + } + offset_x += el->w; - if (el->tag == TAG_IMG && el->img_h + 10 > max_h) max_h = el->img_h + 10; - if ((el->tag == TAG_INPUT || el->tag == TAG_BUTTON) && 20 + 10 > max_h) max_h = 20 + 10; } + cur_line_y += max_h; cur_line_x = 10; line_element_count = 0; @@ -340,10 +367,31 @@ static void flush_line(bool centered) { } +static uint32_t parse_html_color(const char *str) { + if (!str) return COLOR_TEXT; + while (*str == ' ' || *str == '\"' || *str == '\'') str++; + if (*str == '#') { + char *end; + uint32_t val = (uint32_t)strtol(str + 1, &end, 16); + return 0xFF000000 | val; // Assumes RRGGBB + } + if (str_istarts_with(str, "red")) return 0xFFFF0000; + if (str_istarts_with(str, "green")) return 0xFF008000; + if (str_istarts_with(str, "blue")) return 0xFF0000FF; + if (str_istarts_with(str, "white")) return 0xFFFFFFFF; + if (str_istarts_with(str, "black")) return 0xFF000000; + if (str_istarts_with(str, "yellow")) return 0xFFFFFF00; + if (str_istarts_with(str, "gray")) return 0xFF808080; + if (str_istarts_with(str, "purple")) return 0xFF800080; + return COLOR_TEXT; +} + static void parse_html(const char *html) { browser_clear(); cur_line_y = 10; cur_line_y = 10; cur_line_x = 10; line_element_count = 0; int i = 0; bool is_centered = false; bool is_bold = false; uint32_t current_color = COLOR_TEXT; char current_link[256] = ""; + float current_scale = 15.0f; float base_scale = 15.0f; + bool is_space_pending = false; char current_form_action[256] = ""; int current_form_id = 0; bool skip_content = false; next_form_id = 1; @@ -369,20 +417,68 @@ static void parse_html(const char *html) { if (tag_name[0] == '/') { if (str_istarts_with(tag_name+1, "center")) { flush_line(is_centered); is_centered = false; } - else if (tag_name[1] == 'h' && tag_name[2] >= '1' && tag_name[2] <= '6') { flush_line(is_centered); cur_line_y += 10; is_bold = false; } + else if (tag_name[1] == 'h' && tag_name[2] >= '1' && tag_name[2] <= '6') { flush_line(is_centered); cur_line_y += 10; is_bold = false; base_scale = 15.0f; current_scale = 15.0f; } else if (str_istarts_with(tag_name+1, "form")) { flush_line(is_centered); current_form_id = 0; current_form_action[0] = 0; } else if (str_istarts_with(tag_name+1, "a")) current_link[0] = 0; else if (str_istarts_with(tag_name+1, "p") || str_istarts_with(tag_name+1, "li") || str_istarts_with(tag_name+1, "ol") || str_istarts_with(tag_name+1, "div")) flush_line(is_centered); - else if (str_istarts_with(tag_name+1, "font")) current_color = COLOR_TEXT; + else if (str_istarts_with(tag_name+1, "font")) { current_color = COLOR_TEXT; current_scale = base_scale; } else if (str_istarts_with(tag_name+1, "head") || (tag_name[1] == 's' && tag_name[2] == 'c') || (tag_name[1] == 's' && tag_name[2] == 'i') || (tag_name[1] == 's' && tag_name[2] == 't') || str_istarts_with(tag_name+1, "title") || str_istarts_with(tag_name+1, "noscript") || str_istarts_with(tag_name+1, "style")) skip_content = false; } else { if (str_istarts_with(tag_name, "center")) { flush_line(is_centered); is_centered = true; } - else if (tag_name[0] == 'h' && tag_name[1] >= '1' && tag_name[1] <= '6') { flush_line(is_centered); cur_line_y += 10; is_bold = true; } + else if (tag_name[0] == 'h' && tag_name[1] >= '1' && tag_name[1] <= '6') { + flush_line(is_centered); cur_line_y += 10; is_bold = true; + if (tag_name[1] == '1') base_scale = 32.0f; + else if (tag_name[1] == '2') base_scale = 24.0f; + else if (tag_name[1] == '3') base_scale = 20.0f; + else base_scale = 18.0f; + current_scale = base_scale; + } + else if (str_istarts_with(tag_name, "font")) { + char *color_str = str_istrstr(attr_buf, "color=\""); + if (color_str) { + current_color = parse_html_color(color_str + 7); + } else { + color_str = str_istrstr(attr_buf, "color="); + if (color_str) current_color = parse_html_color(color_str + 6); + } + + char *size_str = str_istrstr(attr_buf, "size=\""); + int offset = 0; + if (size_str) { + offset = 6; + } else { + size_str = str_istrstr(attr_buf, "size="); + if (size_str) offset = 5; + } + if (size_str) { + char s_char = size_str[offset]; + if (s_char == '+') { + int inc = size_str[offset+1] - '0'; + int new_sz = 3 + inc; + if (new_sz > 7) new_sz = 7; + if (new_sz < 1) new_sz = 1; + s_char = '0' + new_sz; + } else if (s_char == '-') { + int dec = size_str[offset+1] - '0'; + int new_sz = 3 - dec; + if (new_sz > 7) new_sz = 7; + if (new_sz < 1) new_sz = 1; + s_char = '0' + new_sz; + } + if (s_char == '1') current_scale = 10.0f; + else if (s_char == '2') current_scale = 13.0f; + else if (s_char == '3') current_scale = 15.0f; + else if (s_char == '4') current_scale = 18.0f; + else if (s_char == '5') current_scale = 24.0f; + else if (s_char == '6') current_scale = 32.0f; + else if (s_char >= '7' && s_char <= '9') current_scale = 48.0f; + } + } else if (str_istarts_with(tag_name, "br")) flush_line(is_centered); - else if (str_istarts_with(tag_name, "h") || str_istarts_with(tag_name, "p") || str_istarts_with(tag_name, "hr") || str_istarts_with(tag_name, "li") || str_istarts_with(tag_name, "ol") || str_istarts_with(tag_name, "div")) flush_line(is_centered); + else if (str_istarts_with(tag_name, "p") || str_istarts_with(tag_name, "li") || str_istarts_with(tag_name, "ol") || str_istarts_with(tag_name, "div")) flush_line(is_centered); else if (str_istarts_with(tag_name, "form")) { flush_line(is_centered); current_form_id = next_form_id++; @@ -402,6 +498,16 @@ static void parse_html(const char *html) { while(href[l] && href[l] != '\"' && l < 255) { current_link[l] = href[l]; l++; } current_link[l] = 0; } + } else if (str_istarts_with(tag_name, "hr")) { + flush_line(is_centered); + RenderElement *el = &elements[element_count++]; + for (int k=0; k<(int)sizeof(RenderElement); k++) ((char*)el)[k] = 0; + el->tag = TAG_HR; + el->w = WIN_W - SCROLL_BAR_W - 40; + el->h = 10; // Extra padding + el->centered = true; + line_elements[line_element_count++] = element_count - 1; + flush_line(is_centered); } else if (str_istarts_with(tag_name, "img")) { RenderElement *el = &elements[element_count++]; int idx = element_count - 1; @@ -460,27 +566,49 @@ static void parse_html(const char *html) { } } else { if (!skip_content) { + while (html[i] && (html[i] == ' ' || html[i] == '\n' || html[i] == '\r')) { + is_space_pending = true; + i++; + } + while (html[i] && html[i] != '<') { - while (html[i] && (html[i] == ' ' || html[i] == '\n' || html[i] == '\r')) i++; - if (!html[i] || html[i] == '<') break; - char word[256]; int w_idx = 0; - while (html[i] && html[i] != '<' && html[i] != ' ' && html[i] != '\n' && html[i] != '\r' && w_idx < 255) { + if (is_space_pending) { + if (cur_line_x > 10) word[w_idx++] = ' '; + is_space_pending = false; + } + + while (html[i] && html[i] != '<' && html[i] != ' ' && html[i] != '\n' && html[i] != '\r' && w_idx < 254) { word[w_idx++] = html[i++]; } + + if (html[i] == ' ' || html[i] == '\n' || html[i] == '\r') { + is_space_pending = true; + while (html[i] && (html[i] == ' ' || html[i] == '\n' || html[i] == '\r')) i++; + } + word[w_idx] = 0; if (w_idx > 0) { if (element_count >= MAX_ELEMENTS) break; - int word_w = ui_get_string_width(word); - if (cur_line_x + word_w > WIN_W - SCROLL_BAR_W - 20) flush_line(is_centered); + int word_w = ui_get_string_width_scaled(word, current_scale); + if (cur_line_x + word_w > WIN_W - SCROLL_BAR_W - 20) { + flush_line(is_centered); + if (word[0] == ' ') { + for (int k=0; kcontent[k] = word[k]; k++; } - el->content[k++] = ' '; el->content[k] = 0; - el->w = ui_get_string_width(el->content); el->h = 16; + el->content[k] = 0; + el->w = word_w; + el->h = ui_get_font_height_scaled(current_scale); el->tag = TAG_NONE; el->color = current_link[0] ? COLOR_LINK : current_color; el->centered = is_centered; el->bold = is_bold; + el->scale = current_scale; if (current_link[0]) { int k=0; while(current_link[k]) { el->link_url[k] = current_link[k]; k++; } el->link_url[k] = 0; } line_elements[line_element_count++] = element_count - 1; @@ -541,9 +669,12 @@ static void browser_paint(void) { ui_draw_rect(win_browser, el->x, draw_y, 1, el->h, 0xFFFFFFFF); ui_draw_rect(win_browser, el->x + el->w - 1, draw_y, 1, el->h, 0xFF888888); ui_draw_string(win_browser, el->x + 10, draw_y + 4, el->attr_value, 0xFF000000); + } else if (el->tag == TAG_HR) { + ui_draw_rect(win_browser, el->x, draw_y + el->h / 2, el->w, 2, 0xFF888888); + ui_draw_rect(win_browser, el->x, draw_y + (el->h / 2) + 2, el->w, 1, 0xFFFFFFFF); } else { - ui_draw_string(win_browser, el->x, draw_y, el->content, el->color); - if (el->bold) ui_draw_string(win_browser, el->x + 1, draw_y, el->content, el->color); + ui_draw_string_scaled(win_browser, el->x, draw_y, el->content, el->color, el->scale); + if (el->bold) ui_draw_string_scaled(win_browser, el->x + 1, draw_y, el->content, el->color, el->scale); } } diff --git a/src/kernel/userland/libc/libui.c b/src/kernel/userland/libc/libui.c index 200d0f0..58c65b6 100644 --- a/src/kernel/userland/libc/libui.c +++ b/src/kernel/userland/libc/libui.c @@ -57,3 +57,21 @@ uint32_t ui_get_string_width(const char *str) { uint32_t ui_get_font_height(void) { return (uint32_t)syscall3(SYS_GUI, GUI_CMD_GET_FONT_HEIGHT, 0, 0); } + +void ui_draw_string_scaled(ui_window_t win, int x, int y, const char *str, uint32_t color, float scale) { + 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; + uint64_t packed_arg5 = ((uint64_t)scale_bits << 32) | (color & 0xFFFFFFFF); + syscall5(SYS_GUI, GUI_CMD_DRAW_STRING_SCALED, (uint64_t)win, coords, (uint64_t)str, packed_arg5); +} + +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); +} + +uint32_t ui_get_font_height_scaled(float scale) { + uint32_t scale_bits = *(uint32_t*)&scale; + return (uint32_t)syscall3(SYS_GUI, GUI_CMD_GET_FONT_HEIGHT_SCALED, (uint64_t)scale_bits, 0); +} diff --git a/src/kernel/userland/libc/libui.h b/src/kernel/userland/libc/libui.h index 1cf4d92..00408bc 100644 --- a/src/kernel/userland/libc/libui.h +++ b/src/kernel/userland/libc/libui.h @@ -15,6 +15,9 @@ #define GUI_CMD_GET_STRING_WIDTH 8 #define GUI_CMD_GET_FONT_HEIGHT 9 #define GUI_CMD_DRAW_STRING_BITMAP 10 +#define GUI_CMD_DRAW_STRING_SCALED 11 +#define GUI_CMD_GET_STRING_WIDTH_SCALED 12 +#define GUI_CMD_GET_FONT_HEIGHT_SCALED 13 // Event Types #define GUI_EVENT_NONE 0 @@ -52,4 +55,8 @@ uint32_t ui_get_string_width(const char *str); uint32_t ui_get_font_height(void); 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); +uint32_t ui_get_string_width_scaled(const char *str, float scale); +uint32_t ui_get_font_height_scaled(float scale); + #endif