[Bf-blender-cvs] [524a9e3db81] master: BLF: Fallback Font Stack

Harley Acheson noreply at git.blender.org
Fri Jun 17 19:31:57 CEST 2022


Commit: 524a9e3db8102c89abf3b80cddaea60c314d67ae
Author: Harley Acheson
Date:   Fri Jun 17 10:30:34 2022 -0700
Branches: master
https://developer.blender.org/rB524a9e3db8102c89abf3b80cddaea60c314d67ae

BLF: Fallback Font Stack

Allow use of multiple fonts acting together like a fallback stack,
where if a glyph is not found in one it can be retrieved from another.

See D12622 for much more detail

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

Reviewed by Brecht Van Lommel

===================================================================

M	source/blender/blenfont/BLF_api.h
M	source/blender/blenfont/intern/blf.c
M	source/blender/blenfont/intern/blf_font.c
M	source/blender/blenfont/intern/blf_font_default.c
M	source/blender/blenfont/intern/blf_glyph.c
M	source/blender/blenfont/intern/blf_internal.h
M	source/blender/blenfont/intern/blf_internal_types.h
M	source/blender/blenlib/intern/string_utf8.c
M	source/blender/editors/interface/interface_style.cc
M	source/blender/windowmanager/intern/wm_playanim.c

===================================================================

diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index e5e2b1711b1..78c8612f7f5 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -14,6 +14,15 @@
 extern "C" {
 #endif
 
+/* Name of subfolder inside BLENDER_DATAFILES that contains font files. */
+#define BLF_DATAFILES_FONTS_DIR "fonts"
+
+/* File name of the default variable-width font. */
+#define BLF_DEFAULT_PROPORTIONAL_FONT "droidsans.ttf"
+
+/* File name of the default fixed-pitch font. */
+#define BLF_DEFAULT_MONOSPACED_FONT "bmonofont-i18n.ttf"
+
 /* enable this only if needed (unused circa 2016) */
 #define BLF_BLUR_ENABLE 0
 
@@ -37,12 +46,14 @@ void BLF_cache_flush_set_fn(void (*cache_flush_fn)(void));
  */
 int BLF_load(const char *name) ATTR_NONNULL();
 int BLF_load_mem(const char *name, const unsigned char *mem, int mem_size) ATTR_NONNULL();
+bool BLF_is_loaded(const char *name) ATTR_NONNULL();
 
 int BLF_load_unique(const char *name) ATTR_NONNULL();
 int BLF_load_mem_unique(const char *name, const unsigned char *mem, int mem_size) ATTR_NONNULL();
 
 void BLF_unload(const char *name) ATTR_NONNULL();
 void BLF_unload_id(int fontid);
+void BLF_unload_all(void);
 
 char *BLF_display_name_from_file(const char *filepath);
 
@@ -312,6 +323,7 @@ int BLF_set_default(void);
 
 int BLF_load_default(bool unique);
 int BLF_load_mono_default(bool unique);
+void BLF_load_font_stack(void);
 
 #ifdef DEBUG
 void BLF_state_print(int fontid);
@@ -331,6 +343,9 @@ void BLF_state_print(int fontid);
 #define BLF_HINTING_FULL (1 << 10)
 #define BLF_BOLD (1 << 11)
 #define BLF_ITALIC (1 << 12)
+#define BLF_MONOSPACED (1 << 13) /* Intended USE is monospaced, regardless of font type. */
+#define BLF_DEFAULT (1 << 14) /* A font within the default stack of fonts. */
+#define BLF_LAST_RESORT (1 << 15) /* Must only be used as last font in the stack. */
 
 #define BLF_DRAW_STR_DUMMY_MAX 1024
 
diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c
index a944ab332bd..a1fcc17ca3f 100644
--- a/source/blender/blenfont/intern/blf.c
+++ b/source/blender/blenfont/intern/blf.c
@@ -34,13 +34,6 @@
 #include "blf_internal.h"
 #include "blf_internal_types.h"
 
-/* Max number of font in memory.
- * Take care that now every font have a glyph cache per size/dpi,
- * so we don't need load the same font with different size, just
- * load one and call BLF_size.
- */
-#define BLF_MAX_FONT 16
-
 #define BLF_RESULT_CHECK_INIT(r_info) \
   if (r_info) { \
     memset(r_info, 0, sizeof(*(r_info))); \
@@ -48,7 +41,7 @@
   ((void)0)
 
 /* Font array. */
-static FontBLF *global_font[BLF_MAX_FONT] = {NULL};
+FontBLF *global_font[BLF_MAX_FONT] = {NULL};
 
 /* XXX: should these be made into global_font_'s too? */
 
@@ -134,6 +127,11 @@ bool BLF_has_glyph(int fontid, unsigned int unicode)
   return false;
 }
 
+bool BLF_is_loaded(const char *name)
+{
+  return blf_search(name) >= 0;
+}
+
 int BLF_load(const char *name)
 {
   /* check if we already load this font. */
@@ -255,6 +253,20 @@ void BLF_unload_id(int fontid)
   }
 }
 
