speedup font drawing:
authorCampbell Barton <ideasman42@gmail.com>
Sun, 11 Sep 2011 08:12:16 +0000 (08:12 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Sun, 11 Sep 2011 08:12:16 +0000 (08:12 +0000)
 for ascii characters in a utf8 string use glyph_ascii_table lookup rather than call blf_glyph_search(), otherwise fallback to blf_utf8_next() and blf_glyph_search().

source/blender/blenfont/intern/blf_font.c
source/blender/blenfont/intern/blf_internal.h
source/blender/blenfont/intern/blf_util.c

index fb6505fe935f28112a62159e54c79587e427c13d..52aace1d3d7af74488a3142e392caa899015d621 100644 (file)
@@ -97,14 +97,52 @@ void blf_font_size(FontBLF *font, int size, int dpi)
        }
 }
 
+static void blf_font_ensure_ascii_table(FontBLF *font)
+{
+       /* build ascii on demand */
+       if(font->glyph_ascii_table['0']==NULL) {
+               GlyphBLF *g;
+               unsigned int i;
+               for(i=0; i<256; i++) {
+                       g= blf_glyph_search(font->glyph_cache, i);
+                       if (!g) {
+                               FT_UInt glyph_index= FT_Get_Char_Index(font->face, i);
+                               g= blf_glyph_add(font, glyph_index, i);
+                       }
+                       font->glyph_ascii_table[i]= g;
+               }
+       }
+}
+
+/* Fast path for runs of ASCII characters. Given that common UTF-8
+ * input will consist of an overwhelming majority of ASCII
+ * characters.
+ */
+
+/* Note,
+ * blf_font_ensure_ascii_table(font); must be called before this macro */
+
+#define BLF_UTF8_NEXT_FAST(font, g, str, i, c)                                \
+       if(((c)= (str)[i]) < 0x80) {                                              \
+               g= (font)->glyph_ascii_table[c];                                      \
+               i++;                                                                  \
+       }                                                                         \
+       else if ((c= blf_utf8_next((unsigned char *)(str), &(i)))) {              \
+               if ((g= blf_glyph_search((font)->glyph_cache, c)) == NULL) {          \
+                       g= blf_glyph_add(font, FT_Get_Char_Index((font)->face, c), c);    \
+               }                                                                     \
+       }                                                                         \
+
+
+
 void blf_font_draw(FontBLF *font, const char *str, unsigned int len)
 {
        unsigned int c;
        GlyphBLF *g, *g_prev;
        FT_Vector delta;
-       FT_UInt glyph_index;
        int pen_x, pen_y;
-       int i, has_kerning, st;
+       int has_kerning, st;
+       unsigned int i;
 
        if (!font->glyph_cache)
                return;
@@ -115,17 +153,15 @@ void blf_font_draw(FontBLF *font, const char *str, unsigned int len)
        has_kerning= FT_HAS_KERNING(font->face);
        g_prev= NULL;
 
+       blf_font_ensure_ascii_table(font);
+
        while (str[i] && i < len) {
-               c= blf_utf8_next((unsigned char *)str, &i);
+
+               BLF_UTF8_NEXT_FAST(font, g, str, i, c);
+
                if (c == 0)
                        break;
 
-               g= blf_glyph_search(font->glyph_cache, c);
-               if (!g) {
-                       glyph_index= FT_Get_Char_Index(font->face, c);
-                       g= blf_glyph_add(font, glyph_index, c);
-               }
-
                /* if we don't found a glyph, skip it. */
                if (!g)
                        continue;
@@ -157,9 +193,8 @@ void blf_font_draw_ascii(FontBLF *font, const char *str, unsigned int len)
        char c;
        GlyphBLF *g, *g_prev;
        FT_Vector delta;
-       FT_UInt glyph_index;
        int pen_x, pen_y;
-       int i, has_kerning, st;
+       int has_kerning, st;
 
        if (!font->glyph_cache)
                return;
@@ -169,18 +204,8 @@ void blf_font_draw_ascii(FontBLF *font, const char *str, unsigned int len)
        has_kerning= FT_HAS_KERNING(font->face);
        g_prev= NULL;
 
-       /* build ascii on demand */
-       if(font->glyph_ascii_table['0']==NULL) {
-               for(i=0; i<256; i++) {
-                       g= blf_glyph_search(font->glyph_cache, i);
-                       if (!g) {
-                               glyph_index= FT_Get_Char_Index(font->face, i);
-                               g= blf_glyph_add(font, glyph_index, i);
-                       }
-                       font->glyph_ascii_table[i]= g;
-               }
-       }
-       
+       blf_font_ensure_ascii_table(font);
+
        while ((c= *(str++)) && len--) {
                g= font->glyph_ascii_table[c];
 
@@ -216,10 +241,10 @@ void blf_font_buffer(FontBLF *font, const char *str)
        unsigned char b_col_char[4];
        GlyphBLF *g, *g_prev;
        FT_Vector delta;
-       FT_UInt glyph_index;
        float a, *fbuf;
        int pen_x, y, x;
-       int i, has_kerning, st, chx, chy;
+       int has_kerning, st, chx, chy;
+       unsigned int i;
 
        if (!font->glyph_cache || (!font->b_fbuf && !font->b_cbuf))
                return;
@@ -234,18 +259,16 @@ void blf_font_buffer(FontBLF *font, const char *str)
        b_col_char[2]= font->b_col[2] * 255;
        b_col_char[3]= font->b_col[3] * 255;
 
+       blf_font_ensure_ascii_table(font);
+
        while (str[i]) {
                int pen_y;
-               c= blf_utf8_next((unsigned char *)str, &i);
+
+               BLF_UTF8_NEXT_FAST(font, g, str, i, c);
+
                if (c == 0)
                        break;
 
-               g= blf_glyph_search(font->glyph_cache, c);
-               if (!g) {
-                       glyph_index= FT_Get_Char_Index(font->face, c);
-                       g= blf_glyph_add(font, glyph_index, c);
-               }
-
                /* if we don't found a glyph, skip it. */
                if (!g)
                        continue;
@@ -363,10 +386,10 @@ void blf_font_boundbox(FontBLF *font, const char *str, rctf *box)
        unsigned int c;
        GlyphBLF *g, *g_prev;
        FT_Vector delta;
-       FT_UInt glyph_index;
        rctf gbox;
        int pen_x, pen_y;
-       int i, has_kerning, st;
+       int has_kerning, st;
+       unsigned int i;
 
        if (!font->glyph_cache)
                return;
@@ -382,17 +405,15 @@ void blf_font_boundbox(FontBLF *font, const char *str, rctf *box)
        has_kerning= FT_HAS_KERNING(font->face);
        g_prev= NULL;
 
+       blf_font_ensure_ascii_table(font);
+
        while (str[i]) {
-               c= blf_utf8_next((unsigned char *)str, &i);
+
+               BLF_UTF8_NEXT_FAST(font, g, str, i, c);
+
                if (c == 0)
                        break;
 
-               g= blf_glyph_search(font->glyph_cache, c);
-               if (!g) {
-                       glyph_index= FT_Get_Char_Index(font->face, c);
-                       g= blf_glyph_add(font, glyph_index, c);
-               }
-
                /* if we don't found a glyph, skip it. */
                if (!g)
                        continue;
@@ -534,7 +555,7 @@ void blf_font_free(FontBLF *font)
 
 static void blf_font_fill(FontBLF *font)
 {
-       int i;
+       unsigned int i;
 
        font->aspect[0]= 1.0f;
        font->aspect[1]= 1.0f;
index 9271d8d5a9e771b9c6ba263511ed68c081fd45d7..ba0b9985dd4f6f666915cf1e90d982b3d035957c 100644 (file)
@@ -40,7 +40,7 @@ struct rctf;
 
 unsigned int blf_next_p2(unsigned int x);
 unsigned int blf_hash(unsigned int val);
-int blf_utf8_next(unsigned char *buf, int *iindex);
+int blf_utf8_next(unsigned char *buf, unsigned int *iindex);
 
 char *blf_dir_search(const char *file);
 char *blf_dir_metrics_search(const char *filename);
index ab6b516787e7802873eda37faeccdafb9cfb6633..edd23ac1ba6848b326f01a8ae3dfe411e8f345a7 100644 (file)
@@ -72,7 +72,7 @@ unsigned int blf_hash(unsigned int val)
  * The original name: imlib_font_utf8_get_next
  * more info here: http://docs.enlightenment.org/api/imlib2/html/
  */
-int blf_utf8_next(unsigned char *buf, int *iindex)
+int blf_utf8_next(unsigned char *buf, unsigned int *iindex)
 {
        /* Reads UTF8 bytes from 'buf', starting at 'index' and
         * returns the code point of the next valid code point.