Refactor: BLF Use Vector for Glyph Cache List #118174

Closed
Harley Acheson wants to merge 3 commits from Harley/blender:BlfGlyphCacheList into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
5 changed files with 87 additions and 75 deletions

View File

@ -101,7 +101,7 @@ void BLF_cache_clear()
for (int i = 0; i < BLF_MAX_FONT; i++) {
FontBLF *font = global_font[i];
if (font) {
blf_glyph_cache_clear(font);
font->cache->clear();
}
}
}

View File

@ -482,9 +482,9 @@ static void blf_font_draw_ex(FontBLF *font,
}
void blf_font_draw(FontBLF *font, const char *str, const size_t str_len, ResultBLF *r_info)
{
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
GlyphCacheBLF *gc = font->cache->acquire();
blf_font_draw_ex(font, gc, str, str_len, r_info, 0);
blf_glyph_cache_release(font);
font->cache->release();
}
int blf_font_draw_mono(
@ -497,7 +497,7 @@ int blf_font_draw_mono(
size_t i = 0;
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
GlyphCacheBLF *gc = font->cache->acquire();
blf_batch_draw_begin(font);
@ -518,7 +518,7 @@ int blf_font_draw_mono(
blf_batch_draw_end();
blf_glyph_cache_release(font);
font->cache->release();
return columns;
}
@ -674,9 +674,9 @@ static void blf_font_draw_buffer_ex(FontBLF *font,
void blf_font_draw_buffer(FontBLF *font, const char *str, const size_t str_len, ResultBLF *r_info)
{
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
GlyphCacheBLF *gc = font->cache->acquire();
blf_font_draw_buffer_ex(font, gc, str, str_len, r_info, 0);
blf_glyph_cache_release(font);
font->cache->release();
}
/** \} */
@ -731,7 +731,7 @@ size_t blf_font_width_to_strlen(
ft_pix width_new;
size_t i, i_prev;
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
GlyphCacheBLF *gc = font->cache->acquire();
const int width_i = int(width);
for (i_prev = i = 0, width_new = pen_x = 0, g_prev = nullptr; (i < str_len) && str[i];
@ -747,7 +747,7 @@ size_t blf_font_width_to_strlen(
*r_width = ft_pix_to_int(width_new);
}
blf_glyph_cache_release(font);
font->cache->release();
return i_prev;
}
@ -759,7 +759,7 @@ size_t blf_font_width_to_rstrlen(
size_t i, i_prev, i_tmp;
const char *s, *s_prev;
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
GlyphCacheBLF *gc = font->cache->acquire();
i = BLI_strnlen(str, str_len);
s = BLI_str_find_prev_char_utf8(&str[i], str);
@ -790,7 +790,7 @@ size_t blf_font_width_to_rstrlen(
*r_width = ft_pix_to_int(width_new);
}
blf_glyph_cache_release(font);
font->cache->release();
return i;
}
@ -867,9 +867,9 @@ static void blf_font_boundbox_ex(FontBLF *font,
void blf_font_boundbox(
FontBLF *font, const char *str, const size_t str_len, rcti *r_box, ResultBLF *r_info)
{
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
GlyphCacheBLF *gc = font->cache->acquire();
blf_font_boundbox_ex(font, gc, str, str_len, r_box, r_info, 0);
blf_glyph_cache_release(font);
font->cache->release();
}
void blf_font_width_and_height(FontBLF *font,
@ -945,9 +945,9 @@ float blf_font_height(FontBLF *font, const char *str, const size_t str_len, Resu
float blf_font_fixed_width(FontBLF *font)
{
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
GlyphCacheBLF *gc = font->cache->acquire();
float width = (gc) ? float(gc->fixed_width) : font->size / 2.0f;
blf_glyph_cache_release(font);
font->cache->release();
return width;
}
@ -966,7 +966,7 @@ void blf_font_boundbox_foreach_glyph(FontBLF *font,
ft_pix pen_x = 0;
size_t i = 0;
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
GlyphCacheBLF *gc = font->cache->acquire();
while ((i < str_len) && str[i]) {
const size_t i_curr = i;
@ -987,7 +987,7 @@ void blf_font_boundbox_foreach_glyph(FontBLF *font,
pen_x += g->advance_x;
}
blf_glyph_cache_release(font);
font->cache->release();
}
struct CursorPositionForeachGlyph_Data {
@ -1104,7 +1104,7 @@ static void blf_font_wrap_apply(FontBLF *font,
ft_pix line_height = blf_font_height_max_ft_pix(font);
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
GlyphCacheBLF *gc = font->cache->acquire();
struct WordWrapVars {
ft_pix wrap_width;
@ -1183,7 +1183,7 @@ static void blf_font_wrap_apply(FontBLF *font,
r_info->width = ft_pix_to_int(pen_x_next);
}
blf_glyph_cache_release(font);
font->cache->release();
}
/** Utility for #blf_font_draw__wrap. */
@ -1376,7 +1376,6 @@ static void blf_font_fill(FontBLF *font)
font->char_width = 1.0f;
font->char_spacing = 0.0f;
BLI_listbase_clear(&font->cache);
font->kerning_cache = nullptr;
#if BLF_BLUR_ENABLE
font->blur = 0;
@ -1756,7 +1755,7 @@ static FontBLF *blf_font_new_impl(const char *filepath,
font->ft_lib = ft_library ? (FT_Library)ft_library : ft_lib;
BLI_mutex_init(&font->glyph_cache_mutex);
font->cache = new GlyphCacheListBLF(font);
/* If we have static details about this font file, we don't have to load the Face yet. */
bool face_needed = true;
@ -1826,7 +1825,7 @@ void blf_font_attach_from_mem(FontBLF *font, const uchar *mem, const size_t mem_
void blf_font_free(FontBLF *font)
{
blf_glyph_cache_clear(font);
delete font->cache;
if (font->kerning_cache) {
MEM_freeN(font->kerning_cache);
@ -1854,8 +1853,6 @@ void blf_font_free(FontBLF *font)
MEM_freeN(font->mem_name);
}
BLI_mutex_end(&font->glyph_cache_mutex);
MEM_freeN(font);
}

View File

@ -71,25 +71,9 @@ static float from_16dot16(FT_Fixed value)
/** \} */
/* -------------------------------------------------------------------- */
/** \name Glyph Cache
/** \name Glyph Cache Entries
* \{ */
static GlyphCacheBLF *blf_glyph_cache_find(const FontBLF *font, const float size)
{
GlyphCacheBLF *gc = (GlyphCacheBLF *)font->cache.first;
while (gc) {
if (gc->size == size && (gc->bold == ((font->flags & BLF_BOLD) != 0)) &&
(gc->italic == ((font->flags & BLF_ITALIC) != 0)) &&
(gc->char_weight == font->char_weight) && (gc->char_slant == font->char_slant) &&
(gc->char_width == font->char_width) && (gc->char_spacing == font->char_spacing))
{
return gc;
}
gc = gc->next;
}
return nullptr;
}
static GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
{
GlyphCacheBLF *gc = (GlyphCacheBLF *)MEM_callocN(sizeof(GlyphCacheBLF), "blf_glyph_cache_new");
@ -124,28 +108,9 @@ static GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
gc->fixed_width = 1;
}
BLI_addhead(&font->cache, gc);
return gc;
}
GlyphCacheBLF *blf_glyph_cache_acquire(FontBLF *font)
{
BLI_mutex_lock(&font->glyph_cache_mutex);
GlyphCacheBLF *gc = blf_glyph_cache_find(font, font->size);
if (!gc) {
gc = blf_glyph_cache_new(font);
}
return gc;
}
void blf_glyph_cache_release(FontBLF *font)
{
BLI_mutex_unlock(&font->glyph_cache_mutex);
}
static void blf_glyph_cache_free(GlyphCacheBLF *gc)
{
for (uint i = 0; i < ARRAY_SIZE(gc->bucket); i++) {
@ -162,15 +127,55 @@ static void blf_glyph_cache_free(GlyphCacheBLF *gc)
MEM_freeN(gc);
}
void blf_glyph_cache_clear(FontBLF *font)
{
BLI_mutex_lock(&font->glyph_cache_mutex);
/* -------------------------------------------------------------------- */
/** \name Glyph Cache List
* \{ */
while (GlyphCacheBLF *gc = static_cast<GlyphCacheBLF *>(BLI_pophead(&font->cache))) {
blf_glyph_cache_free(gc);
GlyphCacheListBLF::GlyphCacheListBLF(FontBLF *font) : list{}, font(font) {}
GlyphCacheListBLF ::~GlyphCacheListBLF()
{
clear();
};
GlyphCacheBLF *GlyphCacheListBLF::acquire()
{
glyph_cache_mutex.lock();
GlyphCacheBLF *gc = nullptr;
for (GlyphCacheBLF *entry : list) {
if (entry->size == font->size && (entry->bold == ((font->flags & BLF_BOLD) != 0)) &&
(entry->italic == ((font->flags & BLF_ITALIC) != 0)) &&
(entry->char_weight == font->char_weight) && (entry->char_slant == font->char_slant) &&
(entry->char_width == font->char_width) && (entry->char_spacing == font->char_spacing))
Harley marked this conversation as resolved
Review

Typically we don't use auto unless the type name is already written on a line (for example with casting) or it's actually not possible to write concretely. That's because it's helpful information to the reader who would have to look elsewhere otherwise.

Typically we don't use `auto` unless the type name is already written on a line (for example with casting) or it's actually not possible to write concretely. That's because it's helpful information to the reader who would have to look elsewhere otherwise.
{
gc = entry;
break;
}
}
BLI_mutex_unlock(&font->glyph_cache_mutex);
if (!gc) {
gc = blf_glyph_cache_new(font);
list.append(gc);
}
return gc;
}
void GlyphCacheListBLF::release()
{
this->glyph_cache_mutex.unlock();
}
void GlyphCacheListBLF::clear()
{
glyph_cache_mutex.lock();
for (GlyphCacheBLF *entry : list) {
blf_glyph_cache_free(entry);
}
list.clear();
glyph_cache_mutex.unlock();
}
/**

View File

@ -166,10 +166,6 @@ void blf_str_offset_to_glyph_bounds(struct FontBLF *font,
void blf_font_free(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);
/**
* Create (or load from cache) a fully-rendered bitmap glyph.
*/

View File

@ -8,6 +8,10 @@
#pragma once
#include <mutex>
#include "BLI_vector.hh"
#include "GPU_texture.h"
#include "GPU_vertex_buffer.h"
@ -106,6 +110,19 @@ typedef struct KerningCacheBLF {
int ascii_table[KERNING_CACHE_TABLE_SIZE][KERNING_CACHE_TABLE_SIZE];
} KerningCacheBLF;
Harley marked this conversation as resolved Outdated

private is redundant for classes which are private by default

`private` is redundant for classes which are private by default
class GlyphCacheListBLF {
Harley marked this conversation as resolved
Review

blender::Vector is generally preferable since it has methods to work better with other Blender containers, and it has an inline buffer to avoid allocations for small numbers of elements

`blender::Vector` is generally preferable since it has methods to work better with other Blender containers, and it has an inline buffer to avoid allocations for small numbers of elements
blender::Vector<GlyphCacheBLF *> list;
FontBLF *font;
Review

Sorry, I didn't realize this pointer here as the resolution to the need to pass "font" to the functions. I'll propose an alternative change to see what you think

Sorry, I didn't realize this pointer here as the resolution to the need to pass "font" to the functions. I'll propose an alternative change to see what you think
std::mutex glyph_cache_mutex;
public:
Harley marked this conversation as resolved
Review

It would probably be simpler/easy to switch to std::mutex now too :)

It would probably be simpler/easy to switch to `std::mutex` now too :)
GlyphCacheListBLF(FontBLF *font);
~GlyphCacheListBLF();
GlyphCacheBLF *acquire();
void release();
void clear();
};
typedef struct GlyphCacheBLF {
struct GlyphCacheBLF *next;
struct GlyphCacheBLF *prev;
@ -355,9 +372,9 @@ typedef struct FontBLF {
/**
* List of glyph caches (#GlyphCacheBLF) for this font for size, DPI, bold, italic.
* Use blf_glyph_cache_acquire(font) and blf_glyph_cache_release(font) to access cache!
* Use font->cache->acquire() and font->cache->release() to access cache!
*/
ListBase cache;
GlyphCacheListBLF *cache;
/** Cache of unscaled kerning values. Will be NULL if font does not have kerning. */
KerningCacheBLF *kerning_cache;
@ -379,7 +396,4 @@ typedef struct FontBLF {
/** Data for buffer usage (drawing into a texture buffer) */
FontBufInfoBLF buf_info;
/** Mutex lock for glyph cache. */
ThreadMutex glyph_cache_mutex;
} FontBLF;