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_SLIGHT (1 << 9)
#define BLF_HINTING_FULL (1 << 10)
#define BLF_BOLD (1 << 11)
#define BLF_ITALIC (1 << 12)
#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);
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);
@@ -311,13 +310,7 @@ void blf_font_size(FontBLF *font, unsigned int size, unsigned int dpi)
font->dpi = dpi;
if (!gc) {
gc = blf_glyph_cache_new(font);
if (gc) {
font->glyph_cache = gc;
}
else {
font->glyph_cache = NULL;
}
blf_glyph_cache_new(font);
}
blf_glyph_cache_release(font);
}
@@ -1309,7 +1302,6 @@ void blf_font_free(FontBLF *font)
BLI_spin_lock(&blf_glyph_cache_mutex);
GlyphCacheBLF *gc;
font->glyph_cache = NULL;
while ((gc = BLI_pophead(&font->cache))) {
blf_glyph_cache_free(gc);
}
@@ -1356,7 +1348,6 @@ static void blf_font_fill(FontBLF *font)
font->size = 0;
BLI_listbase_clear(&font->cache);
BLI_listbase_clear(&font->kerning_caches);
font->glyph_cache = NULL;
font->kerning_cache = NULL;
#if BLF_BLUR_ENABLE
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;
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;
}
p = p->next;
@@ -127,7 +128,7 @@ GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, unsigned int size, unsigned i
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 *gc;
@@ -137,6 +138,8 @@ GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
gc->prev = NULL;
gc->size = font->size;
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->bucket, 0, sizeof(gc->bucket));
@@ -172,20 +175,13 @@ GlyphCacheBLF *blf_glyph_cache_acquire(FontBLF *font)
{
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);
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)
@@ -202,7 +198,6 @@ void blf_glyph_cache_clear(FontBLF *font)
while ((gc = BLI_pophead(&font->cache))) {
blf_glyph_cache_free(gc);
}
font->glyph_cache = NULL;
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;
}
int load_flags;
int render_mode;
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 {
int flags = FT_LOAD_NO_BITMAP;
load_flags = FT_LOAD_NO_BITMAP;
render_mode = FT_RENDER_MODE_NORMAL;
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) {
flags |= FT_LOAD_TARGET_LIGHT;
load_flags |= FT_LOAD_TARGET_LIGHT;
}
else if (font->flags & BLF_HINTING_FULL) {
flags |= FT_LOAD_TARGET_NORMAL;
load_flags |= FT_LOAD_TARGET_NORMAL;
}
else {
/* Default, hinting disabled until FreeType has been upgraded
* 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) {
@@ -300,23 +332,18 @@ GlyphBLF *blf_glyph_add(FontBLF *font, GlyphCacheBLF *gc, unsigned int index, un
/* get the glyph. */
slot = font->face->glyph;
err = FT_Render_Glyph(slot, render_mode);
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 */
/* Accum errors for later, fine if not interested beyond "ok vs any error" */
FT_Bitmap_New(&tempbitmap);
/* Does Blender use Pitch 1 always? It works so far */
err += FT_Bitmap_Convert(font->ft_lib, &slot->bitmap, &tempbitmap, 1);
err += FT_Bitmap_Copy(font->ft_lib, &tempbitmap, &slot->bitmap);
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) {
BLI_spin_unlock(font->ft_lib_mutex);

View File

@@ -65,6 +65,9 @@ typedef struct GlyphCacheBLF {
/* and dpi. */
unsigned int dpi;
bool bold;
bool italic;
/* and the glyphs. */
ListBase bucket[257];
@@ -218,13 +221,10 @@ typedef struct FontBLF {
/* font options. */
int flags;
/* list of glyph cache for this font. */
ListBase cache;
/* current glyph cache, size and dpi.
/* 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!
*/
GlyphCacheBLF *glyph_cache;
ListBase cache;
/* list of kerning cache for this font. */
ListBase kerning_caches;

View File

@@ -66,6 +66,7 @@ void BLF_thumb_preview(const char *filename,
int font_shrink = 4;
FontBLF *font;
GlyphCacheBLF *gc;
int i;
/* 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;
blf_font_size(font, (unsigned int)MAX2(font_size_min, font_size_curr), dpi);
/* font->glyph_cache remains NULL if blf_font_size() failed to set font size */
if (!font->glyph_cache) {
gc = blf_glyph_cache_find(font, font->size, font->dpi);
/* There will be no matching glyph cache if blf_font_size() failed to set font size. */
if (!gc) {
break;
}
@@ -106,7 +107,7 @@ void BLF_thumb_preview(const char *filename,
font_size_curr -= (font_size_curr / font_shrink);
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
* 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) {
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);