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
92 lines
2.5 KiB
C
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);
|
|
}
|
|
}
|