1.1 --- a/src/font.c Thu Apr 18 22:53:55 2024 +0200 1.2 +++ b/src/font.c Fri Apr 19 22:28:29 2024 +0200 1.3 @@ -29,6 +29,14 @@ 1.4 #include "ascension/context.h" 1.5 #include "ascension/error.h" 1.6 1.7 +#include <assert.h> 1.8 +#include <cx/array_list.h> 1.9 + 1.10 +void asc_font(enum AscFontStyle style, int size) { 1.11 + asc_context.active_font.style = style; 1.12 + asc_context.active_font.size = size; 1.13 +} 1.14 + 1.15 static char const *asc_font_filename(enum AscFontStyle style) { 1.16 // TODO: do not assume we are running from the program dir 1.17 switch (style) { 1.18 @@ -43,31 +51,49 @@ 1.19 } 1.20 } 1.21 1.22 -void asc_font(enum AscFontStyle style, int size) { 1.23 - for (unsigned int i = 0 ; i < asc_context.fonts_loaded ; i++) { 1.24 - AscFont *font = &asc_context.fonts[i]; 1.25 - if (font->size == size && font->style == style) { 1.26 - asc_context.active_font = i; 1.27 - return; 1.28 +struct asc_font_cache_entry { 1.29 + AscFont font; 1.30 + TTF_Font *ttf; 1.31 +}; 1.32 + 1.33 +static CxList *asc_font_cache; 1.34 + 1.35 +static void asc_font_unload(struct asc_font_cache_entry *entry) { 1.36 + TTF_CloseFont(entry->ttf); 1.37 + asc_dprintf("Closed font size %u, style %u", entry->font.size, entry->font.style); 1.38 +} 1.39 + 1.40 +void asc_font_cache_init(void) { 1.41 + assert(asc_font_cache == NULL); 1.42 + asc_font_cache = cxArrayListCreateSimple( 1.43 + sizeof(struct asc_font_cache_entry), 16 1.44 + ); 1.45 + asc_font_cache->simple_destructor = (cx_destructor_func) asc_font_unload; 1.46 +} 1.47 + 1.48 +void asc_font_cache_destroy(void) { 1.49 + assert(asc_font_cache != NULL); 1.50 + cxListDestroy(asc_font_cache); 1.51 +} 1.52 + 1.53 + 1.54 +TTF_Font *asc_font_load(AscFont font) { 1.55 + CxIterator iter = cxListIterator(asc_font_cache); 1.56 + cx_foreach(struct asc_font_cache_entry*, cache, iter) { 1.57 + if (cache->font.style == font.style && cache->font.size == font.size) { 1.58 + return cache->ttf; 1.59 } 1.60 } 1.61 1.62 - if (asc_context.fonts_loaded == ASC_MAX_FONTS) { 1.63 - asc_error("Too many fonts. Cannot load more until cache is repaired."); 1.64 - asc_context.active_font = ASC_MAX_FONTS; 1.65 - return; 1.66 - } 1.67 - 1.68 - unsigned int slot = asc_context.fonts_loaded++; 1.69 - AscFont *font = &asc_context.fonts[slot]; 1.70 - font->size = size; 1.71 - font->style = style; 1.72 - font->ptr = TTF_OpenFont(asc_font_filename(style), size); 1.73 - if (font->ptr == NULL) { 1.74 - asc_context.fonts_loaded--; 1.75 + struct asc_font_cache_entry entry; 1.76 + entry.font = font; 1.77 + entry.ttf = TTF_OpenFont(asc_font_filename(font.style), font.size); 1.78 + if (entry.ttf == NULL) { 1.79 asc_error(TTF_GetError()); 1.80 + return NULL; 1.81 } else { 1.82 - asc_dprintf("Loaded font size %u, style %u in slot %u", size, style, slot); 1.83 - asc_context.active_font = slot; 1.84 + cxListAdd(asc_font_cache, &entry); 1.85 + asc_dprintf("Loaded font size %d, style %d from disk", font.size, font.style); 1.86 + return entry.ttf; 1.87 } 1.88 }