Fix space based ligatures not rendering correctly

The new infinite ligature cache needed to be keyed by total number of
cells as well as total number of glyphs, otherwise a space based
ligature which is the same glyph rendered in different numbers of cells
wold render incorrectly when present in multiple forms. Fixes #3729
This commit is contained in:
Kovid Goyal 2021-06-16 18:41:01 +05:30
parent 71c8d82c33
commit 9d3a2cc219
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 14 additions and 11 deletions

View File

@ -7,6 +7,9 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
0.21.2 [future]
----------------------
- Fix a regression in 0.21.0 that broke rendering of private use unicode symbols followed
by spaces, when they also exist not followed by spaces (:iss:`3729`)
- Add support for the XTVERSION escape code
- macOS: Fix middle-click to paste from clipboard not working (:iss:`3730`)

View File

@ -238,9 +238,9 @@ do_increment(FontGroup *fg, int *error) {
static SpritePosition*
sprite_position_for(FontGroup *fg, Font *font, glyph_index *glyphs, unsigned glyph_count, uint8_t ligature_index, int *error) {
sprite_position_for(FontGroup *fg, Font *font, glyph_index *glyphs, unsigned glyph_count, uint8_t ligature_index, unsigned cell_count, int *error) {
bool created;
SpritePosition *s = find_or_create_sprite_position(&font->sprite_position_hash_table, glyphs, glyph_count, ligature_index, &created);
SpritePosition *s = find_or_create_sprite_position(&font->sprite_position_hash_table, glyphs, glyph_count, ligature_index, cell_count, &created);
if (!s) { *error = 1; return NULL; }
if (created) {
s->x = fg->sprite_tracker.x; s->y = fg->sprite_tracker.y; s->z = fg->sprite_tracker.z;
@ -576,7 +576,7 @@ static void
render_box_cell(FontGroup *fg, CPUCell *cpu_cell, GPUCell *gpu_cell) {
int error = 0;
glyph_index glyph = box_glyph_id(cpu_cell->ch);
SpritePosition *sp = sprite_position_for(fg, &fg->fonts[BOX_FONT], &glyph, 1, false, &error);
SpritePosition *sp = sprite_position_for(fg, &fg->fonts[BOX_FONT], &glyph, 1, 0, 1, &error);
if (sp == NULL) {
sprite_map_set_error(error); PyErr_Print();
set_sprite(gpu_cell, 0, 0, 0);
@ -649,7 +649,7 @@ render_group(FontGroup *fg, unsigned int num_cells, unsigned int num_glyphs, CPU
if (is_repeat_glyph) {
sp[i] = sp[i-1];
} else {
sp[i] = sprite_position_for(fg, font, glyphs, glyph_count, ligature_index++, &error);
sp[i] = sprite_position_for(fg, font, glyphs, glyph_count, ligature_index++, num_cells, &error);
}
if (error != 0) { sprite_map_set_error(error); PyErr_Print(); return; }
if (!sp[i]->rendered) all_rendered = false;
@ -1449,7 +1449,7 @@ test_sprite_position_for(PyObject UNUSED *self, PyObject *args) {
}
FontGroup *fg = font_groups;
if (!num_font_groups) { PyErr_SetString(PyExc_RuntimeError, "must create font group first"); return NULL; }
SpritePosition *pos = sprite_position_for(fg, &fg->fonts[fg->medium_font_idx], glyphs, PyTuple_GET_SIZE(args), 0, &error);
SpritePosition *pos = sprite_position_for(fg, &fg->fonts[fg->medium_font_idx], glyphs, PyTuple_GET_SIZE(args), 0, 1, &error);
if (pos == NULL) { sprite_map_set_error(error); return NULL; }
return Py_BuildValue("HHH", pos->x, pos->y, pos->z);
}

View File

@ -26,12 +26,12 @@ free_glyph_cache_global_resources(void) {
}
static inline unsigned
key_size_for_glyph_count(unsigned count) { return count + 2; }
static unsigned
key_size_for_glyph_count(unsigned count) { return count + 3; }
SpritePosition*
find_or_create_sprite_position(SpritePosition **head_, glyph_index *glyphs, glyph_index count, glyph_index ligature_index, bool *created) {
find_or_create_sprite_position(SpritePosition **head_, glyph_index *glyphs, glyph_index count, glyph_index ligature_index, glyph_index cell_count, bool *created) {
SpritePosItem **head = (SpritePosItem**)head_, *p;
const unsigned key_sz = key_size_for_glyph_count(count);
if (key_sz > scratch_sz) {
@ -40,8 +40,8 @@ find_or_create_sprite_position(SpritePosition **head_, glyph_index *glyphs, glyp
scratch_sz = key_sz + 16;
}
const unsigned key_sz_bytes = key_sz * sizeof(glyph_index);
scratch[0] = count; scratch[1] = ligature_index;
memcpy(scratch + 2, glyphs, count * sizeof(glyph_index));
scratch[0] = count; scratch[1] = ligature_index; scratch[2] = cell_count;
memcpy(scratch + 3, glyphs, count * sizeof(glyph_index));
HASH_FIND(hh, *head, scratch, key_sz_bytes, p);
if (p) { *created = false; return (SpritePosition*)p; }

View File

@ -21,7 +21,7 @@ typedef struct SpritePosition {
void free_sprite_position_hash_table(SpritePosition **head);
SpritePosition*
find_or_create_sprite_position(SpritePosition **head, glyph_index *glyphs, glyph_index count, glyph_index ligature_index, bool *created);
find_or_create_sprite_position(SpritePosition **head, glyph_index *glyphs, glyph_index count, glyph_index ligature_index, glyph_index cell_count, bool *created);
#define GlyphPropertiesHead \
uint8_t data;