Migrate glyph properties hash table to verstable

This commit is contained in:
Kovid Goyal
2024-07-09 10:26:42 +05:30
parent 94ebc972ce
commit 9727ea1cac
3 changed files with 71 additions and 52 deletions

View File

@@ -28,11 +28,6 @@ typedef enum {
} LigatureType; } LigatureType;
#define SPECIAL_FILLED_MASK 1
#define SPECIAL_VALUE_MASK 2
#define EMPTY_FILLED_MASK 4
#define EMPTY_VALUE_MASK 8
typedef struct { typedef struct {
size_t max_y; size_t max_y;
unsigned int x, y, z, xnum, ynum; unsigned int x, y, z, xnum, ynum;
@@ -61,7 +56,7 @@ typedef struct {
SPRITE_POSITION_MAP_HANDLE sprite_position_hash_table; SPRITE_POSITION_MAP_HANDLE sprite_position_hash_table;
hb_feature_t* ffs_hb_features; hb_feature_t* ffs_hb_features;
size_t num_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; bool bold, italic, emoji_presentation;
SpacerStrategy spacer_strategy; SpacerStrategy spacer_strategy;
} Font; } Font;
@@ -354,12 +349,20 @@ create_features_for_face(const char *psname, PyObject *features, FontFeatures *o
return true; 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 static bool
init_font(Font *f, PyObject *face, bool bold, bool italic, bool emoji_presentation) { init_font(Font *f, PyObject *face, bool bold, bool italic, bool emoji_presentation) {
f->face = face; Py_INCREF(f->face); f->face = face; Py_INCREF(f->face);
f->bold = bold; f->italic = italic; f->emoji_presentation = emoji_presentation; f->bold = bold; f->italic = italic; f->emoji_presentation = emoji_presentation;
f->sprite_position_hash_table = create_sprite_position_hash_table(); if (!init_hash_tables(f)) return false;
if (!f->sprite_position_hash_table) { PyErr_NoMemory(); return false; }
const FontFeatures *features = features_for_face(face); const FontFeatures *features = features_for_face(face);
f->ffs_hb_features = calloc(1 + features->count, sizeof(hb_feature_t)); f->ffs_hb_features = calloc(1 + features->count, sizeof(hb_feature_t));
if (!f->ffs_hb_features) { PyErr_NoMemory(); return false; } 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) { is_special_glyph(glyph_index glyph_id, Font *font, CellData* cell_data) {
// A glyph is special if the codepoint it corresponds to matches a // A glyph is special if the codepoint it corresponds to matches a
// different glyph in the font // different glyph in the font
GlyphProperties *s = find_or_create_glyph_properties(&font->glyph_properties_hash_table, glyph_id); GlyphProperties s = find_glyph_properties(font->glyph_properties_hash_table, glyph_id);
if (s == NULL) return false; if (!s.special_set) {
if (!(s->data & SPECIAL_FILLED_MASK)) {
bool is_special = cell_data->current_codepoint ? ( bool is_special = cell_data->current_codepoint ? (
glyph_id != glyph_id_for_codepoint(font->face, cell_data->current_codepoint) ? true : false) glyph_id != glyph_id_for_codepoint(font->face, cell_data->current_codepoint) ? true : false)
: :
false; false;
uint8_t val = is_special ? SPECIAL_VALUE_MASK : 0; s.special_set = 1; s.special_val = is_special;
s->data |= val | SPECIAL_FILLED_MASK; set_glyph_properties(font->glyph_properties_hash_table, glyph_id, s);
} }
return s->data & SPECIAL_VALUE_MASK; return s.special_val;
} }
static bool static bool
is_empty_glyph(glyph_index glyph_id, Font *font) { is_empty_glyph(glyph_index glyph_id, Font *font) {
// A glyph is empty if its metrics have a width of zero // 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); GlyphProperties s = find_glyph_properties(font->glyph_properties_hash_table, glyph_id);
if (s == NULL) return false; if (!s.empty_set) {
if (!(s->data & EMPTY_FILLED_MASK)) { s.empty_val = is_glyph_empty(font->face, glyph_id) ? 1 : 0;
uint8_t val = is_glyph_empty(font->face, glyph_id) ? EMPTY_VALUE_MASK : 0; s.empty_set = 1;
s->data |= val | EMPTY_FILLED_MASK; set_glyph_properties(font->glyph_properties_hash_table, glyph_id, s);
} }
return s->data & EMPTY_VALUE_MASK; return s.empty_val;
} }
static unsigned int static unsigned int
@@ -1278,7 +1280,7 @@ test_shape(PyObject UNUSED *self, PyObject *args) {
if (face == NULL) return NULL; if (face == NULL) return NULL;
font = calloc(1, sizeof(Font)); font = calloc(1, sizeof(Font));
font->face = face; font->face = face;
font->sprite_position_hash_table = create_sprite_position_hash_table(); if (!init_hash_tables(font)) return NULL;
} else { } else {
FontGroup *fg = font_groups; FontGroup *fg = font_groups;
font = fg->fonts + fg->medium_font_idx; 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"); 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_count = 1; // the 0 index font is the box font
fg->fonts[0].sprite_position_hash_table = create_sprite_position_hash_table(); 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; #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"); fg->medium_font_idx = initialize_font(fg, 0, "medium");
I(bold); I(italic); I(bi); I(bold); I(italic); I(bi);

View File

@@ -84,36 +84,42 @@ void
free_sprite_position_hash_table(SPRITE_POSITION_MAP_HANDLE *map) { free_sprite_position_hash_table(SPRITE_POSITION_MAP_HANDLE *map) {
sprite_pos_map **mapref = (sprite_pos_map**)map; sprite_pos_map **mapref = (sprite_pos_map**)map;
if (*mapref) { if (*mapref) {
vt_cleanup(*mapref); *mapref = NULL; vt_cleanup(*mapref); free(*mapref); *mapref = NULL;
} }
} }
#include "kitty-uthash.h"
typedef struct GlyphPropertiesItem { #define NAME glyph_props_map
GlyphPropertiesHead #define KEY_TY glyph_index
UT_hash_handle hh; #define VAL_TY GlyphProperties
unsigned key; #include "kitty-verstable.h"
} GlyphPropertiesItem;
GLYPH_PROPERTIES_MAP_HANDLE
GlyphProperties* create_glyph_properties_hash_table(void) {
find_or_create_glyph_properties(GlyphProperties **head_, unsigned glyph) { glyph_props_map *ans = calloc(1, sizeof(glyph_props_map));
GlyphPropertiesItem **head = (GlyphPropertiesItem**)head_, *p; if (ans) vt_init(ans);
HASH_FIND_INT(*head, &glyph, p); return (GLYPH_PROPERTIES_MAP_HANDLE)ans;
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;
} }
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 void
free_glyph_properties_hash_table(GlyphProperties **head_) { free_glyph_properties_hash_table(GLYPH_PROPERTIES_MAP_HANDLE *map_) {
GlyphPropertiesItem **head = (GlyphPropertiesItem**)head_, *s, *tmp; glyph_props_map **mapref = (glyph_props_map**)map_;
HASH_ITER(hh, *head, s, tmp) { if (*mapref) {
HASH_DEL(*head, s); vt_clear(*mapref); free(*mapref); *mapref = NULL;
free(s);
} }
} }

View File

@@ -24,13 +24,24 @@ free_sprite_position_hash_table(SPRITE_POSITION_MAP_HANDLE *handle);
SpritePosition* 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); 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 { typedef union GlyphProperties {
GlyphPropertiesHead 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; } GlyphProperties;
void free_glyph_properties_hash_table(GlyphProperties **head); typedef struct {int x;} *GLYPH_PROPERTIES_MAP_HANDLE;
GlyphProperties*
find_or_create_glyph_properties(GlyphProperties **head, unsigned glyph); 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);