Commit: ecdc8de661a002471f932ef1b9036e9fee78507e
Author: Campbell Barton
Date:   Sat Aug 29 01:59:26 2015 +1000
Branches: temp-blf-wordwrap
https://developer.blender.org/rBecdc8de661a002471f932ef1b9036e9fee78507e

Initial BLF word-wrapping support

Avoid code duplication by using single word-wrap function
which takes a callback to do the actual work.

===================================================================

M       source/blender/blenfont/BLF_api.h
M       source/blender/blenfont/intern/blf.c
M       source/blender/blenfont/intern/blf_font.c
M       source/blender/blenfont/intern/blf_internal.h

===================================================================

diff --git a/source/blender/blenfont/BLF_api.h 
b/source/blender/blenfont/BLF_api.h
index d8dee71..49fc2be 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -210,6 +210,7 @@ void BLF_state_print(int fontid);
 #define BLF_MATRIX           (1 << 4)
 #define BLF_ASPECT           (1 << 5)
 #define BLF_HINTING          (1 << 6)
+#define BLF_WORDWRAP         (1 << 7)
 
 #define BLF_DRAW_STR_DUMMY_MAX 1024
 
diff --git a/source/blender/blenfont/intern/blf.c 
b/source/blender/blenfont/intern/blf.c
index 127826f..9402a17 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -561,7 +561,12 @@ void BLF_draw(int fontid, const char *str, size_t len)
 
        if (font && font->glyph_cache) {
                blf_draw__start(font, &mode, &param);
-               blf_font_draw(font, str, len);
+               if (font->flags & BLF_WORDWRAP) {
+                       blf_font_draw__wrap(font, str, len);
+               }
+               else {
+                       blf_font_draw(font, str, len, 0);
+               }
                blf_draw__end(mode, param);
        }
 }
@@ -573,7 +578,12 @@ void BLF_draw_ascii(int fontid, const char *str, size_t 
len)
 
        if (font && font->glyph_cache) {
                blf_draw__start(font, &mode, &param);
-               blf_font_draw_ascii(font, str, len);
+               if (font->flags & BLF_WORDWRAP) {
+                       blf_font_draw_ascii__wrap(font, str, len);
+               }
+               else {
+                       blf_font_draw_ascii(font, str, len, 0);
+               }
                blf_draw__end(mode, param);
        }
 }
@@ -638,7 +648,7 @@ void BLF_boundbox(int fontid, const char *str, size_t len, 
rctf *box)
        FontBLF *font = blf_get(fontid);
 
        if (font) {
-               blf_font_boundbox(font, str, len, box);
+               blf_font_boundbox(font, str, len, 0, box);
        }
 }
 
diff --git a/source/blender/blenfont/intern/blf_font.c 
b/source/blender/blenfont/intern/blf_font.c
index 46e0e0e..97594f0 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -174,12 +174,12 @@ static void blf_font_ensure_ascii_table(FontBLF *font)
        }                                                                       
     \
 } (void)0
 
-void blf_font_draw(FontBLF *font, const char *str, size_t len)
+void blf_font_draw(FontBLF *font, const char *str, size_t len, int pen_y)
 {
        unsigned int c;
        GlyphBLF *g, *g_prev = NULL;
        FT_Vector delta;
-       int pen_x = 0, pen_y = 0;
+       int pen_x = 0;
        size_t i = 0;
        GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
 
@@ -206,12 +206,12 @@ void blf_font_draw(FontBLF *font, const char *str, size_t 
len)
 }
 
 /* faster version of blf_font_draw, ascii only for view dimensions */
-void blf_font_draw_ascii(FontBLF *font, const char *str, size_t len)
+void blf_font_draw_ascii(FontBLF *font, const char *str, size_t len, int pen_y)
 {
        unsigned char c;
        GlyphBLF *g, *g_prev = NULL;
        FT_Vector delta;
-       int pen_x = 0, pen_y = 0;
+       int pen_x = 0;
        GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
 
        BLF_KERNING_VARS(font, has_kerning, kern_mode);
@@ -558,12 +558,12 @@ size_t blf_font_width_to_rstrlen(FontBLF *font, const 
char *str, size_t len, flo
        return i_prev;
 }
 
-void blf_font_boundbox(FontBLF *font, const char *str, size_t len, rctf *box)
+void blf_font_boundbox(FontBLF *font, const char *str, size_t len, int pen_y, 
rctf *box)
 {
        unsigned int c;
        GlyphBLF *g, *g_prev = NULL;
        FT_Vector delta;
-       int pen_x = 0, pen_y = 0;
+       int pen_x = 0;
        size_t i = 0;
        GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
 
@@ -611,6 +611,128 @@ void blf_font_boundbox(FontBLF *font, const char *str, 
size_t len, rctf *box)
        }
 }
 
