BLF Refactor: blf_utf8_next_fast
Simplification of BLF glyph loading See D13026 for details. Differential Revision: https://developer.blender.org/D13026 Reviewed by Campbell Barton
This commit is contained in:
parent
59534dbee2
commit
70947ebc65
|
@ -300,24 +300,8 @@ static void blf_batch_draw_end(void)
|
|||
BLI_INLINE GlyphBLF *blf_utf8_next_fast(
|
||||
FontBLF *font, GlyphCacheBLF *gc, const char *str, size_t str_len, size_t *i_p)
|
||||
{
|
||||
GlyphBLF *g;
|
||||
uint charcode = (uint)str[*i_p];
|
||||
if (charcode < GLYPH_ASCII_TABLE_SIZE) {
|
||||
g = (gc->glyph_ascii_table)[charcode];
|
||||
if (UNLIKELY(g == NULL)) {
|
||||
g = blf_glyph_add(font, gc, FT_Get_Char_Index(font->face, charcode), charcode);
|
||||
gc->glyph_ascii_table[charcode] = g;
|
||||
}
|
||||
(*i_p)++;
|
||||
}
|
||||
else {
|
||||
charcode = BLI_str_utf8_as_unicode_step(str, str_len, i_p);
|
||||
g = blf_glyph_search(gc, charcode);
|
||||
if (UNLIKELY(g == NULL)) {
|
||||
g = blf_glyph_add(font, gc, FT_Get_Char_Index(font->face, charcode), charcode);
|
||||
}
|
||||
}
|
||||
return g;
|
||||
uint charcode = BLI_str_utf8_as_unicode_step(str, str_len, i_p);
|
||||
return blf_glyph_ensure(font, gc, charcode);
|
||||
}
|
||||
|
||||
BLI_INLINE int blf_kerning(FontBLF *font, const GlyphBLF *g_prev, const GlyphBLF *g)
|
||||
|
@ -388,7 +372,7 @@ static void blf_font_draw_ex(FontBLF *font,
|
|||
pen_x += blf_kerning(font, g_prev, g);
|
||||
|
||||
/* do not return this loop if clipped, we want every character tested */
|
||||
blf_glyph_render(font, gc, g, (float)pen_x, (float)pen_y);
|
||||
blf_glyph_draw(font, gc, g, (float)pen_x, (float)pen_y);
|
||||
|
||||
pen_x += g->advance_i;
|
||||
g_prev = g;
|
||||
|
@ -431,7 +415,7 @@ int blf_font_draw_mono(FontBLF *font, const char *str, const size_t str_len, int
|
|||
}
|
||||
|
||||
/* do not return this loop if clipped, we want every character tested */
|
||||
blf_glyph_render(font, gc, g, (float)pen_x, (float)pen_y);
|
||||
blf_glyph_draw(font, gc, g, (float)pen_x, (float)pen_y);
|
||||
|
||||
col = BLI_wcwidth((char32_t)g->c);
|
||||
if (col < 0) {
|
||||
|
@ -857,7 +841,7 @@ float blf_font_fixed_width(FontBLF *font)
|
|||
GlyphCacheBLF *gc = blf_glyph_cache_acquire(font);
|
||||
GlyphBLF *g = blf_glyph_search(gc, c);
|
||||
if (!g) {
|
||||
g = blf_glyph_add(font, gc, FT_Get_Char_Index(font->face, c), c);
|
||||
g = blf_glyph_ensure(font, gc, FT_Get_Char_Index(font->face, c));
|
||||
|
||||
/* if we don't find the glyph. */
|
||||
if (!g) {
|
||||
|
|
|
@ -175,33 +175,8 @@ GlyphBLF *blf_glyph_search(GlyphCacheBLF *gc, unsigned int c)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
GlyphBLF *blf_glyph_add(FontBLF *font, GlyphCacheBLF *gc, unsigned int index, unsigned int c)
|
||||
static bool blf_glyph_render(FontBLF *font, FT_UInt glyph_index)
|
||||
{
|
||||
FT_GlyphSlot slot;
|
||||
GlyphBLF *g;
|
||||
FT_Error err;
|
||||
FT_Bitmap bitmap, tempbitmap;
|
||||
FT_BBox bbox;
|
||||
unsigned int key;
|
||||
|
||||
g = blf_glyph_search(gc, c);
|
||||
if (g) {
|
||||
return g;
|
||||
}
|
||||
|
||||
/* glyphs are dynamically created as needed by font rendering. this means that
|
||||
* to make font rendering thread safe we have to do locking here. note that this
|
||||
* must be a lock for the whole library and not just per font, because the font
|
||||
* renderer uses a shared buffer internally */
|
||||
BLI_spin_lock(font->ft_lib_mutex);
|
||||
|
||||
/* search again after locking */
|
||||
g = blf_glyph_search(gc, c);
|
||||
if (g) {
|
||||
BLI_spin_unlock(font->ft_lib_mutex);
|
||||
return g;
|
||||
}
|
||||
|
||||
int load_flags;
|
||||
int render_mode;
|
||||
|
||||
|
@ -228,7 +203,10 @@ GlyphBLF *blf_glyph_add(FontBLF *font, GlyphCacheBLF *gc, unsigned int index, un
|
|||
}
|
||||
}
|
||||
|
||||
err = FT_Load_Glyph(font->face, (FT_UInt)index, load_flags);
|
||||
FT_Error err = FT_Load_Glyph(font->face, glyph_index, load_flags);
|
||||
if (err != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Do not oblique a font that is designed to be italic! */
|
||||
if (((font->flags & BLF_ITALIC) != 0) && !(font->face->style_flags & FT_STYLE_FLAG_ITALIC) &&
|
||||
|
@ -243,9 +221,8 @@ GlyphBLF *blf_glyph_add(FontBLF *font, GlyphCacheBLF *gc, unsigned int index, un
|
|||
}
|
||||
|
||||
/* Do not embolden an already bold font! */
|
||||
if (((font->flags & BLF_BOLD) != 0) &&
|
||||
!(font->face->style_flags & FT_STYLE_FLAG_BOLD) &
|
||||
(font->face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)) {
|
||||
if (((font->flags & BLF_BOLD) != 0) && !(font->face->style_flags & FT_STYLE_FLAG_BOLD) &&
|
||||
(font->face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)) {
|
||||
/* Strengthen the width more than the height. */
|
||||
const FT_Pos extra_x = FT_MulFix(font->face->units_per_EM, font->face->size->metrics.x_scale) /
|
||||
14;
|
||||
|
@ -263,15 +240,12 @@ GlyphBLF *blf_glyph_add(FontBLF *font, GlyphCacheBLF *gc, unsigned int index, un
|
|||
}
|
||||
}
|
||||
|
||||
if (err) {
|
||||
BLI_spin_unlock(font->ft_lib_mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* get the glyph. */
|
||||
slot = font->face->glyph;
|
||||
FT_GlyphSlot slot = font->face->glyph;
|
||||
err = FT_Render_Glyph(slot, render_mode);
|
||||
|
||||
FT_Bitmap tempbitmap;
|
||||
|
||||
if (font->flags & BLF_MONOCHROME) {
|
||||
/* Convert result from 1 bit per pixel to 8 bit per pixel */
|
||||
/* Accum errors for later, fine if not interested beyond "ok vs any error" */
|
||||
|
@ -284,45 +258,69 @@ GlyphBLF *blf_glyph_add(FontBLF *font, GlyphCacheBLF *gc, unsigned int index, un
|
|||
}
|
||||
|
||||
if (err || slot->format != FT_GLYPH_FORMAT_BITMAP) {
|
||||
BLI_spin_unlock(font->ft_lib_mutex);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GlyphBLF *blf_glyph_ensure(FontBLF *font, GlyphCacheBLF *gc, uint charcode)
|
||||
{
|
||||
GlyphBLF *g = (charcode < GLYPH_ASCII_TABLE_SIZE) ? (gc->glyph_ascii_table)[charcode] :
|
||||
blf_glyph_search(gc, charcode);
|
||||
if (g) {
|
||||
return g;
|
||||
}
|
||||
|
||||
FT_UInt glyph_index = FT_Get_Char_Index(font->face, charcode);
|
||||
|
||||
if (!blf_glyph_render(font, glyph_index)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
g = (GlyphBLF *)MEM_callocN(sizeof(GlyphBLF), "blf_glyph_add");
|
||||
g->c = c;
|
||||
g->idx = (FT_UInt)index;
|
||||
bitmap = slot->bitmap;
|
||||
g->dims[0] = (int)bitmap.width;
|
||||
g->dims[1] = (int)bitmap.rows;
|
||||
FT_GlyphSlot slot = font->face->glyph;
|
||||
|
||||
const int buffer_size = g->dims[0] * g->dims[1];
|
||||
|
||||
if (buffer_size != 0) {
|
||||
if (font->flags & BLF_MONOCHROME) {
|
||||
/* Font buffer uses only 0 or 1 values, Blender expects full 0..255 range */
|
||||
for (int i = 0; i < buffer_size; i++) {
|
||||
bitmap.buffer[i] = bitmap.buffer[i] ? 255 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
g->bitmap = MEM_mallocN((size_t)buffer_size, "glyph bitmap");
|
||||
memcpy(g->bitmap, bitmap.buffer, (size_t)buffer_size);
|
||||
}
|
||||
/* glyphs are dynamically created as needed by font rendering. this means that
|
||||
* to make font rendering thread safe we have to do locking here. note that this
|
||||
* must be a lock for the whole library and not just per font, because the font
|
||||
* renderer uses a shared buffer internally */
|
||||
BLI_spin_lock(font->ft_lib_mutex);
|
||||
|
||||
g = (GlyphBLF *)MEM_callocN(sizeof(GlyphBLF), "blf_glyph_get");
|
||||
g->c = charcode;
|
||||
g->idx = glyph_index;
|
||||
g->advance = ((float)slot->advance.x) / 64.0f;
|
||||
g->advance_i = (int)g->advance;
|
||||
g->pos[0] = slot->bitmap_left;
|
||||
g->pos[1] = slot->bitmap_top;
|
||||
g->dims[0] = slot->bitmap.width;
|
||||
g->dims[1] = slot->bitmap.rows;
|
||||
g->pitch = slot->bitmap.pitch;
|
||||
|
||||
FT_BBox bbox;
|
||||
FT_Outline_Get_CBox(&(slot->outline), &bbox);
|
||||
g->box.xmin = ((float)bbox.xMin) / 64.0f;
|
||||
g->box.xmax = ((float)bbox.xMax) / 64.0f;
|
||||
g->box.ymin = ((float)bbox.yMin) / 64.0f;
|
||||
g->box.ymax = ((float)bbox.yMax) / 64.0f;
|
||||
|
||||
key = blf_hash(g->c);
|
||||
const int buffer_size = slot->bitmap.width * slot->bitmap.rows;
|
||||
if (buffer_size != 0) {
|
||||
if (font->flags & BLF_MONOCHROME) {
|
||||
/* Font buffer uses only 0 or 1 values, Blender expects full 0..255 range */
|
||||
for (int i = 0; i < buffer_size; i++) {
|
||||
slot->bitmap.buffer[i] = slot->bitmap.buffer[i] ? 255 : 0;
|
||||
}
|
||||
}
|
||||
g->bitmap = MEM_mallocN((size_t)buffer_size, "glyph bitmap");
|
||||
memcpy(g->bitmap, slot->bitmap.buffer, (size_t)buffer_size);
|
||||
}
|
||||
|
||||
unsigned int key = blf_hash(g->c);
|
||||
BLI_addhead(&(gc->bucket[key]), g);
|
||||
if (charcode < GLYPH_ASCII_TABLE_SIZE) {
|
||||
gc->glyph_ascii_table[charcode] = g;
|
||||
}
|
||||
|
||||
BLI_spin_unlock(font->ft_lib_mutex);
|
||||
|
||||
|
@ -419,7 +417,7 @@ 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, GlyphCacheBLF *gc, GlyphBLF *g, float x, float y)
|
||||
void blf_glyph_draw(FontBLF *font, GlyphCacheBLF *gc, GlyphBLF *g, float x, float y)
|
||||
{
|
||||
if ((!g->dims[0]) || (!g->dims[1])) {
|
||||
return;
|
||||
|
|
|
@ -140,13 +140,10 @@ 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,
|
||||
struct GlyphCacheBLF *gc,
|
||||
unsigned int index,
|
||||
unsigned int c);
|
||||
struct GlyphBLF *blf_glyph_ensure(struct FontBLF *font, struct GlyphCacheBLF *gc, uint charcode);
|
||||
|
||||
void blf_glyph_free(struct GlyphBLF *g);
|
||||
void blf_glyph_render(
|
||||
void blf_glyph_draw(
|
||||
struct FontBLF *font, struct GlyphCacheBLF *gc, struct GlyphBLF *g, float x, float y);
|
||||
|
||||
#ifdef WIN32
|
||||
|
|
Loading…
Reference in New Issue