diff options
author | Julian Eisel <julian@blender.org> | 2020-06-05 14:09:31 +0300 |
---|---|---|
committer | Julian Eisel <julian@blender.org> | 2020-06-05 14:09:31 +0300 |
commit | 920a58d9b6d667894cf166cbbd25e4c2fbd238ea (patch) | |
tree | 7ca5a9da640753b5e070c439ac3bdd14dfad92cf /source/blender/blenfont | |
parent | c94b6209861ca7cc3985b53474feed7d94c0221a (diff) | |
parent | a1d55bdd530390e58c51abe9707b8d3b0ae3e861 (diff) |
Merge branch 'master' into wm-drag-drop-rewritewm-drag-drop-rewrite
Diffstat (limited to 'source/blender/blenfont')
-rw-r--r-- | source/blender/blenfont/BLF_api.h | 21 | ||||
-rw-r--r-- | source/blender/blenfont/intern/blf.c | 40 | ||||
-rw-r--r-- | source/blender/blenfont/intern/blf_font.c | 114 | ||||
-rw-r--r-- | source/blender/blenfont/intern/blf_glyph.c | 78 | ||||
-rw-r--r-- | source/blender/blenfont/intern/blf_internal.h | 14 | ||||
-rw-r--r-- | source/blender/blenfont/intern/blf_internal_types.h | 16 | ||||
-rw-r--r-- | source/blender/blenfont/intern/blf_thumbs.c | 4 | ||||
-rw-r--r-- | source/blender/blenfont/intern/blf_util.c | 4 |
8 files changed, 209 insertions, 82 deletions
diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h index 9aee8c9b78b..ddb88cf61ed 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,26 @@ 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_step_ofs, + const struct rcti *glyph_step_bounds, + const int glyph_advance_x, + const struct rctf *glyph_bounds, + const int glyph_bearing[2], + 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..2f7d5a60a6f 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); @@ -910,8 +946,8 @@ void BLF_buffer(int fontid, if (font) { font->buf_info.fbuf = fbuf; font->buf_info.cbuf = cbuf; - font->buf_info.w = w; - font->buf_info.h = h; + font->buf_info.dims[0] = w; + font->buf_info.dims[1] = h; font->buf_info.ch = nch; font->buf_info.display = display; } diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index 4d56f6f868f..e5e03418073 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -99,7 +99,7 @@ static void blf_batch_draw_init(void) GPU_vertbuf_attr_get_raw_data(g_batch.verts, g_batch.glyph_size_loc, &g_batch.glyph_size_step); g_batch.glyph_len = 0; - /* A dummy vbo containing 4 points, attribs are not used. */ + /* A dummy VBO containing 4 points, attributes are not used. */ GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); GPU_vertbuf_data_alloc(vbo, 4); @@ -613,28 +613,28 @@ static void blf_font_draw_buffer_ex(FontBLF *font, BLF_KERNING_STEP_FAST(font, kern_mode, g_prev, g, c_prev, c, pen_x); } - chx = pen_x + ((int)g->pos_x); - chy = pen_y_basis + g->height; + chx = pen_x + ((int)g->pos[0]); + chy = pen_y_basis + g->dims[1]; if (g->pitch < 0) { - pen_y = pen_y_basis + (g->height - (int)g->pos_y); + pen_y = pen_y_basis + (g->dims[1] - g->pos[1]); } else { - pen_y = pen_y_basis - (g->height - (int)g->pos_y); + pen_y = pen_y_basis - (g->dims[1] - g->pos[1]); } - if ((chx + g->width) >= 0 && chx < buf_info->w && (pen_y + g->height) >= 0 && - pen_y < buf_info->h) { + if ((chx + g->dims[0]) >= 0 && chx < buf_info->dims[0] && (pen_y + g->dims[1]) >= 0 && + pen_y < buf_info->dims[1]) { /* don't draw beyond the buffer bounds */ - int width_clip = g->width; - int height_clip = g->height; - int yb_start = g->pitch < 0 ? 0 : g->height - 1; + int width_clip = g->dims[0]; + int height_clip = g->dims[1]; + int yb_start = g->pitch < 0 ? 0 : g->dims[1] - 1; - if (width_clip + chx > buf_info->w) { - width_clip -= chx + width_clip - buf_info->w; + if (width_clip + chx > buf_info->dims[0]) { + width_clip -= chx + width_clip - buf_info->dims[0]; } - if (height_clip + pen_y > buf_info->h) { - height_clip -= pen_y + height_clip - buf_info->h; + if (height_clip + pen_y > buf_info->dims[1]) { + height_clip -= pen_y + height_clip - buf_info->dims[1]; } /* drawing below the image? */ @@ -652,7 +652,7 @@ static void blf_font_draw_buffer_ex(FontBLF *font, if (a_byte) { const float a = (a_byte / 255.0f) * b_col_float[3]; const size_t buf_ofs = (((size_t)(chx + x) + - ((size_t)(pen_y + y) * (size_t)buf_info->w)) * + ((size_t)(pen_y + y) * (size_t)buf_info->dims[0])) * (size_t)buf_info->ch); float *fbuf = buf_info->fbuf + buf_ofs; @@ -689,7 +689,7 @@ static void blf_font_draw_buffer_ex(FontBLF *font, if (a_byte) { const float a = (a_byte / 255.0f) * b_col_float[3]; const size_t buf_ofs = (((size_t)(chx + x) + - ((size_t)(pen_y + y) * (size_t)buf_info->w)) * + ((size_t)(pen_y + y) * (size_t)buf_info->dims[0])) * (size_t)buf_info->ch); unsigned char *cbuf = buf_info->cbuf + buf_ofs; @@ -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->dims[0]); + gbox.ymin = pen_y; + gbox.ymax = gbox.ymin - g->dims[1]; + + pen_x += g->advance_i; + + if (user_fn(str, i_curr, &gbox, g->advance_i, &g->box, g->pos, 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, @@ -1287,8 +1365,8 @@ static void blf_font_fill(FontBLF *font) font->buf_info.fbuf = NULL; font->buf_info.cbuf = NULL; - font->buf_info.w = 0; - font->buf_info.h = 0; + font->buf_info.dims[0] = 0; + font->buf_info.dims[1] = 0; font->buf_info.ch = 0; font->buf_info.col_init[0] = 0; font->buf_info.col_init[1] = 0; diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c index a38cb323777..ce17069e53f 100644 --- a/source/blender/blenfont/intern/blf_glyph.c +++ b/source/blender/blenfont/intern/blf_glyph.c @@ -212,7 +212,7 @@ void blf_glyph_cache_free(GlyphCacheBLF *gc) GlyphBLF *g; unsigned int i; - for (i = 0; i < 257; i++) { + for (i = 0; i < ARRAY_SIZE(gc->bucket); i++) { while ((g = BLI_pophead(&gc->bucket[i]))) { blf_glyph_free(g); } @@ -327,26 +327,27 @@ GlyphBLF *blf_glyph_add(FontBLF *font, GlyphCacheBLF *gc, unsigned int index, un g->c = c; g->idx = (FT_UInt)index; bitmap = slot->bitmap; - g->width = (int)bitmap.width; - g->height = (int)bitmap.rows; + g->dims[0] = (int)bitmap.width; + g->dims[1] = (int)bitmap.rows; - if (g->width && g->height) { + const int buffer_size = g->dims[0] * g->dims[1]; + + if (buffer_size != 0) { if (font->flags & BLF_MONOCHROME) { /* Font buffer uses only 0 or 1 values, Blender expects full 0..255 range */ - int i; - for (i = 0; i < (g->width * g->height); i++) { + for (int i = 0; i < buffer_size; i++) { bitmap.buffer[i] = bitmap.buffer[i] ? 255 : 0; } } - g->bitmap = (unsigned char *)MEM_mallocN((size_t)g->width * (size_t)g->height, "glyph bitmap"); - memcpy((void *)g->bitmap, (void *)bitmap.buffer, (size_t)g->width * (size_t)g->height); + g->bitmap = MEM_mallocN((size_t)buffer_size, "glyph bitmap"); + memcpy(g->bitmap, bitmap.buffer, (size_t)buffer_size); } g->advance = ((float)slot->advance.x) / 64.0f; g->advance_i = (int)g->advance; - g->pos_x = (float)slot->bitmap_left; - g->pos_y = (float)slot->bitmap_top; + g->pos[0] = slot->bitmap_left; + g->pos[1] = slot->bitmap_top; g->pitch = slot->bitmap.pitch; FT_Outline_Get_CBox(&(slot->outline), &bbox); @@ -431,10 +432,10 @@ static void blf_texture3_draw(const unsigned char color_in[4], static void blf_glyph_calc_rect(rctf *rect, GlyphBLF *g, float x, float y) { - rect->xmin = floorf(x + g->pos_x); - rect->xmax = rect->xmin + (float)g->width; - rect->ymin = floorf(y + g->pos_y); - rect->ymax = rect->ymin - (float)g->height; + rect->xmin = floorf(x + (float)g->pos[0]); + rect->xmax = rect->xmin + (float)g->dims[0]; + rect->ymin = floorf(y + (float)g->pos[1]); + rect->ymax = rect->ymin - (float)g->dims[1]; } static void blf_glyph_calc_rect_test(rctf *rect, GlyphBLF *g, float x, float y) @@ -443,9 +444,9 @@ static void blf_glyph_calc_rect_test(rctf *rect, GlyphBLF *g, float x, float y) * width used by BLF_width. This allows that the text slightly * overlaps the clipping border to achieve better alignment. */ rect->xmin = floorf(x); - rect->xmax = rect->xmin + MIN2(g->advance, (float)g->width); + rect->xmax = rect->xmin + MIN2(g->advance, (float)g->dims[0]); rect->ymin = floorf(y); - rect->ymax = rect->ymin - (float)g->height; + rect->ymax = rect->ymin - (float)g->dims[1]; } static void blf_glyph_calc_rect_shadow(rctf *rect, GlyphBLF *g, float x, float y, FontBLF *font) @@ -455,7 +456,7 @@ static void blf_glyph_calc_rect_shadow(rctf *rect, GlyphBLF *g, float x, float y void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, float y) { - if ((!g->width) || (!g->height)) { + if ((!g->dims[0]) || (!g->dims[1])) { return; } @@ -466,7 +467,7 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl g->offset = gc->bitmap_len; - int buff_size = g->width * g->height; + int buff_size = g->dims[0] * g->dims[1]; int bitmap_len = gc->bitmap_len + buff_size; if (bitmap_len > gc->bitmap_len_alloc) { @@ -514,7 +515,7 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl if (font->shadow == 0) { blf_texture_draw(font->shadow_color, - (int[2]){g->width, g->height}, + g->dims, g->offset, rect_ofs.xmin, rect_ofs.ymin, @@ -523,7 +524,7 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl } else if (font->shadow <= 4) { blf_texture3_draw(font->shadow_color, - (int[2]){g->width, g->height}, + g->dims, g->offset, rect_ofs.xmin, rect_ofs.ymin, @@ -532,7 +533,7 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl } else { blf_texture5_draw(font->shadow_color, - (int[2]){g->width, g->height}, + g->dims, g->offset, rect_ofs.xmin, rect_ofs.ymin, @@ -547,39 +548,18 @@ void blf_glyph_render(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, fl #if BLF_BLUR_ENABLE switch (font->blur) { case 3: - blf_texture3_draw(font->color, - (int[2]){g->width, g->height}, - g->offset, - rect.xmin, - rect.ymin, - rect.xmax, - rect.ymax); + blf_texture3_draw( + font->color, g->dims, g->offset, rect.xmin, rect.ymin, rect.xmax, rect.ymax); break; case 5: - blf_texture5_draw(font->color, - (int[2]){g->width, g->height}, - g->offset, - rect.xmin, - rect.ymin, - rect.xmax, - rect.ymax); + blf_texture5_draw( + font->color, g->dims, g->offset, rect.xmin, rect.ymin, rect.xmax, rect.ymax); break; default: - blf_texture_draw(font->color, - (int[2]){g->width, g->height}, - g->offset, - rect.xmin, - rect.ymin, - rect.xmax, - rect.ymax); + blf_texture_draw( + font->color, g->dims, g->offset, rect.xmin, rect.ymin, rect.xmax, rect.ymax); } #else - blf_texture_draw(font->color, - (int[2]){g->width, g->height}, - g->offset, - rect.xmin, - rect.ymin, - rect.xmax, - rect.ymax); + blf_texture_draw(font->color, g->dims, g->offset, rect.xmin, rect.ymin, rect.xmax, rect.ymax); #endif } diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h index efcf9e15100..4ae592d323f 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,19 @@ 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_step_ofs, + const struct rcti *glyph_step_bounds, + const int glyph_advance_x, + const struct rctf *glyph_bounds, + const int glyph_bearing[2], + 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_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h index 6fae3eb4376..362cbf6730f 100644 --- a/source/blender/blenfont/intern/blf_internal_types.h +++ b/source/blender/blenfont/intern/blf_internal_types.h @@ -119,17 +119,16 @@ typedef struct GlyphBLF { */ unsigned char *bitmap; - /* glyph width and height. */ - int width; - int height; + /* Glyph width and height. */ + int dims[2]; int pitch; - /* X and Y bearing of the glyph. + /** + * X and Y bearing of the glyph. * The X bearing is from the origin to the glyph left bbox edge. * The Y bearing is from the baseline to the top of the glyph edge. */ - float pos_x; - float pos_y; + int pos[2]; struct GlyphCacheBLF *glyph_cache; } GlyphBLF; @@ -141,9 +140,8 @@ typedef struct FontBufInfoBLF { /* the same but unsigned char */ unsigned char *cbuf; - /* buffer size, keep signed so comparisons with negative values work */ - int w; - int h; + /** Buffer size, keep signed so comparisons with negative values work. */ + int dims[2]; /* number of channels. */ int ch; diff --git a/source/blender/blenfont/intern/blf_thumbs.c b/source/blender/blenfont/intern/blf_thumbs.c index b7308d47d71..37eed29f6fe 100644 --- a/source/blender/blenfont/intern/blf_thumbs.c +++ b/source/blender/blenfont/intern/blf_thumbs.c @@ -78,8 +78,8 @@ void BLF_thumb_preview(const char *filename, /* Would be done via the BLF API, but we're not using a fontid here */ font->buf_info.cbuf = buf; font->buf_info.ch = channels; - font->buf_info.w = w; - font->buf_info.h = h; + font->buf_info.dims[0] = w; + font->buf_info.dims[1] = h; /* Always create the image with a white font, * the caller can theme how it likes */ 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; |