UI: Ability to Print Bold and Italics

Adds the ability to print text in bold or italics style, synthesized from a single base UI font.

Differential Revision: https://developer.blender.org/D7893

Reviewed by Brecht Van Lommel
This commit is contained in:
2020-06-05 15:39:17 -07:00
parent fc672ce8e2
commit b74cc23dc4
6 changed files with 73 additions and 46 deletions

View File

@@ -279,6 +279,8 @@ void BLF_state_print(int fontid);
#define BLF_HINTING_NONE (1 << 8) #define BLF_HINTING_NONE (1 << 8)
#define BLF_HINTING_SLIGHT (1 << 9) #define BLF_HINTING_SLIGHT (1 << 9)
#define BLF_HINTING_FULL (1 << 10) #define BLF_HINTING_FULL (1 << 10)
#define BLF_BOLD (1 << 11)
#define BLF_ITALIC (1 << 12)
#define BLF_DRAW_STR_DUMMY_MAX 1024 #define BLF_DRAW_STR_DUMMY_MAX 1024

View File

@@ -290,7 +290,6 @@ void blf_font_size(FontBLF *font, unsigned int size, unsigned int dpi)
gc = blf_glyph_cache_find(font, size, dpi); gc = blf_glyph_cache_find(font, size, dpi);
if (gc) { if (gc) {
font->glyph_cache = gc;
/* Optimization: do not call FT_Set_Char_Size if size did not change. */ /* Optimization: do not call FT_Set_Char_Size if size did not change. */
if (font->size == size && font->dpi == dpi) { if (font->size == size && font->dpi == dpi) {
blf_glyph_cache_release(font); blf_glyph_cache_release(font);
@@ -311,13 +310,7 @@ void blf_font_size(FontBLF *font, unsigned int size, unsigned int dpi)
font->dpi = dpi; font->dpi = dpi;
if (!gc) { if (!gc) {
gc = blf_glyph_cache_new(font); blf_glyph_cache_new(font);
if (gc) {
font->glyph_cache = gc;
}
else {
font->glyph_cache = NULL;
}
} }
blf_glyph_cache_release(font); blf_glyph_cache_release(font);
} }
@@ -1309,7 +1302,6 @@ void blf_font_free(FontBLF *font)
BLI_spin_lock(&blf_glyph_cache_mutex); BLI_spin_lock(&blf_glyph_cache_mutex);
GlyphCacheBLF *gc; GlyphCacheBLF *gc;
font->glyph_cache = NULL;
while ((gc = BLI_pophead(&font->cache))) { while ((gc = BLI_pophead(&font->cache))) {
blf_glyph_cache_free(gc); blf_glyph_cache_free(gc);
} }
@@ -1356,7 +1348,6 @@ static void blf_font_fill(FontBLF *font)
font->size = 0; font->size = 0;
BLI_listbase_clear(&font->cache); BLI_listbase_clear(&font->cache);
BLI_listbase_clear(&font->kerning_caches); BLI_listbase_clear(&font->kerning_caches);
font->glyph_cache = NULL;
font->kerning_cache = NULL; font->kerning_cache = NULL;
#if BLF_BLUR_ENABLE #if BLF_BLUR_ENABLE
font->blur = 0; font->blur = 0;

View File

@@ -119,7 +119,8 @@ GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, unsigned int size, unsigned i
p = (GlyphCacheBLF *)font->cache.first; p = (GlyphCacheBLF *)font->cache.first;
while (p) { while (p) {
if (p->size == size && p->dpi == dpi) { if (p->size == size && p->dpi == dpi && (p->bold == ((font->flags & BLF_BOLD) != 0)) &&
(p->italic == ((font->flags & BLF_ITALIC) != 0))) {
return p; return p;
} }
p = p->next; p = p->next;
@@ -127,7 +128,7 @@ GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, unsigned int size, unsigned i
return NULL; return NULL;
} }
/* Create a new glyph cache for the current size and dpi. */ /* Create a new glyph cache for the current size, dpi, bold, italic. */
GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font) GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
{ {
GlyphCacheBLF *gc; GlyphCacheBLF *gc;
@@ -137,6 +138,8 @@ GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
gc->prev = NULL; gc->prev = NULL;
gc->size = font->size; gc->size = font->size;
gc->dpi = font->dpi; gc->dpi = font->dpi;
gc->bold = ((font->flags & BLF_BOLD) != 0);
gc->italic = ((font->flags & BLF_ITALIC) != 0);
memset(gc->glyph_ascii_table, 0, sizeof(gc->glyph_ascii_table)); memset(gc->glyph_ascii_table, 0, sizeof(gc->glyph_ascii_table));
memset(gc->bucket, 0, sizeof(gc->bucket)); memset(gc->bucket, 0, sizeof(gc->bucket));
@@ -172,20 +175,13 @@ GlyphCacheBLF *blf_glyph_cache_acquire(FontBLF *font)
{ {
BLI_spin_lock(font->glyph_cache_mutex); BLI_spin_lock(font->glyph_cache_mutex);
GlyphCacheBLF *gc; GlyphCacheBLF *gc = blf_glyph_cache_find(font, font->size, font->dpi);
if (!font->glyph_cache) { if (!gc) {
gc = blf_glyph_cache_new(font); gc = blf_glyph_cache_new(font);
if (gc) {
font->glyph_cache = gc;
}
else {
font->glyph_cache = NULL;
return NULL;
}
} }
return font->glyph_cache; return gc;
} }
void blf_glyph_cache_release(FontBLF *font) void blf_glyph_cache_release(FontBLF *font)
@@ -202,7 +198,6 @@ void blf_glyph_cache_clear(FontBLF *font)
while ((gc = BLI_pophead(&font->cache))) { while ((gc = BLI_pophead(&font->cache))) {
blf_glyph_cache_free(gc); blf_glyph_cache_free(gc);
} }
font->glyph_cache = NULL;
BLI_spin_unlock(font->glyph_cache_mutex); BLI_spin_unlock(font->glyph_cache_mutex);
} }
@@ -269,28 +264,65 @@ GlyphBLF *blf_glyph_add(FontBLF *font, GlyphCacheBLF *gc, unsigned int index, un
return g; return g;
} }
int load_flags;
int render_mode;
if (font->flags & BLF_MONOCHROME) { if (font->flags & BLF_MONOCHROME) {
err = FT_Load_Glyph(font->face, (FT_UInt)index, FT_LOAD_TARGET_MONO); load_flags = FT_LOAD_TARGET_MONO;
render_mode = FT_RENDER_MODE_MONO;
} }
else { else {
int flags = FT_LOAD_NO_BITMAP; load_flags = FT_LOAD_NO_BITMAP;
render_mode = FT_RENDER_MODE_NORMAL;
if (font->flags & BLF_HINTING_NONE) { if (font->flags & BLF_HINTING_NONE) {
flags |= FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING; load_flags |= FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING;
} }
else if (font->flags & BLF_HINTING_SLIGHT) { else if (font->flags & BLF_HINTING_SLIGHT) {
flags |= FT_LOAD_TARGET_LIGHT; load_flags |= FT_LOAD_TARGET_LIGHT;
} }
else if (font->flags & BLF_HINTING_FULL) { else if (font->flags & BLF_HINTING_FULL) {
flags |= FT_LOAD_TARGET_NORMAL; load_flags |= FT_LOAD_TARGET_NORMAL;
} }
else { else {
/* Default, hinting disabled until FreeType has been upgraded /* Default, hinting disabled until FreeType has been upgraded
* to give good results on all platforms. */ * to give good results on all platforms. */
flags |= FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING; load_flags |= FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING;
} }
}
err = FT_Load_Glyph(font->face, (FT_UInt)index, flags); err = FT_Load_Glyph(font->face, (FT_UInt)index, load_flags);
/* 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) &&
(font->face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)) {
/* For (fake) italic: a shear transform with a 6 degree angle. */
FT_Matrix transform;
transform.xx = 0x10000L;
transform.yx = 0x00000L;
transform.xy = 0x03000L;
transform.yy = 0x10000L;
FT_Outline_Transform(&font->face->glyph->outline, &transform);
}
/* 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)) {
/* 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;
const FT_Pos extra_y = FT_MulFix(font->face->units_per_EM, font->face->size->metrics.y_scale) /
28;
FT_Outline_EmboldenXY(&font->face->glyph->outline, extra_x, extra_y);
if ((font->face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) == 0) {
/* Need to increase advance, but not for fixed-width fonts. */
font->face->glyph->advance.x += (int) (extra_x * 1.05f);
font->face->glyph->advance.y += extra_y;
}
else {
/* Widened fixed-pitch font gets a nudge left. */
FT_Outline_Translate(&font->face->glyph->outline, (extra_x / -2), 0);
}
} }
if (err) { if (err) {
@@ -300,23 +332,18 @@ GlyphBLF *blf_glyph_add(FontBLF *font, GlyphCacheBLF *gc, unsigned int index, un
/* get the glyph. */ /* get the glyph. */
slot = font->face->glyph; slot = font->face->glyph;
err = FT_Render_Glyph(slot, render_mode);
if (font->flags & BLF_MONOCHROME) { if (font->flags & BLF_MONOCHROME) {
err = FT_Render_Glyph(slot, FT_RENDER_MODE_MONO);
/* Convert result from 1 bit per pixel to 8 bit per pixel */ /* 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" */ /* Accum errors for later, fine if not interested beyond "ok vs any error" */
FT_Bitmap_New(&tempbitmap); FT_Bitmap_New(&tempbitmap);
/* Does Blender use Pitch 1 always? It works so far */ /* Does Blender use Pitch 1 always? It works so far */
err += FT_Bitmap_Convert(font->ft_lib, &slot->bitmap, &tempbitmap, 1); err += FT_Bitmap_Convert(font->ft_lib, &slot->bitmap, &tempbitmap, 1);
err += FT_Bitmap_Copy(font->ft_lib, &tempbitmap, &slot->bitmap); err += FT_Bitmap_Copy(font->ft_lib, &tempbitmap, &slot->bitmap);
err += FT_Bitmap_Done(font->ft_lib, &tempbitmap); err += FT_Bitmap_Done(font->ft_lib, &tempbitmap);
} }
else {
err = FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
}
if (err || slot->format != FT_GLYPH_FORMAT_BITMAP) { if (err || slot->format != FT_GLYPH_FORMAT_BITMAP) {
BLI_spin_unlock(font->ft_lib_mutex); BLI_spin_unlock(font->ft_lib_mutex);

View File

@@ -65,6 +65,9 @@ typedef struct GlyphCacheBLF {
/* and dpi. */ /* and dpi. */
unsigned int dpi; unsigned int dpi;
bool bold;
bool italic;
/* and the glyphs. */ /* and the glyphs. */
ListBase bucket[257]; ListBase bucket[257];
@@ -218,13 +221,10 @@ typedef struct FontBLF {
/* font options. */ /* font options. */
int flags; int flags;
/* list of glyph cache for this font. */ /* List of glyph caches (GlyphCacheBLF) for this font for size, dpi, bold, italic.
ListBase cache;
/* current glyph cache, size and dpi.
* Use blf_glyph_cache_acquire(font) and blf_glyph_cache_release(font) to access cache! * Use blf_glyph_cache_acquire(font) and blf_glyph_cache_release(font) to access cache!
*/ */
GlyphCacheBLF *glyph_cache; ListBase cache;
/* list of kerning cache for this font. */ /* list of kerning cache for this font. */
ListBase kerning_caches; ListBase kerning_caches;

View File

@@ -66,6 +66,7 @@ void BLF_thumb_preview(const char *filename,
int font_shrink = 4; int font_shrink = 4;
FontBLF *font; FontBLF *font;
GlyphCacheBLF *gc;
int i; int i;
/* Create a new blender font obj and fill it with default values */ /* Create a new blender font obj and fill it with default values */
@@ -96,9 +97,9 @@ void BLF_thumb_preview(const char *filename,
int draw_str_i18n_nbr = 0; int draw_str_i18n_nbr = 0;
blf_font_size(font, (unsigned int)MAX2(font_size_min, font_size_curr), dpi); blf_font_size(font, (unsigned int)MAX2(font_size_min, font_size_curr), dpi);
gc = blf_glyph_cache_find(font, font->size, font->dpi);
/* font->glyph_cache remains NULL if blf_font_size() failed to set font size */ /* There will be no matching glyph cache if blf_font_size() failed to set font size. */
if (!font->glyph_cache) { if (!gc) {
break; break;
} }
@@ -106,7 +107,7 @@ void BLF_thumb_preview(const char *filename,
font_size_curr -= (font_size_curr / font_shrink); font_size_curr -= (font_size_curr / font_shrink);
font_shrink += 1; font_shrink += 1;
font->pos[1] -= font->glyph_cache->ascender * 1.1f; font->pos[1] -= gc->ascender * 1.1f;
/* We fallback to default english strings in case not enough chars are available in current /* We fallback to default english strings in case not enough chars are available in current
* font for given translated string (useful in non-latin i18n context, like Chinese, * font for given translated string (useful in non-latin i18n context, like Chinese,

View File

@@ -169,6 +169,12 @@ void UI_fontstyle_draw_ex(const uiFontStyle *fs,
if (fs_params->word_wrap == 1) { if (fs_params->word_wrap == 1) {
font_flag |= BLF_WORD_WRAP; font_flag |= BLF_WORD_WRAP;
} }
if (fs->bold) {
font_flag |= BLF_BOLD;
}
if (fs->italic) {
font_flag |= BLF_ITALIC;
}
BLF_enable(fs->uifont_id, font_flag); BLF_enable(fs->uifont_id, font_flag);