kitty/kitty/glyph-cache.c
Kovid Goyal 9d3a2cc219
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
2021-06-16 18:41:01 +05:30

92 lines
2.5 KiB
C

/*
* glyph-cache.c
* Copyright (C) 2021 Kovid Goyal <kovid at kovidgoyal.net>
*
* Distributed under terms of the GPL3 license.
*/
#include "glyph-cache.h"
#include "kitty-uthash.h"
typedef struct SpritePosItem {
SpritePositionHead
UT_hash_handle hh;
glyph_index key[];
} SpritePosItem;
static glyph_index *scratch = NULL;
static unsigned scratch_sz = 0;
void
free_glyph_cache_global_resources(void) {
free(scratch);
scratch = NULL; scratch_sz = 0;
}
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, 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) {
scratch = realloc(scratch, sizeof(glyph_index) * (key_sz + 16));
if (!scratch) return NULL;
scratch_sz = key_sz + 16;
}
const unsigned key_sz_bytes = key_sz * 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; }
p = calloc(1, sizeof(SpritePosItem) + key_sz_bytes);
if (!p) return NULL;
memcpy(p->key, scratch, key_sz_bytes);
HASH_ADD(hh, *head, key, key_sz_bytes, p);
*created = true;
return (SpritePosition*)p;
}
void
free_sprite_position_hash_table(SpritePosition **head_) {
SpritePosItem **head = (SpritePosItem**)head_, *s, *tmp;
HASH_ITER(hh, *head, s, tmp) {
HASH_DEL(*head, s);
free(s);
}
}
typedef struct GlyphPropertiesItem {
GlyphPropertiesHead
UT_hash_handle hh;
unsigned key;
} GlyphPropertiesItem;
GlyphProperties*
find_or_create_glyph_properties(GlyphProperties **head_, unsigned glyph) {
GlyphPropertiesItem **head = (GlyphPropertiesItem**)head_, *p;
HASH_FIND_INT(*head, &glyph, p);
if (p) return (GlyphProperties*)p;
p = calloc(1, sizeof(GlyphPropertiesItem));
if (!p) return NULL;
p->key = glyph;
HASH_ADD_INT(*head, key, p);
return (GlyphProperties*)p;
}
void
free_glyph_properties_hash_table(GlyphProperties **head_) {
GlyphPropertiesItem **head = (GlyphPropertiesItem**)head_, *s, *tmp;
HASH_ITER(hh, *head, s, tmp) {
HASH_DEL(*head, s);
free(s);
}
}