[Bf-blender-cvs] [eddf5ad5819] master: BLF: Refactor blf_glyph.c

Harley Acheson noreply at git.blender.org
Sat Nov 6 19:29:58 CET 2021


Commit: eddf5ad5819fb48b2d8ebccc30a869f86718b565
Author: Harley Acheson
Date:   Sat Nov 6 11:28:28 2021 -0700
Branches: master
https://developer.blender.org/rBeddf5ad5819fb48b2d8ebccc30a869f86718b565

BLF: Refactor blf_glyph.c

Cleanup and Simplification of blf_glyph.c

See D13095 for details.

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

Reviewed by Campbell Barton

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

M	source/blender/blenfont/intern/blf_glyph.c

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

diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c
index c4ffb3f87f1..716670ac9c4 100644
--- a/source/blender/blenfont/intern/blf_glyph.c
+++ b/source/blender/blenfont/intern/blf_glyph.c
@@ -55,27 +55,25 @@
 #include "BLI_math_vector.h"
 #include "BLI_strict_flags.h"
 
+/* Find a glyph cache that matches a size, dpi, styles. */
 GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, unsigned int size, unsigned int dpi)
 {
-  GlyphCacheBLF *p;
-
-  p = (GlyphCacheBLF *)font->cache.first;
-  while (p) {
-    if (p->size == size && p->dpi == dpi && (p->bold == ((font->flags & BLF_BOLD) != 0)) &&
-        (p->italic == ((font->flags & BLF_ITALIC) != 0))) {
-      return p;
+  GlyphCacheBLF *gc = (GlyphCacheBLF *)font->cache.first;
+  while (gc) {
+    if (gc->size == size && gc->dpi == dpi && (gc->bold == ((font->flags & BLF_BOLD) != 0)) &&
+        (gc->italic == ((font->flags & BLF_ITALIC) != 0))) {
+      return gc;
     }
-    p = p->next;
+    gc = gc->next;
   }
   return NULL;
 }
 
-/* Create a new glyph cache for the current size, dpi, bold, italic. */
+/* Create a new glyph cache for the current size, dpi, styles. */
 GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
 {
-  GlyphCacheBLF *gc;
+  GlyphCacheBLF *gc = (GlyphCacheBLF *)MEM_callocN(sizeof(GlyphCacheBLF), "blf_glyph_cache_new");
 
-  gc = (GlyphCacheBLF *)MEM_callocN(sizeof(GlyphCacheBLF), "blf_glyph_cache_new");
   gc->next = NULL;
   gc->prev = NULL;
   gc->size = font->size;
@@ -138,34 +136,85 @@ void blf_glyph_cache_free(GlyphCacheBLF *gc)
   MEM_freeN(gc);
 }
 
-static GlyphBLF *blf_glyph_search(GlyphCacheBLF *gc, unsigned int c)
+/* Try to find a glyph in cache, return NULL if not found. */
+static GlyphBLF *blf_glyph_cache_find_glyph(GlyphCacheBLF *gc, uint charcode)
 {
-  GlyphBLF *p;
-  unsigned int key;
-
-  key = blf_hash(c);
-  p = gc->bucket[key].first;
-  while (p) {
-    if (p->c == c) {
-      return p;
+  if (charcode < GLYPH_ASCII_TABLE_SIZE) {
+    return gc->glyph_ascii_table[charcode];
+  }
+
+  GlyphBLF *g = gc->bucket[blf_hash(charcode)].first;
+  while (g) {
+    if (g->c == charcode) {
+      return g;
     }
-    p = p->next;
+    g = g->next;
   }
   return NULL;
 }
 
-static bool blf_glyph_render(FontBLF *font, FT_UInt glyph_index)
+/* Add a rendered glyph to a cache. */
+static GlyphBLF *blf_glyph_cache_add_glyph(
+    FontBLF *font, GlyphCacheBLF *gc, FT_GlyphSlot glyph, uint charcode, FT_UInt glyph_index)
+{
+  GlyphBLF *g = (GlyphBLF *)MEM_callocN(sizeof(GlyphBLF), "blf_glyph_get");
+  g->c = charcode;
+  g->idx = glyph_index;
+  g->advance = ((float)glyph->advance.x) / 64.0f;
+  g->advance_i = (int)g->advance;
+  g->pos[0] = glyph->bitmap_left;
+  g->pos[1] = glyph->bitmap_top;
+  g->dims[0] = (int)glyph->bitmap.width;
+  g->dims[1] = (int)glyph->bitmap.rows;
+  g->pitch = glyph->bitmap.pitch;
+
+  FT_BBox bbox;
+  FT_Outline_Get_CBox(&(glyph->outline), &bbox);
+  g->box.xmin = ((float)bbox.xMin) / 64.0f;
+  g->box.xmax = ((float)bbox.xMax) / 64.0f;
+  g->box.ymin = ((float)bbox.yMin) / 64.0f;
+  g->box.ymax = ((float)bbox.yMax) / 64.0f;
+
+  const int buffer_size = (int)(glyph->bitmap.width * glyph->bitmap.rows);
+  if (buffer_size != 0) {
+    if (font->flags & BLF_MONOCHROME) {
+      /* Font buffer uses only 0 or 1 values, Blender expects full 0..255 range. */
+      for (int i = 0; i < buffer_size; i++) {
+        glyph->bitmap.buffer[i] = glyph->bitmap.buffer[i] ? 255 : 0;
+      }
+    }
+    g->bitmap = MEM_mallocN((size_t)buffer_size, "glyph bitmap");
+    memcpy(g->bitmap, glyph->bitmap.buffer, (size_t)buffer_size);
+  }
+
+  unsigned int key = blf_hash(g->c);
+  BLI_addhead(&(gc->bucket[key]), g);
+  if (charcode < GLYPH_ASCII_TABLE_SIZE) {
+    gc->glyph_ascii_table[charcode] = g;
+  }
+
+  return g;
+}
+
+/* Return a glyph index from a charcode. Not found returns zero, which is a valid
+ * printable character (.notdef or "tofu"). Font is allowed to change here. */
+static FT_UInt blf_glyph_index_from_charcode(FontBLF **font, const uint charcode)
+{
+  FT_UInt glyph_index = FT_Get_Char_Index((*font)->face, charcode);
+  /* TODO: If not found in this font, check others, update font pointer. */
+  return glyph_index;
+}
+
+/* Load a glyph into the glyph slot of a font's face object. */
+static FT_GlyphSlot blf_glyph_load(FontBLF *font, FT_UInt glyph_index)
 {
   int load_flags;
-  int render_mode;
 
   if (font->flags & BLF_MONOCHROME) {
     load_flags = FT_LOAD_TARGET_MONO;
-    render_mode = FT_RENDER_MODE_MONO;
   }
   else {
     load_flags = FT_LOAD_NO_BITMAP;
-    render_mode = FT_RENDER_MODE_NORMAL;
     if (font->flags & BLF_HINTING_NONE) {
       load_flags |= FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING;
     }
@@ -182,46 +231,29 @@ static bool blf_glyph_render(FontBLF *font, FT_UInt glyph_index)
     }
   }
 
-  FT_Error err = FT_Load_Glyph(font->face, glyph_index, load_flags);
-  if (err != 0) {
-    return false;
+  if (FT_Load_Glyph(font->face, glyph_index, load_flags) == 0) {
+    return font->face->glyph;
   }
+  return NULL;
+}
 
-  /* 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 += (FT_Pos)(((float)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);
-    }
+/* Convert a glyph from outlines to a bitmap that we can display. */
+static bool blf_glyph_render_bitmap(FontBLF *font, FT_GlyphSlot glyph)
+{
+  int render_mode;
+
+  if (font->flags & BLF_MONOCHROME) {
+    render_mode = FT_RENDER_MODE_MONO;
+  }
+  else {
+    render_mode = FT_RENDER_MODE_NORMAL;
   }
 
-  /* get the glyph. */
-  FT_GlyphSlot slot = font->face->glyph;
-  err = FT_Render_Glyph(slot, render_mode);
+  /* Render the glyph curves to a bitmap. */
+  FT_Error err = FT_Render_Glyph(glyph, render_mode);
+  if (err != 0) {
+    return false;
+  }
 
   FT_Bitmap tempbitmap;
 
@@ -231,78 +263,163 @@ static bool blf_glyph_render(FontBLF *font, FT_UInt glyph_index)
     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_Convert(font->ft_lib, &glyph->bitmap, &tempbitmap, 1);
+    err += FT_Bitmap_Copy(font->ft_lib, &tempbitmap, &glyph->bitmap);
     err += FT_Bitmap_Done(font->ft_lib, &tempbitmap);
   }
 
-  if (err || slot->format != FT_GLYPH_FORMAT_BITMAP) {
+  if (err || glyph->format != FT_GLYPH_FORMAT_BITMAP) {
     return false;
   }
 
   return true;
 }
 
-GlyphBLF *blf_glyph_ensure(FontBLF *font, GlyphCacheBLF *gc, uint charcode)
+/* Convert a floating point value to a FreeType 16.16 fixed point value. */
+static FT_Fixed to_16dot16(double val)
 {
-  GlyphBLF *g = (charcode < GLYPH_ASCII_TABLE_SIZE) ? (gc->glyph_ascii_table)[charcode] :
-                                                      blf_glyph_search(gc, charcode);
-  if (g) {
-    return g;
+  return (FT_Fixed)(lround(val * 65536.0));
+}
+
+/* Glyph weight by factor. -1 (min stroke width) <= 0 (normal) => 1 (max boldness). */
+static bool blf_glyph_transform_weight(FT_GlyphSlot glyph, float factor, bool monospaced)
+{
+  if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
+    /* Fake bold if the font does not have this variable axis. */
+    const FT_Pos average_width = FT_MulFix(glyph->face->units_per_EM,
+                                           glyph->face->size->metrics.x_scale);
+    FT_Pos change = (FT_Pos)((float)average_width * factor * 0.1f);
+    FT_Outline_EmboldenXY(&glyph->outline, change, change / 2);
+    if (monospaced) {
+      /* Widened fixed-pitch font needs a nudge left. */
+      FT_Outline_Translate(&glyph->outline, change / -2, 0);
+    }
+    else {
+      /* Need to increase advance. */
+      glyph->advance.x += change;
+      glyph->advance.y += change / 2;
+    }
+    return true;
   }
+  return false;
+}
 
-  FT_UInt glyph_index = FT_Get_Char_Index(font->face, charcode);
+/* Glyph oblique by factor. -1 (max negative) <= 0 (no slant) => 1 (max positive).
+ * Note that left-leaning italics are possibile in some RTL writing systems. */
+static bool blf_glyph_transform_slant(FT_GlyphSlot glyph, float factor)
+{
+  if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
+    FT_Matrix transform = {to_16dot16(1), to_16dot16(factor / 2.0f), 0, to_16dot16(1)};
+    FT_Outline_Transform(&glyph->outline, &transform);
+    return true;
+  }
+  return false;
+}
 
-  if (!blf_glyph_render(font, glyph_index)) {
-    return NULL;
+/* Glyph width by factor. -1 (min width) <= 0 (normal) => 1 (max width). */
+static bool UNUSED_FUNCTION(blf_glyph_transform_width)(FT_GlyphSlot glyph, float factor)
+{
+  if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
+    float scale = (factor * 0.4f) + 1.0f; /* 0.6f - 1.4f */
+    FT_Matrix matrix = {to_16dot16(scale), 0, 0, to_16d

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list