forked from enlightenment/efl
* 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:
parent
757c5e757e
commit
b70ae3c927
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue