--- a/src/font.c Thu Apr 18 22:53:55 2024 +0200 +++ b/src/font.c Fri Apr 19 22:28:29 2024 +0200 @@ -29,6 +29,14 @@ #include "ascension/context.h" #include "ascension/error.h" +#include <assert.h> +#include <cx/array_list.h> + +void asc_font(enum AscFontStyle style, int size) { + asc_context.active_font.style = style; + asc_context.active_font.size = size; +} + static char const *asc_font_filename(enum AscFontStyle style) { // TODO: do not assume we are running from the program dir switch (style) { @@ -43,31 +51,49 @@ } } -void asc_font(enum AscFontStyle style, int size) { - for (unsigned int i = 0 ; i < asc_context.fonts_loaded ; i++) { - AscFont *font = &asc_context.fonts[i]; - if (font->size == size && font->style == style) { - asc_context.active_font = i; - return; +struct asc_font_cache_entry { + AscFont font; + TTF_Font *ttf; +}; + +static CxList *asc_font_cache; + +static void asc_font_unload(struct asc_font_cache_entry *entry) { + TTF_CloseFont(entry->ttf); + asc_dprintf("Closed font size %u, style %u", entry->font.size, entry->font.style); +} + +void asc_font_cache_init(void) { + assert(asc_font_cache == NULL); + asc_font_cache = cxArrayListCreateSimple( + sizeof(struct asc_font_cache_entry), 16 + ); + asc_font_cache->simple_destructor = (cx_destructor_func) asc_font_unload; +} + +void asc_font_cache_destroy(void) { + assert(asc_font_cache != NULL); + cxListDestroy(asc_font_cache); +} + + +TTF_Font *asc_font_load(AscFont font) { + CxIterator iter = cxListIterator(asc_font_cache); + cx_foreach(struct asc_font_cache_entry*, cache, iter) { + if (cache->font.style == font.style && cache->font.size == font.size) { + return cache->ttf; } } - if (asc_context.fonts_loaded == ASC_MAX_FONTS) { - asc_error("Too many fonts. Cannot load more until cache is repaired."); - asc_context.active_font = ASC_MAX_FONTS; - return; - } - - unsigned int slot = asc_context.fonts_loaded++; - AscFont *font = &asc_context.fonts[slot]; - font->size = size; - font->style = style; - font->ptr = TTF_OpenFont(asc_font_filename(style), size); - if (font->ptr == NULL) { - asc_context.fonts_loaded--; + struct asc_font_cache_entry entry; + entry.font = font; + entry.ttf = TTF_OpenFont(asc_font_filename(font.style), font.size); + if (entry.ttf == NULL) { asc_error(TTF_GetError()); + return NULL; } else { - asc_dprintf("Loaded font size %u, style %u in slot %u", size, style, slot); - asc_context.active_font = slot; + cxListAdd(asc_font_cache, &entry); + asc_dprintf("Loaded font size %d, style %d from disk", font.size, font.style); + return entry.ttf; } }