+void BLF_unload_all(void)
+{
+  for (int i = 0; i < BLF_MAX_FONT; i++) {
+    FontBLF *font = global_font[i];
+    if (font) {
+      blf_font_free(font);
+      global_font[i] = NULL;
+    }
+  }
+  blf_mono_font = -1;
+  blf_mono_font_render = -1;
+  BLF_default_set(-1);
+}
+
 void BLF_enable(int fontid, int option)
 {
   FontBLF *font = blf_get(fontid);
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c
index a170f27d247..26a72fcb95a 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -18,6 +18,7 @@
 
 #include FT_FREETYPE_H
 #include FT_GLYPH_H
+#include FT_TRUETYPE_TABLES_H /* For TT_OS2 */
 
 #include "MEM_guardedalloc.h"
 
@@ -1288,6 +1289,25 @@ FontBLF *blf_font_new(const char *name, const char *filepath)
   font->filepath = BLI_strdup(filepath);
   blf_font_fill(font);
 
+    /* Save TrueType table with bits to quickly test most unicode block coverage. */
+  TT_OS2 *os2_table = (TT_OS2 *)FT_Get_Sfnt_Table(font->face, FT_SFNT_OS2);
+  if (os2_table) {
+    font->UnicodeRanges[0] = (uint)os2_table->ulUnicodeRange1;
+    font->UnicodeRanges[1] = (uint)os2_table->ulUnicodeRange2;
+    font->UnicodeRanges[2] = (uint)os2_table->ulUnicodeRange3;
+    font->UnicodeRanges[3] = (uint)os2_table->ulUnicodeRange4;
+  }
+
+  /* Detect "Last resort" fonts. They have everything. Usually except last 5 bits.  */
+  if (font->UnicodeRanges[0] == 0xffffffffU && font->UnicodeRanges[1] == 0xffffffffU &&
+      font->UnicodeRanges[2] == 0xffffffffU && font->UnicodeRanges[3] >= 0x7FFFFFFU) {
+    font->flags |= BLF_LAST_RESORT;
+  }
+
+  if (FT_IS_FIXED_WIDTH(font->face)) {
+    font->flags |= BLF_MONOSPACED;
+  }
+
   if (FT_HAS_KERNING(font->face)) {
     /* Create kerning cache table and fill with value indicating "unset". */
     font->kerning_cache = MEM_mallocN(sizeof(KerningCacheBLF), __func__);
diff --git a/source/blender/blenfont/intern/blf_font_default.c b/source/blender/blenfont/intern/blf_font_default.c
index 3a68423e64e..1bde25b5776 100644
--- a/source/blender/blenfont/intern/blf_font_default.c
+++ b/source/blender/blenfont/intern/blf_font_default.c
@@ -11,13 +11,14 @@
 
 #include "BLF_api.h"
 
+#include "BLI_fileops.h"
 #include "BLI_path_util.h"
 
 #include "BKE_appdir.h"
 
 static int blf_load_font_default(const char *filename, const bool unique)
 {
-  const char *dir = BKE_appdir_folder_id(BLENDER_DATAFILES, "fonts");
+  const char *dir = BKE_appdir_folder_id(BLENDER_DATAFILES, BLF_DATAFILES_FONTS_DIR);
   if (dir == NULL) {
     fprintf(stderr,
             "%s: 'fonts' data path not found for '%s', will not be able to display text\n",
@@ -34,10 +35,46 @@ static int blf_load_font_default(const char *filename, const bool unique)
 
 int BLF_load_default(const bool unique)
 {
-  return blf_load_font_default("droidsans.ttf", unique);
+  int font_id = blf_load_font_default(BLF_DEFAULT_PROPORTIONAL_FONT, unique);
+  BLF_enable(font_id, BLF_DEFAULT);
+  return font_id;
 }
 
 int BLF_load_mono_default(const bool unique)
 {
-  return blf_load_font_default("bmonofont-i18n.ttf", unique);
+  int font_id = blf_load_font_default(BLF_DEFAULT_MONOSPACED_FONT, unique);
+  BLF_enable(font_id, BLF_MONOSPACED | BLF_DEFAULT);
+  return font_id;
+}
+
+void BLF_load_font_stack()
+{
+  /* Load these if not already, might have been replaced by user custom. */
+  BLF_load_default(false);
+  BLF_load_mono_default(false);
+
+  const char *path = BKE_appdir_folder_id(BLENDER_DATAFILES, BLF_DATAFILES_FONTS_DIR SEP_STR);
+  if (path && BLI_exists(path)) {
+    struct direntry *dir;
+    uint num_files = BLI_filelist_dir_contents(path, &dir);
+    for (int f = 0; f < num_files; f++) {
+      if (!FILENAME_IS_CURRPAR(dir[f].relname) && !BLI_is_dir(dir[f].path)) {
+        if (!BLF_is_loaded(dir[f].path)) {
+          int font_id = BLF_load(dir[f].path);
+          if (font_id == -1) {
+            fprintf(stderr, "Unable to load font: %s\n", dir[f].path);
+          }
+          else {
+            BLF_enable(font_id, BLF_DEFAULT);
+            /* TODO: FontBLF will later load FT_Face on demand.  When this is in
+             * place we can drop this face now since we have all needed data. */
+          }
+        }
+      }
+    }
+    BLI_filelist_free(dir, num_files);
+  }
+  else {
+    fprintf(stderr, "Fonts not found at %s\n", path);
+  }
 }
diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index 2694b179a11..32d4be3be0c 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -39,6 +39,7 @@
 
 #include "BLI_math_vector.h"
 #include "BLI_strict_flags.h"
+#include "BLI_string_utf8.h"
 
 /* -------------------------------------------------------------------- */
 /** \name Internal Utilities
@@ -222,6 +223,335 @@ static GlyphBLF *blf_glyph_cache_add_glyph(
   return g;
 }
 
+/* This table can be used to find a coverage bit based on a charcode. later we can get default
+ * language and script from codepoint.  */
+
+typedef struct eUnicodeBlock {
+  unsigned int first;
+  unsigned int last;
+  int coverage_bit; /* 0-122. -1 is N/A. */
+  /* Later we add primary script and language for Harfbuzz, data from
+   * https://en.wikipedia.org/wiki/Unicode_block */
+} eUnicodeBlock;
+
+static eUnicodeBlock unicode_blocks[] = {
+    /* Must be in ascending order by start of range. */
+    {0x0, 0x7F, 0},           /* Basic Latin. */
+    {0x80, 0xFF, 1},          /* Latin-1 Supplement. */
+    {0x100, 0x17F, 2},        /* Latin Extended-A. */
+    {0x180, 0x24F, 3},        /* Latin Extended-B. */
+    {0x250, 0x2AF, 4},        /* IPA Extensions. */
+    {0x2B0, 0x2FF, 5},        /* Spacing Modifier Letters. */
+    {0x300, 0x36F, 6},        /* Combining Diacritical Marks. */
+    {0x370, 0x3FF, 7},        /* Greek. */
+    {0x400, 0x52F, 9},        /* Cyrillic. */
+    {0x530, 0x58F, 10},       /* Armenian. */
+    {0x590, 0x5FF, 11},       /* Hebrew. */
+    {0x600, 0x6FF, 13},       /* Arabic. */
+    {0x700, 0x74F, 71},       /* Syriac. */
+    {0x750, 0x77F, 13},       /* Arabic Supplement. */
+    {0x780, 0x7BF, 72},       /* Thaana. */
+    {0x7C0, 0x7FF, 14},       /* NKo. */
+    {0x800, 0x83F, -1},       /* Samaritan. */
+    {0x840, 0x85F, -1},       /* Mandaic. */
+    {0x900, 0x97F, 15},       /* Devanagari. */
+    {0x980, 0x9FF, 16},       /* Bengali. */
+    {0xA00, 0xA7F, 17},       /* Gurmukhi. */
+    {0xA80, 0xAFF, 18},       /* Gujarati. */
+    {0xB00, 0xB7F, 19},       /* Oriya. */
+    {0xB80, 0xBFF, 20},       /* Tamil. */
+    {0xC00, 0xC7F, 21},       /* Telugu. */
+    {0xC80, 0xCFF, 22},       /* Kannada. */
+    {0xD00, 0xD7F, 23},       /* Malayalam. */
+    {0xD80, 0xDFF, 73},       /* Sinhala. */
+    {0xE00, 0xE7F, 24},       /* Thai. */
+    {0xE80, 0xEFF, 25},       /* Lao. */
+    {0xF00, 0xFFF, 70},       /* Tibetan. */
+    {0x1000, 0x109F, 74},     /* Myanmar. */
+    {0x10A0, 0x10FF, 26},     /* Georgian. */
+    {0x1100, 0x11FF, 28},     /* Hangul Jamo. */
+    {0x1200, 0x139F, 75},     /* Ethiopic. */
+    {0

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list