unicode-combining: store seen combining chains "globally" in the term struct

Instead of storing combining data per cell, realize that most
combinations are re-occurring and that there's lots of available space
left in the unicode range, and store seen base+combining combinations
chains in a per-terminal array.

When we encounter a combining character, we first try to pre-compose,
like before. If that fails, we then search for the current
base+combining combo in the list of previously seen combinations. If
not found there either, we allocate a new combo and add it to the
list. Regardless, the result is an index into this array. We store
this index, offsetted by COMB_CHARS_LO=0x40000000ul in the cell.

When rendering, we need to check if the cell character is a plain
character, or if it's a composed character (identified by checking if
the cell character is >= COMB_CHARS_LO).

Then we render the grapheme pretty much like before.
This commit is contained in:
Daniel Eklöf 2020-05-03 11:03:22 +02:00
parent ae7383189a
commit 62e0774319
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
8 changed files with 97 additions and 92 deletions

View file

@ -822,6 +822,8 @@ term_init(const struct config *conf, struct fdm *fdm, struct wayland *wayl,
.normal = {.damage = tll_init(), .scroll_damage = tll_init(), .sixel_images = tll_init()},
.alt = {.damage = tll_init(), .scroll_damage = tll_init(), .sixel_images = tll_init()},
.grid = &term->normal,
.composed_count = 0,
.composed = NULL,
.meta = {
.esc_prefix = true,
.eight_bit = true,
@ -1086,6 +1088,8 @@ term_destroy(struct terminal *term)
tll_free(term->normal.scroll_damage);
tll_free(term->alt.scroll_damage);
free(term->composed);
free(term->window_title);
tll_free_and_free(term->window_title_stack, free);
@ -2295,10 +2299,6 @@ term_print(struct terminal *term, wchar_t wc, int width)
cell->wc = term->vt.last_printed = wc;
cell->attrs = term->vt.attrs;
#if FOOT_UNICODE_MAX_COMBINING_CHARS > 0
row->comb_chars[term->grid->cursor.point.col].count = 0;
#endif
row->dirty = true;
cell->attrs.clean = 0;