Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Antalik <richardantalik@gmail.com>2019-09-14 03:22:42 +0300
committerRichard Antalik <richardantalik@gmail.com>2019-09-14 03:24:42 +0300
commita960dc451930796ca310cc88f00fb701374b2f7f (patch)
tree3bd2b69426bc36605792718e5b44e2917ac49427 /source/blender/blenfont/intern
parentab3a9dc1ed28d44bd71f5e255da74ef4d6f1fdbf (diff)
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
Diffstat (limited to 'source/blender/blenfont/intern')
-rw-r--r--source/blender/blenfont/intern/blf.c36
-rw-r--r--source/blender/blenfont/intern/blf_font.c261
-rw-r--r--source/blender/blenfont/intern/blf_glyph.c65
-rw-r--r--source/blender/blenfont/intern/blf_internal.h16
-rw-r--r--source/blender/blenfont/intern/blf_internal_types.h7
5 files changed, 274 insertions, 111 deletions
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 {