diff --git a/legacy/evas/src/lib/engines/common/evas_font_draw.c b/legacy/evas/src/lib/engines/common/evas_font_draw.c index f25f238102..5f106335d5 100644 --- a/legacy/evas/src/lib/engines/common/evas_font_draw.c +++ b/legacy/evas/src/lib/engines/common/evas_font_draw.c @@ -75,7 +75,7 @@ evas_common_font_draw_finish(void) #endif static void -_fash_int_free(Fash_Int *fash) +_fash_int2_free(Fash_Int_Map2 *fash) { int i; @@ -83,6 +83,15 @@ _fash_int_free(Fash_Int *fash) free(fash); } +static void +_fash_int_free(Fash_Int *fash) +{ + int i; + + for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_int2_free(fash->bucket[i]); + free(fash); +} + static Fash_Int * _fash_int_new(void) { @@ -94,27 +103,41 @@ _fash_int_new(void) static Fash_Item_Index_Map * _fash_int_find(Fash_Int *fash, int item) { - int maj, min; + int grp, maj, min; - item &= 0xffff; // fixme: to do > 65k + item &= 0xffffff; // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16) + grp = (item >> 16) & 0xff; maj = (item >> 8) & 0xff; min = item & 0xff; - if (!fash->bucket[maj]) return NULL; - return &(fash->bucket[maj]->item[min]); + if (!fash->bucket[grp]) return NULL; + if (!fash->bucket[grp]->bucket[maj]) return NULL; + return &(fash->bucket[grp]->bucket[maj]->item[min]); } static void _fash_int_add(Fash_Int *fash, int item, RGBA_Font_Int *fint, int index) { - int maj, min; + int grp, maj, min; - item &= 0xffff; // fixme: to do > 65k + item &= 0xffffff; // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16) + grp = (item >> 16) & 0xff; maj = (item >> 8) & 0xff; min = item & 0xff; - if (!fash->bucket[maj]) - fash->bucket[maj] = calloc(1, sizeof(Fash_Int_Map)); - fash->bucket[maj]->item[min].fint = fint; - fash->bucket[maj]->item[min].index = index; + if (!fash->bucket[grp]) + fash->bucket[grp] = calloc(1, sizeof(Fash_Int_Map2)); + if (!fash->bucket[grp]->bucket[maj]) + fash->bucket[grp]->bucket[maj] = calloc(1, sizeof(Fash_Int_Map)); + fash->bucket[grp]->bucket[maj]->item[min].fint = fint; + fash->bucket[grp]->bucket[maj]->item[min].index = index; +} + +static void +_fash_gl2_free(Fash_Glyph_Map2 *fash) +{ + int i; + + for (i = 0; i < 256; i++) if (fash->bucket[i]) free(fash->bucket[i]); + free(fash); } static void @@ -122,7 +145,7 @@ _fash_gl_free(Fash_Glyph *fash) { int i; - for (i = 0; i < 256; i++) if (fash->bucket[i]) free(fash->bucket[i]); + for (i = 0; i < 256; i++) if (fash->bucket[i]) _fash_gl2_free(fash->bucket[i]); free(fash); } @@ -137,26 +160,31 @@ _fash_gl_new(void) static RGBA_Font_Glyph * _fash_gl_find(Fash_Glyph *fash, int item) { - int maj, min; + int grp, maj, min; - item &= 0xffff; // fixme: to do > 65k + item &= 0xffffff; // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16) + grp = (item >> 16) & 0xff; maj = (item >> 8) & 0xff; min = item & 0xff; - if (!fash->bucket[maj]) return NULL; - return fash->bucket[maj]->item[min]; + if (!fash->bucket[grp]) return NULL; + if (!fash->bucket[grp]->bucket[maj]) return NULL; + return fash->bucket[grp]->bucket[maj]->item[min]; } static void _fash_gl_add(Fash_Glyph *fash, int item, RGBA_Font_Glyph *glyph) { - int maj, min; + int grp, maj, min; - item &= 0xffff; // fixme: to do > 65k + item &= 0xffffff; // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16) + grp = (item >> 16) & 0xff; maj = (item >> 8) & 0xff; min = item & 0xff; - if (!fash->bucket[maj]) - fash->bucket[maj] = calloc(1, sizeof(Fash_Int_Map)); - fash->bucket[maj]->item[min] = glyph; + if (!fash->bucket[grp]) + fash->bucket[grp] = calloc(1, sizeof(Fash_Glyph_Map2)); + if (!fash->bucket[grp]->bucket[maj]) + fash->bucket[grp]->bucket[maj] = calloc(1, sizeof(Fash_Glyph_Map)); + fash->bucket[grp]->bucket[maj]->item[min] = glyph; } EAPI RGBA_Font_Glyph * @@ -165,9 +193,11 @@ evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, FT_UInt index) RGBA_Font_Glyph *fg; FT_UInt hindex; FT_Error error; + int size; const FT_Int32 hintflags[3] = { FT_LOAD_NO_HINTING, FT_LOAD_FORCE_AUTOHINT, FT_LOAD_NO_AUTOHINT }; + evas_common_font_int_promote(fi); if (fi->fash) { fg = _fash_gl_find(fi->fash, index); @@ -180,6 +210,7 @@ evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, FT_UInt index) // fg = eina_hash_find(fi->glyphs, &hindex); // if (fg) return fg; + evas_common_font_int_reload(fi); FTLOCK(); // error = FT_Load_Glyph(fi->src->ft.face, index, FT_LOAD_NO_BITMAP); error = FT_Load_Glyph(fi->src->ft.face, index, @@ -227,6 +258,10 @@ evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, FT_UInt index) if (!fi->fash) fi->fash = _fash_gl_new(); if (fi->fash) _fash_gl_add(fi->fash, index, fg); + size = sizeof(RGBA_Font_Glyph) + sizeof(Eina_List) + + (fg->glyph_out->bitmap.width * fg->glyph_out->bitmap.rows) + 200; + fi->usage += size; + if (fi->inuse) evas_common_font_int_use_increase(size); // eina_hash_direct_add(fi->glyphs, &fg->index, fg); return fg; @@ -261,6 +296,7 @@ _evas_common_get_char_index(RGBA_Font_Int* fi, int gl) // return FT_Get_Char_Index(fi->src->ft.face, gl); // } + evas_common_font_int_reload(fi); FTLOCK(); result.index = FT_Get_Char_Index(fi->src->ft.face, gl); FTUNLOCK(); @@ -323,8 +359,9 @@ evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl) #endif if (!fi->src->ft.face) /* Charmap not loaded, FI/FS blank */ { - if (evas_common_font_source_load_complete(fi->src)) - return 0; + evas_common_font_int_reload(fi); +// if (evas_common_font_source_load_complete(fi->src)) +// return 0; #if 0 /* FIXME: disable this. this can eat a LOT of memory and in my tests with expedite at any rate shows no visible improvements */ /* index = FT_Get_Char_Index(fi->src->ft.face, gl); @@ -362,7 +399,7 @@ evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl) if (index != 0) { if (!fi->ft.size) - evas_common_font_int_load_complete(fi); + evas_common_font_int_load_complete(fi); if (!fn->fash) fn->fash = _fash_int_new(); if (fn->fash) _fash_int_add(fn->fash, gl, fi, index); *fi_ret = fi; @@ -697,6 +734,7 @@ evas_common_font_draw_internal(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font #ifdef BIDI_SUPPORT if (visual_text) free(visual_text); #endif + evas_common_font_int_use_trim(); } EAPI void @@ -746,6 +784,7 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int #ifdef EVAS_FRAME_QUEUING LKL(fn->lock); #endif + evas_common_font_int_reload(fi); // evas_common_font_size_use(fn); use_kerning = FT_HAS_KERNING(fi->src->ft.face); func = evas_common_gfx_func_composite_mask_color_span_get(dc->col.col, dst, 1, dc->render_op); diff --git a/legacy/evas/src/lib/engines/common/evas_font_load.c b/legacy/evas/src/lib/engines/common/evas_font_load.c index 8b579567b6..a3b56509c2 100644 --- a/legacy/evas/src/lib/engines/common/evas_font_load.c +++ b/legacy/evas/src/lib/engines/common/evas_font_load.c @@ -11,12 +11,12 @@ static int font_cache_usage = 0; static int font_cache = 0; static int font_dpi = 75; -static Eina_Hash * fonts_src = NULL; -static Eina_Hash * fonts = NULL; -static Eina_List * fonts_lru = NULL; +static Eina_Hash *fonts_src = NULL; +static Eina_Hash *fonts = NULL; +static Eina_List *fonts_lru = NULL; +static Eina_Inlist *fonts_use_lru = NULL; +static int fonts_use_usage = 0; -//static Eina_Bool font_modify_cache_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata); -//static Eina_Bool font_flush_free_glyph_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata); static void _evas_common_font_int_clear(RGBA_Font_Int *fi); static int @@ -33,10 +33,8 @@ static int _evas_font_cache_int_hash(const RGBA_Font_Int *key, int key_length __UNUSED__) { int hash; - hash = eina_hash_djb2(key->src->name, eina_stringshare_strlen(key->src->name) + 1); hash ^= eina_hash_int32(&key->size, sizeof (int)); - return hash; } @@ -46,55 +44,32 @@ _evas_common_font_source_free(RGBA_Font_Source *fs) FTLOCK(); FT_Done_Face(fs->ft.face); FTUNLOCK(); -#if 0 /* FIXME: Disable as it is only used by dead code using deprecated datatype. */ -// if (fs->charmap) evas_array_hash_free(fs->charmap); -#endif if (fs->name) eina_stringshare_del(fs->name); free(fs); } -/* -static Eina_Bool -font_flush_free_glyph_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata) -{ - RGBA_Font_Glyph *fg; - fg = data; - FTLOCK(); - FT_Done_Glyph(fg->glyph); - FTUNLOCK(); - // extension calls - if (fg->ext_dat_free) fg->ext_dat_free(fg->ext_dat); - free(fg); - return 1; - hash = 0; - key = 0; - fdata = 0; -} -*/ static void _evas_common_font_int_free(RGBA_Font_Int *fi) { FT_Done_Size(fi->ft.size); evas_common_font_int_modify_cache_by(fi, -1); - _evas_common_font_int_clear(fi); -// eina_hash_foreach(fi->glyphs, font_flush_free_glyph_cb, NULL); -// eina_hash_free(fi->glyphs); - eina_hash_free(fi->kerning); -// eina_hash_free(fi->indexes); #ifdef HAVE_PTHREAD pthread_mutex_destroy(&fi->ft_mutex); #endif - evas_common_font_source_free(fi->src); - - if (fi->references == 0) - fonts_lru = eina_list_remove(fonts_lru, fi); - + if (fi->references == 0) fonts_lru = eina_list_remove(fonts_lru, fi); if (fi->fash) fi->fash->freeme(fi->fash); + if (fi->inuse) + { + fonts_use_lru = eina_inlist_remove(fonts_use_lru, EINA_INLIST_GET(fi)); + fi->inuse = 0; + fonts_use_usage -= fi->usage; + fi->usage = 0; + } free(fi); } @@ -114,7 +89,6 @@ evas_common_font_load_shutdown(void) { eina_hash_free(fonts); fonts = NULL; - eina_hash_free(fonts_src); fonts_src = NULL; } @@ -128,11 +102,10 @@ evas_common_font_dpi_set(int dpi) EAPI RGBA_Font_Source * evas_common_font_source_memory_load(const char *name, const void *data, int data_size) { - int error; + int error; RGBA_Font_Source *fs; assert(name != NULL); - fs = calloc(1, sizeof(RGBA_Font_Source) + data_size); if (!fs) return NULL; fs->data = ((unsigned char *)fs) + sizeof(RGBA_Font_Source); @@ -151,10 +124,16 @@ evas_common_font_source_memory_load(const char *name, const void *data, int data fs->file = NULL; FTLOCK(); error = FT_Select_Charmap(fs->ft.face, ft_encoding_unicode); + if (error) + { + FT_Done_Face(fs->ft.face); + fs->ft.face = NULL; + free(fs); + return NULL; + } FTUNLOCK(); fs->ft.orig_upem = fs->ft.face->units_per_EM; fs->references = 1; - eina_hash_direct_add(fonts_src, fs->name, fs); return fs; } @@ -165,25 +144,54 @@ evas_common_font_source_load(const char *name) RGBA_Font_Source *fs; assert(name != NULL); - fs = calloc(1, sizeof(RGBA_Font_Source)); if (!fs) return NULL; fs->data = NULL; fs->data_size = 0; fs->current_size = 0; fs->ft.face = NULL; - fs->name = eina_stringshare_add(name); fs->file = fs->name; - fs->ft.orig_upem = 0; - fs->references = 1; - eina_hash_direct_add(fonts_src, fs->name, fs); return fs; } +void +evas_common_font_source_unload(RGBA_Font_Source *fs) +{ + FTLOCK(); + FT_Done_Face(fs->ft.face); + fs->ft.face = NULL; + FTUNLOCK(); +} + +void +evas_common_font_source_reload(RGBA_Font_Source *fs) +{ + if (fs->ft.face) return; + if (fs->data) + { + int error; + + FTLOCK(); + error = FT_New_Memory_Face(evas_ft_lib, fs->data, fs->data_size, 0, &(fs->ft.face)); + FTUNLOCK(); + if (error) return; + FTLOCK(); + error = FT_Select_Charmap(fs->ft.face, ft_encoding_unicode); + if (error) + { + FT_Done_Face(fs->ft.face); + fs->ft.face = NULL; + } + FTUNLOCK(); + } + else + evas_common_font_source_load_complete(fs); +} + EAPI int evas_common_font_source_load_complete(RGBA_Font_Source *fs) { @@ -197,16 +205,14 @@ evas_common_font_source_load_complete(RGBA_Font_Source *fs) fs->ft.face = NULL; return error; } - error = FT_Select_Charmap(fs->ft.face, ft_encoding_unicode); if (error) { FT_Done_Face(fs->ft.face); - FTUNLOCK(); + FTUNLOCK(); fs->ft.face = NULL; return error; } - FTUNLOCK(); fs->ft.orig_upem = fs->ft.face->units_per_EM; return error; @@ -232,7 +238,6 @@ evas_common_font_source_free(RGBA_Font_Source *fs) { fs->references--; if (fs->references > 0) return; - eina_hash_del(fonts_src, fs->name, fs); } @@ -246,49 +251,35 @@ evas_common_font_size_use(RGBA_Font *fn) { if (fi->src->current_size != fi->size) { - FTLOCK(); + evas_common_font_source_reload(fi->src); + FTLOCK(); FT_Activate_Size(fi->ft.size); - FTUNLOCK(); + FTUNLOCK(); fi->src->current_size = fi->size; } } } -//static int -//_evas_common_font_int_cmp(const int *key1, __UNUSED__ int key1_length, -// const int *key2, __UNUSED__ int key2_length) -//{ -// return *key1 - *key2; -//} - static int _evas_common_font_double_int_cmp(const int *key1, __UNUSED__ int key1_length, const int *key2, __UNUSED__ int key2_length) { - if (key1[0] - key2[0] == 0) - return key1[1] - key2[1]; + if (key1[0] - key2[0] == 0) return key1[1] - key2[1]; return key1[0] - key2[0]; } static int _evas_common_font_double_int_hash(const unsigned int key[2], int key_length) { - int tmp; - - tmp = eina_hash_int32(&key[0], key_length); - tmp ^= eina_hash_int32(&key[1], key_length); - - return tmp; + return + eina_hash_int32(&key[0], key_length) ^ + eina_hash_int32(&key[1], key_length); } static void _evas_common_font_int_cache_init(RGBA_Font_Int *fi) { /* Add some font kerning cache. */ -// fi->indexes = eina_hash_new(NULL, -// EINA_KEY_CMP(_evas_common_font_int_cmp), -// EINA_KEY_HASH(eina_hash_int32), -// free, 3); fi->kerning = eina_hash_new(NULL, EINA_KEY_CMP(_evas_common_font_double_int_cmp), EINA_KEY_HASH(_evas_common_font_double_int_hash), @@ -305,27 +296,19 @@ evas_common_font_int_memory_load(const char *name, int size, const void *data, i fi = evas_common_font_int_find(name, size); if (fi) return fi; - fi = calloc(1, sizeof(RGBA_Font_Int)); if (!fi) return NULL; - fi->src = evas_common_font_source_find(name); - if (!fi->src) - fi->src = evas_common_font_source_memory_load(name, data, data_size); - + if (!fi->src) fi->src = evas_common_font_source_memory_load(name, data, data_size); if (!fi->src) { free(fi); return NULL; } - fi->size = size; - _evas_common_font_int_cache_init(fi); - fi = evas_common_font_int_load_init(fi); evas_common_font_int_load_complete(fi); - return fi; } @@ -336,24 +319,18 @@ evas_common_font_int_load(const char *name, int size) fi = evas_common_font_int_find(name, size); if (fi) return fi; - fi = calloc(1, sizeof(RGBA_Font_Int)); if (!fi) return NULL; - fi->src = evas_common_font_source_find(name); if (!fi->src && evas_file_path_is_file(name)) fi->src = evas_common_font_source_load(name); - if (!fi->src) { free(fi); return NULL; } - fi->size = size; - _evas_common_font_int_cache_init(fi); - return evas_common_font_int_load_init(fi); } @@ -361,16 +338,8 @@ EAPI RGBA_Font_Int * evas_common_font_int_load_init(RGBA_Font_Int *fi) { fi->ft.size = NULL; -// fi->glyphs = eina_hash_new(NULL, -// EINA_KEY_CMP(_evas_common_font_int_cmp), -// EINA_KEY_HASH(eina_hash_int32), -// NULL, -// 6); - fi->usage = 0; fi->references = 1; - eina_hash_direct_add(fonts, fi, fi); - return fi; } @@ -419,38 +388,32 @@ evas_common_font_int_load_complete(RGBA_Font_Int *fi) if (d == 0) break; } fi->real_size = chosen_size; - FTLOCK(); + FTLOCK(); error = FT_Set_Pixel_Sizes(fi->src->ft.face, chosen_width, fi->real_size); - FTUNLOCK(); + FTUNLOCK(); if (error) { /* couldn't choose the size anyway... what now? */ } } fi->src->current_size = 0; - fi->max_h = 0; - val = (int)fi->src->ft.face->bbox.yMax; if (fi->src->ft.face->units_per_EM != 0) { dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM; ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv); } - else - ret = val; + else ret = val; fi->max_h += ret; - val = -(int)fi->src->ft.face->bbox.yMin; if (fi->src->ft.face->units_per_EM != 0) { dv = (fi->src->ft.orig_upem * 2048) / fi->src->ft.face->units_per_EM; ret = (val * fi->src->ft.face->size->metrics.y_scale) / (dv * dv); } - else - ret = val; + else ret = val; fi->max_h += ret; - return fi; } @@ -462,54 +425,6 @@ evas_common_font_memory_load(const char *name, int size, const void *data, int d fi = evas_common_font_int_memory_load(name, size, data, data_size); if (!fi) return NULL; - fn = calloc(1, sizeof(RGBA_Font)); - if (!fn) - { - free(fi); - return NULL; - } - fn->fonts = eina_list_append(fn->fonts, fi); - fn->hinting = FONT_BYTECODE_HINT; - fi->hinting = fn->hinting; - fn->references = 1; - LKI(fn->lock); -#ifdef EVAS_FRAME_QUEUING - LKI(fn->ref_fq_add); - LKI(fn->ref_fq_del); - pthread_cond_init(&(fn->cond_fq_del), NULL); -#endif - return fn; -} - -EAPI RGBA_Font * -evas_common_font_load(const char *name, int size) -{ - RGBA_Font *fn; - RGBA_Font_Int *fi; - - fi = evas_common_font_int_load(name, size); - if (!fi) return NULL; - - /* First font, complete load */ - if (!fi->ft.size) - { - if (!fi->src->ft.face) - { - if (evas_common_font_source_load_complete(fi->src)) - { - fi->references--; - if (fi->references == 0) - { - fonts_lru = eina_list_prepend(fonts_lru, fi); - evas_common_font_int_modify_cache_by(fi, 1); - evas_common_font_flush(); - } - return NULL; - } - } - evas_common_font_int_load_complete(fi); - } - fn = calloc(1, sizeof(RGBA_Font)); if (!fn) { @@ -532,6 +447,75 @@ evas_common_font_load(const char *name, int size) LKI(fn->ref_fq_del); pthread_cond_init(&(fn->cond_fq_del), NULL); #endif + if (fi->inuse) evas_common_font_int_promote(fi); + else + { + fi->inuse = 1; + fonts_use_lru = eina_inlist_prepend(fonts_use_lru, EINA_INLIST_GET(fi)); + } + return fn; +} + + +//ZZZ: font struct looks like: +// fn->(fi, fi, fi, ...) +// fi->fs + +EAPI RGBA_Font * +evas_common_font_load(const char *name, int size) +{ + RGBA_Font *fn; + RGBA_Font_Int *fi; + + fi = evas_common_font_int_load(name, size); + if (!fi) return NULL; + /* First font, complete load */ + if (!fi->ft.size) + { + if (!fi->src->ft.face) + { + if (evas_common_font_source_load_complete(fi->src)) + { + fi->references--; + if (fi->references == 0) + { + fonts_lru = eina_list_prepend(fonts_lru, fi); + evas_common_font_int_modify_cache_by(fi, 1); + evas_common_font_flush(); + } + return NULL; + } + } + evas_common_font_int_load_complete(fi); + } + fn = calloc(1, sizeof(RGBA_Font)); + if (!fn) + { + fi->references--; + if (fi->references == 0) + { + fonts_lru = eina_list_prepend(fonts_lru, fi); + evas_common_font_int_modify_cache_by(fi, 1); + evas_common_font_flush(); + } + return NULL; + } + fn->fonts = eina_list_append(fn->fonts, fi); + fn->hinting = FONT_BYTECODE_HINT; + fi->hinting = fn->hinting; + fn->references = 1; + LKI(fn->lock); +#ifdef EVAS_FRAME_QUEUING + LKI(fn->ref_fq_add); + LKI(fn->ref_fq_del); + pthread_cond_init(&(fn->cond_fq_del), NULL); +#endif + if (fi->inuse) evas_common_font_int_promote(fi); + else + { + fi->inuse = 1; + fonts_use_lru = eina_inlist_prepend(fonts_use_lru, EINA_INLIST_GET(fi)); + } return fn; } @@ -540,13 +524,18 @@ evas_common_font_add(RGBA_Font *fn, const char *name, int size) { RGBA_Font_Int *fi; - if (!fn) - return NULL; + if (!fn) return NULL; fi = evas_common_font_int_load(name, size); if (fi) { fn->fonts = eina_list_append(fn->fonts, fi); fi->hinting = fn->hinting; + if (fi->inuse) evas_common_font_int_promote(fi); + else + { + fi->inuse = 1; + fonts_use_lru = eina_inlist_prepend(fonts_use_lru, EINA_INLIST_GET(fi)); + } return fn; } return NULL; @@ -564,6 +553,12 @@ evas_common_font_memory_add(RGBA_Font *fn, const char *name, int size, const voi { fn->fonts = eina_list_append(fn->fonts, fi); fi->hinting = fn->hinting; + if (fi->inuse) evas_common_font_int_promote(fi); + else + { + fi->inuse = 1; + fonts_use_lru = eina_inlist_prepend(fonts_use_lru, EINA_INLIST_GET(fi)); + } return fn; } return NULL; @@ -590,7 +585,6 @@ evas_common_font_free(RGBA_Font *fn) LKU(fn->ref_fq_add); LKU(fn->ref_fq_del); #endif - EINA_LIST_FOREACH(fn->fonts, l, fi) { fi->references--; @@ -609,7 +603,6 @@ evas_common_font_free(RGBA_Font *fn) LKD(fn->ref_fq_del); pthread_cond_destroy(&(fn->cond_fq_del)); #endif - free(fn); } @@ -619,11 +612,12 @@ evas_common_font_hinting_set(RGBA_Font *fn, Font_Hint_Flags hinting) Eina_List *l; RGBA_Font_Int *fi; - if (!fn) - return; + if (!fn) return; fn->hinting = hinting; EINA_LIST_FOREACH(fn->fonts, l, fi) - fi->hinting = fn->hinting; + { + fi->hinting = fn->hinting; + } } EAPI Eina_Bool @@ -656,7 +650,6 @@ evas_common_hinting_available(Font_Hint_Flags hinting) return EINA_TRUE; #endif } - /* shouldn't get here - need to add another case statement */ return EINA_FALSE; } @@ -700,7 +693,7 @@ evas_common_font_memory_hinting_add(RGBA_Font *fn, const char *name, int size, c static void _evas_common_font_int_clear(RGBA_Font_Int *fi) { - int i, j; + int i, j, k; LKL(fi->ft_mutex); if (!fi->fash) @@ -708,30 +701,40 @@ _evas_common_font_int_clear(RGBA_Font_Int *fi) LKU(fi->ft_mutex); return; } - evas_common_font_int_modify_cache_by(fi, -1); - - for (j = 0; j <= 0xff; j++) // fixme: to do > 65k - { - Fash_Glyph_Map *fmap = fi->fash->bucket[j]; - if (fmap) - { - for (i = 0; i <= 0xff; i++) - { - RGBA_Font_Glyph *fg = fmap->item[i]; - if ((fg) && (fg != (void *)(-1))) + if (fi->fash) + { + for (k = 0; k <= 0xff; k++) // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16) + { + Fash_Glyph_Map2 *fmap2 = fi->fash->bucket[k]; + if (fmap2) + { + for (j = 0; j <= 0xff; j++) // 24bits for unicode - v6 up to E01EF (chrs) & 10FFFD for private use (plane 16) + { + Fash_Glyph_Map *fmap = fmap2->bucket[j]; + if (fmap) { - FT_Done_Glyph(fg->glyph); - /* extension calls */ - if (fg->ext_dat_free) fg->ext_dat_free(fg->ext_dat); - free(fg); - fmap->item[i] = NULL; + for (i = 0; i <= 0xff; i++) + { + RGBA_Font_Glyph *fg = fmap->item[i]; + if ((fg) && (fg != (void *)(-1))) + { + FT_Done_Glyph(fg->glyph); + /* extension calls */ + if (fg->ext_dat_free) fg->ext_dat_free(fg->ext_dat); + free(fg); + fmap->item[i] = NULL; + } + } } - } - } + } + } + } + fi->fash->freeme(fi->fash); + fi->fash = NULL; } - fi->fash->freeme(fi->fash); - fi->fash = NULL; + if (fi->inuse) fonts_use_usage -= fi->usage; + fi->usage = 0; LKU(fi->ft_mutex); } @@ -749,23 +752,63 @@ evas_common_font_all_clear(void) eina_hash_foreach(fonts, _evas_common_font_all_clear_cb, NULL); } -/* -static Eina_Bool -font_modify_cache_cb(const Eina_Hash *hash, const void *key, void *data, void *fdata) +void +evas_common_font_int_promote(RGBA_Font_Int *fi) { - int *dir; - RGBA_Font_Glyph *fg; - - fg = data; - dir = fdata; - font_cache_usage += (*dir) * - ((fg->glyph_out->bitmap.width * fg->glyph_out->bitmap.rows) + - sizeof(RGBA_Font_Glyph) + sizeof(Eina_List) + 400); // fudge values - return 1; - hash = 0; - key = 0; + return; + if (fonts_use_lru == (Eina_Inlist *)fi) return; + if (!fi->inuse) return; + fonts_use_lru = eina_inlist_remove(fonts_use_lru, EINA_INLIST_GET(fi)); + fonts_use_lru = eina_inlist_prepend(fonts_use_lru, EINA_INLIST_GET(fi)); } -*/ + +void +evas_common_font_int_use_increase(int size) +{ + fonts_use_usage += size; +} + +void +evas_common_font_int_use_trim(void) +{ + Eina_Inlist *l; + + return; + if (fonts_use_usage <= (font_cache << 1)) return; + if (!fonts_use_lru) return; + l = fonts_use_lru->last; + while (l) + { + RGBA_Font_Int *fi = (RGBA_Font_Int *)l; + if (fonts_use_usage <= (font_cache << 1)) break; + // FIXME: del fi->kerning content + _evas_common_font_int_clear(fi); + evas_common_font_int_unload(fi); + evas_common_font_int_promote(fi); + l = l->prev; + } +} + +void +evas_common_font_int_unload(RGBA_Font_Int *fi) +{ + return; + if (!fi->src->ft.face) return; + _evas_common_font_int_clear(fi); + FT_Done_Size(fi->ft.size); + fi->ft.size = NULL; + evas_common_font_source_unload(fi->src); +} + +void +evas_common_font_int_reload(RGBA_Font_Int *fi) +{ + return; + if (fi->src->ft.face) return; + evas_common_font_source_reload(fi->src); + evas_common_font_int_load_complete(fi); +} + /* when the fi->references == 0 we increase this instead of really deleting * we then check if the cache_useage size is larger than allowed * !If the cache is NOT too large we dont delete font_int @@ -773,33 +816,8 @@ font_modify_cache_cb(const Eina_Hash *hash, const void *key, void *data, void *f EAPI void evas_common_font_int_modify_cache_by(RGBA_Font_Int *fi, int dir) { - int sz_hash = 0; - int i, j; - - if (fi->fash) - { - for (j = 0; j <= 0xff; j++) // fixme: to do > 65k - { - Fash_Glyph_Map *fmap = fi->fash->bucket[j]; - if (fmap) - { - for (i = 0; i <= 0xff; i++) - { - RGBA_Font_Glyph *fg = fmap->item[i]; - if ((fg) && (fg != (void *)(-1))) - sz_hash += - sizeof(RGBA_Font_Glyph) + sizeof(Eina_List) + - (fg->glyph_out->bitmap.width * - fg->glyph_out->bitmap.rows) + - 400; - } - } - } - } -// if (fi->glyphs) sz_hash = eina_hash_population(fi->glyphs); -// eina_hash_foreach(fi->glyphs, font_modify_cache_cb, &dir); - font_cache_usage += dir * (sizeof(RGBA_Font) + sz_hash + - sizeof(FT_FaceRec) + 16384); /* fudge values */ + font_cache_usage += dir * (sizeof(RGBA_Font) + fi->usage + + sizeof(FT_FaceRec) + 16384); /* fudge values */ } EAPI int @@ -813,6 +831,7 @@ evas_common_font_cache_set(int size) { font_cache = size; evas_common_font_flush(); + evas_common_font_int_use_trim(); } EAPI void @@ -838,10 +857,8 @@ evas_common_font_flush_last(void) RGBA_Font_Int *fi = NULL; if (!fonts_lru) return ; - fi = eina_list_data_get(fonts_lru); fonts_lru = eina_list_remove_list(fonts_lru, fonts_lru); - eina_hash_del(fonts, fi, fi); } @@ -855,7 +872,6 @@ evas_common_font_int_find(const char *name, int size) tmp_fn.name = (char*) eina_stringshare_add(name); tmp_fi.src = &tmp_fn; tmp_fi.size = size; - fi = eina_hash_find(fonts, &tmp_fi); if (fi) { @@ -866,7 +882,6 @@ evas_common_font_int_find(const char *name, int size) } fi->references++; } - eina_stringshare_del(tmp_fn.name); return fi; } diff --git a/legacy/evas/src/lib/engines/common/evas_font_main.c b/legacy/evas/src/lib/engines/common/evas_font_main.c index 6beb412cc3..8a11a10e98 100644 --- a/legacy/evas/src/lib/engines/common/evas_font_main.c +++ b/legacy/evas/src/lib/engines/common/evas_font_main.c @@ -85,6 +85,7 @@ evas_common_font_ascent_get(RGBA_Font *fn) } #endif fi = fn->fonts->data; + evas_common_font_int_reload(fi); if (fi->src->current_size != fi->size) { FTLOCK(); @@ -114,6 +115,7 @@ evas_common_font_descent_get(RGBA_Font *fn) // evas_common_font_size_use(fn); fi = fn->fonts->data; + evas_common_font_int_reload(fi); if (fi->src->current_size != fi->size) { FTLOCK(); @@ -139,7 +141,8 @@ evas_common_font_max_ascent_get(RGBA_Font *fn) // evas_common_font_size_use(fn); fi = fn->fonts->data; - if (fi->src->current_size != fi->size) + evas_common_font_int_reload(fi); + if (fi->src->current_size != fi->size) { FTLOCK(); FT_Activate_Size(fi->ft.size); @@ -163,6 +166,7 @@ evas_common_font_max_descent_get(RGBA_Font *fn) // evas_common_font_size_use(fn); fi = fn->fonts->data; + evas_common_font_int_reload(fi); if (fi->src->current_size != fi->size) { FTLOCK(); @@ -186,6 +190,7 @@ evas_common_font_get_line_advance(RGBA_Font *fn) // evas_common_font_size_use(fn); fi = fn->fonts->data; + evas_common_font_int_reload(fi); if (fi->src->current_size != fi->size) { FTLOCK(); diff --git a/legacy/evas/src/lib/engines/common/evas_font_private.h b/legacy/evas/src/lib/engines/common/evas_font_private.h index 5bbb6979c4..57940ee49d 100644 --- a/legacy/evas/src/lib/engines/common/evas_font_private.h +++ b/legacy/evas/src/lib/engines/common/evas_font_private.h @@ -20,4 +20,13 @@ extern LK(lock_bidi); // for fribidi API calls # define BIDIUNLOCK() # endif +void evas_common_font_source_unload(RGBA_Font_Source *fs); +void evas_common_font_source_reload(RGBA_Font_Source *fs); + +void evas_common_font_int_promote(RGBA_Font_Int *fi); +void evas_common_font_int_use_increase(int size); +void evas_common_font_int_use_trim(void); +void evas_common_font_int_unload(RGBA_Font_Int *fi); +void evas_common_font_int_reload(RGBA_Font_Int *fi); + #endif /* !_EVAS_FONT_PRIVATE_H */ diff --git a/legacy/evas/src/lib/engines/common/evas_font_query.c b/legacy/evas/src/lib/engines/common/evas_font_query.c index 7fdfb2fca6..4fe45799ff 100644 --- a/legacy/evas/src/lib/engines/common/evas_font_query.c +++ b/legacy/evas/src/lib/engines/common/evas_font_query.c @@ -27,6 +27,7 @@ evas_common_font_query_kerning(RGBA_Font_Int* fi, * values to kern by - given same font, same size and same * prev_index and index. auto/bytecode or none hinting doesn't * matter */ + evas_common_font_int_reload(fi); FTLOCK(); if (FT_Get_Kerning(fi->src->ft.face, key[0], key[1], @@ -83,6 +84,7 @@ evas_common_font_query_size(RGBA_Font *fn, const Eina_Unicode *text, const Evas_ pen_x = 0; pen_y = 0; // evas_common_font_size_use(fn); + evas_common_font_int_reload(fi); use_kerning = FT_HAS_KERNING(fi->src->ft.face); prev_index = 0; for (chr = 0, char_index = 0; *text; text++, char_index ++) @@ -167,6 +169,7 @@ evas_common_font_query_size(RGBA_Font *fn, const Eina_Unicode *text, const Evas_ } if (w) *w = end_x - start_x; if (h) *h = evas_common_font_max_ascent_get(fn) + evas_common_font_max_descent_get(fn); + evas_common_font_int_use_trim(); } /* text x inset */ @@ -188,6 +191,7 @@ evas_common_font_query_inset(RGBA_Font *fn, const Eina_Unicode *text) // evas_common_font_size_use(fn); index = evas_common_font_glyph_search(fn, &fi, gl); LKL(fi->ft_mutex); + evas_common_font_int_reload(fi); if (fi->src->current_size != fi->size) { FTLOCK(); @@ -212,6 +216,7 @@ evas_common_font_query_inset(RGBA_Font *fn, const Eina_Unicode *text) (int)fi->src->ft.face->glyph->metrics.horiAdvance >> 6 ); */ + evas_common_font_int_use_trim(); return fg->glyph_out->left; } @@ -239,6 +244,7 @@ evas_common_font_query_advance(RGBA_Font *fn, const Eina_Unicode *text, const Ev pen_x = 0; pen_y = 0; // evas_common_font_size_use(fn); + evas_common_font_int_reload(fi); FTLOCK(); use_kerning = FT_HAS_KERNING(fi->src->ft.face); FTUNLOCK(); @@ -308,6 +314,7 @@ evas_common_font_query_advance(RGBA_Font *fn, const Eina_Unicode *text, const Ev #ifndef BIDI_SUPPORT intl_props = NULL; #endif + evas_common_font_int_use_trim(); } /* x y w h for char at char pos for null it returns the position right after @@ -358,6 +365,7 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const Eina_Unicode *in_text, c pen_x = 0; pen_y = 0; + evas_common_font_int_reload(fi); // evas_common_font_size_use(fn); if (fi->src->current_size != fi->size) { @@ -477,6 +485,7 @@ end: if (visual_text) free(visual_text); #endif + evas_common_font_int_use_trim(); return ret_val; } @@ -525,6 +534,7 @@ evas_common_font_query_char_at_coords(RGBA_Font *fn, const Eina_Unicode *in_text pen_x = 0; pen_y = 0; + evas_common_font_int_reload(fi); // evas_common_font_size_use(fn); if (fi->src->current_size != fi->size) { @@ -629,6 +639,7 @@ end: intl_props = NULL; #endif + evas_common_font_int_use_trim(); return ret_val; } @@ -657,6 +668,7 @@ evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const Eina_Unicode *in_text pen_x = 0; pen_y = 0; + evas_common_font_int_reload(fi); // evas_common_font_size_use(fn); use_kerning = FT_HAS_KERNING(fi->src->ft.face); prev_index = 0; @@ -745,5 +757,6 @@ evas_common_font_query_last_up_to_pos(RGBA_Font *fn, const Eina_Unicode *in_text } end: + evas_common_font_int_use_trim(); return ret; } diff --git a/legacy/evas/src/lib/include/evas_common.h b/legacy/evas/src/lib/include/evas_common.h index 1407eabba1..6168a9cdbc 100644 --- a/legacy/evas/src/lib/include/evas_common.h +++ b/legacy/evas/src/lib/include/evas_common.h @@ -773,8 +773,9 @@ struct _RGBA_Map_Point // for fonts... ///// typedef struct _Fash_Item_Index_Map Fash_Item_Index_Map; -typedef struct _Fash_Int_Map Fash_Int_Map; -typedef struct _Fash_Int Fash_Int; +typedef struct _Fash_Int_Map Fash_Int_Map; +typedef struct _Fash_Int_Map2 Fash_Int_Map2; +typedef struct _Fash_Int Fash_Int; struct _Fash_Item_Index_Map { RGBA_Font_Int *fint; @@ -784,85 +785,83 @@ struct _Fash_Int_Map { Fash_Item_Index_Map item[256]; }; -struct _Fash_Int +struct _Fash_Int_Map2 { Fash_Int_Map *bucket[256]; +}; +struct _Fash_Int +{ + Fash_Int_Map2 *bucket[256]; void (*freeme) (Fash_Int *fash); }; ///// -typedef struct _Fash_Glyph_Map Fash_Glyph_Map; -typedef struct _Fash_Glyph Fash_Glyph; +typedef struct _Fash_Glyph_Map Fash_Glyph_Map; +typedef struct _Fash_Glyph_Map2 Fash_Glyph_Map2; +typedef struct _Fash_Glyph Fash_Glyph; struct _Fash_Glyph_Map { RGBA_Font_Glyph *item[256]; }; -struct _Fash_Glyph +struct _Fash_Glyph_Map2 { Fash_Glyph_Map *bucket[256]; +}; +struct _Fash_Glyph +{ + Fash_Glyph_Map2 *bucket[256]; void (*freeme) (Fash_Glyph *fash); }; ///// struct _RGBA_Font { - Eina_List *fonts; - Font_Hint_Flags hinting; - int references; - Fash_Int *fash; - unsigned char sizeok : 1; - LK(lock); + Eina_List *fonts; + Fash_Int *fash; + Font_Hint_Flags hinting; + int references; #ifdef EVAS_FRAME_QUEUING + int ref_fq[2]; //ref_fq[0] is for addition, ref_fq[1] is for deletion + pthread_cond_t cond_fq_del; LK(ref_fq_add); LK(ref_fq_del); - pthread_cond_t cond_fq_del; - int ref_fq[2]; //ref_fq[0] is for addition, ref_fq[1] is for deletion #endif + LK(lock); + unsigned char sizeok : 1; }; struct _RGBA_Font_Int { + EINA_INLIST; RGBA_Font_Source *src; - + Eina_Hash *kerning; + Fash_Glyph *fash; unsigned int size; int real_size; int max_h; - + int references; + int usage; struct { FT_Size size; } ft; - -// Eina_Hash *glyphs; - LK(ft_mutex); - - Eina_Hash *kerning; -// Eina_Hash *indexes; - - int usage; - Font_Hint_Flags hinting; - - int references; - - Fash_Glyph *fash; - unsigned char sizeok : 1; + Font_Hint_Flags hinting; + unsigned char sizeok : 1; + unsigned char inuse : 1; }; struct _RGBA_Font_Source { const char *name; const char *file; - void *data; - int data_size; unsigned int current_size; - + int data_size; + int references; struct { - int orig_upem; - FT_Face face; + int orig_upem; + FT_Face face; } ft; - - int references; }; struct _RGBA_Font_Glyph