diff options
author | dec05eba <dec05eba@protonmail.com> | 2021-11-25 07:47:39 +0100 |
---|---|---|
committer | dec05eba <dec05eba@protonmail.com> | 2021-11-25 07:47:39 +0100 |
commit | 0e3128798912a46705323d5c6546c2bdf2ade678 (patch) | |
tree | bb9bd49d9718695ffb2f1fda1e6b8dce63aad035 /src/graphics | |
parent | 6b7fbf4fe476d908fd44ca9421363e053324ba69 (diff) |
Fix possible corrupt font atlas
Diffstat (limited to 'src/graphics')
-rw-r--r-- | src/graphics/font.c | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/src/graphics/font.c b/src/graphics/font.c index fd1439d..82a8029 100644 --- a/src/graphics/font.c +++ b/src/graphics/font.c @@ -16,6 +16,10 @@ static int round_float(float value) { return value + 0.5f; } +static int max_int(int a, int b) { + return a >= b ? a : b; +} + int mgl_font_load_from_file(mgl_font *self, const mgl_memory_mapped_file *mapped_file, unsigned int character_size) { self->texture.id = 0; @@ -25,9 +29,12 @@ int mgl_font_load_from_file(mgl_font *self, const mgl_memory_mapped_file *mapped self->font_atlas.prev_height = 0; self->font_atlas.pointer_position = (mgl_vec2i){ GLYPH_PADDING, GLYPH_PADDING }; self->font_atlas.render_section = MGL_ATLAS_SECTION_INITIAL; + self->font_atlas.initial_section_height = 0; + self->font_atlas.right_section_height = 0; self->character_size = character_size; mgl_font_char_map_init(&self->char_map); + self->current_line_max_height = 0; self->font_info = NULL; self->font_info = malloc(sizeof(stbtt_fontinfo)); @@ -51,6 +58,7 @@ void mgl_font_unload(mgl_font *self) { mgl_texture_unload(&self->texture); mgl_font_char_map_deinit(&self->char_map); + self->current_line_max_height = 0; free(self->font_info); self->font_info = NULL; @@ -64,9 +72,9 @@ static int align_up_to_next_value_of(int value, int alignment) { return value + (alignment - offset_to_next_alignment); } -static void mgl_font_handle_new_render_position(mgl_font *self, int glyph_width, int glyph_height) { +static void mgl_font_handle_new_render_position(mgl_font *self, int glyph_width) { if(self->font_atlas.pointer_position.x + glyph_width + GLYPH_PADDING >= self->font_atlas.width) { - if(self->font_atlas.pointer_position.y + glyph_height + GLYPH_PADDING >= self->font_atlas.height && self->font_atlas.render_section != MGL_ATLAS_SECTION_RIGHT) { + if(self->font_atlas.pointer_position.y + self->current_line_max_height + (int)self->character_size + GLYPH_PADDING >= self->font_atlas.height && self->font_atlas.render_section != MGL_ATLAS_SECTION_RIGHT) { /* Texture atlas looks like this with glyphs filling the texture: |----| @@ -91,11 +99,14 @@ static void mgl_font_handle_new_render_position(mgl_font *self, int glyph_width, /* Texture overflow, enlargen the font atlas! */ /* TODO: Create a new texture and copy the texture content instead of rendering all glyphs again */ - if(mgl_texture_resize(&self->texture, self->font_atlas.width * 2, self->font_atlas.height * 2, NULL) == 0) { + const int new_width = align_up_to_next_value_of(self->font_atlas.width * 2, self->character_size + GLYPH_PADDING); + const int new_height = align_up_to_next_value_of(self->font_atlas.height * 2, self->character_size + GLYPH_PADDING); + if(mgl_texture_resize(&self->texture, new_width, new_height, NULL) == 0) { + self->font_atlas.initial_section_height = self->font_atlas.pointer_position.y + self->current_line_max_height; self->font_atlas.prev_width = self->font_atlas.width; self->font_atlas.prev_height = self->font_atlas.height; - self->font_atlas.width = align_up_to_next_value_of(self->font_atlas.width * 2, self->character_size); - self->font_atlas.height = align_up_to_next_value_of(self->font_atlas.height * 2, self->character_size); + self->font_atlas.width = new_width; + self->font_atlas.height = new_height; self->font_atlas.render_section = MGL_ATLAS_SECTION_RIGHT; self->font_atlas.pointer_position.x = self->font_atlas.prev_width; @@ -113,18 +124,20 @@ static void mgl_font_handle_new_render_position(mgl_font *self, int glyph_width, } else { fprintf(stderr, "Error: failed to resize font atlas\n"); } - } else if(self->font_atlas.render_section == MGL_ATLAS_SECTION_RIGHT && self->font_atlas.pointer_position.y + glyph_height + GLYPH_PADDING >= self->font_atlas.prev_height) { + } else if(self->font_atlas.render_section == MGL_ATLAS_SECTION_RIGHT && self->font_atlas.pointer_position.y + self->current_line_max_height + (int)self->character_size + GLYPH_PADDING >= self->font_atlas.prev_height) { + self->font_atlas.right_section_height = self->font_atlas.pointer_position.y + self->current_line_max_height; self->font_atlas.render_section = MGL_ATLAS_SECTION_BOTTOM; self->font_atlas.pointer_position.x = GLYPH_PADDING; - self->font_atlas.pointer_position.y += self->character_size + GLYPH_PADDING; + self->font_atlas.pointer_position.y = max_int(self->font_atlas.initial_section_height, self->font_atlas.right_section_height) + GLYPH_PADDING; } else { if(self->font_atlas.render_section != MGL_ATLAS_SECTION_RIGHT) { self->font_atlas.pointer_position.x = GLYPH_PADDING; } else { self->font_atlas.pointer_position.x = self->font_atlas.prev_width; } - self->font_atlas.pointer_position.y += self->character_size + GLYPH_PADDING; + self->font_atlas.pointer_position.y += self->current_line_max_height + GLYPH_PADDING; } + self->current_line_max_height = 0; } } @@ -136,7 +149,7 @@ int mgl_font_get_glyph(mgl_font *self, uint32_t codepoint, mgl_font_glyph *glyph if(self->texture.id == 0 && mgl_texture_init(&self->texture) != 0) return -1; - const int initial_atlas_size = align_up_to_next_value_of(128, self->character_size); + const int initial_atlas_size = align_up_to_next_value_of(128, self->character_size + GLYPH_PADDING); /* TODO: Scale by character size */ mgl_texture_load_options load_options = { .compressed = false, @@ -198,7 +211,7 @@ int mgl_font_get_glyph(mgl_font *self, uint32_t codepoint, mgl_font_glyph *glyph if(existing_char_entry) { render_offset = existing_char_entry->render_offset; } else { - mgl_font_handle_new_render_position(self, width, height); + mgl_font_handle_new_render_position(self, width); render_offset.x = self->font_atlas.pointer_position.x; render_offset.y = self->font_atlas.pointer_position.y; @@ -217,6 +230,9 @@ int mgl_font_get_glyph(mgl_font *self, uint32_t codepoint, mgl_font_glyph *glyph } existing_char_entry->render_offset = render_offset; + if(height > self->current_line_max_height) + self->current_line_max_height = height; + self->font_atlas.pointer_position.x += width + GLYPH_PADDING; } |