diff options
author | Campbell Barton <ideasman42@gmail.com> | 2020-04-28 06:25:43 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2020-04-28 06:34:56 +0300 |
commit | e78470d95411764c59af58dc996398a02bc40ae6 (patch) | |
tree | e6e325a1b5e0e017f4341ceaa65f0140b361ccdc /source/blender | |
parent | 33017e952913a3be04e7ac8b720a12fd9d33a76f (diff) |
BLF: add utility function to loop over glyph bounds
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenfont/BLF_api.h | 19 | ||||
-rw-r--r-- | source/blender/blenfont/intern/blf.c | 36 | ||||
-rw-r--r-- | source/blender/blenfont/intern/blf_font.c | 78 | ||||
-rw-r--r-- | source/blender/blenfont/intern/blf_internal.h | 12 | ||||
-rw-r--r-- | source/blender/blenfont/intern/blf_util.c | 4 |
5 files changed, 147 insertions, 2 deletions
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h index 9aee8c9b78b..f6f1393bd21 100644 --- a/source/blender/blenfont/BLF_api.h +++ b/source/blender/blenfont/BLF_api.h @@ -37,6 +37,7 @@ extern "C" { struct ColorManagedDisplay; struct ResultBLF; struct rctf; +struct rcti; int BLF_init(void); void BLF_exit(void); @@ -115,6 +116,24 @@ void BLF_draw_ascii_ex(int fontid, const char *str, size_t len, struct ResultBLF void BLF_draw_ascii(int fontid, const char *str, size_t len) ATTR_NONNULL(2); int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth) ATTR_NONNULL(2); +typedef bool (*BLF_GlyphBoundsFn)(const char *str, + const size_t str_ofs, + const struct rcti *glyph_bounds, + const int glyph_advance_x, + void *user_data); + +void BLF_boundbox_foreach_glyph_ex(int fontid, + const char *str, + size_t len, + BLF_GlyphBoundsFn user_fn, + void *user_data, + struct ResultBLF *r_info) ATTR_NONNULL(2); +void BLF_boundbox_foreach_glyph(int fontid, + const char *str, + size_t len, + BLF_GlyphBoundsFn user_fn, + void *user_data) ATTR_NONNULL(2); + /* 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) ATTR_NONNULL(2); diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c index 520456653d1..394704e1c20 100644 --- a/source/blender/blenfont/intern/blf.c +++ b/source/blender/blenfont/intern/blf.c @@ -682,6 +682,42 @@ int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth) return columns; } +/** + * Run \a user_fn for each character, with the bound-box that would be used for drawing. + * + * \param user_fn: Callback that runs on each glyph, returning false early exits. + * \param user_data: User argument passed to \a user_fn. + * + * \note The font position, clipping, matrix and rotation are not applied. + */ +void BLF_boundbox_foreach_glyph_ex(int fontid, + const char *str, + size_t len, + BLF_GlyphBoundsFn user_fn, + void *user_data, + struct ResultBLF *r_info) +{ + FontBLF *font = blf_get(fontid); + + BLF_RESULT_CHECK_INIT(r_info); + + if (font) { + if (font->flags & BLF_WORD_WRAP) { + /* TODO: word-wrap support. */ + BLI_assert(0); + } + else { + blf_font_boundbox_foreach_glyph(font, str, len, user_fn, user_data, r_info); + } + } +} + +void BLF_boundbox_foreach_glyph( + int fontid, const char *str, size_t len, BLF_GlyphBoundsFn user_fn, void *user_data) +{ + BLF_boundbox_foreach_glyph_ex(fontid, str, len, user_fn, user_data, NULL); +} + size_t BLF_width_to_strlen(int fontid, const char *str, size_t len, float width, float *r_width) { FontBLF *font = blf_get(fontid); diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index 0f93f2ca07b..ed92e9aaff2 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -1201,6 +1201,84 @@ float blf_font_fixed_width(FontBLF *font) return g->advance; } +/* -------------------------------------------------------------------- */ +/** \name Glyph Bound Box with Callback + * \{ */ + +static void blf_font_boundbox_foreach_glyph_ex(FontBLF *font, + GlyphCacheBLF *gc, + const char *str, + size_t len, + BLF_GlyphBoundsFn user_fn, + void *user_data, + struct ResultBLF *r_info, + int pen_y) +{ + unsigned int c, c_prev = BLI_UTF8_ERR; + GlyphBLF *g, *g_prev = NULL; + int pen_x = 0; + size_t i = 0, i_curr; + rcti gbox; + + if (len == 0) { + /* early output. */ + return; + } + + GlyphBLF **glyph_ascii_table = blf_font_ensure_ascii_table(font, gc); + + BLF_KERNING_VARS(font, has_kerning, kern_mode); + + blf_font_ensure_ascii_kerning(font, gc, kern_mode); + + while ((i < len) && str[i]) { + i_curr = i; + BLF_UTF8_NEXT_FAST(font, gc, 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_FAST(font, kern_mode, g_prev, g, c_prev, c, pen_x); + } + + gbox.xmin = pen_x; + gbox.xmax = gbox.xmin + MIN2(g->advance_i, g->width); + gbox.ymin = pen_y; + gbox.ymax = gbox.ymin - g->height; + + pen_x += g->advance_i; + + if (user_fn(str, i_curr, &gbox, g->advance_i, user_data) == false) { + break; + } + + g_prev = g; + c_prev = c; + } + + if (r_info) { + r_info->lines = 1; + r_info->width = pen_x; + } +} +void blf_font_boundbox_foreach_glyph(FontBLF *font, + const char *str, + size_t len, + BLF_GlyphBoundsFn user_fn, + void *user_data, + struct ResultBLF *r_info) +{ + GlyphCacheBLF *gc = blf_glyph_cache_acquire(font); + blf_font_boundbox_foreach_glyph_ex(font, gc, str, len, user_fn, user_data, r_info, 0); + blf_glyph_cache_release(font); +} + +/** \} */ + int blf_font_count_missing_chars(FontBLF *font, const char *str, const size_t len, diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h index efcf9e15100..98ada87d16d 100644 --- a/source/blender/blenfont/intern/blf_internal.h +++ b/source/blender/blenfont/intern/blf_internal.h @@ -29,6 +29,7 @@ struct GlyphBLF; struct GlyphCacheBLF; struct ResultBLF; struct rctf; +struct rcti; void blf_batch_draw_vao_clear(void); void blf_batch_draw_begin(struct FontBLF *font); @@ -98,6 +99,17 @@ int blf_font_width_max(struct FontBLF *font); float blf_font_descender(struct FontBLF *font); float blf_font_ascender(struct FontBLF *font); +void blf_font_boundbox_foreach_glyph(struct FontBLF *font, + const char *str, + size_t len, + bool (*user_fn)(const char *str, + const size_t str_ofs, + const struct rcti *glyph_bounds, + const int glyph_advance_x, + void *user_data), + void *user_data, + struct ResultBLF *r_info); + int blf_font_count_missing_chars(struct FontBLF *font, const char *str, const size_t len, diff --git a/source/blender/blenfont/intern/blf_util.c b/source/blender/blenfont/intern/blf_util.c index e55759199a2..a70a9ea6819 100644 --- a/source/blender/blenfont/intern/blf_util.c +++ b/source/blender/blenfont/intern/blf_util.c @@ -27,10 +27,10 @@ #include <stdlib.h> #include <string.h> -#include "blf_internal.h" - #include "BLI_utildefines.h" +#include "blf_internal.h" + unsigned int blf_next_p2(unsigned int x) { x -= 1; |