+
+
+/* -------------------------------------------------------------------- */
+/** \name Word-Wrap Support
+ * \{ */
+
+struct WordWrapVars {
+       int x_span;
+       size_t start, last[2];
+};
+
+#define BLF_WORDWRAP_VARS(_font, _wrap) \
+       struct WordWrapVars _wrap = {(int)_font->clip_rec.xmax - 
(int)_font->pos[0], 0, {0, 0}}
+
+/**
+ * Generic function to add word-wrap support for other existing functions.
+ */
+static void blf_font_wrap_apply(
+        FontBLF *font, const char *str, size_t len,
+        void (*callback)(FontBLF *font, const char *str, size_t len, int 
pen_y, void *userdata),
+        void *userdata)
+{
+       unsigned int c;
+       GlyphBLF *g, *g_prev = NULL;
+       FT_Vector delta;
+       int pen_x = 0, pen_y = 0;
+       size_t i = 0;
+       GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
+
+       BLF_KERNING_VARS(font, has_kerning, kern_mode);
+
+       BLF_WORDWRAP_VARS(font, wrap);
+
+       blf_font_ensure_ascii_table(font);
+
+       while ((i < len) && str[i]) {
+
+               /* wrap vars */
+               size_t i_curr = i;
+               int pen_x_next;
+               bool do_draw = false;
+
+               BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
+
+               if (UNLIKELY(c == BLI_UTF8_ERR))
+                       break;
+               if (UNLIKELY(g == NULL))
+                       continue;
+               if (has_kerning)
+                       BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, 
pen_x);
+
+               pen_x_next = pen_x + g->advance_i;
+               if (UNLIKELY((pen_x_next >= wrap.x_span) && (wrap.start != 
wrap.last[0]))) {
+                       do_draw = true;
+               }
+               else if (UNLIKELY(((i < len) && str[i]) == 0)) {
+                       wrap.last[0] = i;
+                       wrap.last[1] = i;
+                       do_draw = true;
+               }
+               else if (UNLIKELY(g->c != ' ' && (g_prev ? g_prev->c == ' ' : 
false))) {
+                       wrap.last[0] = i_curr;
+                       wrap.last[1] = i;
+               }
+
+               if (UNLIKELY(do_draw)) {
+                       callback(font, &str[wrap.start], (wrap.last[0] - 
wrap.start), pen_y, userdata);
+                       wrap.start = wrap.last[0];
+                       i = wrap.last[1];
+                       pen_x = 0;
+                       pen_y -= font->glyph_cache->max_glyph_height;
+                       g_prev = NULL;
+                       continue;
+               }
+
+               pen_x = pen_x_next;
+               g_prev = g;
+       }
+}
+
+/* blf_font_draw__wrap */
+static void blf_font_draw__wrap_cb(FontBLF *font, const char *str, size_t len, 
int pen_y, void *UNUSED(userdata))
+{
+       blf_font_draw(font, str, len, pen_y);
+}
+void blf_font_draw__wrap(FontBLF *font, const char *str, size_t len)
+{
+       blf_font_wrap_apply(font, str, len, blf_font_draw__wrap_cb, NULL);
+}
+
+/* blf_font_draw_ascii__wrap */
+static void blf_font_draw_ascii__wrap_cb(FontBLF *font, const char *str, 
size_t len, int pen_y, void *UNUSED(userdata))
+{
+       blf_font_draw_ascii(font, str, len, pen_y);
+}
+void blf_font_draw_ascii__wrap(FontBLF *font, const char *str, size_t len)
+{
+       blf_font_wrap_apply(font, str, len, blf_font_draw_ascii__wrap_cb, NULL);
+}
+
+/* blf_font_boundbox__wrap */
+static void blf_font_boundbox_wrap_cb(FontBLF *font, const char *str, size_t 
len, int pen_y, void *userdata)
+{
+       rctf *box = userdata;
+       rctf box_single;
+
+       blf_font_boundbox(font, str, len, pen_y, &box_single);
+       BLI_rctf_union(box, &box_single);
+}
+void blf_font_boundbox__wrap(FontBLF *font, const char *str, size_t len, rctf 
*box)
+{
+       box->xmin = 32000.0f;
+       box->xmax = -32000.0f;
+       box->ymin = 32000.0f;
+       box->ymax = -32000.0f;
+
+       blf_font_wrap_apply(font, str, len, blf_font_boundbox_wrap_cb, box);
+}
+
+/** \} */
+
+
 void blf_font_width_and_height(FontBLF *font, const char *str, size_t len, 
float *width, float *height)
 {
        float xa, ya;
@@ -625,7 +747,12 @@ void blf_font_width_and_height(FontBLF *font, const char 
*str, size_t len, float
                ya = 1.0f;
        }
 
-       blf_font_boundbox(font, str, len, &box);
+       if (font->flags & BLF_WORDWRAP) {
+               blf_font_boundbox__wrap(font, str, len, &box);
+       }
+       else {
+               blf_font_boundbox(font, str, len, 0, &box);
+       }
        *width  = (BLI_rctf_size_x(&box) * xa);
        *height = (BLI_rctf_size_y(&box) * ya);
 }
