From f2341f829654c4dc97fcf9fd1f74a6526c4f50ff Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 18 Sep 2015 20:10:26 +1000 Subject: BLF: initial word-wrap support - Adds support for word wrapping to Blender's BLF font library. - Splits lines when width limit is reached or on explicit \n newlines. Details: - Word wrapping is used when `BLF_WORD_WRAP` flag is enabled. - There is a single loop to handle line wrapping, this runs callback, passing in a substring, this way we can avoid code-duplication for all word-wrapped versions of functions... OR... avoid having to add support for word-wrapping directly into each function. - The `ResultBLF` struct was added to be able to get the number of wrapped lines, when calling otherwise unrelated functions such as `BLF_draw/BLF_width/BLF_boundbox`, which can be passed as the last argument to `BLF_*_ex()` functions. - The `ResultBLF` struct is used to store the result of drawing (currently only the number of lines wrapped, and the width). --- source/blender/blenfont/intern/blf.c | 157 ++++++++++-- source/blender/blenfont/intern/blf_font.c | 277 ++++++++++++++++++--- source/blender/blenfont/intern/blf_internal.h | 18 +- .../blender/blenfont/intern/blf_internal_types.h | 9 +- source/blender/blenfont/intern/blf_thumbs.c | 6 +- 5 files changed, 389 insertions(+), 78 deletions(-) (limited to 'source/blender/blenfont/intern') diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c index 127826f98c8..8a48384f06f 100644 --- a/source/blender/blenfont/intern/blf.c +++ b/source/blender/blenfont/intern/blf.c @@ -53,6 +53,8 @@ #include "BIF_gl.h" #include "BLF_api.h" +#include "IMB_colormanagement.h" + #include "blf_internal_types.h" #include "blf_internal.h" @@ -66,6 +68,11 @@ /* call BLF_default_set first! */ #define ASSERT_DEFAULT_SET BLI_assert(global_font_default != -1) +#define BLF_RESULT_CHECK_INIT(r_info) \ +if (r_info) { \ + memset(r_info, 0, sizeof(*(r_info))); \ +} ((void)0) + /* Font array. */ static FontBLF *global_font[BLF_MAX_FONT] = {NULL}; @@ -491,7 +498,7 @@ void BLF_rotation_default(float angle) } } -static void blf_draw__start(FontBLF *font, GLint *mode, GLint *param) +static void blf_draw_gl__start(FontBLF *font, GLint *mode, GLint *param) { /* * The pixmap alignment hack is handle @@ -535,7 +542,7 @@ static void blf_draw__start(FontBLF *font, GLint *mode, GLint *param) glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } -static void blf_draw__end(GLint mode, GLint param) +static void blf_draw_gl__end(GLint mode, GLint param) { /* and restore the original value. */ if (param != GL_MODULATE) @@ -554,29 +561,56 @@ static void blf_draw__end(GLint mode, GLint param) glDisable(GL_TEXTURE_2D); } -void BLF_draw(int fontid, const char *str, size_t len) +void BLF_draw_ex( + int fontid, const char *str, size_t len, + struct ResultBLF *r_info) { FontBLF *font = blf_get(fontid); GLint mode, param; + BLF_RESULT_CHECK_INIT(r_info); + if (font && font->glyph_cache) { - blf_draw__start(font, &mode, ¶m); - blf_font_draw(font, str, len); - blf_draw__end(mode, param); + blf_draw_gl__start(font, &mode, ¶m); + if (font->flags & BLF_WORD_WRAP) { + blf_font_draw__wrap(font, str, len, r_info); + } + else { + blf_font_draw(font, str, len, r_info); + } + blf_draw_gl__end(mode, param); } } +void BLF_draw(int fontid, const char *str, size_t len) +{ + BLF_draw_ex(fontid, str, len, NULL); +} -void BLF_draw_ascii(int fontid, const char *str, size_t len) +void BLF_draw_ascii_ex( + int fontid, const char *str, size_t len, + struct ResultBLF *r_info) { FontBLF *font = blf_get(fontid); GLint mode, param; + BLF_RESULT_CHECK_INIT(r_info); + if (font && font->glyph_cache) { - blf_draw__start(font, &mode, ¶m); - blf_font_draw_ascii(font, str, len); - blf_draw__end(mode, param); + blf_draw_gl__start(font, &mode, ¶m); + if (font->flags & BLF_WORD_WRAP) { + /* use non-ascii draw function for word-wrap */ + blf_font_draw__wrap(font, str, len, r_info); + } + else { + blf_font_draw_ascii(font, str, len, r_info); + } + blf_draw_gl__end(mode, param); } } +void BLF_draw_ascii(int fontid, const char *str, size_t len) +{ + BLF_draw_ascii_ex(fontid, str, len, NULL); +} int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth) { @@ -585,9 +619,9 @@ int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth) int columns = 0; if (font && font->glyph_cache) { - blf_draw__start(font, &mode, ¶m); + blf_draw_gl__start(font, &mode, ¶m); columns = blf_font_draw_mono(font, str, len, cwidth); - blf_draw__end(mode, param); + blf_draw_gl__end(mode, param); } return columns; @@ -633,21 +667,34 @@ size_t BLF_width_to_rstrlen(int fontid, const char *str, size_t len, float width return 0; } -void BLF_boundbox(int fontid, const char *str, size_t len, rctf *box) +void BLF_boundbox_ex( + int fontid, const char *str, size_t len, rctf *r_box, + struct ResultBLF *r_info) { FontBLF *font = blf_get(fontid); + BLF_RESULT_CHECK_INIT(r_info); + if (font) { - blf_font_boundbox(font, str, len, box); + if (font->flags & BLF_WORD_WRAP) { + blf_font_boundbox__wrap(font, str, len, r_box, r_info); + } + else { + blf_font_boundbox(font, str, len, r_box, r_info); + } } } +void BLF_boundbox(int fontid, const char *str, size_t len, rctf *r_box) +{ + BLF_boundbox_ex(fontid, str, len, r_box, NULL); +} void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_width, float *r_height) { FontBLF *font = blf_get(fontid); if (font && font->glyph_cache) { - blf_font_width_and_height(font, str, len, r_width, r_height); + blf_font_width_and_height(font, str, len, r_width, r_height, NULL); } else { *r_width = *r_height = 0.0f; @@ -662,16 +709,24 @@ void BLF_width_and_height_default(const char *str, size_t len, float *r_width, f BLF_width_and_height(global_font_default, str, len, r_width, r_height); } -float BLF_width(int fontid, const char *str, size_t len) +float BLF_width_ex( + int fontid, const char *str, size_t len, + struct ResultBLF *r_info) { FontBLF *font = blf_get(fontid); + BLF_RESULT_CHECK_INIT(r_info); + if (font && font->glyph_cache) { - return blf_font_width(font, str, len); + return blf_font_width(font, str, len, r_info); } return 0.0f; } +float BLF_width(int fontid, const char *str, size_t len) +{ + return BLF_width_ex(fontid, str, len, NULL); +} float BLF_fixed_width(int fontid) { @@ -692,18 +747,26 @@ float BLF_width_default(const char *str, size_t len) return BLF_width(global_font_default, str, len); } -float BLF_height(int fontid, const char *str, size_t len) +float BLF_height_ex( + int fontid, const char *str, size_t len, + struct ResultBLF *r_info) { FontBLF *font = blf_get(fontid); + BLF_RESULT_CHECK_INIT(r_info); + if (font && font->glyph_cache) { - return blf_font_height(font, str, len); + return blf_font_height(font, str, len, r_info); } return 0.0f; } +float BLF_height(int fontid, const char *str, size_t len) +{ + return BLF_height_ex(fontid, str, len, NULL); +} -float BLF_height_max(int fontid) +int BLF_height_max(int fontid) { FontBLF *font = blf_get(fontid); @@ -711,7 +774,7 @@ float BLF_height_max(int fontid) return font->glyph_cache->max_glyph_height; } - return 0.0f; + return 0; } float BLF_width_max(int fontid) @@ -789,6 +852,15 @@ void BLF_clipping_default(float xmin, float ymin, float xmax, float ymax) } } +void BLF_wordwrap(int fontid, int wrap_width) +{ + FontBLF *font = blf_get(fontid); + + if (font) { + font->wrap_width = wrap_width; + } +} + void BLF_shadow(int fontid, int level, float r, float g, float b, float a) { FontBLF *font = blf_get(fontid); @@ -831,21 +903,52 @@ void BLF_buffer_col(int fontid, float r, float g, float b, float a) FontBLF *font = blf_get(fontid); if (font) { - font->buf_info.col[0] = r; - font->buf_info.col[1] = g; - font->buf_info.col[2] = b; - font->buf_info.col[3] = a; + ARRAY_SET_ITEMS(font->buf_info.col_init, r, g, b, a); } } -void BLF_draw_buffer(int fontid, const char *str) + +static void blf_draw_buffer__start(FontBLF *font) +{ + FontBufInfoBLF *buf_info = &font->buf_info; + + buf_info->col_char[0] = buf_info->col_init[0] * 255; + buf_info->col_char[1] = buf_info->col_init[1] * 255; + buf_info->col_char[2] = buf_info->col_init[2] * 255; + buf_info->col_char[3] = buf_info->col_init[3] * 255; + + if (buf_info->display) { + copy_v4_v4(buf_info->col_float, buf_info->col_init); + IMB_colormanagement_display_to_scene_linear_v3(buf_info->col_float, buf_info->display); + } + else { + srgb_to_linearrgb_v4(buf_info->col_float, buf_info->col_init); + } +} +static void blf_draw_buffer__end(void) {} + +void BLF_draw_buffer_ex( + int fontid, const char *str, size_t len, + struct ResultBLF *r_info) { FontBLF *font = blf_get(fontid); if (font && font->glyph_cache && (font->buf_info.fbuf || font->buf_info.cbuf)) { - blf_font_buffer(font, str); + blf_draw_buffer__start(font); + if (font->flags & BLF_WORD_WRAP) { + blf_font_draw_buffer__wrap(font, str, len, r_info); + } + else { + blf_font_draw_buffer(font, str, len, r_info); + } + blf_draw_buffer__end(); } } +void BLF_draw_buffer( + int fontid, const char *str, size_t len) +{ + BLF_draw_buffer_ex(fontid, str, len, NULL); +} #ifdef DEBUG void BLF_state_print(int fontid) diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index 46e0e0e5359..edb982538ff 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -58,8 +58,6 @@ #include "BIF_gl.h" #include "BLF_api.h" -#include "IMB_colormanagement.h" - #include "blf_internal_types.h" #include "blf_internal.h" @@ -174,12 +172,14 @@ static void blf_font_ensure_ascii_table(FontBLF *font) } \ } (void)0 -void blf_font_draw(FontBLF *font, const char *str, size_t len) +static void blf_font_draw_ex( + FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info, + int pen_y) { unsigned int c; GlyphBLF *g, *g_prev = NULL; FT_Vector delta; - int pen_x = 0, pen_y = 0; + int pen_x = 0; size_t i = 0; GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table; @@ -203,15 +203,26 @@ void blf_font_draw(FontBLF *font, const char *str, size_t len) pen_x += g->advance_i; g_prev = g; } + + if (r_info) { + r_info->lines = 1; + r_info->width = pen_x; + } +} +void blf_font_draw(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info) +{ + blf_font_draw_ex(font, str, len, r_info, 0); } /* faster version of blf_font_draw, ascii only for view dimensions */ -void blf_font_draw_ascii(FontBLF *font, const char *str, size_t len) +static void blf_font_draw_ascii_ex( + FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info, + int pen_y) { unsigned char c; GlyphBLF *g, *g_prev = NULL; FT_Vector delta; - int pen_x = 0, pen_y = 0; + int pen_x = 0; GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table; BLF_KERNING_VARS(font, has_kerning, kern_mode); @@ -231,6 +242,15 @@ void blf_font_draw_ascii(FontBLF *font, const char *str, size_t len) pen_x += g->advance_i; g_prev = g; } + + if (r_info) { + r_info->lines = 1; + r_info->width = pen_x; + } +} +void blf_font_draw_ascii(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info) +{ + blf_font_draw_ascii_ex(font, str, len, r_info, 0); } /* use fixed column width, but an utf8 character may occupy multiple columns */ @@ -268,24 +288,22 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth) } /* Sanity checks are done by BLF_draw_buffer() */ -void blf_font_buffer(FontBLF *font, const char *str) +static void blf_font_draw_buffer_ex( + FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info, + int pen_y) { unsigned int c; GlyphBLF *g, *g_prev = NULL; FT_Vector delta; - int pen_x = (int)font->pos[0], pen_y = 0; + int pen_x = (int)font->pos[0]; + int pen_y_basis = (int)font->pos[1] + pen_y; size_t i = 0; GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table; /* buffer specific vars */ FontBufInfoBLF *buf_info = &font->buf_info; - float b_col_float[4]; - const unsigned char b_col_char[4] = { - (unsigned char)(buf_info->col[0] * 255), - (unsigned char)(buf_info->col[1] * 255), - (unsigned char)(buf_info->col[2] * 255), - (unsigned char)(buf_info->col[3] * 255)}; - + const float *b_col_float = buf_info->col_float; + const unsigned char *b_col_char = buf_info->col_char; int chx, chy; int y, x; float a; @@ -295,15 +313,8 @@ void blf_font_buffer(FontBLF *font, const char *str) blf_font_ensure_ascii_table(font); /* another buffer specific call for color conversion */ - if (buf_info->display) { - copy_v4_v4(b_col_float, buf_info->col); - IMB_colormanagement_display_to_scene_linear_v3(b_col_float, buf_info->display); - } - else { - srgb_to_linearrgb_v4(b_col_float, buf_info->col); - } - while (str[i]) { + while ((i < len) && str[i]) { BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table); if (UNLIKELY(c == BLI_UTF8_ERR)) @@ -314,13 +325,13 @@ void blf_font_buffer(FontBLF *font, const char *str) BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x); chx = pen_x + ((int)g->pos_x); - chy = (int)font->pos[1] + g->height; + chy = pen_y_basis + g->height; if (g->pitch < 0) { - pen_y = (int)font->pos[1] + (g->height - (int)g->pos_y); + pen_y = pen_y_basis + (g->height - (int)g->pos_y); } else { - pen_y = (int)font->pos[1] - (g->height - (int)g->pos_y); + pen_y = pen_y_basis - (g->height - (int)g->pos_y); } if ((chx + g->width) >= 0 && chx < buf_info->w && (pen_y + g->height) >= 0 && pen_y < buf_info->h) { @@ -429,6 +440,16 @@ void blf_font_buffer(FontBLF *font, const char *str) pen_x += g->advance_i; g_prev = g; } + + if (r_info) { + r_info->lines = 1; + r_info->width = pen_x; + } +} +void blf_font_draw_buffer( + FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info) +{ + blf_font_draw_buffer_ex(font, str, len, r_info, 0); } size_t blf_font_width_to_strlen(FontBLF *font, const char *str, size_t len, float width, float *r_width) @@ -558,12 +579,14 @@ size_t blf_font_width_to_rstrlen(FontBLF *font, const char *str, size_t len, flo return i_prev; } -void blf_font_boundbox(FontBLF *font, const char *str, size_t len, rctf *box) +static void blf_font_boundbox_ex( + FontBLF *font, const char *str, size_t len, rctf *box, struct ResultBLF *r_info, + int pen_y) { unsigned int c; GlyphBLF *g, *g_prev = NULL; FT_Vector delta; - int pen_x = 0, pen_y = 0; + int pen_x = 0; size_t i = 0; GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table; @@ -609,9 +632,168 @@ void blf_font_boundbox(FontBLF *font, const char *str, size_t len, rctf *box) box->xmax = 0.0f; box->ymax = 0.0f; } + + if (r_info) { + r_info->lines = 1; + r_info->width = pen_x; + } } +void blf_font_boundbox(FontBLF *font, const char *str, size_t len, rctf *r_box, struct ResultBLF *r_info) +{ + blf_font_boundbox_ex(font, str, len, r_box, r_info, 0); +} + + +/* -------------------------------------------------------------------- */ +/** \name Word-Wrap Support + * \{ */ + -void blf_font_width_and_height(FontBLF *font, const char *str, size_t len, float *width, float *height) +/** + * Generic function to add word-wrap support for other existing functions. + * + * Wraps on spaces and respects newlines. + * Intentionally ignores non-unix newlines, tabs and more advanced text formatting. + * + * \note If we want rich text - we better have a higher level API to handle that + * (color, bold, switching fonts... etc). + */ +static void blf_font_wrap_apply( + FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info, + void (*callback)(FontBLF *font, const char *str, size_t len, int pen_y, void *userdata), + void *userdata) +{ + unsigned int c; + GlyphBLF *g, *g_prev = NULL; + FT_Vector delta; + int pen_x = 0, pen_y = 0; + size_t i = 0; + GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table; + int lines = 0; + + BLF_KERNING_VARS(font, has_kerning, kern_mode); + + struct WordWrapVars { + int wrap_width; + size_t start, last[2]; + } wrap = {font->wrap_width != -1 ? font->wrap_width : INT_MAX, 0, {0, 0}}; + + blf_font_ensure_ascii_table(font); + // printf("%s wrapping (%d, %d) `%s`:\n", __func__, len, strlen(str), str); + while ((i < len) && str[i]) { + + /* wrap vars */ + size_t i_curr = i; + int pen_x_next; + bool do_draw = false; + + BLF_UTF8_NEXT_FAST(font, 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(font, kern_mode, g_prev, g, delta, pen_x); + + /** + * Implementation Detail (utf8). + * + * Take care with single byte offsets here, + * since this is utf8 we can't be sure a single byte is a single character. + * + * This is _only_ done when we know for sure the character is ascii (newline or a space). + */ + pen_x_next = pen_x + g->advance_i; + if (UNLIKELY((pen_x_next >= wrap.wrap_width) && (wrap.start != wrap.last[0]))) { + do_draw = true; + } + else if (UNLIKELY(((i < len) && str[i]) == 0)) { + /* need check here for trailing newline, else we draw it */ + wrap.last[0] = i + ((g->c != '\n') ? 1 : 0); + wrap.last[1] = i; + do_draw = true; + } + else if (UNLIKELY(g->c == '\n')) { + wrap.last[0] = i_curr + 1; + wrap.last[1] = i; + do_draw = true; + } + else if (UNLIKELY(g->c != ' ' && (g_prev ? g_prev->c == ' ' : false))) { + wrap.last[0] = i_curr; + wrap.last[1] = i; + } + + if (UNLIKELY(do_draw)) { + // printf("(%d..%d) `%.*s`\n", wrap.start, wrap.last[0], (wrap.last[0] - wrap.start) - 1, &str[wrap.start]); + callback(font, &str[wrap.start], (wrap.last[0] - wrap.start) - 1, pen_y, userdata); + wrap.start = wrap.last[0]; + i = wrap.last[1]; + pen_x = 0; + pen_y -= font->glyph_cache->max_glyph_height; + g_prev = NULL; + lines += 1; + continue; + } + + pen_x = pen_x_next; + g_prev = g; + } + + // printf("done! %d lines\n", lines); + + if (r_info) { + r_info->lines = lines; + /* width of last line only (with wrapped lines) */ + r_info->width = pen_x; + } +} + +/* blf_font_draw__wrap */ +static void blf_font_draw__wrap_cb(FontBLF *font, const char *str, size_t len, int pen_y, void *UNUSED(userdata)) +{ + blf_font_draw_ex(font, str, len, NULL, pen_y); +} +void blf_font_draw__wrap(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info) +{ + blf_font_wrap_apply(font, str, len, r_info, blf_font_draw__wrap_cb, NULL); +} + +/* blf_font_boundbox__wrap */ +static void blf_font_boundbox_wrap_cb(FontBLF *font, const char *str, size_t len, int pen_y, void *userdata) +{ + rctf *box = userdata; + rctf box_single; + + blf_font_boundbox_ex(font, str, len, &box_single, NULL, pen_y); + BLI_rctf_union(box, &box_single); +} +void blf_font_boundbox__wrap(FontBLF *font, const char *str, size_t len, rctf *box, struct ResultBLF *r_info) +{ + box->xmin = 32000.0f; + box->xmax = -32000.0f; + box->ymin = 32000.0f; + box->ymax = -32000.0f; + + blf_font_wrap_apply(font, str, len, r_info, blf_font_boundbox_wrap_cb, box); +} + +/* blf_font_draw_buffer__wrap */ +static void blf_font_draw_buffer__wrap_cb(FontBLF *font, const char *str, size_t len, int pen_y, void *UNUSED(userdata)) +{ + blf_font_draw_buffer_ex(font, str, len, NULL, pen_y); +} +void blf_font_draw_buffer__wrap(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info) +{ + blf_font_wrap_apply(font, str, len, r_info, blf_font_draw_buffer__wrap_cb, NULL); +} + +/** \} */ + + +void blf_font_width_and_height( + FontBLF *font, const char *str, size_t len, + float *r_width, float *r_height, struct ResultBLF *r_info) { float xa, ya; rctf box; @@ -625,12 +807,17 @@ void blf_font_width_and_height(FontBLF *font, const char *str, size_t len, float ya = 1.0f; } - blf_font_boundbox(font, str, len, &box); - *width = (BLI_rctf_size_x(&box) * xa); - *height = (BLI_rctf_size_y(&box) * ya); + if (font->flags & BLF_WORD_WRAP) { + blf_font_boundbox__wrap(font, str, len, &box, r_info); + } + else { + blf_font_boundbox(font, str, len, &box, r_info); + } + *r_width = (BLI_rctf_size_x(&box) * xa); + *r_height = (BLI_rctf_size_y(&box) * ya); } -float blf_font_width(FontBLF *font, const char *str, size_t len) +float blf_font_width(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info) { float xa; rctf box; @@ -640,11 +827,16 @@ float blf_font_width(FontBLF *font, const char *str, size_t len) else xa = 1.0f; - blf_font_boundbox(font, str, len, &box); + if (font->flags & BLF_WORD_WRAP) { + blf_font_boundbox__wrap(font, str, len, &box, r_info); + } + else { + blf_font_boundbox(font, str, len, &box, r_info); + } return BLI_rctf_size_x(&box) * xa; } -float blf_font_height(FontBLF *font, const char *str, size_t len) +float blf_font_height(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info) { float ya; rctf box; @@ -654,7 +846,12 @@ float blf_font_height(FontBLF *font, const char *str, size_t len) else ya = 1.0f; - blf_font_boundbox(font, str, len, &box); + if (font->flags & BLF_WORD_WRAP) { + blf_font_boundbox__wrap(font, str, len, &box, r_info); + } + else { + blf_font_boundbox(font, str, len, &box, r_info); + } return BLI_rctf_size_y(&box) * ya; } @@ -744,10 +941,10 @@ static void blf_font_fill(FontBLF *font) font->buf_info.w = 0; font->buf_info.h = 0; font->buf_info.ch = 0; - font->buf_info.col[0] = 0; - font->buf_info.col[1] = 0; - font->buf_info.col[2] = 0; - font->buf_info.col[3] = 0; + font->buf_info.col_init[0] = 0; + font->buf_info.col_init[1] = 0; + font->buf_info.col_init[2] = 0; + font->buf_info.col_init[3] = 0; font->ft_lib = ft_lib; font->ft_lib_mutex = &ft_lib_mutex; diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h index 85410a4d856..55bc61e0e43 100644 --- a/source/blender/blenfont/intern/blf_internal.h +++ b/source/blender/blenfont/intern/blf_internal.h @@ -31,6 +31,7 @@ #ifndef __BLF_INTERNAL_H__ #define __BLF_INTERNAL_H__ +struct ResultBLF; struct FontBLF; struct GlyphBLF; struct GlyphCacheBLF; @@ -51,16 +52,19 @@ struct FontBLF *blf_font_new_from_mem(const char *name, const unsigned char *mem void blf_font_attach_from_mem(struct FontBLF *font, const unsigned char *mem, int mem_size); void blf_font_size(struct FontBLF *font, unsigned int size, unsigned int dpi); -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); +void blf_font_draw(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info); +void blf_font_draw__wrap(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info); +void blf_font_draw_ascii(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info); 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); +void blf_font_draw_buffer(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info); +void blf_font_draw_buffer__wrap(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info); 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); -float blf_font_height(struct FontBLF *font, const char *str, size_t len); +void blf_font_boundbox(struct FontBLF *font, const char *str, size_t len, struct rctf *r_box, struct ResultBLF *r_info); +void blf_font_boundbox__wrap(struct FontBLF *font, const char *str, size_t len, struct rctf *r_box, struct ResultBLF *r_info); +void blf_font_width_and_height(struct FontBLF *font, const char *str, size_t len, float *r_width, float *r_height, struct ResultBLF *r_info); +float blf_font_width(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info); +float blf_font_height(struct FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info); float blf_font_fixed_width(struct FontBLF *font); int blf_font_count_missing_chars(struct FontBLF *font, const char *str, const size_t len, int *r_tot_chars); diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h index 1404b9de250..f17401a9991 100644 --- a/source/blender/blenfont/intern/blf_internal_types.h +++ b/source/blender/blenfont/intern/blf_internal_types.h @@ -152,7 +152,11 @@ typedef struct FontBufInfoBLF { /* and the color, the alphas is get from the glyph! * color is srgb space */ - float col[4]; + float col_init[4]; + /* cached conversion from 'col_init' */ + unsigned char col_char[4]; + float col_float[4]; + } FontBufInfoBLF; typedef struct FontBLF { @@ -195,6 +199,9 @@ typedef struct FontBLF { /* clipping rectangle. */ rctf clip_rec; + /* the width to wrap the text, see BLF_WORD_WRAP */ + int wrap_width; + /* font dpi (default 72). */ unsigned int dpi; diff --git a/source/blender/blenfont/intern/blf_thumbs.c b/source/blender/blenfont/intern/blf_thumbs.c index 4eea5d581d0..76479593b54 100644 --- a/source/blender/blenfont/intern/blf_thumbs.c +++ b/source/blender/blenfont/intern/blf_thumbs.c @@ -84,7 +84,7 @@ void BLF_thumb_preview( /* Always create the image with a white font, * the caller can theme how it likes */ - memcpy(font->buf_info.col, font_color, sizeof(font->buf_info.col)); + memcpy(font->buf_info.col_init, font_color, sizeof(font->buf_info.col_init)); font->pos[1] = (float)h; font_size_curr = font_size; @@ -110,10 +110,10 @@ void BLF_thumb_preview( if (blf_font_count_missing_chars( font, draw_str_i18n, draw_str_i18n_len, &draw_str_i18n_nbr) > (draw_str_i18n_nbr / 2)) { - blf_font_buffer(font, draw_str[i]); + blf_font_draw_buffer(font, draw_str[i], (size_t)draw_str_i18n_nbr, NULL); } else { - blf_font_buffer(font, draw_str_i18n); + blf_font_draw_buffer(font, draw_str_i18n, draw_str_i18n_len, NULL); } } -- cgit v1.2.3