terminal: dumb glyph cache for truetype text

This commit is contained in:
K. Lange 2022-08-21 14:44:20 +09:00
parent d2f3644430
commit 8f6711bce9

View File

@ -609,6 +609,85 @@ static void draw_semi_block(int c, int x, int y, uint32_t fg, uint32_t bg) {
#include "apps/ununicode.h"
struct GlyphCacheEntry {
struct TT_Font * font;
sprite_t * sprite;
uint32_t size;
uint32_t glyph;
uint32_t color;
};
static struct GlyphCacheEntry glyph_cache[1024];
static unsigned long _hits = 0;
static unsigned long _misses = 0;
static unsigned long _wrongcolor = 0;
static void _menu_action_cache_stats(struct MenuEntry * self) {
char msg[400];
unsigned long count = 0;
unsigned long size = 0;
for (int i = 0; i < 1024; ++i) {
if (glyph_cache[i].sprite) {
count++;
size += glyph_cache[i].sprite->width * glyph_cache[i].sprite->height * 4;
}
}
snprintf(msg, 400,
"Hits: %lu\n"
"Misses: %lu\n"
"Wrong color: %lu\n"
"Populated cache entries: %lu\n"
"Size of sprites: %lu\n",
_hits, _misses, _wrongcolor, count, size);
write(fd_slave, msg, strlen(msg));
}
static void _menu_action_clear_cache(struct MenuEntry * self) {
for (int i = 0; i < 1024; ++i) {
if (glyph_cache[i].sprite) {
sprite_free(glyph_cache[i].sprite);
}
}
memset(glyph_cache,0,sizeof(glyph_cache));
}
static void draw_cached_glyph(gfx_context_t * ctx, struct TT_Font * _font, uint32_t size, int x, int y, uint32_t glyph, uint32_t fg, int flags) {
unsigned int hash = (((uintptr_t)_font >> 8) ^ (glyph * size)) & 1023;
struct GlyphCacheEntry * entry = &glyph_cache[hash];
if (entry->font != _font || entry->size != size || entry->glyph != glyph) {
if (entry->sprite) sprite_free(entry->sprite);
int wide = (flags & ANSI_WIDE) ? 2 : 1;
tt_set_size(_font, size);
entry->font = _font;
entry->size = size;
entry->glyph = glyph;
entry->sprite = create_sprite(char_width * wide, char_height, ALPHA_EMBEDDED);
entry->color = _ALP(fg) == 255 ? fg : 0xFFFFFFFF;
gfx_context_t * _ctx = init_graphics_sprite(entry->sprite);
draw_fill(_ctx, 0);
tt_draw_glyph(_ctx, entry->font, 0, char_offset, glyph, entry->color);
free(_ctx);
_misses++;
} else {
_hits++;
}
if (entry->color != fg) {
_wrongcolor++;
draw_sprite_alpha_paint(ctx, entry->sprite, x, y, 1.0, fg);
} else {
draw_sprite(ctx, entry->sprite, x, y);
}
}
/* Write a character to the window. */
static void term_write_char(uint32_t val, uint16_t x, uint16_t y, uint32_t fg, uint32_t bg, uint8_t flags) {
uint32_t _fg, _bg;
@ -695,10 +774,9 @@ static void term_write_char(uint32_t val, uint16_t x, uint16_t y, uint32_t fg, u
}
}
tt_set_size(_font, font_size);
int _x = x + decor_left_width;
int _y = y + char_offset + decor_top_height + menu_bar_height;
tt_draw_glyph(ctx, _font, _x, _y, glyph, _fg);
int _y = y + decor_top_height + menu_bar_height;
draw_cached_glyph(ctx, _font, font_size, _x,_y, glyph, _fg, flags);
} else {
/* Convert other unicode characters. */
if (val > 128) {
@ -2430,6 +2508,11 @@ int main(int argc, char ** argv) {
menu_insert(m, menu_create_normal(NULL, "2.0", "200%", _menu_action_set_scale));
menu_set_insert(terminal_menu_bar.set, "zoom", m);
m = menu_create();
menu_insert(m, menu_create_normal(NULL, NULL, "View stats", _menu_action_cache_stats));
menu_insert(m, menu_create_normal(NULL, NULL, "Clear cache", _menu_action_clear_cache));
menu_set_insert(terminal_menu_bar.set, "cache", m);
m = menu_create();
_menu_toggle_borders_bar = menu_create_normal(_no_frame ? NULL : "check", NULL, "Show borders", _menu_action_hide_borders);
menu_insert(m, _menu_toggle_borders_bar);
@ -2439,6 +2522,7 @@ int main(int argc, char ** argv) {
menu_insert(m, menu_create_normal(_free_size ? NULL : "check", NULL, "Snap to Cell Size", _menu_action_toggle_free_size));
menu_insert(m, menu_create_separator());
menu_insert(m, menu_create_normal(NULL, NULL, "Redraw", _menu_action_redraw));
menu_insert(m, menu_create_submenu(NULL,"cache","Glyph cache..."));
menu_set_insert(terminal_menu_bar.set, "view", m);
m = menu_create();