term: turn ‘box-drawings’ array into three dynamically allocated arrays

The box_drawings array is now quite large, and uses up ~4K
when *empty*.

This patch splits it up into three separate, dynamically allocated
arrays; one for the traditional box+line drawing and block elements
glyphs, one for braille, and one for the legacy computing symbols.

When we need to render a glyph, the *entire* array (that it belongs
to) is allocated.

I.e this is one step closer to a dynamic glyph cache (like the one
fcft uses), but doesn’t go all the way.

This is especially nice for people with
‘box-drawings-uses-font-glyphs=yes’; for them, the custom glyphs now
uses 3*8 bytes (for the three array pointers), instead of 4K.
This commit is contained in:
Daniel Eklöf 2021-09-14 09:50:49 +02:00
parent ac2091f107
commit 37b15adcd8
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
3 changed files with 87 additions and 42 deletions

View file

@ -513,10 +513,12 @@ render_cell(struct terminal *term, pixman_image_t *pix,
if (base != 0) { if (base != 0) {
if (unlikely( if (unlikely(
/* Classic box drawings */ /* Classic box drawings */
(base >= 0x2500 && base <= 0x259f) || (base >= GLYPH_BOX_DRAWING_FIRST &&
base <= GLYPH_BOX_DRAWING_LAST) ||
/* Braille */ /* Braille */
(base >= 0x2800 && base <= 0x28ff) || (base >= GLYPH_BRAILLE_FIRST &&
base <= GLYPH_BRAILLE_LAST) ||
/* /*
* Unicode 13 "Symbols for Legacy Computing" * Unicode 13 "Symbols for Legacy Computing"
@ -524,42 +526,50 @@ render_cell(struct terminal *term, pixman_image_t *pix,
* *
* Note, the full range is U+1FB00 - U+1FBF9 * Note, the full range is U+1FB00 - U+1FBF9
*/ */
(base >= GLYPH_LEGACY_FIRST &&
/* Unicode 13 sextants */ base <= GLYPH_LEGACY_LAST)) &&
(base >= 0x1fb00 && base <= 0x1fb8b) ||
(base >= 0x1fb9a && base <= 0x1fb9b)) &&
likely(!term->conf->box_drawings_uses_font_glyphs)) likely(!term->conf->box_drawings_uses_font_glyphs))
{ {
/* Box drawing characters */ struct fcft_glyph ***arr;
size_t idx = base >= 0x1fb00 size_t count;
? (base >= 0x1fb9a size_t idx;
? base - 0x1fb9a + 556
: base - 0x1fb00 + 416)
: (base >= 0x2800
? base - 0x2800 + 160
: base - 0x2500);
xassert(idx < ALEN(term->box_drawing)); if (base >= GLYPH_LEGACY_FIRST) {
arr = &term->custom_glyphs.legacy;
count = GLYPH_LEGACY_COUNT;
idx = base - GLYPH_LEGACY_FIRST;
} else if (base >= GLYPH_BRAILLE_FIRST) {
arr = &term->custom_glyphs.braille;
count = GLYPH_BRAILLE_COUNT;
idx = base - GLYPH_BRAILLE_FIRST;
} else {
arr = &term->custom_glyphs.box_drawing;
count = GLYPH_BOX_DRAWING_COUNT;
idx = base - GLYPH_BOX_DRAWING_FIRST;
}
if (likely(term->box_drawing[idx] != NULL)) if (unlikely(*arr == NULL))
single = term->box_drawing[idx]; *arr = xcalloc(count, sizeof((*arr)[0]));
if (likely((*arr)[idx] != NULL))
single = (*arr)[idx];
else { else {
mtx_lock(&term->render.workers.lock); mtx_lock(&term->render.workers.lock);
/* Other thread may have instantiated it while we /* Other thread may have instantiated it while we
* acquired the lock */ * acquired the lock */
if (term->box_drawing[idx] == NULL) single = (*arr)[idx];
term->box_drawing[idx] = box_drawing(term, base); if (likely(single == NULL))
single = (*arr)[idx] = box_drawing(term, base);
mtx_unlock(&term->render.workers.lock); mtx_unlock(&term->render.workers.lock);
single = term->box_drawing[idx];
xassert(single != NULL);
} }
glyph_count = 1; if (single != NULL) {
glyphs = &single; glyph_count = 1;
cell_cols = single->cols; glyphs = &single;
cell_cols = single->cols;
}
} }
else if (base >= CELL_COMB_CHARS_LO && base <= CELL_COMB_CHARS_HI) else if (base >= CELL_COMB_CHARS_LO && base <= CELL_COMB_CHARS_HI)

View file

@ -626,15 +626,28 @@ err_sem_destroy:
} }
static void static void
free_box_drawing(struct fcft_glyph **box_drawing) free_custom_glyph(struct fcft_glyph **glyph)
{ {
if (*box_drawing == NULL) if (*glyph == NULL)
return; return;
free(pixman_image_get_data((*box_drawing)->pix)); free(pixman_image_get_data((*glyph)->pix));
pixman_image_unref((*box_drawing)->pix); pixman_image_unref((*glyph)->pix);
free(*box_drawing); free(*glyph);
*box_drawing = NULL; *glyph = NULL;
}
static void
free_custom_glyphs(struct fcft_glyph ***glyphs, size_t count)
{
if (*glyphs == NULL)
return;
for (size_t i = 0; i < count; i++)
free_custom_glyph(&(*glyphs)[i]);
free(*glyphs);
*glyphs = NULL;
} }
static bool static bool
@ -647,8 +660,12 @@ term_set_fonts(struct terminal *term, struct fcft_font *fonts[static 4])
term->fonts[i] = fonts[i]; term->fonts[i] = fonts[i];
} }
for (size_t i = 0; i < ALEN(term->box_drawing); i++) free_custom_glyphs(
free_box_drawing(&term->box_drawing[i]); &term->custom_glyphs.box_drawing, GLYPH_BOX_DRAWING_COUNT);
free_custom_glyphs(
&term->custom_glyphs.braille, GLYPH_BRAILLE_COUNT);
free_custom_glyphs(
&term->custom_glyphs.legacy, GLYPH_LEGACY_COUNT);
const int old_cell_width = term->cell_width; const int old_cell_width = term->cell_width;
const int old_cell_height = term->cell_height; const int old_cell_height = term->cell_height;
@ -1590,8 +1607,13 @@ term_destroy(struct terminal *term)
for (size_t i = 0; i < 4; i++) for (size_t i = 0; i < 4; i++)
free(term->font_sizes[i]); free(term->font_sizes[i]);
for (size_t i = 0; i < ALEN(term->box_drawing); i++)
free_box_drawing(&term->box_drawing[i]); free_custom_glyphs(
&term->custom_glyphs.box_drawing, GLYPH_BOX_DRAWING_COUNT);
free_custom_glyphs(
&term->custom_glyphs.braille, GLYPH_BRAILLE_COUNT);
free_custom_glyphs(
&term->custom_glyphs.legacy, GLYPH_LEGACY_COUNT);
free(term->search.buf); free(term->search.buf);

