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

@ -402,9 +402,20 @@ render_cell(struct terminal *term, pixman_image_t *pix,
struct fcft_font *font = attrs_to_font(term, &cell->attrs);
const struct fcft_glyph *glyph = NULL;
const struct composed *composed = NULL;
if (cell->wc != 0)
glyph = fcft_glyph_rasterize(font, cell->wc, term->font_subpixel);
if (cell->wc != 0) {
wchar_t base = cell->wc;
if (base >= COMB_CHARS_LO &&
base < (COMB_CHARS_LO + term->composed_count))
{
composed = &term->composed[base - COMB_CHARS_LO];
base = composed->base;
}
glyph = fcft_glyph_rasterize(font, base, term->font_subpixel);
}
int cell_cols = glyph != NULL ? max(1, glyph->cols) : 1;
@ -442,25 +453,25 @@ render_cell(struct terminal *term, pixman_image_t *pix,
}
}
#if FOOT_UNICODE_MAX_COMBINING_CHARS > 0
/* Combining characters */
const struct combining_chars *comb_chars = &row->comb_chars[col];
for (size_t i = 0; i < comb_chars->count; i++) {
const struct fcft_glyph *g = fcft_glyph_rasterize(
font, comb_chars->chars[i], term->font_subpixel);
if (composed != NULL) {
for (size_t i = 0; i < composed->count; i++) {
const struct fcft_glyph *g = fcft_glyph_rasterize(
font, composed->combining[i], term->font_subpixel);
if (g == NULL)
continue;
if (g == NULL)
continue;
pixman_image_composite32(
PIXMAN_OP_OVER, clr_pix, g->pix, pix, 0, 0, 0, 0,
/* Some fonts use a negative offset, while others use a
* "normal" offset */
x + (g->x < 0 ? term->cell_width : 0) + g->x,
y + font_baseline(term) - g->y,
g->width, g->height);
pixman_image_composite32(
PIXMAN_OP_OVER, clr_pix, g->pix, pix, 0, 0, 0, 0,
/* Some fonts use a negative offset, while others use a
* "normal" offset */
x + (g->x < 0 ? term->cell_width : 0) + g->x,
y + font_baseline(term) - g->y,
g->width, g->height);
}
}
#endif
pixman_image_unref(clr_pix);
/* Underline */