Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2013-12-16 14:47:10 +0400
committerCampbell Barton <ideasman42@gmail.com>2013-12-16 15:00:30 +0400
commitce3f42e16a9e501b7c0221a6ed152d0926cc59e7 (patch)
treeaca1331a4d0d5db6856ec79e9bd33f2d999a493e /source/blender/blenfont
parentc193dbe30b40beb435d6edde7117469f4706f98e (diff)
BLF API: Add BLF_width_to_strlen,rstrlen gives a byte offset from a string width
Diffstat (limited to 'source/blender/blenfont')
-rw-r--r--source/blender/blenfont/BLF_api.h5
-rw-r--r--source/blender/blenfont/intern/blf.c40
-rw-r--r--source/blender/blenfont/intern/blf_font.c129
-rw-r--r--source/blender/blenfont/intern/blf_internal.h2
4 files changed, 176 insertions, 0 deletions
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index b25166f4b18..6ba3bedd4b6 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 746ee3c0d93..a5aa19704ec 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 40943225223..b435e38323c 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 9f6bad9b00d..8cb2d377449 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);