This commit is contained in:
agra
2026-03-03 13:25:25 +02:00
parent 6ffe22acb0
commit 343ea4bf08
9 changed files with 736 additions and 169 deletions

View File

@@ -1,95 +1,11 @@
#import "modules/std.sx";
#import "ui/types.sx";
#import "ui/glyph_cache.sx";
FIRST_CHAR :s32: 32;
NUM_CHARS :s32: 96;
ATLAS_W :s32: 512;
ATLAS_H :s32: 512;
// Global glyph cache pointer for views (Label, Button) to access
g_font : *GlyphCache = xx 0;
// Matches stbtt_bakedchar memory layout
BakedChar :: struct {
x0, y0, x1, y1: u16;
xoff, yoff, xadvance: f32;
}
// Matches stbtt_aligned_quad memory layout
AlignedQuad :: struct {
x0, y0, s0, t0: f32;
x1, y1, s1, t1: f32;
}
FontAtlas :: struct {
texture_id: u32;
font_size: f32;
char_data: [*]BakedChar;
bitmap: [*]u8;
ascent: f32;
descent: f32;
line_height: f32;
// Bake font glyphs into a bitmap. Call upload_texture() after GL is ready.
init :: (self: *FontAtlas, path: [:0]u8, size: f32) {
file_size : s32 = 0;
font_data := read_file_bytes(path, @file_size);
if xx font_data == 0 {
out("Failed to load font: ");
out(path);
out("\n");
return;
}
self.font_size = size;
// Allocate baked char data (96 entries for ASCII 32..127)
self.char_data = xx context.allocator.alloc(xx NUM_CHARS * size_of(BakedChar));
// Bake font bitmap (512x512 single-channel alpha)
bitmap_size : s64 = xx ATLAS_W * xx ATLAS_H;
self.bitmap = xx context.allocator.alloc(bitmap_size);
stbtt_BakeFontBitmap(font_data, 0, size, self.bitmap, ATLAS_W, ATLAS_H, FIRST_CHAR, NUM_CHARS, xx self.char_data);
// Get font vertical metrics
fontinfo : [256]u8 = ---;
stbtt_InitFont(xx @fontinfo, font_data, 0);
ascent_i : s32 = 0;
descent_i : s32 = 0;
linegap_i : s32 = 0;
stbtt_GetFontVMetrics(xx @fontinfo, @ascent_i, @descent_i, @linegap_i);
scale := stbtt_ScaleForPixelHeight(xx @fontinfo, size);
self.ascent = xx ascent_i * scale;
self.descent = xx descent_i * scale;
self.line_height = self.ascent - self.descent + xx linegap_i * scale;
font_data_ptr : *void = xx font_data;
free(font_data_ptr);
out("Font loaded: ");
out(path);
out("\n");
}
measure_text :: (self: *FontAtlas, text: string, font_size: f32) -> Size {
if self.char_data == null { return Size.zero(); }
scale := font_size / self.font_size;
xpos : f32 = 0.0;
ypos : f32 = 0.0;
q : AlignedQuad = ---;
i : s64 = 0;
while i < text.len {
ch : s32 = xx text[i];
if ch >= FIRST_CHAR and ch < FIRST_CHAR + NUM_CHARS {
stbtt_GetBakedQuad(xx self.char_data, ATLAS_W, ATLAS_H, ch - FIRST_CHAR, @xpos, @ypos, xx @q, 1);
}
i += 1;
}
Size.{ width = xpos * scale, height = self.line_height * scale };
}
}
// Global font atlas pointer for views (Label, Button) to access
g_font : *FontAtlas = xx 0;
set_global_font :: (font: *FontAtlas) {
set_global_font :: (font: *GlyphCache) {
g_font = font;
}