* 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
This commit is contained in:
Cedric BAIL 2009-02-10 15:53:17 +00:00
parent 757c5e757e
commit b70ae3c927
5 changed files with 185 additions and 47 deletions

View File

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

View File

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

View File

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

View File

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

View File

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