feat: add word processor, spreadsheet, kernel and userspace memory improvements

This commit is contained in:
2026-03-05 19:18:11 +01:00
parent fcb6f8e247
commit ead7d296f7
28 changed files with 4146 additions and 56 deletions
+1
View File
@@ -87,6 +87,7 @@ struct DesktopState {
SvgIcon icon_procmgr;
SvgIcon icon_mandelbrot;
SvgIcon icon_devexplorer;
SvgIcon icon_spreadsheet;
bool ctx_menu_open;
int ctx_menu_x, ctx_menu_y;
+16 -13
View File
@@ -321,7 +321,7 @@ struct SvgEdgeList {
int capacity;
void init(int cap) {
edges = (SvgEdge*)montauk::alloc(cap * sizeof(SvgEdge));
edges = (SvgEdge*)montauk::malloc(cap * sizeof(SvgEdge));
count = 0;
capacity = cap;
}
@@ -800,7 +800,7 @@ inline void svg_rasterize(const SvgEdgeList& el, uint32_t* pixels, int w, int h,
// Temporary array for x-intersections on each scanline
// Allocate enough for all edges (each edge can intersect at most once per scanline)
int maxIsect = el.count + 16;
fixed_t* isect = (fixed_t*)montauk::alloc(maxIsect * sizeof(fixed_t));
fixed_t* isect = (fixed_t*)montauk::malloc(maxIsect * sizeof(fixed_t));
for (int y = 0; y < h; ++y) {
// Scanline center in fixed-point
@@ -858,7 +858,7 @@ inline void svg_rasterize(const SvgEdgeList& el, uint32_t* pixels, int w, int h,
}
}
montauk::free(isect);
montauk::mfree(isect);
}
// ---------------------------------------------------------------------------
@@ -1018,7 +1018,7 @@ inline void svg_rasterize_blend(const SvgEdgeList& el, uint32_t* pixels, int w,
if (el.count == 0) return;
int maxIsect = el.count + 16;
fixed_t* isect = (fixed_t*)montauk::alloc(maxIsect * sizeof(fixed_t));
fixed_t* isect = (fixed_t*)montauk::malloc(maxIsect * sizeof(fixed_t));
uint32_t fr = (fill >> 16) & 0xFF;
uint32_t fg = (fill >> 8) & 0xFF;
@@ -1081,7 +1081,7 @@ inline void svg_rasterize_blend(const SvgEdgeList& el, uint32_t* pixels, int w,
}
}
montauk::free(isect);
montauk::mfree(isect);
}
// ---------------------------------------------------------------------------
@@ -1091,7 +1091,7 @@ inline SvgIcon svg_render(const char* svg_data, int svg_len, int target_w, int t
SvgIcon icon;
icon.width = target_w;
icon.height = target_h;
icon.pixels = (uint32_t*)montauk::alloc(target_w * target_h * sizeof(uint32_t));
icon.pixels = (uint32_t*)montauk::malloc(target_w * target_h * sizeof(uint32_t));
// Clear to transparent
svg_memset(icon.pixels, 0, target_w * target_h * sizeof(uint32_t));
@@ -1204,6 +1204,9 @@ inline SvgIcon svg_render(const char* svg_data, int svg_len, int target_w, int t
SvgEdgeList el;
el.init(SVG_MAX_EDGES);
// Heap-allocated path data buffer (avoids 8 KiB on the stack)
char* d_buf = (char*)montauk::malloc(SVG_MAX_PATH_LEN);
// Scan for <path, <circle, <rect elements — rasterize each individually
// Skip elements inside <defs> blocks (they define reusable items, not rendered directly)
const char* p = svg_data;
@@ -1249,7 +1252,6 @@ inline SvgIcon svg_render(const char* svg_data, int svg_len, int target_w, int t
int alpha = svg_get_element_opacity(elem_start, elem_len);
// Extract and rasterize path
char d_buf[SVG_MAX_PATH_LEN];
int d_len = svg_get_attr(elem_start, elem_len, " d", d_buf, SVG_MAX_PATH_LEN);
if (d_len > 0) {
el.clear();
@@ -1359,7 +1361,8 @@ inline SvgIcon svg_render(const char* svg_data, int svg_len, int target_w, int t
++p;
}
montauk::free(el.edges);
montauk::mfree(d_buf);
montauk::mfree(el.edges);
return icon;
}
@@ -1378,7 +1381,7 @@ inline SvgIcon svg_load(const char* vfs_path, int target_w, int target_h, Color
return {nullptr, 0, 0};
}
char* buf = (char*)montauk::alloc(size + 1);
char* buf = (char*)montauk::malloc(size + 1);
montauk::read(fd, (uint8_t*)buf, 0, size);
montauk::close(fd);
buf[size] = '\0';
@@ -1389,12 +1392,12 @@ inline SvgIcon svg_load(const char* vfs_path, int target_w, int target_h, Color
int hi_h = target_h * SS;
SvgIcon hi = svg_render(buf, (int)size, hi_w, hi_h, fill_color);
montauk::free(buf);
montauk::mfree(buf);
if (!hi.pixels) return {nullptr, 0, 0};
// Allocate final icon at target resolution
uint32_t* out = (uint32_t*)montauk::alloc(target_w * target_h * 4);
uint32_t* out = (uint32_t*)montauk::malloc(target_w * target_h * 4);
for (int i = 0; i < target_w * target_h; i++) out[i] = 0;
// Downsample: average each SSxSS block using premultiplied alpha
@@ -1432,7 +1435,7 @@ inline SvgIcon svg_load(const char* vfs_path, int target_w, int target_h, Color
}
}
montauk::free(hi.pixels);
montauk::mfree(hi.pixels);
return {out, target_w, target_h};
}
@@ -1440,7 +1443,7 @@ inline SvgIcon svg_load(const char* vfs_path, int target_w, int target_h, Color
// Free icon pixel data
// ---------------------------------------------------------------------------
inline void svg_free(SvgIcon& icon) {
if (icon.pixels) montauk::free(icon.pixels);
if (icon.pixels) montauk::mfree(icon.pixels);
icon.pixels = nullptr;
icon.width = 0;
icon.height = 0;
+15 -2
View File
@@ -130,6 +130,13 @@ static inline void terminal_init_cells(TerminalState* t, int cols, int rows, int
int screen_cells = rows * cols;
t->cells = (TermCell*)montauk::alloc(total_cells * sizeof(TermCell));
t->alt_cells = (TermCell*)montauk::alloc(screen_cells * sizeof(TermCell));
if (!t->cells || !t->alt_cells) {
// Allocation failed — leave terminal in a safe but unusable state
if (t->cells) { montauk::free(t->cells); t->cells = nullptr; }
if (t->alt_cells) { montauk::free(t->alt_cells); t->alt_cells = nullptr; }
t->cols = 0; t->rows = 0;
return;
}
for (int i = 0; i < total_cells; i++) {
t->cells[i] = {' ', colors::TERM_FG, colors::TERM_BG};
}
@@ -143,7 +150,8 @@ static inline void terminal_init(TerminalState* t, int cols, int rows) {
t->cursor_visible = true;
t->child_pid = montauk::spawn_redir("0:/os/shell.elf");
montauk::childio_settermsz(t->child_pid, cols, rows);
if (t->child_pid > 0)
montauk::childio_settermsz(t->child_pid, cols, rows);
}
static inline void terminal_put_char(TerminalState* t, char ch) {
@@ -467,7 +475,7 @@ static inline void terminal_feed(TerminalState* t, const char* data, int len) {
}
static inline void terminal_render(TerminalState* t, uint32_t* pixels, int pw, int ph) {
if (!t->dirty) return;
if (!t->dirty || !t->cells) return;
t->dirty = false;
int cell_w = mono_cell_width();
@@ -593,6 +601,11 @@ static inline void terminal_resize(TerminalState* t, int new_cols, int new_rows)
int new_total = new_capacity * new_cols;
TermCell* new_cells = (TermCell*)montauk::alloc(new_total * sizeof(TermCell));
TermCell* new_alt = (TermCell*)montauk::alloc(new_rows * new_cols * sizeof(TermCell));
if (!new_cells || !new_alt) {
if (new_cells) montauk::free(new_cells);
if (new_alt) montauk::free(new_alt);
return; // keep existing buffers
}
// Clear new buffers
for (int i = 0; i < new_total; i++)