From b70ae3c9274e9d01e78917584981da80f17f333e Mon Sep 17 00:00:00 2001 From: Cedric BAIL Date: Tue, 10 Feb 2009 15:53:17 +0000 Subject: [PATCH] * evas/src/lib/include/evas_common.h, * evas/src/lib/engines/common/evas_font.h, * evas/src/lib/engines/common/evas_font_draw.c, * evas/src/lib/engines/common/evas_font_load.c, * evas/src/lib/engines/common/evas_font_query.c: Add cache for font kerning. This patch give something around 2% for all tests around text in expedite, except for Textblock Intl where it give a 3 times boost. Regarding text rendering speed, something is strange when used by evas_pipe. All tests using Styles are around 40% faster without evas_pipe. 30% faster for Text Change. But Text Basic 7% slower. So it should be possible to have faster rendering when using evas_pipe for font rendering. SVN revision: 38993 --- .../evas/src/lib/engines/common/evas_font.h | 1 + .../src/lib/engines/common/evas_font_draw.c | 57 +++++++--- .../src/lib/engines/common/evas_font_load.c | 68 ++++++++++++ .../src/lib/engines/common/evas_font_query.c | 100 ++++++++++++------ legacy/evas/src/lib/include/evas_common.h | 6 ++ 5 files changed, 185 insertions(+), 47 deletions(-) diff --git a/legacy/evas/src/lib/engines/common/evas_font.h b/legacy/evas/src/lib/engines/common/evas_font.h index ab7b879e00..9843c7f1d7 100644 --- a/legacy/evas/src/lib/engines/common/evas_font.h +++ b/legacy/evas/src/lib/engines/common/evas_font.h @@ -60,6 +60,7 @@ EAPI RGBA_Font_Int *evas_common_font_int_find (const char *name, /* query */ +EAPI int evas_common_font_query_kerning (RGBA_Font_Int* fi, FT_UInt prev, FT_UInt index, int* kerning); EAPI void evas_common_font_query_size (RGBA_Font *fn, const char *text, int *w, int *h); EAPI int evas_common_font_query_inset (RGBA_Font *fn, const char *text); EAPI void evas_common_font_query_advance (RGBA_Font *fn, const char *text, int *h_adv, int *v_adv); 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 9efaf45fdc..4e7459e5ea 100644 --- a/legacy/evas/src/lib/engines/common/evas_font_draw.c +++ b/legacy/evas/src/lib/engines/common/evas_font_draw.c @@ -50,6 +50,46 @@ evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, FT_UInt index) return fg; } +typedef struct _Font_Char_Index Font_Char_Index; +struct _Font_Char_Index +{ + FT_UInt index; + int gl; +}; + +static FT_UInt +_evas_common_get_char_index(RGBA_Font_Int* fi, int gl) +{ + Font_Char_Index *result; + +#ifdef HAVE_PTHREAD + pthread_mutex_lock(&fi->ft_mutex); +#endif + + result = eina_hash_find(fi->indexes, &gl); + if (result) goto on_correct; + + result = malloc(sizeof (Font_Char_Index)); + if (!result) + { +#ifdef HAVE_PTHREAD + pthread_mutex_unlock(&fi->ft_mutex); +#endif + return FT_Get_Char_Index(fi->src->ft.face, gl); + } + + result->index = FT_Get_Char_Index(fi->src->ft.face, gl); + result->gl = gl; + + eina_hash_direct_add(fi->indexes, &result->gl, result); + + on_correct: +#ifdef HAVE_PTHREAD + pthread_mutex_unlock(&fi->ft_mutex); +#endif + return result->index; +} + EAPI int evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl) { @@ -112,7 +152,7 @@ evas_common_font_glyph_search(RGBA_Font *fn, RGBA_Font_Int **fi_ret, int gl) } else /* Charmap not loaded, FS loaded */ { - index = FT_Get_Char_Index(fi->src->ft.face, gl); + index = _evas_common_get_char_index(fi, gl); if (index != 0) { if (!fi->ft.size) @@ -184,7 +224,7 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int FT_UInt index; RGBA_Font_Glyph *fg; int chr_x, chr_y; - int gl; + int gl, kern; gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr); if (gl == 0) break; @@ -194,18 +234,9 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int /* you want performance */ if ((use_kerning) && (prev_index) && (index) && (pface == fi->src->ft.face)) - { - FT_Vector delta; + if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) + pen_x += kern; - /* NOTE: ft2 seems to have a bug. and sometimes returns bizarre - * values to kern by - given same font, same size and same - * prev_index and index. auto/bytecode or none hinting doesnt - * matter */ - if (FT_Get_Kerning(fi->src->ft.face, prev_index, index, - ft_kerning_default, - &delta) == 0) - pen_x += delta.x >> 6; - } pface = fi->src->ft.face; fg = evas_common_font_int_cache_glyph_get(fi, index); if (!fg) continue; 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 fae7caf118..4bfd4272fc 100644 --- a/legacy/evas/src/lib/engines/common/evas_font_load.c +++ b/legacy/evas/src/lib/engines/common/evas_font_load.c @@ -138,6 +138,63 @@ evas_common_font_size_use(RGBA_Font *fn) } } +static unsigned int +_evas_common_font_int_length(const void *key) +{ + return sizeof (int); +} + +static unsigned int +_evas_common_font_double_int_length(const void *key) +{ + return sizeof (int) * 2; +} + +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]; + return key1[0] - key2[0]; +} + +static int +_evas_common_font_double_int_hash(const 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; +} + +static void +_evas_commont_font_int_cache_init(RGBA_Font_Int *fi) +{ + /* Add some font kerning cache. */ + fi->indexes = eina_hash_new(EINA_KEY_LENGTH(_evas_common_font_int_length), + EINA_KEY_CMP(_evas_common_font_int_cmp), + eina_hash_int32, + free, 3); + fi->kerning = eina_hash_new(EINA_KEY_LENGTH(_evas_common_font_double_int_length), + EINA_KEY_CMP(_evas_common_font_double_int_cmp), + EINA_KEY_HASH(_evas_common_font_double_int_hash), + free, 3); +#ifdef HAVE_PTHREAD + pthread_mutex_init(&fi->ft_mutex, NULL); +#endif +} + + EAPI RGBA_Font_Int * evas_common_font_int_memory_load(const char *name, int size, const void *data, int data_size) { @@ -161,6 +218,8 @@ evas_common_font_int_memory_load(const char *name, int size, const void *data, i fi->size = size; + _evas_commont_font_int_cache_init(fi); + fi = evas_common_font_int_load_init(fi); evas_common_font_int_load_complete(fi); @@ -190,6 +249,8 @@ evas_common_font_int_load(const char *name, int size) fi->size = size; + _evas_commont_font_int_cache_init(fi); + return evas_common_font_int_load_init(fi); } @@ -558,6 +619,13 @@ evas_common_font_flush_last(void) 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); free(fi); 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 4595874124..5ed5c9cfa8 100644 --- a/legacy/evas/src/lib/engines/common/evas_font_query.c +++ b/legacy/evas/src/lib/engines/common/evas_font_query.c @@ -1,5 +1,62 @@ #include "evas_common.h" +EAPI int +evas_common_font_query_kerning(RGBA_Font_Int* fi, + FT_UInt prev, FT_UInt index, + int* kerning) +{ + int *result; + FT_Vector delta; + int key[2]; + int error = 1; + + key[0] = prev; + key[1] = index; + +#ifdef HAVE_PTHREAD + pthread_mutex_lock(&fi->ft_mutex); +#endif + + result = eina_hash_find(fi->kerning, key); + if (result) + { + *kerning = result[2]; + goto on_correct; + } + + /* NOTE: ft2 seems to have a bug. and sometimes returns bizarre + * values to kern by - given same font, same size and same + * prev_index and index. auto/bytecode or none hinting doesnt + * matter */ + if (FT_Get_Kerning(fi->src->ft.face, + key[0], key[1], + ft_kerning_default, &delta) == 0) + { + int *push; + + *kerning = delta.x >> 6; + + push = malloc(sizeof (int) * 3); + if (!push) return 1; + + push[0] = key[0]; + push[1] = key[1]; + push[2] = *kerning; + + eina_hash_direct_add(fi->kerning, push, push); + + goto on_correct; + } + + error = 0; + + on_correct: +#ifdef HAVE_PTHREAD + pthread_mutex_unlock(&fi->ft_mutex); +#endif + return error; +} + /* string extents */ EAPI void evas_common_font_query_size(RGBA_Font *fn, const char *text, int *w, int *h) @@ -38,16 +95,9 @@ evas_common_font_query_size(RGBA_Font *fn, const char *text, int *w, int *h) kern = 0; if ((use_kerning) && (prev_index) && (index) && (pface == fi->src->ft.face)) - { - FT_Vector delta; + if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) + pen_x += kern; - if (FT_Get_Kerning(fi->src->ft.face, prev_index, index, - ft_kerning_default, &delta) == 0) - { - kern = delta.x >> 6; - pen_x += kern; - } - } pface = fi->src->ft.face; fg = evas_common_font_int_cache_glyph_get(fi, index); if (!fg) continue; @@ -138,7 +188,7 @@ evas_common_font_query_advance(RGBA_Font *fn, const char *text, int *h_adv, int FT_UInt index; RGBA_Font_Glyph *fg; int chr_x, chr_y, chr_w; - int gl; + int gl, kern; gl = evas_common_font_utf8_get_next((unsigned char *)text, &chr); if (gl == 0) break; @@ -148,13 +198,9 @@ evas_common_font_query_advance(RGBA_Font *fn, const char *text, int *h_adv, int /* you want performance */ if ((use_kerning) && (prev_index) && (index) && (pface == fi->src->ft.face)) - { - FT_Vector delta; + if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) + pen_x += kern; - if (FT_Get_Kerning(fi->src->ft.face, prev_index, index, - ft_kerning_default, &delta) == 0) - pen_x += delta.x >> 6; - } pface = fi->src->ft.face; fg = evas_common_font_int_cache_glyph_get(fi, index); if (!fg) continue; @@ -211,16 +257,9 @@ evas_common_font_query_char_coords(RGBA_Font *fn, const char *text, int pos, int /* you want performance */ if ((use_kerning) && (prev_index) && (index) && (pface == fi->src->ft.face)) - { - FT_Vector delta; + if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) + pen_x += kern; - if (FT_Get_Kerning(fi->src->ft.face, prev_index, index, - ft_kerning_default, &delta) == 0) - { - kern = delta.x >> 6; - pen_x += kern; - } - } pface = fi->src->ft.face; fg = evas_common_font_int_cache_glyph_get(fi, index); if (!fg) continue; @@ -297,16 +336,9 @@ evas_common_font_query_text_at_pos(RGBA_Font *fn, const char *text, int x, int y /* you want performance */ if ((use_kerning) && (prev_index) && (index) && (pface == fi->src->ft.face)) - { - FT_Vector delta; + if (evas_common_font_query_kerning(fi, prev_index, index, &kern)) + pen_x += kern; - if (FT_Get_Kerning(fi->src->ft.face, prev_index, index, - ft_kerning_default, &delta) == 0) - { - kern = delta.x >> 6; - pen_x += kern; - } - } pface = fi->src->ft.face; fg = evas_common_font_int_cache_glyph_get(fi, index); if (!fg) continue; diff --git a/legacy/evas/src/lib/include/evas_common.h b/legacy/evas/src/lib/include/evas_common.h index c0a4e4bb03..636c454545 100644 --- a/legacy/evas/src/lib/include/evas_common.h +++ b/legacy/evas/src/lib/include/evas_common.h @@ -642,6 +642,12 @@ struct _RGBA_Font_Int Eina_Hash *glyphs; +#ifdef HAVE_PTHREAD + pthread_mutex_t ft_mutex; +#endif + Eina_Hash *kerning; + Eina_Hash *indexes; + int usage; Font_Hint_Flags hinting;