* evas/src/lib/include/evas_common.h,
authorcedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 10 Feb 2009 15:53:17 +0000 (15:53 +0000)
committercedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 10 Feb 2009 15:53:17 +0000 (15:53 +0000)
* 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: http://svn.enlightenment.org/svn/e/trunk/evas@38993 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/lib/engines/common/evas_font.h
src/lib/engines/common/evas_font_draw.c
src/lib/engines/common/evas_font_load.c
src/lib/engines/common/evas_font_query.c
src/lib/include/evas_common.h

index ab7b879..9843c7f 100644 (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);
index 9efaf45..4e7459e 100644 (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;
-
-            /* 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;
index fae7caf..4bfd427 100644 (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);
index 4595874..5ed5c9c 100644 (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 (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;
@@ -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 (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;
@@ -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 (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;
index c0a4e4b..636c454 100644 (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;