* 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.
git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/evas@38993
7cbeb6ba-43b4-40fd-8cce-
4c39aea84d33
/* 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);
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)
{
}
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)
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;
/* you want performance */
if ((use_kerning) && (prev_index) && (index) &&
(pface == fi->src->ft.face))
- {
- FT_Vector delta;
-
- /* 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;
- }
+ if (evas_common_font_query_kerning(fi, prev_index, index, &kern))
+ pen_x += kern;
+
pface = fi->src->ft.face;
fg = evas_common_font_int_cache_glyph_get(fi, index);
if (!fg) continue;
}
}
+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)
{
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);
fi->size = size;
+ _evas_commont_font_int_cache_init(fi);
+
return evas_common_font_int_load_init(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);
free(fi);
#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)
kern = 0;
if ((use_kerning) && (prev_index) && (index) &&
(pface == fi->src->ft.face))
- {
- FT_Vector delta;
-
- if (FT_Get_Kerning(fi->src->ft.face, prev_index, index,
- ft_kerning_default, &delta) == 0)
- {
- kern = delta.x >> 6;
- pen_x += kern;
- }
- }
+ if (evas_common_font_query_kerning(fi, prev_index, index, &kern))
+ pen_x += kern;
+
pface = fi->src->ft.face;
fg = evas_common_font_int_cache_glyph_get(fi, index);
if (!fg) continue;
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;
/* 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;
/* you want performance */
if ((use_kerning) && (prev_index) && (index) &&
(pface == fi->src->ft.face))
- {
- FT_Vector delta;
-
- if (FT_Get_Kerning(fi->src->ft.face, prev_index, index,
- ft_kerning_default, &delta) == 0)
- {
- kern = delta.x >> 6;
- pen_x += kern;
- }
- }
+ if (evas_common_font_query_kerning(fi, prev_index, index, &kern))
+ pen_x += kern;
+
pface = fi->src->ft.face;
fg = evas_common_font_int_cache_glyph_get(fi, index);
if (!fg) continue;
/* you want performance */
if ((use_kerning) && (prev_index) && (index) &&
(pface == fi->src->ft.face))
- {
- FT_Vector delta;
-
- if (FT_Get_Kerning(fi->src->ft.face, prev_index, index,
- ft_kerning_default, &delta) == 0)
- {
- kern = delta.x >> 6;
- pen_x += kern;
- }
- }
+ if (evas_common_font_query_kerning(fi, prev_index, index, &kern))
+ pen_x += kern;
+
pface = fi->src->ft.face;
fg = evas_common_font_int_cache_glyph_get(fi, index);
if (!fg) continue;
Eina_Hash *glyphs;
+#ifdef HAVE_PTHREAD
+ pthread_mutex_t ft_mutex;
+#endif
+ Eina_Hash *kerning;
+ Eina_Hash *indexes;
+
int usage;
Font_Hint_Flags hinting;