BLF: add utility function to loop over glyph bounds

This commit is contained in:
Campbell Barton 2020-04-28 13:25:43 +10:00
parent 33017e9529
commit e78470d954
5 changed files with 147 additions and 2 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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,

View File

@ -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,

View File

@ -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;