From 9d3a2cc219433055332c86e7d92d2a555d42d5b8 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 16 Jun 2021 18:41:01 +0530 Subject: [PATCH] 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 --- docs/changelog.rst | 3 +++ kitty/fonts.c | 10 +++++----- kitty/glyph-cache.c | 10 +++++----- kitty/glyph-cache.h | 2 +- 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index dedae424c..47d469349 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -7,6 +7,9 @@ To update |kitty|, :doc:`follow the instructions `. 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`) diff --git a/kitty/fonts.c b/kitty/fonts.c index 70c8cbb34..ae0157298 100644 --- a/kitty/fonts.c +++ b/kitty/fonts.c @@ -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); } diff --git a/kitty/glyph-cache.c b/kitty/glyph-cache.c index 2e12afa10..e7bcc32ea 100644 --- a/kitty/glyph-cache.c +++ b/kitty/glyph-cache.c @@ -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; } diff --git a/kitty/glyph-cache.h b/kitty/glyph-cache.h index 1798c1949..1fda2a00c 100644 --- a/kitty/glyph-cache.h +++ b/kitty/glyph-cache.h @@ -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;