From ffab6a39249b636127ec8c27b629963dadfb7030 Mon Sep 17 00:00:00 2001 From: wanp Date: Sun, 13 Oct 2024 21:34:05 -0300 Subject: [PATCH] cache font _files_ as well to avoid duplicate buffers --- src/rendering/twn_text.c | 43 +++++++++++++++++++++++++++++++------- src/rendering/twn_text_c.h | 2 -- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/rendering/twn_text.c b/src/rendering/twn_text.c index 7a634e3..82cb153 100644 --- a/src/rendering/twn_text.c +++ b/src/rendering/twn_text.c @@ -31,6 +31,19 @@ typedef struct StringArena { static StringArena string_arena; +typedef struct FontFileBuffer { + size_t len; + unsigned char *buffer; +} FontFileBuffer; + +typedef struct FontFileCacheItem { + char *key; + FontFileBuffer value; +} FontFileCacheItem; + +static FontFileCacheItem *font_file_cache_hash; + + static void string_arena_init(StringArena *arena) { arena->head = cmalloc(sizeof *arena->head); arena->current_block = arena->head; @@ -102,13 +115,23 @@ static FontData *text_load_font_data(const char *path, int height_px) { unsigned char* bitmap = ccalloc(ctx.font_texture_size * ctx.font_texture_size, 1); { - unsigned char *buf = NULL; - int64_t buf_len = file_to_bytes(path, &buf); + unsigned char *buf = NULL; + int64_t buf_len = 0; + + /* if the file was already loaded just get it */ + FontFileCacheItem *font_file_ptr = shgetp_null(font_file_cache_hash, path); + if (font_file_ptr != NULL) { + buf = font_file_ptr->value.buffer; + buf_len = font_file_ptr->value.len; + } else { + buf_len = file_to_bytes(path, &buf); + FontFileBuffer buffer = { buf_len, buf }; + shput(font_file_cache_hash, path, buffer); + } + stbtt_InitFont(&font_data->info, buf, stbtt_GetFontOffsetForIndex(buf, 0)); /* might as well get these now, for later */ - font_data->file_bytes = buf; - font_data->file_bytes_len = buf_len; font_data->scale_factor = stbtt_ScaleForPixelHeight(&font_data->info, (float)height_px); stbtt_GetFontVMetrics( &font_data->info, @@ -142,7 +165,6 @@ static FontData *text_load_font_data(const char *path, int height_px) { static void text_destroy_font_data(FontData *font_data) { - SDL_free(font_data->file_bytes); delete_gpu_texture(font_data->texture); SDL_free(font_data); } @@ -192,7 +214,7 @@ static void text_draw_with(FontData* font_data, char* text, Vec2 position, Color static void ensure_font_cache(const char *font_path, int height_px) { - /* HACK: stupid, bad, don't do this */ + /* HACK: don't */ bool is_cached = false; for (size_t i = 0; i < arrlenu(ctx.text_cache.data); ++i) { FontData *font_data = ctx.text_cache.data[i]; @@ -229,6 +251,8 @@ void render_text(const TextPrimitive *text) { void text_cache_init(TextCache *cache) { arrsetlen(cache->data, 0); string_arena_init(&string_arena); + + sh_new_arena(font_file_cache_hash); } @@ -237,8 +261,13 @@ void text_cache_deinit(TextCache *cache) { text_destroy_font_data(ctx.text_cache.data[i]); } - arrfree(cache->data); + for (size_t i = 0; i < shlenu(font_file_cache_hash); ++i) { + SDL_free(font_file_cache_hash[i].value.buffer); + } + shfree(font_file_cache_hash); + string_arena_deinit(&string_arena); + arrfree(cache->data); } diff --git a/src/rendering/twn_text_c.h b/src/rendering/twn_text_c.h index f73648e..6b3b9c9 100644 --- a/src/rendering/twn_text_c.h +++ b/src/rendering/twn_text_c.h @@ -22,8 +22,6 @@ typedef struct FontData { stbtt_fontinfo info; const char *file_path; - unsigned char *file_bytes; - size_t file_bytes_len; GPUTexture texture;