[Bf-blender-cvs] [ce3f42e] master: BLF API: Add BLF_width_to_strlen, rstrlen gives a byte offset from a string width

Campbell Barton noreply at git.blender.org
Mon Dec 16 12:01:17 CET 2013


Commit: ce3f42e16a9e501b7c0221a6ed152d0926cc59e7
Author: Campbell Barton
Date:   Mon Dec 16 21:47:10 2013 +1100
http://developer.blender.org/rBce3f42e16a9e501b7c0221a6ed152d0926cc59e7

BLF API: Add BLF_width_to_strlen,rstrlen gives a byte offset from a string width

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

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 b25166f..6ba3bed 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -79,6 +79,11 @@ void BLF_draw(int fontid, const char *str, size_t len);
 void BLF_draw_ascii(int fontid, const char *str, size_t len);
 int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth);
 
+/* Get the string byte offset that fits within a given width */
+size_t BLF_width_to_strlen(int fontid, const char *str, size_t len, float width, float *r_width);
+/* Same as BLF_width_to_strlen but search from the string end */
+size_t BLF_width_to_rstrlen(int fontid, const char *str, size_t len, float width, float *r_width);
+
 /* This function return the bounding box of the string
  * and are not multiplied by the aspect.
  */
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index 746ee3c..a5aa197 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -592,6 +592,46 @@ int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth)
 	return columns;
 }
 
+size_t BLF_width_to_strlen(int fontid, const char *str, size_t len, float width, float *r_width)
+{
+	FontBLF *font = blf_get(fontid);
+
+	if (font) {
+		const float xa = (font->flags & BLF_ASPECT) ? font->aspect[0] : 1.0f;
+		size_t ret;
+		ret = blf_font_width_to_strlen(font, str, len, width / xa, r_width);
+		if (r_width) {
+			*r_width *= xa;
+		}
+		return ret;
+	}
+
+	if (r_width) {
+		*r_width = 0.0f;
+	}
+	return 0;
+}
+
+size_t BLF_width_to_rstrlen(int fontid, const char *str, size_t len, float width, float *r_width)
+{
+	FontBLF *font = blf_get(fontid);
+
+	if (font) {
+		const float xa = (font->flags & BLF_ASPECT) ? font->aspect[0] : 1.0f;
+		size_t ret;
+		ret = blf_font_width_to_rstrlen(font, str, len, width / xa, r_width);
+		if (r_width) {
+			*r_width *= xa;
+		}
+		return ret;
+	}
+
+	if (r_width) {
+		*r_width = 0.0f;
+	}
+	return 0;
+}
+
 void BLF_boundbox(int fontid, const char *str, size_t len, rctf *box)
 {
 	FontBLF *font = blf_get(fontid);
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index 4094322..b435e38 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -49,6 +49,7 @@
 #include "BLI_string.h"
 #include "BLI_string_utf8.h"
 #include "BLI_threads.h"
+#include "BLI_alloca.h"
 #include "BLI_linklist.h"  /* linknode */
 #include "BLI_strict_flags.h"
 
@@ -415,6 +416,134 @@ void blf_font_buffer(FontBLF *font, const char *str)
 	}
 }
 
+size_t blf_font_width_to_strlen(FontBLF *font, const char *str, size_t len, float width, float *r_width)
+{
+	unsigned int c;
+	GlyphBLF *g, *g_prev = NULL;
+	FT_Vector delta;
+	int pen_x = 0;
+	size_t i = 0, i_prev;
+	GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
+	const int width_i = (int)width + 1;
+	int width_new;
+
+	BLF_KERNING_VARS(font, has_kerning, kern_mode);
+
+	blf_font_ensure_ascii_table(font);
+
+	while ((i_prev = i), (width_new = pen_x), ((i < len) && str[i]))
+	{
+		BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
+
+		if (c == BLI_UTF8_ERR)
+			break;
+		if (g == NULL)
+			continue;
+		if (has_kerning)
+			BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
+
+		pen_x += (int)g->advance;
+
+		if (width_i < pen_x) {
+			break;
+		}
+
+		g_prev = g;
+	}
+
+	if (r_width) {
+		*r_width = (float)width_new;
+	}
+
+	return i_prev;
+}
+
+size_t blf_font_width_to_rstrlen(FontBLF *font, const char *str, size_t len, float width, float *r_width)
+{
+	unsigned int c;
+	GlyphBLF *g, *g_prev = NULL;
+	FT_Vector delta;
+	int pen_x = 0;
+	size_t i = 0, i_prev;
+	GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table;
+	const int width_i = (int)width + 1;
+	int width_new;
+
+	bool is_malloc;
+	int (*width_accum)[2];
+	int width_accum_ofs = 0;
+
+	BLF_KERNING_VARS(font, has_kerning, kern_mode);
+
+	/* skip allocs in simple cases */
+	len = BLI_strnlen(str, len);
+	if (width_i <= 1 || len == 0) {
+		if (r_width) {
+			*r_width = 0.0f;
+		}
+		return len;
+	}
+
+	if (len < 2048) {
+		width_accum = BLI_array_alloca(width_accum, len);
+		is_malloc = false;
+	}
+	else {
+		width_accum = MEM_mallocN(sizeof(*width_accum) * len, __func__);
+		is_malloc = true;
+	}
+
+	blf_font_ensure_ascii_table(font);
+
+	while ((i < len) && str[i]) {
+		BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table);
+
+		if (c == BLI_UTF8_ERR)
+			break;
+		if (g == NULL)
+			continue;
+		if (has_kerning)
+			BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x);
+
+		pen_x += (int)g->advance;
+
+		width_accum[width_accum_ofs][0] = (int)i;
+		width_accum[width_accum_ofs][1] = pen_x;
+		width_accum_ofs++;
+
+		g_prev = g;
+	}
+
+	if (pen_x > width_i && width_accum_ofs != 0) {
+		const int min_x = pen_x - width_i;
+
+		/* search backwards */
+		width_new = pen_x;
+		while (width_accum_ofs-- > 0) {
+			if (min_x > width_accum[width_accum_ofs][1]) {
+				break;
+			}
+		}
+		width_accum_ofs++;
+		width_new = pen_x - width_accum[width_accum_ofs][1];
+		i_prev = (size_t)width_accum[width_accum_ofs][0];
+	}
+	else {
+		width_new = pen_x;
+		i_prev = 0;
+	}
+
+	if (is_malloc) {
+		MEM_freeN(width_accum);
+	}
+
+	if (r_width) {
+		*r_width = (float)width_new;
+	}
+
+	return i_prev;
+}
+
 void blf_font_boundbox(FontBLF *font, const char *str, size_t len, rctf *box)
 {
 	unsigned int c;
diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h
index 9f6bad9..8cb2d37 100644
--- a/source/blender/blenfont/intern/blf_internal.h
+++ b/source/blender/blenfont/intern/blf_internal.h
@@ -55,6 +55,8 @@ 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);
 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_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);




More information about the Bf-blender-cvs mailing list