Allow multiple fonts

This commit is contained in:
Krzosa Karol
2025-12-01 09:05:06 +01:00
parent c2f4686bc4
commit e34c2b0cef
12 changed files with 102 additions and 112 deletions

View File

@@ -30,9 +30,8 @@ Shader Shader2D;
BlockArena RenderArena;
Rect2 CurrentScissor;
Font MainFont;
Int FontLineSpacing;
Int FontCharSpacing;
Font PrimaryFont;
Font SecondaryFont;
// ---------- shaders (ES3 / WebGL2) ----------
static const char *glsl_vshader_es3 = R"==(#version 300 es
@@ -227,7 +226,7 @@ void EndFrameRender(float wx, float wy, Color color) {
// bind texture unit 0 and the font texture
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, MainFont.texture_id);
glBindTexture(GL_TEXTURE_2D, PrimaryFont.texture_id);
// draw
glDrawArrays(GL_TRIANGLES, 0, it->count);
@@ -308,10 +307,10 @@ void PushQuad2D(Allocator arena, VertexList2D *list, Rect2 rect, Rect2 tex, Colo
}
void DrawRect(Rect2 rect, Color color) {
PushQuad2D(RenderArena, &Vertices, rect, MainFont.white_texture_bounding_box, color);
PushQuad2D(RenderArena, &Vertices, rect, PrimaryFont.white_texture_bounding_box, color);
}
void DrawRect(Rect2I rect, Color color) {
PushQuad2D(RenderArena, &Vertices, ToRect2(rect), MainFont.white_texture_bounding_box, color);
PushQuad2D(RenderArena, &Vertices, ToRect2(rect), PrimaryFont.white_texture_bounding_box, color);
}
void DrawRectOutline(Rect2 rect, Color color, float thickness = 2) {
@@ -319,29 +318,18 @@ void DrawRectOutline(Rect2 rect, Color color, float thickness = 2) {
Rect2 b = CutRight(&rect, thickness);
Rect2 c = CutTop(&rect, thickness);
Rect2 d = CutBottom(&rect, thickness);
PushQuad2D(RenderArena, &Vertices, a, MainFont.white_texture_bounding_box, color);
PushQuad2D(RenderArena, &Vertices, b, MainFont.white_texture_bounding_box, color);
PushQuad2D(RenderArena, &Vertices, c, MainFont.white_texture_bounding_box, color);
PushQuad2D(RenderArena, &Vertices, d, MainFont.white_texture_bounding_box, color);
PushQuad2D(RenderArena, &Vertices, a, PrimaryFont.white_texture_bounding_box, color);
PushQuad2D(RenderArena, &Vertices, b, PrimaryFont.white_texture_bounding_box, color);
PushQuad2D(RenderArena, &Vertices, c, PrimaryFont.white_texture_bounding_box, color);
PushQuad2D(RenderArena, &Vertices, d, PrimaryFont.white_texture_bounding_box, color);
}
void DrawRectOutline(Rect2I rect, Color color, Int thickness = 2) {
DrawRectOutline(ToRect2(rect), color, (float)thickness);
}
Int GetCharSpacing(Font *font, int codepoint = '_') {
Glyph *g = GetGlyph(font, codepoint);
if (g->xadvance) return (Int)g->xadvance;
return (Int)g->size.x;
}
Int GetLineSpacing(Font *font) {
Int result = (Int)(font->ascent - font->descent + font->line_gap);
return result;
}
Vec2 DrawString(Font *font, String16 string, Vec2 pos, Color color, bool draw = true) {
pos.y += GetLineSpacing(font) + font->descent;
pos.y += font->line_spacing + font->descent; // TODO: descent?
Vec2 original_pos = pos;
For(string) {
Glyph *g = GetGlyph(font, it);
@@ -371,7 +359,7 @@ void DrawCircle(Vec2 pos, float radius, Color color) {
int point_i = 0;
int segment_i = 0;
for (; segment_i < vertex_count; segment_i += 3, point_i += 1) {
Rect2 tex = MainFont.white_texture_bounding_box;
Rect2 tex = PrimaryFont.white_texture_bounding_box;
Vertex2D *it = vertices + segment_i;
it[0].color = color;
it[1].color = color;
@@ -386,35 +374,30 @@ void DrawCircle(Vec2 pos, float radius, Color color) {
}
}
GLuint UploadAtlas(Atlas *atlas) {
GLuint tex = 0;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, (GLsizei)atlas->size.x, (GLsizei)atlas->size.y, 0, GL_RED, GL_UNSIGNED_BYTE, atlas->bitmap);
glBindTexture(GL_TEXTURE_2D, 0);
atlas->texture_id = tex;
return tex;
}
void ReloadFont() {
Int size = StyleFontSize;
size = ClampBottom((Int)2, size);
if (MainFont.texture_id) {
glDeleteTextures(1, &MainFont.texture_id);
Dealloc(&MainFont.glyphs);
MainFont = {};
if (PrimaryFont.texture_id) {
glDeleteTextures(1, &PrimaryFont.texture_id);
Dealloc(&PrimaryFont.glyphs);
PrimaryFont = {};
}
Scratch scratch;
Atlas atlas = CreateAtlas(scratch, {2048, 2048});
MainFont = CreateFont(&atlas, (uint32_t)size, StyleFont);
// create and fill texture with ES3-compatible API
GLint filter = GL_NEAREST;
if (StyleFontFilter == 1) filter = GL_LINEAR;
GLuint tex = 0;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// allocate storage and upload
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, (GLsizei)atlas.size.x, (GLsizei)atlas.size.y, 0, GL_RED, GL_UNSIGNED_BYTE, atlas.bitmap);
glBindTexture(GL_TEXTURE_2D, 0);
MainFont.texture_id = tex;
FontCharSpacing = GetCharSpacing(&MainFont);
FontLineSpacing = GetLineSpacing(&MainFont);
PrimaryFont = CreateFont(&atlas, (uint32_t)ClampBottom(2u, (U32)StyleFontSize), StyleFont);
SecondaryFont = CreateFont(&atlas, 10, StyleFont);
SecondaryFont.texture_id = PrimaryFont.texture_id = UploadAtlas(&atlas);
}