font: cache loaded fonts

Instantiating a new font is expensive, both in CPU and
memory. Mitigate by adding a cache. On a hit, instead of instantiating
a new font, clone the one from the cache.

Remember, cloning is basically just a ref counter bump.
This commit is contained in:
Daniel Eklöf 2019-01-15 20:48:04 +01:00
parent fae2e5cb18
commit 7525ae99eb

18
font.c
View file

@ -10,12 +10,15 @@
#define LOG_MODULE "font"
#define LOG_ENABLE_DBG 0
#include "log.h"
#include "tllist.h"
struct font {
char *name;
cairo_scaled_font_t *scaled_font;
};
static tll(const struct font *) cache = tll_init();
static void __attribute__((constructor))
init(void)
{
@ -37,11 +40,18 @@ static void __attribute__((destructor))
fini(void)
{
FcFini();
assert(tll_length(cache) == 0);
}
struct font *
font_new(const char *name)
{
/* Check if font have already been loaded */
tll_foreach(cache, it) {
if (strcmp(name, it->item->name) == 0)
return font_clone(it->item);
}
FcPattern *pattern = FcNameParse((const unsigned char *)name);
if (pattern == NULL) {
LOG_ERR("%s: failed to lookup font", name);
@ -104,6 +114,7 @@ font_new(const char *name)
font->name = strdup(name);
font->scaled_font = scaled_font;
tll_push_back(cache, font);
return font;
}
@ -124,6 +135,13 @@ font_destroy(struct font *font)
if (font == NULL)
return;
tll_foreach(cache, it) {
if (it->item == font) {
tll_remove(cache, it);
break;
}
}
cairo_scaled_font_destroy(font->scaled_font);
free(font->name);
free(font);