mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-03-11 05:33:55 -04:00
font: populate glyph cache (ASCII characters only) when instantiating font
This commit is contained in:
parent
9e57ba2108
commit
fe882bddba
5 changed files with 44 additions and 82 deletions
25
font.c
25
font.c
|
|
@ -25,6 +25,14 @@ fini(void)
|
||||||
FT_Done_FreeType(ft_lib);
|
FT_Done_FreeType(ft_lib);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
font_populate_glyph_cache(struct font *font)
|
||||||
|
{
|
||||||
|
memset(font->cache, 0, sizeof(font->cache));
|
||||||
|
for (size_t i = 0; i < 256; i++)
|
||||||
|
font_glyph_for_utf8(font, &(char){i}, &font->cache[i]);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
font_from_name(const char *name, struct font *font)
|
font_from_name(const char *name, struct font *font)
|
||||||
{
|
{
|
||||||
|
|
@ -94,6 +102,7 @@ font_from_name(const char *name, struct font *font)
|
||||||
FcPatternDestroy(final_pattern);
|
FcPatternDestroy(final_pattern);
|
||||||
|
|
||||||
font->face = ft_face;
|
font->face = ft_face;
|
||||||
|
font_populate_glyph_cache(font);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -114,6 +123,8 @@ font_glyph_for_utf8(const struct font *font, const char *utf8,
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
assert(font->face->glyph->format == FT_GLYPH_FORMAT_BITMAP);
|
||||||
|
|
||||||
FT_Bitmap *bitmap = &font->face->glyph->bitmap;
|
FT_Bitmap *bitmap = &font->face->glyph->bitmap;
|
||||||
assert(bitmap->pixel_mode == FT_PIXEL_MODE_GRAY ||
|
assert(bitmap->pixel_mode == FT_PIXEL_MODE_GRAY ||
|
||||||
bitmap->pixel_mode == FT_PIXEL_MODE_MONO);
|
bitmap->pixel_mode == FT_PIXEL_MODE_MONO);
|
||||||
|
|
@ -172,3 +183,17 @@ font_glyph_for_utf8(const struct font *font, const char *utf8,
|
||||||
};
|
};
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
font_destroy(struct font *font)
|
||||||
|
{
|
||||||
|
if (font->face != NULL)
|
||||||
|
FT_Done_Face(font->face);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 256; i++) {
|
||||||
|
if (font->cache[i].surf != NULL)
|
||||||
|
cairo_surface_destroy(font->cache[i].surf);
|
||||||
|
if (font->cache[i].data != NULL)
|
||||||
|
free(font->cache[i].data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
1
font.h
1
font.h
|
|
@ -6,3 +6,4 @@
|
||||||
bool font_from_name(const char *name, struct font *result);
|
bool font_from_name(const char *name, struct font *result);
|
||||||
bool font_glyph_for_utf8(
|
bool font_glyph_for_utf8(
|
||||||
const struct font *font, const char *utf8, struct glyph *glyph);
|
const struct font *font, const char *utf8, struct glyph *glyph);
|
||||||
|
void font_destroy(struct font *font);
|
||||||
|
|
|
||||||
9
main.c
9
main.c
|
|
@ -896,12 +896,8 @@ out:
|
||||||
free(term.window_title);
|
free(term.window_title);
|
||||||
tll_free_and_free(term.window_title_stack, free);
|
tll_free_and_free(term.window_title_stack, free);
|
||||||
|
|
||||||
for (size_t i = 0; i < sizeof(term.fonts) / sizeof(term.fonts[0]); i++) {
|
for (size_t i = 0; i < sizeof(term.fonts) / sizeof(term.fonts[0]); i++)
|
||||||
struct font *f = &term.fonts[i];
|
font_destroy(&term.fonts[i]);
|
||||||
|
|
||||||
if (f->face != NULL)
|
|
||||||
FT_Done_Face(f->face);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (term.flash.fd != -1)
|
if (term.flash.fd != -1)
|
||||||
close(term.flash.fd);
|
close(term.flash.fd);
|
||||||
|
|
@ -921,4 +917,5 @@ out:
|
||||||
|
|
||||||
cairo_debug_reset_static_data();
|
cairo_debug_reset_static_data();
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
89
render.c
89
render.c
|
|
@ -258,93 +258,30 @@ render_cell(struct terminal *term, struct buffer *buf, const struct cell *cell,
|
||||||
gseq.foreground = _fg;
|
gseq.foreground = _fg;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
int new_glyphs
|
|
||||||
= sizeof(gseq.glyphs) / sizeof(gseq.glyphs[0]) - gseq.count;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct font *font = attrs_to_font(term, &cell->attrs);
|
struct font *font = attrs_to_font(term, &cell->attrs);
|
||||||
|
|
||||||
#if 0
|
struct glyph *glyph = NULL;
|
||||||
struct glyph_cache *entry = cell->c[1] == '\0'
|
if (strnlen(cell->c, 4) == 1) {
|
||||||
? &font->glyph_cache[(unsigned char)cell->c[0]]
|
if (font->cache[(unsigned char)cell->c[0]].surf != NULL)
|
||||||
: NULL;
|
glyph = &font->cache[(unsigned char)cell->c[0]];
|
||||||
|
|
||||||
if (likely(entry != NULL && entry->glyphs != NULL)) {
|
|
||||||
/* Copy cached glyph(s) and upate position */
|
|
||||||
memcpy(gseq.g, entry->glyphs, entry->count * sizeof(gseq.g[0]));
|
|
||||||
for (size_t i = 0; i < entry->count; i++) {
|
|
||||||
gseq.g[i].x += x;
|
|
||||||
gseq.g[i].y += y;
|
|
||||||
}
|
|
||||||
|
|
||||||
new_glyphs = entry->count;
|
|
||||||
} else {
|
|
||||||
/* Must generate new glyph(s) */
|
|
||||||
cairo_status_t status = cairo_scaled_font_text_to_glyphs(
|
|
||||||
font->font, x, y + term->fextents.ascent,
|
|
||||||
cell->c, strnlen(cell->c, 4), &gseq.g, &new_glyphs,
|
|
||||||
NULL, NULL, NULL);
|
|
||||||
|
|
||||||
if (status != CAIRO_STATUS_SUCCESS)
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gseq.g += new_glyphs;
|
struct glyph _glyph;
|
||||||
gseq.count += new_glyphs;
|
if (glyph == NULL) {
|
||||||
assert(gseq.count <= sizeof(gseq.glyphs) / sizeof(gseq.glyphs[0]));
|
if (!font_glyph_for_utf8(font, cell->c, &_glyph))
|
||||||
#else
|
return;
|
||||||
|
glyph = &_glyph;
|
||||||
struct foo_cache {
|
|
||||||
uint8_t *data;
|
|
||||||
cairo_surface_t *surf;
|
|
||||||
int left;
|
|
||||||
int top;
|
|
||||||
};
|
|
||||||
static struct foo_cache foo_cache[4][256] = {0};
|
|
||||||
|
|
||||||
cairo_surface_t *glyph = NULL;
|
|
||||||
double left, top;
|
|
||||||
|
|
||||||
struct foo_cache *e = strnlen(cell->c, 4) == 1
|
|
||||||
? &foo_cache[cell->attrs.italic << 1 | cell->attrs.bold][(unsigned char)cell->c[0]]
|
|
||||||
: NULL;
|
|
||||||
|
|
||||||
if (e == NULL || e->data == NULL) {
|
|
||||||
struct glyph g;
|
|
||||||
if (!font_glyph_for_utf8(font, cell->c, &g))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
if (e != NULL) {
|
|
||||||
e->data = g.data;
|
|
||||||
e->surf = g.surf;
|
|
||||||
e->left = g.left;
|
|
||||||
e->top = g.top;
|
|
||||||
}
|
|
||||||
|
|
||||||
glyph = g.surf;
|
|
||||||
left = g.left;
|
|
||||||
top = g.top;
|
|
||||||
} else {
|
|
||||||
glyph = e->surf;
|
|
||||||
left = e->left;
|
|
||||||
top = e->top;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(glyph != NULL);
|
assert(glyph != NULL);
|
||||||
cairo_set_source_rgb(buf->cairo, fg.r, fg.g, fg.b);
|
cairo_set_source_rgb(buf->cairo, fg.r, fg.g, fg.b);
|
||||||
cairo_set_operator(buf->cairo, CAIRO_OPERATOR_OVER);
|
cairo_set_operator(buf->cairo, CAIRO_OPERATOR_OVER);
|
||||||
cairo_mask_surface(buf->cairo, glyph, x + left, y + term->fextents.ascent - top);
|
cairo_mask_surface(buf->cairo, glyph->surf, x + glyph->left, y + term->fextents.ascent - glyph->top);
|
||||||
|
|
||||||
if (e == NULL) {
|
if (glyph == &_glyph) {
|
||||||
void *raw = cairo_image_surface_get_data(glyph);
|
cairo_surface_destroy(_glyph.surf);
|
||||||
cairo_surface_destroy(glyph);
|
free(_glyph.data);
|
||||||
free(raw);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
||||||
|
|
@ -223,6 +223,8 @@ struct font {
|
||||||
double position;
|
double position;
|
||||||
double thickness;
|
double thickness;
|
||||||
} strikeout;
|
} strikeout;
|
||||||
|
|
||||||
|
struct glyph cache[256];
|
||||||
};
|
};
|
||||||
|
|
||||||
enum cursor_style { CURSOR_BLOCK, CURSOR_UNDERLINE, CURSOR_BAR };
|
enum cursor_style { CURSOR_BLOCK, CURSOR_UNDERLINE, CURSOR_BAR };
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue