From 482690e5fbc3c3facffdedd06f1fe25f7cf5e8c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Mon, 4 Jan 2021 18:32:55 +0100 Subject: [PATCH] render: draw combining characters on top of colored bitmap glyphs (emoji) --- CHANGELOG.md | 2 ++ render.c | 54 ++++++++++++++++++++++++++++++++++------------------ 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c3391eb..e571842f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,8 @@ properly erasing the cell overflowed **into**. * `word-delimiters` option ignores `#` and subsequent characters (https://codeberg.org/dnkl/foot/issues/270) +* Combining characters not being rendered when composed with colored + bitmap glyhps (i.e. colored emojis). ### Security diff --git a/render.c b/render.c index ed4854f0..366951f9 100644 --- a/render.c +++ b/render.c @@ -555,26 +555,44 @@ render_cell(struct terminal *term, pixman_image_t *pix, x + glyph->x, y + font_baseline(term) - glyph->y, glyph->width, glyph->height); - /* Combining characters */ - 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; - - 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); - } - } } + /* Combining characters */ + 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; + + /* + * Fonts _should_ assume the pen position is now + * *after* the base glyph, and thus use negative + * offsets for combining glyphs. + * + * Not all fonts behave like this however, and we + * try to accomodate both variants. + * + * Since we haven't moved our pen position yet, we + * add a full cell width to the offset (or two, in + * case of double-width characters). + * + * If the font does *not* use negative offsets, + * we'd normally use an offset of 0. However, to + * somewhat deal with double-width glyphs we use + * an offset of *one* cell. + */ + int x_ofs = g->x < 0 + ? cell_cols * term->cell_width + : (cell_cols - 1) * term->cell_width; + + pixman_image_composite32( + PIXMAN_OP_OVER, clr_pix, g->pix, pix, 0, 0, 0, 0, + x + x_ofs + g->x, y + font_baseline(term) - g->y, + g->width, g->height); + } + } } pixman_image_unref(clr_pix);