diff options
author | Campbell Barton <ideasman42@gmail.com> | 2013-12-16 14:47:10 +0400 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2013-12-16 15:00:30 +0400 |
commit | ce3f42e16a9e501b7c0221a6ed152d0926cc59e7 (patch) | |
tree | aca1331a4d0d5db6856ec79e9bd33f2d999a493e /source/blender/blenfont/intern | |
parent | c193dbe30b40beb435d6edde7117469f4706f98e (diff) |
BLF API: Add BLF_width_to_strlen,rstrlen gives a byte offset from a string width
Diffstat (limited to 'source/blender/blenfont/intern')
-rw-r--r-- | source/blender/blenfont/intern/blf.c | 40 | ||||
-rw-r--r-- | source/blender/blenfont/intern/blf_font.c | 129 | ||||
-rw-r--r-- | source/blender/blenfont/intern/blf_internal.h | 2 |
3 files changed, 171 insertions, 0 deletions
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); |