[Bf-blender-cvs] [c0845abd897] master: BLF: Fonts with FT_Face Optional

Harley Acheson noreply at git.blender.org
Fri Jul 29 02:52:25 CEST 2022


Commit: c0845abd897ffd547cd0ac226da99318d5c2fb30
Author: Harley Acheson
Date:   Thu Jul 28 17:50:34 2022 -0700
Branches: master
https://developer.blender.org/rBc0845abd897ffd547cd0ac226da99318d5c2fb30

BLF: Fonts with FT_Face Optional

Allow FontBLFs to exist with NULL FT_Face, added only when actually
needed. Speeds up startup and unused fonts are not loaded.

See D15258 for more details.

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

Reviewed by Brecht Van Lommel

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

M	source/blender/blenfont/BLF_api.h
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

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

diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h
index 83ca9158efc..8cb368e2075 100644
--- a/source/blender/blenfont/BLF_api.h
+++ b/source/blender/blenfont/BLF_api.h
@@ -351,6 +351,8 @@ enum {
   BLF_DEFAULT = 1 << 14,
   /** Must only be used as last font in the stack. */
   BLF_LAST_RESORT = 1 << 15,
+  /** Failure to load this font. Don't try again. */
+  BLF_BAD_FONT = 1 << 16,
 };
 
 #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 0efd3537a32..fed01d90314 100644
--- a/source/blender/blenfont/intern/blf_font.c
+++ b/source/blender/blenfont/intern/blf_font.c
@@ -18,8 +18,9 @@
 
 #include FT_FREETYPE_H
 #include FT_GLYPH_H
-#include FT_TRUETYPE_TABLES_H  /* For TT_OS2 */
 #include FT_MULTIPLE_MASTERS_H /* Variable font support. */
+#include FT_TRUETYPE_IDS_H     /* Codepoint coverage constants. */
+#include FT_TRUETYPE_TABLES_H  /* For TT_OS2 */
 
 #include "MEM_guardedalloc.h"
 
@@ -28,6 +29,7 @@
 #include "BLI_listbase.h"
 #include "BLI_math.h"
 #include "BLI_math_color_blend.h"
+#include "BLI_path_util.h"
 #include "BLI_rect.h"
 #include "BLI_string.h"
 #include "BLI_string_utf8.h"
