From c4f84e1969f4c856a5bf0352e99fcb73a4cf56cf Mon Sep 17 00:00:00 2001 From: dec05eba Date: Mon, 8 Nov 2021 16:03:02 +0100 Subject: Do not check for valid utf8 in set text, render the invalid utf8 instead. Mmap fonts instead of loading the whole font --- src/graphics/font.c | 39 +++++++++++++--------------- src/graphics/text.c | 7 +++-- src/system/fileutils.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/system/utf8.c | 20 ++++++++++++--- 4 files changed, 105 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/graphics/font.c b/src/graphics/font.c index 175c571..dfffc7e 100644 --- a/src/graphics/font.c +++ b/src/graphics/font.c @@ -26,16 +26,16 @@ int mgl_font_load_from_file(mgl_font *self, const char *filepath, unsigned int c self->packed_chars = NULL; self->num_packed_chars = 0; - mgl_filedata filedata; - if(mgl_load_file(filepath, &filedata, NULL) != 0) { + mgl_memory_mapped_file mapped_file; + if(mgl_mapped_file_load(filepath, &mapped_file, &(mgl_memory_mapped_file_load_options){ .readable = true, .writable = false }) != 0) { fprintf(stderr, "Error: failed to load font %s, error: mgl_load_file failed\n", filepath); return -1; } stbtt_fontinfo font; - if(!stbtt_InitFont(&font, filedata.data, stbtt_GetFontOffsetForIndex(filedata.data, 0))) { + if(!stbtt_InitFont(&font, mapped_file.data, stbtt_GetFontOffsetForIndex(mapped_file.data, 0))) { fprintf(stderr, "Error: failed to load font %s, error: stbtt_InitFont failed\n", filepath); - mgl_filedata_free(&filedata); + mgl_mapped_file_unload(&mapped_file); return -1; } @@ -43,9 +43,7 @@ int mgl_font_load_from_file(mgl_font *self, const char *filepath, unsigned int c self->packed_chars = malloc(self->num_packed_chars * sizeof(stbtt_packedchar)); if(!self->packed_chars) { fprintf(stderr, "Error: failed to load font %s, error: out of memory\n", filepath); - mgl_filedata_free(&filedata); - mgl_font_unload(self); - return -1; + goto error; } bool atlas_created = false; @@ -62,9 +60,7 @@ int mgl_font_load_from_file(mgl_font *self, const char *filepath, unsigned int c unsigned char *new_atlas = realloc(self->font_atlas.atlas, self->font_atlas.width * self->font_atlas.height); if(!new_atlas) { fprintf(stderr, "Error: failed to load font %s, error: out of memory\n", filepath); - mgl_filedata_free(&filedata); - mgl_font_unload(self); - return -1; + goto error; } self->font_atlas.atlas = new_atlas; @@ -72,19 +68,17 @@ int mgl_font_load_from_file(mgl_font *self, const char *filepath, unsigned int c if(!stbtt_PackBegin(&pc, self->font_atlas.atlas, self->font_atlas.width, self->font_atlas.height, self->font_atlas.width, 1, NULL)) { fprintf(stderr, "Error: failed to load font %s, error: stbtt_PackBegin failed\n", filepath); - mgl_filedata_free(&filedata); - mgl_font_unload(self); - return -1; + goto error; } stbtt_PackSetOversampling(&pc, 2, 2); - if(!stbtt_PackFontRange(&pc, filedata.data, 0, self->character_size, 0, self->num_packed_chars, self->packed_chars)) { + if(!stbtt_PackFontRange(&pc, mapped_file.data, 0, self->character_size, 0, self->num_packed_chars, self->packed_chars)) { stbtt_PackEnd(&pc); continue; } - /*if(!stbtt_PackFontRange(&pc, filedata.data, 0, self->character_size, 0x00004E00, self->num_packed_chars, self->packed_chars)) { + /*if(!stbtt_PackFontRange(&pc, mapped_file.data, 0, self->character_size, 0x00004E00, self->num_packed_chars, self->packed_chars)) { stbtt_PackEnd(&pc); continue; }*/ @@ -96,22 +90,23 @@ int mgl_font_load_from_file(mgl_font *self, const char *filepath, unsigned int c if(!atlas_created) { fprintf(stderr, "Error: failed to load font %s, error: failed to create atlas\n", filepath); - mgl_filedata_free(&filedata); - mgl_font_unload(self); - return -1; + goto error; } if(mgl_texture_load_from_memory(&self->texture, self->font_atlas.atlas, self->font_atlas.width, self->font_atlas.height, MGL_IMAGE_FORMAT_ALPHA, NULL) != 0) { fprintf(stderr, "Error: failed to load font %s, error: mgl_texture_load_from_memory failed\n", filepath); - mgl_filedata_free(&filedata); - mgl_font_unload(self); - return -1; + goto error; } /* TODO: Use stbtt_GetCodepointSDF */ - mgl_filedata_free(&filedata); + mgl_mapped_file_unload(&mapped_file); return 0; + + error: + mgl_mapped_file_unload(&mapped_file); + mgl_font_unload(self); + return -1; } void mgl_font_unload(mgl_font *self) { diff --git a/src/graphics/text.c b/src/graphics/text.c index 28840ce..d330dc0 100644 --- a/src/graphics/text.c +++ b/src/graphics/text.c @@ -47,13 +47,13 @@ static mgl_vec2f mgl_text_calculate_bounds(mgl_text *self) { return bounds; } -int mgl_text_init(mgl_text *self, mgl_font *font, const char *str, size_t str_size) { +void mgl_text_init(mgl_text *self, mgl_font *font, const char *str, size_t str_size) { self->font = font; self->color = (mgl_color){ 255, 255, 255, 255 }; self->position = (mgl_vec2f){ 0.0f, 0.0f }; self->text = NULL; self->text_size = 0; - return mgl_text_set_string(self, str, str_size); + mgl_text_set_string(self, str, str_size); } void mgl_text_deinit(mgl_text *self) { @@ -64,14 +64,13 @@ void mgl_text_deinit(mgl_text *self) { self->bounds = (mgl_vec2f){ 0.0f, 0.0f }; } -int mgl_text_set_string(mgl_text *self, const char *str, size_t str_size) { +void mgl_text_set_string(mgl_text *self, const char *str, size_t str_size) { self->text = str; self->text_size = str_size; if(self->text && self->text_size > 0 && self->font) self->bounds = mgl_text_calculate_bounds(self); else self->bounds = (mgl_vec2f){ 0.0f, 0.0f }; - return 0; } void mgl_text_set_font(mgl_text *self, mgl_font *font) { diff --git a/src/system/fileutils.c b/src/system/fileutils.c index dc8eaca..86d176a 100644 --- a/src/system/fileutils.c +++ b/src/system/fileutils.c @@ -1,5 +1,6 @@ #include "../../include/mgl/system/fileutils.h" #include +#include #include #include #include @@ -49,3 +50,71 @@ void mgl_filedata_free(mgl_filedata *self) { self->data = NULL; self->size = 0; } + +static int load_options_to_open_flag(mgl_memory_mapped_file_load_options *load_options) { + const bool readable = load_options ? load_options->readable : true; + const bool writable = load_options ? load_options->writable : true; + + int open_flag = 0; + if(readable && writable) + open_flag = O_RDWR; + else if(readable) + open_flag = O_RDONLY; + else if(writable) + open_flag = O_WRONLY; + + return open_flag; +} + +static int load_options_to_mmap_prot_flag(mgl_memory_mapped_file_load_options *load_options) { + const bool readable = load_options ? load_options->readable : true; + const bool writable = load_options ? load_options->writable : true; + + int prot_flag = 0; + if(readable) + prot_flag |= PROT_READ; + if(writable) + prot_flag |= PROT_WRITE; + + return prot_flag; +} + +int mgl_mapped_file_load(const char *filepath, mgl_memory_mapped_file *memory_mapped_file, mgl_memory_mapped_file_load_options *load_options) { + memory_mapped_file->data = NULL; + memory_mapped_file->size = 0; + memory_mapped_file->fd = -1; + + int fd = open(filepath, load_options_to_open_flag(load_options)); + if(fd == -1) + return -1; + + struct stat st; + if(fstat(fd, &st) == -1) { + close(fd); + return -1; + } + + void *mapped = mmap(0, st.st_size, load_options_to_mmap_prot_flag(load_options), MAP_SHARED, fd, 0); + if(mapped == MAP_FAILED) { + close(fd); + return -1; + } + + memory_mapped_file->data = mapped; + memory_mapped_file->size = st.st_size; + memory_mapped_file->fd = fd; + return 0; +} + +void mgl_mapped_file_unload(mgl_memory_mapped_file *memory_mapped_file) { + if(memory_mapped_file->data != MAP_FAILED && memory_mapped_file->data != NULL) { + munmap(memory_mapped_file->data, memory_mapped_file->size); + memory_mapped_file->data = NULL; + } + memory_mapped_file->size = 0; + + if(memory_mapped_file->fd != -1) { + close(memory_mapped_file->fd); + memory_mapped_file->fd = -1; + } +} diff --git a/src/system/utf8.c b/src/system/utf8.c index 35b0f2f..201fedf 100644 --- a/src/system/utf8.c +++ b/src/system/utf8.c @@ -20,19 +20,31 @@ static inline bool utf8_get_codepoint_length(unsigned char b, size_t *codepoint_ /* TODO: Optimize (remove branching, etc) */ bool mgl_utf8_decode(const unsigned char *str, size_t size, uint32_t *decoded_codepoint, size_t *codepoint_length) { - if(size == 0) + if(size == 0) { + *decoded_codepoint = 0; + *codepoint_length = 0; return false; + } size_t clen; - if(!utf8_get_codepoint_length(str[0], &clen)) + if(!utf8_get_codepoint_length(str[0], &clen)) { + *decoded_codepoint = str[0]; + *codepoint_length = 1; return false; + } - if(size < clen) + if(size < clen) { + *decoded_codepoint = str[0]; + *codepoint_length = 1; return false; + } for(size_t i = 1; i < clen; ++i) { - if((str[i] & 0xC0) != 0x80) + if((str[i] & 0xC0) != 0x80) { + *decoded_codepoint = str[0]; + *codepoint_length = 1; return false; + } } uint32_t codepoint; -- cgit v1.2.3