From b74cc23dc478f2c4260e2e4269c8450e3d5c450e Mon Sep 17 00:00:00 2001 From: Harley Acheson Date: Fri, 5 Jun 2020 15:39:17 -0700 Subject: 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 --- source/blender/blenfont/BLF_api.h | 2 + source/blender/blenfont/intern/blf_font.c | 11 +-- source/blender/blenfont/intern/blf_glyph.c | 81 ++++++++++++++-------- .../blender/blenfont/intern/blf_internal_types.h | 10 +-- source/blender/blenfont/intern/blf_thumbs.c | 9 +-- 5 files changed, 67 insertions(+), 46 deletions(-) (limited to 'source/blender/blenfont') diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h index ddb88cf61ed..1d0cb2f524c 100644 --- a/source/blender/blenfont/BLF_api.h +++ b/source/blender/blenfont/BLF_api.h @@ -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 diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index e5e03418073..da6224cff7f 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -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; diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c index ce17069e53f..1867df3100c 100644 --- a/source/blender/blenfont/intern/blf_glyph.c +++ b/source/blender/blenfont/intern/blf_glyph.c @@ -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); diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h index 362cbf6730f..34b674670fd 100644 --- a/source/blender/blenfont/intern/blf_internal_types.h +++ b/source/blender/blenfont/intern/blf_internal_types.h @@ -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; diff --git a/source/blender/blenfont/intern/blf_thumbs.c b/source/blender/blenfont/intern/blf_thumbs.c index 37eed29f6fe..6aa39e3aa71 100644 --- a/source/blender/blenfont/intern/blf_thumbs.c +++ b/source/blender/blenfont/intern/blf_thumbs.c @@ -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, -- cgit v1.2.3