View file

@ -333,13 +333,26 @@ struct terminal {
int16_t font_y_ofs; int16_t font_y_ofs;
enum fcft_subpixel font_subpixel; enum fcft_subpixel font_subpixel;
/* struct {
* 0-159: U+02500+0259F struct fcft_glyph **box_drawing;
* 160-415: U+02800-028FF struct fcft_glyph **braille;
* 416-555: U+1FB00-1FB8B struct fcft_glyph **legacy;
* 556-557: U+1FB9A-1FB9B
*/ #define GLYPH_BOX_DRAWING_FIRST 0x2500
struct fcft_glyph *box_drawing[558]; #define GLYPH_BOX_DRAWING_LAST 0x259F
#define GLYPH_BOX_DRAWING_COUNT \
(GLYPH_BOX_DRAWING_LAST - GLYPH_BOX_DRAWING_FIRST + 1)
#define GLYPH_BRAILLE_FIRST 0x2800
#define GLYPH_BRAILLE_LAST 0x28FF
#define GLYPH_BRAILLE_COUNT \
(GLYPH_BRAILLE_LAST - GLYPH_BRAILLE_FIRST + 1)
#define GLYPH_LEGACY_FIRST 0x1FB00
#define GLYPH_LEGACY_LAST 0x1FB9B
#define GLYPH_LEGACY_COUNT \
(GLYPH_LEGACY_LAST - GLYPH_LEGACY_FIRST + 1)
} custom_glyphs;
bool is_sending_paste_data; bool is_sending_paste_data;
ptmx_buffer_list_t ptmx_buffers; ptmx_buffer_list_t ptmx_buffers;