work on fixing up a font "leak". its disabled via returns in funcs -

but also added in 24bit unicode support. needed for unicode v6
absolutely.. so we can have the pile of poo char work.



SVN revision: 53987
This commit is contained in:
Carsten Haitzler 2010-10-29 12:55:42 +00:00
parent 9b279fa367
commit e0e6020902
6 changed files with 370 additions and 290 deletions

View File

@ -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);
@ -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);

View File

@ -14,9 +14,9 @@ static int font_dpi = 75;
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;
}
@ -132,7 +106,6 @@ evas_common_font_source_memory_load(const char *name, const void *data, int data
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,7 +205,6 @@ 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)
{
@ -206,7 +213,6 @@ evas_common_font_source_load_complete(RGBA_Font_Source *fs)
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,6 +251,7 @@ evas_common_font_size_use(RGBA_Font *fn)
{
if (fi->src->current_size != fi->size)
{
evas_common_font_source_reload(fi->src);
FTLOCK();
FT_Activate_Size(fi->ft.size);
FTUNLOCK();
@ -254,41 +260,26 @@ evas_common_font_size_use(RGBA_Font *fn)
}
}
//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;
}
@ -428,29 +397,23 @@ evas_common_font_int_load_complete(RGBA_Font_Int *fi)
}
}
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;
}
@ -465,7 +428,13 @@ evas_common_font_memory_load(const char *name, int size, const void *data, int d
fn = calloc(1, sizeof(RGBA_Font));
if (!fn)
{
free(fi);
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);
@ -478,9 +447,20 @@ evas_common_font_memory_load(const char *name, int size, const void *data, int d
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)
{
@ -489,7 +469,6 @@ evas_common_font_load(const char *name, int size)
fi = evas_common_font_int_load(name, size);
if (!fi) return NULL;
/* First font, complete load */
if (!fi->ft.size)
{
@ -509,7 +488,6 @@ evas_common_font_load(const char *name, int size)
}
evas_common_font_int_load_complete(fi);
}
fn = calloc(1, sizeof(RGBA_Font));
if (!fn)
{
@ -532,6 +510,12 @@ 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;
}
@ -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,12 +612,13 @@ 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;
}
}
EAPI Eina_Bool
evas_common_hinting_available(Font_Hint_Flags hinting)
@ -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,12 +701,17 @@ _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
if (fi->fash)
{
Fash_Glyph_Map *fmap = fi->fash->bucket[j];
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)
{
for (i = 0; i <= 0xff; i++)
@ -730,8 +728,13 @@ _evas_common_font_int_clear(RGBA_Font_Int *fi)
}
}
}
}
}
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,32 +816,7 @@ 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 +
font_cache_usage += dir * (sizeof(RGBA_Font) + fi->usage +
sizeof(FT_FaceRec) + 16384); /* fudge values */
}
@ -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;
}

View File

@ -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,6 +141,7 @@ evas_common_font_max_ascent_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();
@ -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();

View File

@ -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 */

View File

@ -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;
}

View File

@ -774,6 +774,7 @@ struct _RGBA_Map_Point
/////
typedef struct _Fash_Item_Index_Map Fash_Item_Index_Map;
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
{
@ -784,22 +785,31 @@ 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_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);
};
/////
@ -807,62 +817,51 @@ struct _Fash_Glyph
struct _RGBA_Font
{
Eina_List *fonts;
Fash_Int *fash;
Font_Hint_Flags hinting;
int references;
Fash_Int *fash;
unsigned char sizeok : 1;
LK(lock);
#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;
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;
} ft;
int references;
};
struct _RGBA_Font_Glyph