@@ -640,7 +767,12 @@ float blf_font_width(FontBLF *font, const char *str, 
size_t len)
        else
                xa = 1.0f;
 
-       blf_font_boundbox(font, str, len, &box);
+       if (font->flags & BLF_WORDWRAP) {
+               blf_font_boundbox__wrap(font, str, len, &box);
+       }
+       else {
+               blf_font_boundbox(font, str, len, 0, &box);
+       }
        return BLI_rctf_size_x(&box) * xa;
 }
 
@@ -654,7 +786,12 @@ float blf_font_height(FontBLF *font, const char *str, 
size_t len)
        else
                ya = 1.0f;
 
-       blf_font_boundbox(font, str, len, &box);
+       if (font->flags & BLF_WORDWRAP) {
+               blf_font_boundbox__wrap(font, str, len, &box);
+       }
+       else {
+               blf_font_boundbox(font, str, len, 0, &box);
+       }
        return BLI_rctf_size_y(&box) * ya;
 }
 
diff --git a/source/blender/blenfont/intern/blf_internal.h 
b/source/blender/blenfont/intern/blf_internal.h
index 85410a4..515e46e 100644
--- a/source/blender/blenfont/intern/blf_internal.h
+++ b/source/blender/blenfont/intern/blf_internal.h
@@ -51,13 +51,16 @@ struct FontBLF *blf_font_new_from_mem(const char *name, 
const unsigned char *mem
 void blf_font_attach_from_mem(struct FontBLF *font, const unsigned char *mem, 
int mem_size);
 
 void blf_font_size(struct FontBLF *font, unsigned int size, unsigned int dpi);
-void blf_font_draw(struct FontBLF *font, const char *str, size_t len);
-void blf_font_draw_ascii(struct FontBLF *font, const char *str, size_t len);
+void blf_font_draw(struct FontBLF *font, const char *str, size_t len, int 
pen_y);
+void blf_font_draw__wrap(struct FontBLF *font, const char *str, size_t len);
+void blf_font_draw_ascii(struct FontBLF *font, const char *str, size_t len, 
int pen_y);
+void blf_font_draw_ascii__wrap(struct FontBLF *font, const char *str, size_t 
len);
 int blf_font_draw_mono(struct FontBLF *font, const char *str, size_t len, int 
cwidth);
 void blf_font_buffer(struct FontBLF *font, const char *str);
 size_t blf_font_width_to_strlen(struct FontBLF *font, const char *str, size_t 
len, float width, float *r_width);
 size_t blf_font_width_to_rstrlen(struct FontBLF *font, const char *str, size_t 
len, float width, float *r_width);
-void blf_font_boundbox(struct FontBLF *font, const char *str, size_t len, 
struct rctf *box);
+void blf_font_boundbox(struct FontBLF *font, const char *str, size_t len, int 
pen_y, struct rctf *box);
+void blf_font_boundbox__wrap(struct FontBLF *font, const char *str, size_t 
len, struct rctf *box);
 void blf_font_width_and_height(struct FontBLF *font, const char *str, size_t 
len, float *width, float *height);
 float blf_font_width(struct FontBLF *font, const char *str, size_t len);
 float blf_font_height(struct FontBLF *font, const char *str, size_t len);

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to