aboutsummaryrefslogtreecommitdiff
path: root/src/graphics
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-11-25 07:47:39 +0100
committerdec05eba <dec05eba@protonmail.com>2021-11-25 07:47:39 +0100
commit0e3128798912a46705323d5c6546c2bdf2ade678 (patch)
treebb9bd49d9718695ffb2f1fda1e6b8dce63aad035 /src/graphics
parent6b7fbf4fe476d908fd44ca9421363e053324ba69 (diff)
Fix possible corrupt font atlas
Diffstat (limited to 'src/graphics')
-rw-r--r--src/graphics/font.c36
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;
}