Use uthash for glyph properties as well

This commit is contained in:
Kovid Goyal 2021-05-06 13:25:09 +05:30
parent ec68739585
commit 26e1d6fe5c
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 46 additions and 48 deletions

View File

@ -23,7 +23,6 @@ send_sprite_to_gpu_func current_send_sprite_to_gpu = NULL;
static PyObject *python_send_to_gpu_impl = NULL; static PyObject *python_send_to_gpu_impl = NULL;
extern PyTypeObject Line_Type; extern PyTypeObject Line_Type;
typedef struct SpecialGlyphCache SpecialGlyphCache;
enum {NO_FONT=-3, MISSING_FONT=-2, BLANK_FONT=-1, BOX_FONT=0}; enum {NO_FONT=-3, MISSING_FONT=-2, BLANK_FONT=-1, BOX_FONT=0};
typedef enum { typedef enum {
LIGATURE_UNKNOWN, INFINITE_LIGATURE_START, INFINITE_LIGATURE_MIDDLE, INFINITE_LIGATURE_END LIGATURE_UNKNOWN, INFINITE_LIGATURE_START, INFINITE_LIGATURE_MIDDLE, INFINITE_LIGATURE_END
@ -38,13 +37,6 @@ typedef struct {
#define SPECIAL_VALUE_MASK 2 #define SPECIAL_VALUE_MASK 2
#define EMPTY_FILLED_MASK 4 #define EMPTY_FILLED_MASK 4
#define EMPTY_VALUE_MASK 8 #define EMPTY_VALUE_MASK 8
#define SPECIAL_GLYPH_CACHE_SIZE 1024
struct SpecialGlyphCache {
SpecialGlyphCache *next;
glyph_index glyph;
uint8_t data;
};
typedef struct { typedef struct {
size_t max_y; size_t max_y;
@ -75,7 +67,7 @@ typedef struct {
SpritePosition *sprite_position_hash_table; SpritePosition *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;
SpecialGlyphCache special_glyph_cache[SPECIAL_GLYPH_CACHE_SIZE]; GlyphProperties *glyph_properties_hash_table;
bool bold, italic, emoji_presentation; bool bold, italic, emoji_presentation;
SpacerStrategy spacer_strategy; SpacerStrategy spacer_strategy;
} Font; } Font;
@ -130,22 +122,10 @@ font_group_is_unused(FontGroup *fg) {
void void
free_maps(Font *font) { free_maps(Font *font) {
#define free_a_map(type, attr) {\
type *s, *t; \
for (size_t i = 0; i < sizeof(font->attr)/sizeof(font->attr[0]); i++) { \
s = font->attr[i].next; \
while (s) { \
t = s; \
s = s->next; \
free(t); \
} \
}\
memset(font->attr, 0, sizeof(font->attr)); \
}
free_sprite_position_hash_table(&font->sprite_position_hash_table); free_sprite_position_hash_table(&font->sprite_position_hash_table);
font->sprite_position_hash_table = NULL; font->sprite_position_hash_table = NULL;
free_a_map(SpecialGlyphCache, special_glyph_cache); free_glyph_properties_hash_table(&font->glyph_properties_hash_table);
#undef free_a_map font->glyph_properties_hash_table = NULL;
} }
static inline void static inline void
@ -267,28 +247,6 @@ sprite_position_for(FontGroup *fg, Font *font, glyph_index glyph, ExtraGlyphs *e
return s; return s;
} }
static inline SpecialGlyphCache*
special_glyph_cache_for(Font *font, glyph_index glyph, uint8_t filled_mask) {
SpecialGlyphCache *s = font->special_glyph_cache + (glyph & 0x3ff);
// Optimize for the common case of glyph under SPECIAL_GLYPH_CACHE_SIZE already in the cache
if (LIKELY(s->glyph == glyph && s->data & filled_mask)) return s; // Cache hit
while(true) {
if (s->data & filled_mask) {
if (s->glyph == glyph) return s; // Cache hit
} else {
if (!s->glyph) break; // Empty cache slot
else if (s->glyph == glyph) return s; // Cache slot that contains other data than the data indicated by filled_mask
}
if (!s->next) {
s->next = calloc(1, sizeof(SpecialGlyphCache));
if (s->next == NULL) return NULL;
}
s = s->next;
}
s->glyph = glyph;
return s;
}
void void
sprite_tracker_current_layout(FONTS_DATA_HANDLE data, unsigned int *x, unsigned int *y, unsigned int *z) { sprite_tracker_current_layout(FONTS_DATA_HANDLE data, unsigned int *x, unsigned int *y, unsigned int *z) {
FontGroup *fg = (FontGroup*)data; FontGroup *fg = (FontGroup*)data;
@ -778,7 +736,7 @@ static inline 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
SpecialGlyphCache *s = special_glyph_cache_for(font, glyph_id, SPECIAL_FILLED_MASK); GlyphProperties *s = find_or_create_glyph_properties(&font->glyph_properties_hash_table, glyph_id);
if (s == NULL) return false; if (s == NULL) return false;
if (!(s->data & SPECIAL_FILLED_MASK)) { if (!(s->data & SPECIAL_FILLED_MASK)) {
bool is_special = cell_data->current_codepoint ? ( bool is_special = cell_data->current_codepoint ? (
@ -794,7 +752,7 @@ is_special_glyph(glyph_index glyph_id, Font *font, CellData* cell_data) {
static inline bool static inline 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
SpecialGlyphCache *s = special_glyph_cache_for(font, glyph_id, EMPTY_FILLED_MASK); GlyphProperties *s = find_or_create_glyph_properties(&font->glyph_properties_hash_table, glyph_id);
if (s == NULL) return false; if (s == NULL) return false;
if (!(s->data & EMPTY_FILLED_MASK)) { if (!(s->data & EMPTY_FILLED_MASK)) {
uint8_t val = is_glyph_empty(font->face, glyph_id) ? EMPTY_VALUE_MASK : 0; uint8_t val = is_glyph_empty(font->face, glyph_id) ? EMPTY_VALUE_MASK : 0;

View File

@ -61,3 +61,31 @@ free_sprite_position_hash_table(SpritePosition **head_) {
free(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);
}
}

View File

@ -8,6 +8,8 @@
#include "data-types.h" #include "data-types.h"
void free_glyph_cache_global_resources(void);
#define SpritePositionHead \ #define SpritePositionHead \
bool rendered, colored; \ bool rendered, colored; \
sprite_index x, y, z; \ sprite_index x, y, z; \
@ -17,7 +19,17 @@ typedef struct SpritePosition {
} SpritePosition; } SpritePosition;
void free_glyph_cache_global_resources(void);
void free_sprite_position_hash_table(SpritePosition **head); void free_sprite_position_hash_table(SpritePosition **head);
SpritePosition* 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, bool *created);
#define GlyphPropertiesHead \
uint8_t data;
typedef struct GlyphProperties {
GlyphPropertiesHead
} GlyphProperties;
void free_glyph_properties_hash_table(GlyphProperties **head);
GlyphProperties*
find_or_create_glyph_properties(GlyphProperties **head, unsigned glyph);