mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-04-01 07:15:32 -04:00
font: cache loaded fontconfig fallback fonts
This commit is contained in:
parent
a789230cf9
commit
928e86b423
2 changed files with 59 additions and 24 deletions
70
font.c
70
font.c
|
|
@ -212,11 +212,18 @@ from_font_set(FcPattern *pattern, FcFontSet *fonts, int start_idx, const font_li
|
||||||
font->is_fallback = is_fallback;
|
font->is_fallback = is_fallback;
|
||||||
font->pixel_size_fixup = scalable ? pixel_fixup : 1.;
|
font->pixel_size_fixup = scalable ? pixel_fixup : 1.;
|
||||||
font->bgr = fc_rgba == FC_RGBA_BGR || fc_rgba == FC_RGBA_VBGR;
|
font->bgr = fc_rgba == FC_RGBA_BGR || fc_rgba == FC_RGBA_VBGR;
|
||||||
font->fc_idx = font_idx;
|
|
||||||
|
|
||||||
if (!is_fallback) {
|
if (is_fallback) {
|
||||||
font->fc_pattern = pattern;
|
font->fc_idx = 0;
|
||||||
font->fc_fonts = fonts;
|
font->fc_pattern = NULL;
|
||||||
|
font->fc_fonts = NULL;
|
||||||
|
font->fc_loaded_fonts = NULL;
|
||||||
|
font->cache = NULL;
|
||||||
|
} else {
|
||||||
|
font->fc_idx = font_idx;
|
||||||
|
font->fc_pattern = !is_fallback ? pattern : NULL;
|
||||||
|
font->fc_fonts = !is_fallback ? fonts : NULL;
|
||||||
|
font->fc_loaded_fonts = calloc(fonts->nfont, sizeof(font->fc_loaded_fonts[0]));
|
||||||
font->cache = calloc(cache_size, sizeof(font->cache[0]));
|
font->cache = calloc(cache_size, sizeof(font->cache[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -341,19 +348,20 @@ glyph_for_wchar(const struct font *font, wchar_t wc, struct glyph *glyph)
|
||||||
FT_UInt idx = FT_Get_Char_Index(font->face, wc);
|
FT_UInt idx = FT_Get_Char_Index(font->face, wc);
|
||||||
if (idx == 0) {
|
if (idx == 0) {
|
||||||
/* No glyph in this font, try fallback fonts */
|
/* No glyph in this font, try fallback fonts */
|
||||||
struct font fallback;
|
|
||||||
|
|
||||||
/* Try user configured fallback fonts */
|
/* Try user configured fallback fonts */
|
||||||
tll_foreach(font->fallbacks, it) {
|
tll_foreach(font->fallbacks, it) {
|
||||||
if (from_name(it->item, NULL, "", &fallback, true)) {
|
struct font *fallback = malloc(sizeof(*fallback));
|
||||||
if (glyph_for_wchar(&fallback, wc, glyph)) {
|
|
||||||
|
if (from_name(it->item, NULL, "", fallback, true)) {
|
||||||
|
if (glyph_for_wchar(fallback, wc, glyph)) {
|
||||||
LOG_DBG("%C: used fallback %s (fixup = %f)",
|
LOG_DBG("%C: used fallback %s (fixup = %f)",
|
||||||
wc, it->item, fallback.pixel_size_fixup);
|
wc, it->item, fallback->pixel_size_fixup);
|
||||||
font_destroy(&fallback);
|
font_destroy(fallback);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
font_destroy(&fallback);
|
font_destroy(fallback);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -364,17 +372,30 @@ glyph_for_wchar(const struct font *font, wchar_t wc, struct glyph *glyph)
|
||||||
|
|
||||||
assert(font->fc_pattern != NULL);
|
assert(font->fc_pattern != NULL);
|
||||||
assert(font->fc_fonts != NULL);
|
assert(font->fc_fonts != NULL);
|
||||||
|
assert(font->fc_loaded_fonts != NULL);
|
||||||
assert(font->fc_idx != -1);
|
assert(font->fc_idx != -1);
|
||||||
|
|
||||||
for (int i = font->fc_idx + 1; i < font->fc_fonts->nfont; i++) {
|
for (int i = font->fc_idx + 1; i < font->fc_fonts->nfont; i++) {
|
||||||
if (from_font_set(font->fc_pattern, font->fc_fonts, i, NULL, "", &fallback, true)) {
|
if (font->fc_loaded_fonts[i] == NULL) {
|
||||||
if (glyph_for_wchar(&fallback, wc, glyph)) {
|
/* Load font */
|
||||||
LOG_DBG("%C: used fontconfig fallback", wc);
|
struct font *fallback = malloc(sizeof(*fallback));
|
||||||
font_destroy(&fallback);
|
if (!from_font_set(font->fc_pattern, font->fc_fonts, i, NULL,
|
||||||
return true;
|
"", fallback, true))
|
||||||
|
{
|
||||||
|
LOG_WARN("failed to load fontconfig fallback font");
|
||||||
|
free(fallback);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
font_destroy(&fallback);
|
LOG_DBG("loaded new fontconfig fallback font");
|
||||||
|
font->fc_loaded_fonts[i] = fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(font->fc_loaded_fonts[i] != NULL);
|
||||||
|
|
||||||
|
if (glyph_for_wchar(font->fc_loaded_fonts[i], wc, glyph)) {
|
||||||
|
LOG_DBG("%C: used fontconfig fallback", wc);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -584,6 +605,9 @@ font_glyph_for_wc(struct font *font, wchar_t wc)
|
||||||
void
|
void
|
||||||
font_destroy(struct font *font)
|
font_destroy(struct font *font)
|
||||||
{
|
{
|
||||||
|
if (font == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
tll_free_and_free(font->fallbacks, free);
|
tll_free_and_free(font->fallbacks, free);
|
||||||
|
|
||||||
if (font->face != NULL) {
|
if (font->face != NULL) {
|
||||||
|
|
@ -594,15 +618,22 @@ font_destroy(struct font *font)
|
||||||
|
|
||||||
mtx_destroy(&font->lock);
|
mtx_destroy(&font->lock);
|
||||||
|
|
||||||
|
if (font->fc_fonts != NULL) {
|
||||||
|
assert(font->fc_loaded_fonts != NULL);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < font->fc_fonts->nfont; i++)
|
||||||
|
font_destroy(font->fc_loaded_fonts[i]);
|
||||||
|
|
||||||
|
free(font->fc_loaded_fonts);
|
||||||
|
}
|
||||||
|
|
||||||
if (font->fc_pattern != NULL)
|
if (font->fc_pattern != NULL)
|
||||||
FcPatternDestroy(font->fc_pattern);
|
FcPatternDestroy(font->fc_pattern);
|
||||||
if (font->fc_fonts != NULL)
|
if (font->fc_fonts != NULL)
|
||||||
FcFontSetDestroy(font->fc_fonts);
|
FcFontSetDestroy(font->fc_fonts);
|
||||||
|
|
||||||
if (font->cache == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < cache_size; i++) {
|
for (size_t i = 0; i < cache_size && font->cache != NULL; i++) {
|
||||||
if (font->cache[i] == NULL)
|
if (font->cache[i] == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
@ -619,4 +650,5 @@ font_destroy(struct font *font)
|
||||||
free(font->cache[i]);
|
free(font->cache[i]);
|
||||||
}
|
}
|
||||||
free(font->cache);
|
free(font->cache);
|
||||||
|
free(font);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
13
font.h
13
font.h
|
|
@ -30,14 +30,12 @@ struct glyph {
|
||||||
typedef tll(struct glyph) hash_entry_t;
|
typedef tll(struct glyph) hash_entry_t;
|
||||||
|
|
||||||
struct font {
|
struct font {
|
||||||
FcPattern *fc_pattern;
|
mtx_t lock;
|
||||||
FcFontSet *fc_fonts;
|
|
||||||
int fc_idx;
|
|
||||||
|
|
||||||
FT_Face face;
|
FT_Face face;
|
||||||
int load_flags;
|
int load_flags;
|
||||||
int render_flags;
|
int render_flags;
|
||||||
FT_LcdFilter lcd_filter;
|
FT_LcdFilter lcd_filter;
|
||||||
|
|
||||||
double pixel_size_fixup; /* Scale factor - should only be used with ARGB32 glyphs */
|
double pixel_size_fixup; /* Scale factor - should only be used with ARGB32 glyphs */
|
||||||
bool bgr; /* True for FC_RGBA_BGR and FC_RGBA_VBGR */
|
bool bgr; /* True for FC_RGBA_BGR and FC_RGBA_VBGR */
|
||||||
|
|
||||||
|
|
@ -54,8 +52,13 @@ struct font {
|
||||||
bool is_fallback;
|
bool is_fallback;
|
||||||
tll(char *) fallbacks;
|
tll(char *) fallbacks;
|
||||||
|
|
||||||
|
/* Fields below are only valid for non-fallback fonts */
|
||||||
|
FcPattern *fc_pattern;
|
||||||
|
FcFontSet *fc_fonts;
|
||||||
|
int fc_idx;
|
||||||
|
struct font **fc_loaded_fonts; /* fc_fonts->nfont array */
|
||||||
|
|
||||||
hash_entry_t **cache;
|
hash_entry_t **cache;
|
||||||
mtx_t lock;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct font *font_from_name(font_list_t names, const char *attributes);
|
struct font *font_from_name(font_list_t names, const char *attributes);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue