Font_Handle :: #type, distinct u32; Glyph :: struct { ax: float; // advance.x ay: float; // advance.y bw: float; // bitmap.width; bh: float; // bitmap.rows; bl: float; // bitmap_left; bt: float; // bitmap_top; tx: float; // x offset of glyph in texture coordinates } Point :: struct { x: float; y: float; s: float; t: float; color: Vector4; }; Font :: struct { glyphs: [..] Glyph; face: FT_Face; pixel_size: u32; atlas_width: u32; atlas_height: u32; texture: Texture_Handle; } ft : FT_Library; init_freetype :: () { if FT_Init_FreeType(*ft) { log("Couldn't init Freetype\n"); } } create_font :: (renderer: *Renderer, path: string, pixel_size: u32) -> Font_Handle { font: Font; font.pixel_size = pixel_size; array_resize(*font.glyphs, 128); if FT_New_Face(ft, path.data, 0, *font.face) { log("Couldn't create new face\n"); assert(false); } else { FT_Set_Pixel_Sizes(font.face, 0, pixel_size); g := font.face.glyph; w : u32 = 0; h : u32 = 0; index := 0; for 32..128-1 { if FT_Load_Char(font.face, xx it, FT_LOAD_RENDER) { continue; } w += g.bitmap.width + 1; h = max(h, g.bitmap.rows); } atlas_width := w; bytes : [..] u8; bytes.allocator = temp; array_resize(*bytes, w * h); texture := create_texture(renderer, bytes.data, w, h, 1, generate_mips=false, format=.R8_UNORM); font.atlas_width = w; font.atlas_height = h; font.texture = texture; x : u32 = 0; pixel_width := 1.0 / cast(float)atlas_width; for 32..128-1 { if FT_Load_Char(font.face, xx it, FT_LOAD_RENDER) continue; // @Speed: We should put this buffer data into an array and upload everything once after this loop update_texture_region(renderer, texture, x, 0, g.bitmap.width, g.bitmap.rows, 1, g.bitmap.buffer); font.glyphs[it].ax = cast(float)(g.advance.x >> 6); font.glyphs[it].ay = cast(float)(g.advance.y >> 6); font.glyphs[it].bw = cast(float)g.bitmap.width; font.glyphs[it].bh = cast(float)g.bitmap.rows; font.glyphs[it].bl = cast(float)g.bitmap_left; font.glyphs[it].bt = cast(float)g.bitmap_top; font.glyphs[it].tx = cast(float)x / cast(float)w; x += g.bitmap.width + 1; } array_add(*renderer.fonts, font); return xx renderer.fonts.count; } return 0; } #import "freetype-2.12.1";