cache font _files_ as well to avoid duplicate buffers

This commit is contained in:
wanp 2024-10-13 21:34:05 -03:00
parent 82bad550e5
commit ffab6a3924
2 changed files with 36 additions and 9 deletions

View File

@ -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);
}

View File

@ -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;