[Bf-blender-cvs] [e78470d9541] blender-v2.83-release: BLF: add utility function to loop over glyph bounds

Campbell Barton noreply at git.blender.org
Tue Apr 28 05:48:24 CEST 2020


Commit: e78470d95411764c59af58dc996398a02bc40ae6
Author: Campbell Barton
Date:   Tue Apr 28 13:25:43 2020 +1000
Branches: blender-v2.83-release
https://developer.blender.org/rBe78470d95411764c59af58dc996398a02bc40ae6

BLF: add utility function to loop over glyph bounds

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

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
M	source/blender/blenfont/intern/blf_util.c

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

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;



More information about the Bf-blender-cvs mailing list