From 9727ea1cac959578708f9055277ccc960d1fe356 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 9 Jul 2024 10:26:42 +0530 Subject: [PATCH] Migrate glyph properties hash table to verstable --- kitty/fonts.c | 46 ++++++++++++++++++++------------------- kitty/glyph-cache.c | 52 +++++++++++++++++++++++++-------------------- kitty/glyph-cache.h | 25 ++++++++++++++++------ 3 files changed, 71 insertions(+), 52 deletions(-) diff --git a/kitty/fonts.c b/kitty/fonts.c index b10a94e51..347337efd 100644 --- a/kitty/fonts.c +++ b/kitty/fonts.c @@ -28,11 +28,6 @@ typedef enum { } LigatureType; -#define SPECIAL_FILLED_MASK 1 -#define SPECIAL_VALUE_MASK 2 -#define EMPTY_FILLED_MASK 4 -#define EMPTY_VALUE_MASK 8 - typedef struct { size_t max_y; unsigned int x, y, z, xnum, ynum; @@ -61,7 +56,7 @@ typedef struct { SPRITE_POSITION_MAP_HANDLE sprite_position_hash_table; hb_feature_t* ffs_hb_features; size_t num_ffs_hb_features; - GlyphProperties *glyph_properties_hash_table; + GLYPH_PROPERTIES_MAP_HANDLE glyph_properties_hash_table; bool bold, italic, emoji_presentation; SpacerStrategy spacer_strategy; } Font; @@ -354,12 +349,20 @@ create_features_for_face(const char *psname, PyObject *features, FontFeatures *o return true; } +static bool +init_hash_tables(Font *f) { + f->sprite_position_hash_table = create_sprite_position_hash_table(); + if (!f->sprite_position_hash_table) { PyErr_NoMemory(); return false; } + f->glyph_properties_hash_table = create_glyph_properties_hash_table(); + if (!f->glyph_properties_hash_table) { PyErr_NoMemory(); return false; } + return true; +} + static bool init_font(Font *f, PyObject *face, bool bold, bool italic, bool emoji_presentation) { f->face = face; Py_INCREF(f->face); f->bold = bold; f->italic = italic; f->emoji_presentation = emoji_presentation; - f->sprite_position_hash_table = create_sprite_position_hash_table(); - if (!f->sprite_position_hash_table) { PyErr_NoMemory(); return false; } + if (!init_hash_tables(f)) return false; const FontFeatures *features = features_for_face(face); f->ffs_hb_features = calloc(1 + features->count, sizeof(hb_feature_t)); if (!f->ffs_hb_features) { PyErr_NoMemory(); return false; } @@ -863,29 +866,28 @@ static bool is_special_glyph(glyph_index glyph_id, Font *font, CellData* cell_data) { // A glyph is special if the codepoint it corresponds to matches a // different glyph in the font - GlyphProperties *s = find_or_create_glyph_properties(&font->glyph_properties_hash_table, glyph_id); - if (s == NULL) return false; - if (!(s->data & SPECIAL_FILLED_MASK)) { + GlyphProperties s = find_glyph_properties(font->glyph_properties_hash_table, glyph_id); + if (!s.special_set) { bool is_special = cell_data->current_codepoint ? ( glyph_id != glyph_id_for_codepoint(font->face, cell_data->current_codepoint) ? true : false) : false; - uint8_t val = is_special ? SPECIAL_VALUE_MASK : 0; - s->data |= val | SPECIAL_FILLED_MASK; + s.special_set = 1; s.special_val = is_special; + set_glyph_properties(font->glyph_properties_hash_table, glyph_id, s); } - return s->data & SPECIAL_VALUE_MASK; + return s.special_val; } static bool is_empty_glyph(glyph_index glyph_id, Font *font) { // A glyph is empty if its metrics have a width of zero - GlyphProperties *s = find_or_create_glyph_properties(&font->glyph_properties_hash_table, glyph_id); - if (s == NULL) return false; - if (!(s->data & EMPTY_FILLED_MASK)) { - uint8_t val = is_glyph_empty(font->face, glyph_id) ? EMPTY_VALUE_MASK : 0; - s->data |= val | EMPTY_FILLED_MASK; + GlyphProperties s = find_glyph_properties(font->glyph_properties_hash_table, glyph_id); + if (!s.empty_set) { + s.empty_val = is_glyph_empty(font->face, glyph_id) ? 1 : 0; + s.empty_set = 1; + set_glyph_properties(font->glyph_properties_hash_table, glyph_id, s); } - return s->data & EMPTY_VALUE_MASK; + return s.empty_val; } static unsigned int @@ -1278,7 +1280,7 @@ test_shape(PyObject UNUSED *self, PyObject *args) { if (face == NULL) return NULL; font = calloc(1, sizeof(Font)); font->face = face; - font->sprite_position_hash_table = create_sprite_position_hash_table(); + if (!init_hash_tables(font)) return NULL; } else { FontGroup *fg = font_groups; font = fg->fonts + fg->medium_font_idx; @@ -1539,7 +1541,7 @@ initialize_font_group(FontGroup *fg) { if (fg->fonts == NULL) fatal("Out of memory allocating fonts array"); fg->fonts_count = 1; // the 0 index font is the box font fg->fonts[0].sprite_position_hash_table = create_sprite_position_hash_table(); - if (!fg->fonts[0].sprite_position_hash_table) fatal("Out of memory"); + if (!init_hash_tables(fg->fonts)) fatal("Out of memory"); #define I(attr) if (descriptor_indices.attr) fg->attr##_font_idx = initialize_font(fg, descriptor_indices.attr, #attr); else fg->attr##_font_idx = -1; fg->medium_font_idx = initialize_font(fg, 0, "medium"); I(bold); I(italic); I(bi); diff --git a/kitty/glyph-cache.c b/kitty/glyph-cache.c index 982223f9b..6d45371a7 100644 --- a/kitty/glyph-cache.c +++ b/kitty/glyph-cache.c @@ -84,36 +84,42 @@ void free_sprite_position_hash_table(SPRITE_POSITION_MAP_HANDLE *map) { sprite_pos_map **mapref = (sprite_pos_map**)map; if (*mapref) { - vt_cleanup(*mapref); *mapref = NULL; + vt_cleanup(*mapref); free(*mapref); *mapref = NULL; } } -#include "kitty-uthash.h" -typedef struct GlyphPropertiesItem { - GlyphPropertiesHead - UT_hash_handle hh; - unsigned key; -} GlyphPropertiesItem; +#define NAME glyph_props_map +#define KEY_TY glyph_index +#define VAL_TY GlyphProperties +#include "kitty-verstable.h" - -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; +GLYPH_PROPERTIES_MAP_HANDLE +create_glyph_properties_hash_table(void) { + glyph_props_map *ans = calloc(1, sizeof(glyph_props_map)); + if (ans) vt_init(ans); + return (GLYPH_PROPERTIES_MAP_HANDLE)ans; } +GlyphProperties +find_glyph_properties(GLYPH_PROPERTIES_MAP_HANDLE map_, glyph_index glyph) { + glyph_props_map *map = (glyph_props_map*)map_; + glyph_props_map_itr n = vt_get(map, glyph); + if (vt_is_end(n)) return (GlyphProperties){0}; + return n.data->val; +} + +bool +set_glyph_properties(GLYPH_PROPERTIES_MAP_HANDLE map_, glyph_index glyph, GlyphProperties val) { + glyph_props_map *map = (glyph_props_map*)map_; + return !vt_is_end(vt_insert(map, glyph, val)); +} + + 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); +free_glyph_properties_hash_table(GLYPH_PROPERTIES_MAP_HANDLE *map_) { + glyph_props_map **mapref = (glyph_props_map**)map_; + if (*mapref) { + vt_clear(*mapref); free(*mapref); *mapref = NULL; } } diff --git a/kitty/glyph-cache.h b/kitty/glyph-cache.h index 5ed910806..7b70438cb 100644 --- a/kitty/glyph-cache.h +++ b/kitty/glyph-cache.h @@ -24,13 +24,24 @@ free_sprite_position_hash_table(SPRITE_POSITION_MAP_HANDLE *handle); SpritePosition* find_or_create_sprite_position(SPRITE_POSITION_MAP_HANDLE map, glyph_index *glyphs, glyph_index count, glyph_index ligature_index, glyph_index cell_count, bool *created); -#define GlyphPropertiesHead \ - uint8_t data; -typedef struct GlyphProperties { - GlyphPropertiesHead +typedef union GlyphProperties { + struct { + uint8_t special_set : 1; + uint8_t special_val : 1; + uint8_t empty_set : 1; + uint8_t empty_val : 1; + }; + uint8_t val; } GlyphProperties; -void free_glyph_properties_hash_table(GlyphProperties **head); -GlyphProperties* -find_or_create_glyph_properties(GlyphProperties **head, unsigned glyph); +typedef struct {int x;} *GLYPH_PROPERTIES_MAP_HANDLE; + +GLYPH_PROPERTIES_MAP_HANDLE +create_glyph_properties_hash_table(void); + +void free_glyph_properties_hash_table(GLYPH_PROPERTIES_MAP_HANDLE *handle); +GlyphProperties +find_glyph_properties(GLYPH_PROPERTIES_MAP_HANDLE map, glyph_index glyph); +bool +set_glyph_properties(GLYPH_PROPERTIES_MAP_HANDLE map, glyph_index glyph, GlyphProperties val);