[Bf-blender-cvs] [ecdc8de] temp-blf-wordwrap: Initial BLF word-wrapping support

Campbell Barton noreply at git.blender.org
Fri Aug 28 18:35:31 CEST 2015


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);




More information about the Bf-blender-cvs mailing list