@@ -1157,7 +1159,7 @@ int blf_font_ascender(FontBLF *font)
 
 char *blf_display_name(FontBLF *font)
 {
-  if (!font->face->family_name) {
+  if (!blf_ensure_face(font) || !font->face->family_name) {
     return NULL;
   }
   return BLI_sprintfN("%s %s", font->face->family_name, font->face->style_name);
@@ -1244,14 +1246,28 @@ static void blf_font_fill(FontBLF *font)
   font->glyph_cache_mutex = &blf_glyph_cache_mutex;
 }
 
-FontBLF *blf_font_new(const char *name, const char *filepath)
+/**
+ * Create an FT_Face for this font if not already existing.
+ */
+bool blf_ensure_face(FontBLF *font)
 {
-  FontBLF *font;
+  if (font->face) {
+    return true;
+  }
+
+  if (font->flags & BLF_BAD_FONT) {
+    return false;
+  }
+
   FT_Error err;
-  char *mfile;
 
-  font = (FontBLF *)MEM_callocN(sizeof(FontBLF), "blf_font_new");
-  err = FT_New_Face(ft_lib, filepath, 0, &font->face);
+  if (font->filepath) {
+    err = FT_New_Face(ft_lib, font->filepath, 0, &font->face);
+  }
+  if (font->mem) {
+    err = FT_New_Memory_Face(ft_lib, font->mem, (FT_Long)font->mem_size, 0, &font->face);
+  }
+
   if (err) {
     if (ELEM(err, FT_Err_Unknown_File_Format, FT_Err_Unimplemented_Feature)) {
       printf("Format of this font file is not supported\n");
@@ -1259,8 +1275,8 @@ FontBLF *blf_font_new(const char *name, const char *filepath)
     else {
       printf("Error encountered while opening font file\n");
     }
-    MEM_freeN(font);
-    return NULL;
+    font->flags |= BLF_BAD_FONT;
+    return false;
   }
 
   err = FT_Select_Charmap(font->face, FT_ENCODING_UNICODE);
@@ -1272,28 +1288,28 @@ FontBLF *blf_font_new(const char *name, const char *filepath)
   }
   if (err) {
     printf("Can't set a character map!\n");
-    FT_Done_Face(font->face);
-    MEM_freeN(font);
-    return NULL;
+    font->flags |= BLF_BAD_FONT;
+    return false;
   }
 
-  mfile = blf_dir_metrics_search(filepath);
-  if (mfile) {
-    err = FT_Attach_File(font->face, mfile);
-    if (err) {
-      fprintf(stderr, "FT_Attach_File failed to load '%s' with error %d\n", filepath, (int)err);
+  if (font->filepath) {
+    char *mfile = blf_dir_metrics_search(font->filepath);
+    if (mfile) {
+      err = FT_Attach_File(font->face, mfile);
+      if (err) {
+        fprintf(stderr,
+                "FT_Attach_File failed to load '%s' with error %d\n",
+                font->filepath,
+                (int)err);
+      }
+      MEM_freeN(mfile);
     }
-    MEM_freeN(mfile);
   }
 
   if (FT_HAS_MULTIPLE_MASTERS(font->face)) {
     FT_Get_MM_Var(font->face, &(font->variations));
   }
 
-  font->name = BLI_strdup(name);
-  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) {
@@ -1303,17 +1319,11 @@ FontBLF *blf_font_new(const char *name, const char *filepath)
     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)) {
+  if (FT_HAS_KERNING(font->face) && !font->kerning_cache) {
     /* Create kerning cache table and fill with value indicating "unset". */
     font->kerning_cache = MEM_mallocN(sizeof(KerningCacheBLF), __func__);
     for (uint i = 0; i < KERNING_CACHE_TABLE_SIZE; i++) {
@@ -1323,49 +1333,114 @@ FontBLF *blf_font_new(const char *name, const char *filepath)
     }
   }
 
-  return font;
+  return true;
 }
 
-void blf_font_attach_from_mem(FontBLF *font, const unsigned char *mem, int mem_size)
+typedef struct eFaceDetails {
+  char name[50];
+  unsigned int coverage1;
+  unsigned int coverage2;
+  unsigned int coverage3;
+  unsigned int coverage4;
+} eFaceDetails;
+
+/* Details about the fallback fonts we ship, so that we can load only when needed. */
+static const eFaceDetails static_face_details[] = {
+    {"lastresort.woff2", UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX},
+    {"Noto Sans CJK Regular.woff2", 0x30000083L, 0x2BDF3C10L, 0x16L, 0},
+    {"NotoEmoji-VariableFont_wght.woff2", 0x80000003L, 0x241E4ACL, 0x14000000L, 0x4000000L},
+    {"NotoSansArabic-VariableFont_wdth,wght.woff2", TT_UCR_ARABIC, 0, 0, 0},
+    {"NotoSansArmenian-VariableFont_wdth,wght.woff2",
+     TT_UCR_ARMENIAN,
+     TT_UCR_ALPHABETIC_PRESENTATION_FORMS,
+     0,
+     0},
+    {"NotoSansBengali-VariableFont_wdth,wght.woff2", TT_UCR_BENGALI, 0, 0, 0},
+    {"NotoSansDevanagari-Regular.woff2", TT_UCR_DEVANAGARI, 0, 0, 0},
+    {"NotoSansEthiopic-Regular.woff2", 0, 0, TT_UCR_ETHIOPIC, 0},
+    {"NotoSansGeorgian-VariableFont_wdth,wght.woff2", TT_UCR_GEORGIAN, 0, 0, 0},
+    {"NotoSansGujarati-Regular.woff2", TT_UCR_GUJARATI, 0, 0, 0},
+    {"NotoSansGurmukhi-VariableFont_wdth,wght.woff2", TT_UCR_GURMUKHI, 0, 0, 0},
+    {"NotoSansHebrew-VariableFont_wdth,wght.woff2", TT_UCR_HEBREW, 0, 0, 0},
+    {"NotoSansJavanese-Regular.woff2", 0x80000003L, 0x2000L, 0, 0},
+    {"NotoSansKannada-VariableFont_wdth,wght.woff2", TT_UCR_KANNADA, 0, 0, 0},
+    {"NotoSansMalayalam-VariableFont_wdth,wght.woff2", TT_UCR_MALAYALAM, 0, 0, 0},
+    {"NotoSansMath-Regular.woff2", 0, TT_UCR_MATHEMATICAL_OPERATORS, 0, 0},
+    {"NotoSansMyanmar-Regular.woff2", 0, 0, TT_UCR_MYANMAR, 0},
+    {"NotoSansSymbols-VariableFont_wght.woff2", 0x3L, 0x200E4B4L, 0, 0},
+    {"NotoSansSymbols2-Regular.woff2", 0x80000003L, 0x200E3E4L, 0x40020L, 0x580A048L},
+    {"NotoSansTamil-VariableFont_wdth,wght.woff2", TT_UCR_TAMIL, 0, 0, 0},
+    {"NotoSansTelugu-VariableFont_wdth,wght.woff2", TT_UCR_TELUGU, 0, 0, 0},
+    {"NotoSansThai-VariableFont_wdth,wght.woff2", TT_UCR_THAI, 0, 0, 0},
+};
+
+/* Create a new font from filename OR from passed memory pointer. */
+FontBLF *blf_font_new_ex(const char *name,
+                         const char *filepath,
+                         const unsigned char *mem,
+                         int mem_size)
 {
-  FT_Open_Args open;
+  FontBLF *font = (FontBLF *)MEM_callocN(sizeof(FontBLF), "blf_font_new");
 
-  open.flags = FT_OPEN_MEMORY;
-  open.memory_base = (const FT_Byte *)mem;
-  open.memory_size = mem_size;
-  FT_Attach_Stream(font->face, &open);
-}
-
-FontBLF *blf_font_new_from_mem(const char *name, const unsigned char *mem, int mem_size)
-{
-  FontBLF *font;
-  FT_Error err;
+  font->name = BLI_strdup(name);
+  font->filepath = filepath ? BLI_strdup(filepath) : NULL;
+  if (mem) {
+    font->mem = (void *)mem;
+    font->mem_size = mem_size;
+  }
+  blf_font_fill(font);
 
-  font = (FontBLF *)MEM_callocN(sizeof(FontBLF), "blf_font_new_from_mem");
-  err = FT_New_Memory_Face(ft_lib, mem, mem_size, 0, &font->face);
-  if (err) {
-    MEM_freeN(font);
-    return NULL;
+  /* If we have static details about this font we don't need to load the Face. */
+  const eFaceDetails *static_details = NULL;
+  char filename[256];
+  for (int i = 0; i < ARRAY_SIZE(static_face_details); i++) {
+    BLI_split_file_part(font->filepath, filename, sizeof(filename));
+    if (STREQ(static_face_details[i].name, filename)) {
+      static_details = &static_face_details[i];
+      font->UnicodeRanges[0] = static_details->coverage1;
+      font->UnicodeRanges[1] = static_details->coverage2;
+      font->UnicodeRanges[2] = static_details->coverage3;
+      font->UnicodeRanges[3] = static_details->coverage4;
+      break;
+    }
   }
 
-  err = FT_Select_Charmap(font->face, ft_encoding_unicode);
-  if (err) {
-    printf("Can't set the unicode character map!\n");
-    FT_Done_Face(font->face);
-    MEM_freeN(font);
-    return NULL;
+  if (!static_details) {
+    if (!blf_ensure_face(font)) {
+      blf_font_free(font);
+      return NULL;
+    }
   }
 
-  if (FT_HAS_MULTIPLE_MASTERS(font->face)) {
-    FT_Get_MM_Var(font->face, &(font->variations));
+  /* 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;
   }
 
-  font->name = BLI_strdup(name);
-  font->filepath = NULL;
-  blf_font_fill(font);
   return font;
 }
 
+FontBLF *blf_font_new(const char *name, const char *filename)
+{
+  return blf_font_new_ex(name, filename, NULL, 0);
+}
+
+FontBLF *blf_font_new_from_mem(const char *name, const unsigned char *mem, int mem_size)
+{
+  return blf_font_new_ex(name, NULL, mem, mem_size);
+}
+
+void blf_font_attach_from_mem(FontBLF *font, const unsigned char *mem, int mem_size)
+{
+  FT_Open_Args open;
+
+  open.flags = FT_OPEN_MEMORY;
+  open.memory_base = (const FT_B

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list