From a960dc451930796ca310cc88f00fb701374b2f7f Mon Sep 17 00:00:00 2001 From: Richard Antalik Date: Fri, 13 Sep 2019 17:22:42 -0700 Subject: BLF: make library glyph cache handling thread-safe Functions that utilize glyph cache should lock and unlock cache by calling `blf_glyph_cache_acquire()` and `blf_glyph_cache_release()`. Function `blf_glyph_cache_acquire()` will create glyph cache, if it doesn't exist. Locking mutex is global and shared by all fonts. Reviewed By: brecht Differential Revision: https://developer.blender.org/D5701 --- source/blender/blenfont/intern/blf.c | 36 +-- source/blender/blenfont/intern/blf_font.c | 261 +++++++++++++++------ source/blender/blenfont/intern/blf_glyph.c | 65 +++-- source/blender/blenfont/intern/blf_internal.h | 16 +- .../blender/blenfont/intern/blf_internal_types.h | 7 +- 5 files changed, 274 insertions(+), 111 deletions(-) (limited to 'source/blender') diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c index 793e9805899..8e1ff77b1c7 100644 --- a/source/blender/blenfont/intern/blf.c +++ b/source/blender/blenfont/intern/blf.c @@ -608,7 +608,7 @@ void BLF_draw_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_in BLF_RESULT_CHECK_INIT(r_info); - if (font && font->glyph_cache) { + if (font) { blf_draw_gl__start(font); if (font->flags & BLF_WORD_WRAP) { blf_font_draw__wrap(font, str, len, r_info); @@ -634,7 +634,7 @@ void BLF_draw_ascii_ex(int fontid, const char *str, size_t len, struct ResultBLF BLF_RESULT_CHECK_INIT(r_info); - if (font && font->glyph_cache) { + if (font) { blf_draw_gl__start(font); if (font->flags & BLF_WORD_WRAP) { /* use non-ascii draw function for word-wrap */ @@ -646,6 +646,7 @@ void BLF_draw_ascii_ex(int fontid, const char *str, size_t len, struct ResultBLF blf_draw_gl__end(font); } } + void BLF_draw_ascii(int fontid, const char *str, size_t len) { if (len == 0 || str[0] == '\0') { @@ -664,7 +665,7 @@ int BLF_draw_mono(int fontid, const char *str, size_t len, int cwidth) FontBLF *font = blf_get(fontid); int columns = 0; - if (font && font->glyph_cache) { + if (font) { blf_draw_gl__start(font); columns = blf_font_draw_mono(font, str, len, cwidth); blf_draw_gl__end(font); @@ -729,6 +730,7 @@ void BLF_boundbox_ex( } } } + void BLF_boundbox(int fontid, const char *str, size_t len, rctf *r_box) { BLF_boundbox_ex(fontid, str, len, r_box, NULL); @@ -738,7 +740,7 @@ void BLF_width_and_height(int fontid, const char *str, size_t len, float *r_widt { FontBLF *font = blf_get(fontid); - if (font && font->glyph_cache) { + if (font) { blf_font_width_and_height(font, str, len, r_width, r_height, NULL); } else { @@ -752,12 +754,13 @@ float BLF_width_ex(int fontid, const char *str, size_t len, struct ResultBLF *r_ BLF_RESULT_CHECK_INIT(r_info); - if (font && font->glyph_cache) { + if (font) { 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); @@ -767,7 +770,7 @@ float BLF_fixed_width(int fontid) { FontBLF *font = blf_get(fontid); - if (font && font->glyph_cache) { + if (font) { return blf_font_fixed_width(font); } @@ -780,12 +783,13 @@ float BLF_height_ex(int fontid, const char *str, size_t len, struct ResultBLF *r BLF_RESULT_CHECK_INIT(r_info); - if (font && font->glyph_cache) { + if (font) { 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); @@ -795,8 +799,8 @@ int BLF_height_max(int fontid) { FontBLF *font = blf_get(fontid); - if (font && font->glyph_cache) { - return font->glyph_cache->glyph_height_max; + if (font) { + return blf_font_height_max(font); } return 0; @@ -806,8 +810,8 @@ float BLF_width_max(int fontid) { FontBLF *font = blf_get(fontid); - if (font && font->glyph_cache) { - return font->glyph_cache->glyph_width_max; + if (font) { + return blf_font_width_max(font); } return 0.0f; @@ -817,8 +821,8 @@ float BLF_descender(int fontid) { FontBLF *font = blf_get(fontid); - if (font && font->glyph_cache) { - return font->glyph_cache->descender; + if (font) { + return blf_font_descender(font); } return 0.0f; @@ -828,8 +832,8 @@ float BLF_ascender(int fontid) { FontBLF *font = blf_get(fontid); - if (font && font->glyph_cache) { - return font->glyph_cache->ascender; + if (font) { + return blf_font_ascender(font); } return 0.0f; @@ -939,7 +943,7 @@ void BLF_draw_buffer_ex(int fontid, const char *str, size_t len, struct ResultBL { FontBLF *font = blf_get(fontid); - if (font && font->glyph_cache && (font->buf_info.fbuf || font->buf_info.cbuf)) { + if (font && (font->buf_info.fbuf || font->buf_info.cbuf)) { blf_draw_buffer__start(font); if (font->flags & BLF_WORD_WRAP) { blf_font_draw_buffer__wrap(font, str, len, r_info); diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index d75da6a126f..e0dfa6a2223 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -68,6 +68,7 @@ BatchBLF g_batch; /* freetype2 handle ONLY for this file!. */ static FT_Library ft_lib; static SpinLock ft_lib_mutex; +static SpinLock blf_glyph_cache_mutex; /* -------------------------------------------------------------------- */ /** \name Glyph Batching @@ -216,6 +217,7 @@ int blf_font_init(void) { memset(&g_batch, 0, sizeof(g_batch)); BLI_spin_init(&ft_lib_mutex); + BLI_spin_init(&blf_glyph_cache_mutex); return FT_Init_FreeType(&ft_lib); } @@ -223,6 +225,7 @@ void blf_font_exit(void) { FT_Done_FreeType(ft_lib); BLI_spin_end(&ft_lib_mutex); + BLI_spin_end(&blf_glyph_cache_mutex); blf_batch_draw_exit(); } @@ -231,11 +234,14 @@ void blf_font_size(FontBLF *font, unsigned int size, unsigned int dpi) GlyphCacheBLF *gc; FT_Error err; + blf_glyph_cache_acquire(font); + gc = blf_glyph_cache_find(font, size, dpi); if (gc) { font->glyph_cache = gc; /* Optimization: do not call FT_Set_Char_Size if size did not change. */ if (font->size == size && font->dpi == dpi) { + blf_glyph_cache_release(font); return; } } @@ -244,6 +250,8 @@ void blf_font_size(FontBLF *font, unsigned int size, unsigned int dpi) if (err) { /* FIXME: here we can go through the fixed size and choice a close one */ printf("The current font don't support the size, %u and dpi, %u\n", size, dpi); + + blf_glyph_cache_release(font); return; } @@ -259,28 +267,35 @@ void blf_font_size(FontBLF *font, unsigned int size, unsigned int dpi) font->glyph_cache = NULL; } } + blf_glyph_cache_release(font); } -static void blf_font_ensure_ascii_table(FontBLF *font) +static GlyphBLF **blf_font_ensure_ascii_table(FontBLF *font, GlyphCacheBLF *gc) { - GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table; + GlyphBLF **glyph_ascii_table; + + glyph_ascii_table = gc->glyph_ascii_table; /* build ascii on demand */ if (glyph_ascii_table['0'] == NULL) { GlyphBLF *g; unsigned int i; for (i = 0; i < 256; i++) { - g = blf_glyph_search(font->glyph_cache, i); + g = blf_glyph_search(gc, i); if (!g) { FT_UInt glyph_index = FT_Get_Char_Index(font->face, i); - g = blf_glyph_add(font, glyph_index, i); + g = blf_glyph_add(font, gc, glyph_index, i); } glyph_ascii_table[i] = g; } } + + return glyph_ascii_table; } -static void blf_font_ensure_ascii_kerning(FontBLF *font, const FT_UInt kern_mode) +static void blf_font_ensure_ascii_kerning(FontBLF *font, + GlyphCacheBLF *gc, + const FT_UInt kern_mode) { KerningCacheBLF *kc = font->kerning_cache; @@ -289,7 +304,7 @@ static void blf_font_ensure_ascii_kerning(FontBLF *font, const FT_UInt kern_mode if (!kc || kc->mode != kern_mode) { font->kerning_cache = kc = blf_kerning_cache_find(font); if (!kc) { - font->kerning_cache = kc = blf_kerning_cache_new(font); + font->kerning_cache = kc = blf_kerning_cache_new(font, gc); } } } @@ -300,16 +315,16 @@ static void blf_font_ensure_ascii_kerning(FontBLF *font, const FT_UInt kern_mode */ /* Note, - * blf_font_ensure_ascii_table(font); must be called before this macro */ + * blf_font_ensure_ascii_table(font, gc); must be called before this macro */ -#define BLF_UTF8_NEXT_FAST(_font, _g, _str, _i, _c, _glyph_ascii_table) \ +#define BLF_UTF8_NEXT_FAST(_font, _gc, _g, _str, _i, _c, _glyph_ascii_table) \ if (((_c) = (_str)[_i]) < 0x80) { \ _g = (_glyph_ascii_table)[_c]; \ _i++; \ } \ else if ((_c = BLI_str_utf8_as_unicode_step(_str, &(_i))) != BLI_UTF8_ERR) { \ - if ((_g = blf_glyph_search((_font)->glyph_cache, _c)) == NULL) { \ - _g = blf_glyph_add(_font, FT_Get_Char_Index((_font)->face, _c), _c); \ + if ((_g = blf_glyph_search(_gc, _c)) == NULL) { \ + _g = blf_glyph_add(_font, _gc, FT_Get_Char_Index((_font)->face, _c), _c); \ } \ } \ else { \ @@ -325,7 +340,7 @@ static void blf_font_ensure_ascii_kerning(FontBLF *font, const FT_UInt kern_mode (FT_UInt)FT_KERNING_UNFITTED) /* Note, - * blf_font_ensure_ascii_kerning(font, kern_mode); must be called before this macro */ + * blf_font_ensure_ascii_kerning(font, gc, kern_mode); must be called before this macro */ #define BLF_KERNING_STEP_FAST(_font, _kern_mode, _g_prev, _g, _c_prev, _c, _pen_x) \ { \ @@ -353,29 +368,33 @@ static void blf_font_ensure_ascii_kerning(FontBLF *font, const FT_UInt kern_mode } \ (void)0 -static void blf_font_draw_ex( - FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info, int pen_y) +static void blf_font_draw_ex(FontBLF *font, + GlyphCacheBLF *gc, + const char *str, + size_t len, + 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; - GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table; if (len == 0) { /* early output, don't do any IMM OpenGL. */ return; } + GlyphBLF **glyph_ascii_table = blf_font_ensure_ascii_table(font, gc); + BLF_KERNING_VARS(font, has_kerning, kern_mode); - blf_font_ensure_ascii_table(font); - blf_font_ensure_ascii_kerning(font, kern_mode); + blf_font_ensure_ascii_kerning(font, gc, kern_mode); blf_batch_draw_begin(font); while ((i < len) && str[i]) { - BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table); + BLF_UTF8_NEXT_FAST(font, gc, g, str, i, c, glyph_ascii_table); if (UNLIKELY(c == BLI_UTF8_ERR)) { break; @@ -388,7 +407,7 @@ static void blf_font_draw_ex( } /* do not return this loop if clipped, we want every character tested */ - blf_glyph_render(font, g, (float)pen_x, (float)pen_y); + blf_glyph_render(font, gc, g, (float)pen_x, (float)pen_y); pen_x += g->advance_i; g_prev = g; @@ -404,7 +423,9 @@ static void blf_font_draw_ex( } 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); + GlyphCacheBLF *gc = blf_glyph_cache_acquire(font); + blf_font_draw_ex(font, gc, str, len, r_info, 0); + blf_glyph_cache_release(font); } /* faster version of blf_font_draw, ascii only for view dimensions */ @@ -414,12 +435,13 @@ static void blf_font_draw_ascii_ex( unsigned int c, c_prev = BLI_UTF8_ERR; GlyphBLF *g, *g_prev = NULL; int pen_x = 0; - GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table; + + GlyphCacheBLF *gc = blf_glyph_cache_acquire(font); + GlyphBLF **glyph_ascii_table = blf_font_ensure_ascii_table(font, gc); BLF_KERNING_VARS(font, has_kerning, kern_mode); - blf_font_ensure_ascii_table(font); - blf_font_ensure_ascii_kerning(font, kern_mode); + blf_font_ensure_ascii_kerning(font, gc, kern_mode); blf_batch_draw_begin(font); @@ -433,7 +455,7 @@ static void blf_font_draw_ascii_ex( } /* do not return this loop if clipped, we want every character tested */ - blf_glyph_render(font, g, (float)pen_x, (float)pen_y); + blf_glyph_render(font, gc, g, (float)pen_x, (float)pen_y); pen_x += g->advance_i; g_prev = g; @@ -446,7 +468,10 @@ static void blf_font_draw_ascii_ex( r_info->lines = 1; r_info->width = pen_x; } + + blf_glyph_cache_release(font); } + 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); @@ -460,14 +485,14 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth) int col, columns = 0; int pen_x = 0, pen_y = 0; size_t i = 0; - GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table; - blf_font_ensure_ascii_table(font); + GlyphCacheBLF *gc = blf_glyph_cache_acquire(font); + GlyphBLF **glyph_ascii_table = blf_font_ensure_ascii_table(font, gc); blf_batch_draw_begin(font); while ((i < len) && str[i]) { - BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table); + BLF_UTF8_NEXT_FAST(font, gc, g, str, i, c, glyph_ascii_table); if (UNLIKELY(c == BLI_UTF8_ERR)) { break; @@ -477,7 +502,7 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth) } /* do not return this loop if clipped, we want every character tested */ - blf_glyph_render(font, g, (float)pen_x, (float)pen_y); + blf_glyph_render(font, gc, g, (float)pen_x, (float)pen_y); col = BLI_wcwidth((wchar_t)c); if (col < 0) { @@ -490,19 +515,25 @@ int blf_font_draw_mono(FontBLF *font, const char *str, size_t len, int cwidth) blf_batch_draw_end(); + blf_glyph_cache_release(font); return columns; } /* Sanity checks are done by BLF_draw_buffer() */ -static void blf_font_draw_buffer_ex( - FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info, int pen_y) +static void blf_font_draw_buffer_ex(FontBLF *font, + GlyphCacheBLF *gc, + const char *str, + size_t len, + struct ResultBLF *r_info, + int pen_y) { unsigned int c, c_prev = BLI_UTF8_ERR; GlyphBLF *g, *g_prev = NULL; 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; + + GlyphBLF **glyph_ascii_table = blf_font_ensure_ascii_table(font, gc); /* buffer specific vars */ FontBufInfoBLF *buf_info = &font->buf_info; @@ -513,13 +544,12 @@ static void blf_font_draw_buffer_ex( BLF_KERNING_VARS(font, has_kerning, kern_mode); - blf_font_ensure_ascii_table(font); - blf_font_ensure_ascii_kerning(font, kern_mode); + blf_font_ensure_ascii_kerning(font, gc, kern_mode); /* another buffer specific call for color conversion */ while ((i < len) && str[i]) { - BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table); + BLF_UTF8_NEXT_FAST(font, gc, g, str, i, c, glyph_ascii_table); if (UNLIKELY(c == BLI_UTF8_ERR)) { break; @@ -647,9 +677,12 @@ static void blf_font_draw_buffer_ex( 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); + GlyphCacheBLF *gc = blf_glyph_cache_acquire(font); + blf_font_draw_buffer_ex(font, gc, str, len, r_info, 0); + blf_glyph_cache_release(font); } static bool blf_font_width_to_strlen_glyph_process(FontBLF *font, @@ -684,19 +717,20 @@ size_t blf_font_width_to_strlen( GlyphBLF *g, *g_prev; int pen_x, width_new; size_t i, i_prev; - GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table; + + GlyphCacheBLF *gc = blf_glyph_cache_acquire(font); + GlyphBLF **glyph_ascii_table = blf_font_ensure_ascii_table(font, gc); const int width_i = (int)width; BLF_KERNING_VARS(font, has_kerning, kern_mode); - blf_font_ensure_ascii_table(font); if (has_kerning) { - blf_font_ensure_ascii_kerning(font, kern_mode); + blf_font_ensure_ascii_kerning(font, gc, kern_mode); } for (i_prev = i = 0, width_new = pen_x = 0, g_prev = NULL, c_prev = 0; (i < len) && str[i]; i_prev = i, width_new = pen_x, c_prev = c, g_prev = g) { - BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table); + BLF_UTF8_NEXT_FAST(font, gc, g, str, i, c, glyph_ascii_table); if (blf_font_width_to_strlen_glyph_process( font, has_kerning, kern_mode, c_prev, c, g_prev, g, &pen_x, width_i)) { @@ -708,6 +742,7 @@ size_t blf_font_width_to_strlen( *r_width = (float)width_new; } + blf_glyph_cache_release(font); return i_prev; } @@ -719,14 +754,15 @@ size_t blf_font_width_to_rstrlen( int pen_x, width_new; size_t i, i_prev, i_tmp; char *s, *s_prev; - GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table; + + GlyphCacheBLF *gc = blf_glyph_cache_acquire(font); + GlyphBLF **glyph_ascii_table = blf_font_ensure_ascii_table(font, gc); const int width_i = (int)width; BLF_KERNING_VARS(font, has_kerning, kern_mode); - blf_font_ensure_ascii_table(font); if (has_kerning) { - blf_font_ensure_ascii_kerning(font, kern_mode); + blf_font_ensure_ascii_kerning(font, gc, kern_mode); } i = BLI_strnlen(str, len); @@ -736,7 +772,7 @@ size_t blf_font_width_to_rstrlen( i_prev = (size_t)((s_prev != NULL) ? s_prev - str : 0); i_tmp = i; - BLF_UTF8_NEXT_FAST(font, g, str, i_tmp, c, glyph_ascii_table); + BLF_UTF8_NEXT_FAST(font, gc, g, str, i_tmp, c, glyph_ascii_table); for (width_new = pen_x = 0; (s != NULL); i = i_prev, s = s_prev, c = c_prev, g = g_prev, g_prev = NULL, width_new = pen_x) { s_prev = BLI_str_find_prev_char_utf8(str, s); @@ -744,7 +780,7 @@ size_t blf_font_width_to_rstrlen( if (s_prev != NULL) { i_tmp = i_prev; - BLF_UTF8_NEXT_FAST(font, g_prev, str, i_tmp, c_prev, glyph_ascii_table); + BLF_UTF8_NEXT_FAST(font, gc, g_prev, str, i_tmp, c_prev, glyph_ascii_table); BLI_assert(i_tmp == i); } @@ -758,17 +794,24 @@ size_t blf_font_width_to_rstrlen( *r_width = (float)width_new; } + blf_glyph_cache_release(font); return i; } -static void blf_font_boundbox_ex( - FontBLF *font, const char *str, size_t len, rctf *box, struct ResultBLF *r_info, int pen_y) +static void blf_font_boundbox_ex(FontBLF *font, + GlyphCacheBLF *gc, + const char *str, + size_t len, + rctf *box, + 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; - GlyphBLF **glyph_ascii_table = font->glyph_cache->glyph_ascii_table; + + GlyphBLF **glyph_ascii_table = blf_font_ensure_ascii_table(font, gc); rctf gbox; @@ -779,11 +822,10 @@ static void blf_font_boundbox_ex( box->ymin = 32000.0f; box->ymax = -32000.0f; - blf_font_ensure_ascii_table(font); - blf_font_ensure_ascii_kerning(font, kern_mode); + blf_font_ensure_ascii_kerning(font, gc, kern_mode); while ((i < len) && str[i]) { - BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table); + BLF_UTF8_NEXT_FAST(font, gc, g, str, i, c, glyph_ascii_table); if (UNLIKELY(c == BLI_UTF8_ERR)) { break; @@ -834,7 +876,9 @@ static void blf_font_boundbox_ex( 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); + GlyphCacheBLF *gc = blf_glyph_cache_acquire(font); + blf_font_boundbox_ex(font, gc, str, len, r_box, r_info, 0); + blf_glyph_cache_release(font); } /* -------------------------------------------------------------------- */ @@ -850,23 +894,29 @@ void blf_font_boundbox( * \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) +static void blf_font_wrap_apply(FontBLF *font, + const char *str, + size_t len, + struct ResultBLF *r_info, + void (*callback)(FontBLF *font, + GlyphCacheBLF *gc, + 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; int pen_x_next = 0; + GlyphCacheBLF *gc = blf_glyph_cache_acquire(font); + GlyphBLF **glyph_ascii_table = blf_font_ensure_ascii_table(font, gc); + BLF_KERNING_VARS(font, has_kerning, kern_mode); struct WordWrapVars { @@ -874,7 +924,6 @@ static void blf_font_wrap_apply( 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]) { @@ -882,7 +931,7 @@ static void blf_font_wrap_apply( size_t i_curr = i; bool do_draw = false; - BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table); + BLF_UTF8_NEXT_FAST(font, gc, g, str, i, c, glyph_ascii_table); if (UNLIKELY(c == BLI_UTF8_ERR)) { break; @@ -926,11 +975,11 @@ static void blf_font_wrap_apply( // printf("(%03d..%03d) `%.*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); + callback(font, gc, &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->glyph_height_max; + pen_y -= gc->glyph_height_max; g_prev = NULL; lines += 1; continue; @@ -947,13 +996,19 @@ static void blf_font_wrap_apply( /* width of last line only (with wrapped lines) */ r_info->width = pen_x_next; } + + blf_glyph_cache_release(font); } /* 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)) +static void blf_font_draw__wrap_cb(FontBLF *font, + GlyphCacheBLF *gc, + const char *str, + size_t len, + int pen_y, + void *UNUSED(userdata)) { - blf_font_draw_ex(font, str, len, NULL, pen_y); + blf_font_draw_ex(font, gc, str, len, NULL, pen_y); } void blf_font_draw__wrap(FontBLF *font, const char *str, size_t len, struct ResultBLF *r_info) { @@ -962,12 +1017,12 @@ void blf_font_draw__wrap(FontBLF *font, const char *str, size_t len, struct Resu /* blf_font_boundbox__wrap */ static void blf_font_boundbox_wrap_cb( - FontBLF *font, const char *str, size_t len, int pen_y, void *userdata) + FontBLF *font, GlyphCacheBLF *gc, 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); + blf_font_boundbox_ex(font, gc, str, len, &box_single, NULL, pen_y); BLI_rctf_union(box, &box_single); } void blf_font_boundbox__wrap( @@ -982,10 +1037,14 @@ void blf_font_boundbox__wrap( } /* 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)) +static void blf_font_draw_buffer__wrap_cb(FontBLF *font, + GlyphCacheBLF *gc, + const char *str, + size_t len, + int pen_y, + void *UNUSED(userdata)) { - blf_font_draw_buffer_ex(font, str, len, NULL, pen_y); + blf_font_draw_buffer_ex(font, gc, str, len, NULL, pen_y); } void blf_font_draw_buffer__wrap(FontBLF *font, const char *str, @@ -1071,16 +1130,22 @@ float blf_font_height(FontBLF *font, const char *str, size_t len, struct ResultB float blf_font_fixed_width(FontBLF *font) { const unsigned int c = ' '; - GlyphBLF *g = blf_glyph_search(font->glyph_cache, c); + + GlyphCacheBLF *gc = blf_glyph_cache_acquire(font); + blf_font_ensure_ascii_table(font, gc); + + GlyphBLF *g = blf_glyph_search(gc, c); if (!g) { - g = blf_glyph_add(font, FT_Get_Char_Index(font->face, c), c); + g = blf_glyph_add(font, gc, FT_Get_Char_Index(font->face, c), c); /* if we don't find the glyph. */ if (!g) { + blf_glyph_cache_release(font); return 0.0f; } } + blf_glyph_cache_release(font); return g->advance; } @@ -1111,6 +1176,7 @@ int blf_font_count_missing_chars(FontBLF *font, void blf_font_free(FontBLF *font) { + BLI_spin_lock(&blf_glyph_cache_mutex); GlyphCacheBLF *gc; font->glyph_cache = NULL; @@ -1128,6 +1194,8 @@ void blf_font_free(FontBLF *font) MEM_freeN(font->name); } MEM_freeN(font); + + BLI_spin_unlock(&blf_glyph_cache_mutex); } static void blf_font_fill(FontBLF *font) @@ -1177,6 +1245,7 @@ static void blf_font_fill(FontBLF *font) font->ft_lib = ft_lib; font->ft_lib_mutex = &ft_lib_mutex; + font->glyph_cache_mutex = &blf_glyph_cache_mutex; } FontBLF *blf_font_new(const char *name, const char *filename) @@ -1250,3 +1319,51 @@ FontBLF *blf_font_new_from_mem(const char *name, const unsigned char *mem, int m blf_font_fill(font); return font; } + +int blf_font_height_max(FontBLF *font) +{ + int height_max; + + GlyphCacheBLF *gc = blf_glyph_cache_acquire(font); + blf_font_ensure_ascii_table(font, gc); + height_max = gc->glyph_height_max; + + blf_glyph_cache_release(font); + return height_max; +} + +int blf_font_width_max(FontBLF *font) +{ + int width_max; + + GlyphCacheBLF *gc = blf_glyph_cache_acquire(font); + blf_font_ensure_ascii_table(font, gc); + width_max = gc->glyph_width_max; + + blf_glyph_cache_release(font); + return width_max; +} + +float blf_font_descender(FontBLF *font) +{ + float descender; + + GlyphCacheBLF *gc = blf_glyph_cache_acquire(font); + blf_font_ensure_ascii_table(font, gc); + descender = gc->descender; + + blf_glyph_cache_release(font); + return descender; +} + +float blf_font_ascender(FontBLF *font) +{ + float ascender; + + GlyphCacheBLF *gc = blf_glyph_cache_acquire(font); + blf_font_ensure_ascii_table(font, gc); + ascender = gc->ascender; + + blf_glyph_cache_release(font); + return ascender; +} diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c index c0a53cbf282..535366b78fa 100644 --- a/source/blender/blenfont/intern/blf_glyph.c +++ b/source/blender/blenfont/intern/blf_glyph.c @@ -72,7 +72,7 @@ KerningCacheBLF *blf_kerning_cache_find(FontBLF *font) } /* Create a new glyph cache for the current kerning mode. */ -KerningCacheBLF *blf_kerning_cache_new(FontBLF *font) +KerningCacheBLF *blf_kerning_cache_new(FontBLF *font, GlyphCacheBLF *gc) { KerningCacheBLF *kc; @@ -84,13 +84,13 @@ KerningCacheBLF *blf_kerning_cache_new(FontBLF *font) unsigned int i, j; for (i = 0; i < 0x80; i++) { for (j = 0; j < 0x80; j++) { - GlyphBLF *g = blf_glyph_search(font->glyph_cache, i); + GlyphBLF *g = blf_glyph_search(gc, i); if (!g) { FT_UInt glyph_index = FT_Get_Char_Index(font->face, i); - g = blf_glyph_add(font, glyph_index, i); + g = blf_glyph_add(font, gc, glyph_index, i); } /* Can fail on certain fonts */ - GlyphBLF *g_prev = blf_glyph_search(font->glyph_cache, j); + GlyphBLF *g_prev = blf_glyph_search(gc, j); FT_Vector delta = { .x = 0, @@ -180,14 +180,43 @@ GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font) return gc; } +GlyphCacheBLF *blf_glyph_cache_acquire(FontBLF *font) +{ + BLI_spin_lock(font->glyph_cache_mutex); + + GlyphCacheBLF *gc; + + if (!font->glyph_cache) { + gc = blf_glyph_cache_new(font); + if (gc) { + font->glyph_cache = gc; + } + else { + font->glyph_cache = NULL; + return NULL; + } + } + + return font->glyph_cache; +} + +void blf_glyph_cache_release(FontBLF *font) +{ + BLI_spin_unlock(font->glyph_cache_mutex); +} + void blf_glyph_cache_clear(FontBLF *font) { GlyphCacheBLF *gc; + BLI_spin_lock(font->glyph_cache_mutex); + while ((gc = BLI_pophead(&font->cache))) { blf_glyph_cache_free(gc); } font->glyph_cache = NULL; + + BLI_spin_unlock(font->glyph_cache_mutex); } void blf_glyph_cache_free(GlyphCacheBLF *gc) @@ -264,7 +293,7 @@ GlyphBLF *blf_glyph_search(GlyphCacheBLF *gc, unsigned int c) return NULL; } -GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c) +GlyphBLF *blf_glyph_add(FontBLF *font, GlyphCacheBLF *gc, unsigned int index, unsigned int c) { FT_GlyphSlot slot; GlyphBLF *g; @@ -273,7 +302,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c) FT_BBox bbox; unsigned int key; - g = blf_glyph_search(font->glyph_cache, c); + g = blf_glyph_search(gc, c); if (g) { return g; } @@ -285,7 +314,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c) BLI_spin_lock(font->ft_lib_mutex); /* search again after locking */ - g = blf_glyph_search(font->glyph_cache, c); + g = blf_glyph_search(gc, c); if (g) { BLI_spin_unlock(font->ft_lib_mutex); return g; @@ -380,7 +409,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c) g->box.ymax = ((float)bbox.yMax) / 64.0f; key = blf_hash(g->c); - BLI_addhead(&(font->glyph_cache->bucket[key]), g); + BLI_addhead(&(gc->bucket[key]), g); BLI_spin_unlock(font->ft_lib_mutex); @@ -483,15 +512,13 @@ static void blf_glyph_calc_rect_shadow(rctf *rect, GlyphBLF *g, float x, float y blf_glyph_calc_rect(rect, g, x + (float)font->shadow_x, y + (float)font->shadow_y); } -void blf_glyph_render(FontBLF *font, 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)) { return; } if (g->build_tex == 0) { - GlyphCacheBLF *gc = font->glyph_cache; - if (font->tex_size_max == -1) { font->tex_size_max = GPU_max_texture_size(); } @@ -578,8 +605,8 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y) } else if (font->shadow <= 4) { blf_texture3_draw(font->shadow_color, - font->glyph_cache->p2_width, - font->glyph_cache->p2_height, + gc->p2_width, + gc->p2_height, g->uv, rect_ofs.xmin, rect_ofs.ymin, @@ -588,8 +615,8 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y) } else { blf_texture5_draw(font->shadow_color, - font->glyph_cache->p2_width, - font->glyph_cache->p2_height, + gc->p2_width, + gc->p2_height, g->uv, rect_ofs.xmin, rect_ofs.ymin, @@ -605,8 +632,8 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y) switch (font->blur) { case 3: blf_texture3_draw(font->color, - font->glyph_cache->p2_width, - font->glyph_cache->p2_height, + gc->p2_width, + gc->p2_height, g->uv, rect.xmin, rect.ymin, @@ -615,8 +642,8 @@ void blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y) break; case 5: blf_texture5_draw(font->color, - font->glyph_cache->p2_width, - font->glyph_cache->p2_height, + gc->p2_width, + gc->p2_height, g->uv, rect.xmin, rect.ymin, diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h index cfc1d245a11..efcf9e15100 100644 --- a/source/blender/blenfont/intern/blf_internal.h +++ b/source/blender/blenfont/intern/blf_internal.h @@ -93,6 +93,10 @@ void blf_font_width_and_height(struct FontBLF *font, 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_height_max(struct FontBLF *font); +int blf_font_width_max(struct FontBLF *font); +float blf_font_descender(struct FontBLF *font); +float blf_font_ascender(struct FontBLF *font); int blf_font_count_missing_chars(struct FontBLF *font, const char *str, @@ -102,21 +106,27 @@ int blf_font_count_missing_chars(struct FontBLF *font, void blf_font_free(struct FontBLF *font); struct KerningCacheBLF *blf_kerning_cache_find(struct FontBLF *font); -struct KerningCacheBLF *blf_kerning_cache_new(struct FontBLF *font); +struct KerningCacheBLF *blf_kerning_cache_new(struct FontBLF *font, struct GlyphCacheBLF *gc); void blf_kerning_cache_clear(struct FontBLF *font); struct GlyphCacheBLF *blf_glyph_cache_find(struct FontBLF *font, unsigned int size, unsigned int dpi); struct GlyphCacheBLF *blf_glyph_cache_new(struct FontBLF *font); +struct GlyphCacheBLF *blf_glyph_cache_acquire(struct FontBLF *font); +void blf_glyph_cache_release(struct FontBLF *font); void blf_glyph_cache_clear(struct FontBLF *font); void blf_glyph_cache_free(struct GlyphCacheBLF *gc); struct GlyphBLF *blf_glyph_search(struct GlyphCacheBLF *gc, unsigned int c); -struct GlyphBLF *blf_glyph_add(struct FontBLF *font, unsigned int index, unsigned int c); +struct GlyphBLF *blf_glyph_add(struct FontBLF *font, + struct GlyphCacheBLF *gc, + unsigned int index, + unsigned int c); void blf_glyph_free(struct GlyphBLF *g); -void blf_glyph_render(struct FontBLF *font, struct GlyphBLF *g, float x, float y); +void blf_glyph_render( + struct FontBLF *font, struct GlyphCacheBLF *gc, struct GlyphBLF *g, float x, float y); #ifdef WIN32 /* blf_font_win32_compat.c */ diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h index 22950c26b6b..0294a6219b9 100644 --- a/source/blender/blenfont/intern/blf_internal_types.h +++ b/source/blender/blenfont/intern/blf_internal_types.h @@ -249,7 +249,9 @@ typedef struct FontBLF { /* list of glyph cache for this font. */ ListBase cache; - /* current glyph cache, size and dpi. */ + /* current glyph cache, size and dpi. + * Use blf_glyph_cache_acquire(font) and blf_glyph_cache_release(font) to access cache! + */ GlyphCacheBLF *glyph_cache; /* list of kerning cache for this font. */ @@ -272,6 +274,9 @@ typedef struct FontBLF { /* data for buffer usage (drawing into a texture buffer) */ FontBufInfoBLF buf_info; + + /* Mutex lock for glyph cache. */ + SpinLock *glyph_cache_mutex; } FontBLF; typedef struct DirBLF { -- cgit v1.2.3