From 41adeeb47f40c0aa595a0a7c0f39f2cf107ca5ab Mon Sep 17 00:00:00 2001 From: pavel Date: Fri, 3 Jul 2026 09:25:58 +0200 Subject: [PATCH] Embed the bundled monospace font in the client binary The font atlas loader read the bundled Noto Sans Mono from a cwd-relative path with system-font fallbacks, so launching the editor from outside the repo root could pick a different font or fail. The bundled font is now embedded with #load; EditorMono.ttf remains an optional on-disk override, and the system fallback paths are gone. Together with the embedded shaders this makes the binary fully self-contained. Co-Authored-By: Claude Fable 5 --- README.md | 2 +- client/odin/gpu_renderer.odin | 32 ++++++++++++++------------------ 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 591f7fb..2aee58c 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ Use `Ctrl+W` to close the active buffer, or click a tab's `x`. Dirty buffers are SDL mode creates an SDL3 `GPUDevice` and uses a direct SDL3 GPU command-buffer renderer when a GPU backend is available. It batches editor rectangles, selections, cursor lines, panels, and `stb_truetype` font-atlas text into GPU vertices. It falls back to the regular SDL renderer in unsupported environments such as `SDL_VIDEODRIVER=dummy` smoke tests. -The GPU font loader checks `client/odin/assets/fonts/EditorMono.ttf`, `client/odin/assets/fonts/NotoSansMono-Regular.ttf`, then common system monospace font locations. The repo includes a bundled Noto Sans Mono font for the default path. +The bundled Noto Sans Mono font is embedded into the client binary at build time, so the editor always has a working monospace font. Place a `client/odin/assets/fonts/EditorMono.ttf` file to override it. The GPU editor path includes lightweight Kotlin/Java syntax highlighting for comments, block comments, strings, character literals, triple-quoted Kotlin strings, keywords, numbers, and type-like identifiers. diff --git a/client/odin/gpu_renderer.odin b/client/odin/gpu_renderer.odin index 945948b..45233cc 100644 --- a/client/odin/gpu_renderer.odin +++ b/client/odin/gpu_renderer.odin @@ -61,12 +61,12 @@ GPU_FONT_ATLAS_SIZE :: 512 GPU_FONT_PIXEL_HEIGHT :: 15.0 GPU_FONT_BASELINE_OFFSET :: 11.0 GPU_FONT_CELL_PADDING :: 1.0 -GPU_FONT_PATHS := [?]string{ +// The bundled font is embedded at build time so the binary always has a +// working monospace font. EditorMono.ttf remains an optional on-disk override. +@(rodata) +GPU_EMBEDDED_FONT := #load("assets/fonts/NotoSansMono-Regular.ttf") +GPU_FONT_OVERRIDE_PATHS := [?]string{ "client/odin/assets/fonts/EditorMono.ttf", - "client/odin/assets/fonts/NotoSansMono-Regular.ttf", - "/usr/share/fonts/google-noto/NotoSansMono-Regular.ttf", - "/usr/share/fonts/dejavu-sans-mono-fonts/DejaVuSansMono.ttf", - "/usr/share/fonts/dejavu/DejaVuSansMono.ttf", } gpu_renderer_make :: proc(window: ^SDL.Window) -> GPU_Renderer { @@ -436,12 +436,8 @@ gpu_present :: proc(gpu: ^GPU_Renderer) { } gpu_create_font_atlas :: proc(gpu: ^GPU_Renderer) -> bool { - font_bytes, font_path, ok := gpu_read_font_file() - if !ok { - fmt.println("read font failed: no configured monospace font found") - return false - } - defer delete(font_bytes) + font_bytes, font_path, owned := gpu_read_font_file() + defer if owned do delete(font_bytes) atlas_size := GPU_FONT_ATLAS_SIZE * GPU_FONT_ATLAS_SIZE atlas := make([]u8, atlas_size) @@ -509,17 +505,17 @@ gpu_create_font_atlas :: proc(gpu: ^GPU_Renderer) -> bool { return SDL.SubmitGPUCommandBuffer(command) } -gpu_read_font_file :: proc() -> ([]u8, string, bool) { - for path in GPU_FONT_PATHS { - bytes, err := os.read_entire_file(path, context.allocator) - if err == nil && len(bytes) > 0 { - return bytes, path, true +gpu_read_font_file :: proc() -> (bytes: []u8, path: string, owned: bool) { + for override_path in GPU_FONT_OVERRIDE_PATHS { + data, err := os.read_entire_file(override_path, context.allocator) + if err == nil && len(data) > 0 { + return data, override_path, true } if err == nil { - delete(bytes) + delete(data) } } - return nil, "", false + return GPU_EMBEDDED_FONT, "embedded NotoSansMono-Regular.ttf", false } gpu_push_quad :: proc(gpu: ^GPU_Renderer, x0, y0, x1, y1: f32, c: [4]f32) {