Cleanup: comments (long lines) in blenlib
[blender.git] / source / blender / blenlib / intern / freetypefont.c
index a48332c..92553ae 100644 (file)
@@ -21,8 +21,8 @@
  * Code that uses exotic character maps is present but commented out.
  */
 
-/** \file blender/blenlib/intern/freetypefont.c
- *  \ingroup bli
+/** \file
+ * \ingroup bli
  */
 
 #include <ft2build.h>
 static FT_Library library;
 static FT_Error err;
 
-
 static VChar *freetypechar_to_vchar(FT_Face face, FT_ULong charcode, VFontData *vfd)
 {
-       const float scale = vfd->scale;
-       const float eps = 0.0001f;
-       const float eps_sq = eps * eps;
-       /* Blender */
-       struct Nurb *nu;
-       struct VChar *che;
-       struct BezTriple *bezt;
-
-       /* Freetype2 */
-       FT_GlyphSlot glyph;
-       FT_UInt glyph_index;
-       FT_Outline ftoutline;
-       float dx, dy;
-       int j, k, l, l_first = 0;
-
-       /*
-        * Generate the character 3D data
-        *
-        * Get the FT Glyph index and load the Glyph */
-       glyph_index = FT_Get_Char_Index(face, charcode);
-       err = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP);
-
-       /* If loading succeeded, convert the FT glyph to the internal format */
-       if (!err) {
-               /* initialize as -1 to add 1 on first loop each time */
-               int contour_prev;
-               int *onpoints;
-
-               /* First we create entry for the new character to the character list */
-               che = (VChar *) MEM_callocN(sizeof(struct VChar), "objfnt_char");
-
-               /* Take some data for modifying purposes */
-               glyph = face->glyph;
-               ftoutline = glyph->outline;
-
-               /* Set the width and character code */
-               che->index = charcode;
-               che->width = glyph->advance.x * scale;
-
-               BLI_ghash_insert(vfd->characters, POINTER_FROM_UINT(che->index), che);
-
-               /* Start converting the FT data */
-               onpoints = (int *)MEM_callocN((ftoutline.n_contours) * sizeof(int), "onpoints");
-
-               /* get number of on-curve points for beziertriples (including conic virtual on-points) */
-               for (j = 0, contour_prev = -1; j < ftoutline.n_contours; j++) {
-                       const int n = ftoutline.contours[j] - contour_prev;
-                       contour_prev = ftoutline.contours[j];
-
-                       for (k = 0; k < n; k++) {
-                               l = (j > 0) ? (k + ftoutline.contours[j - 1] + 1) : k;
-                               if (k == 0) l_first = l;
-
-                               if (ftoutline.tags[l] == FT_Curve_Tag_On)
-                                       onpoints[j]++;
-
-                               {
-                                       const int l_next = (k < n - 1) ? (l + 1) : l_first;
-                                       if (ftoutline.tags[l]      == FT_Curve_Tag_Conic &&
-                                           ftoutline.tags[l_next] == FT_Curve_Tag_Conic)
-                                       {
-                                               onpoints[j]++;
-                                       }
-                               }
-                       }
-               }
-
-               /* contour loop, bezier & conic styles merged */
-               for (j = 0, contour_prev = -1; j < ftoutline.n_contours; j++) {
-                       const int n = ftoutline.contours[j] - contour_prev;
-                       contour_prev = ftoutline.contours[j];
-
-                       /* add new curve */
-                       nu  =  (Nurb *)MEM_callocN(sizeof(struct Nurb), "objfnt_nurb");
-                       bezt = (BezTriple *)MEM_callocN((onpoints[j]) * sizeof(BezTriple), "objfnt_bezt");
-                       BLI_addtail(&che->nurbsbase, nu);
-
-                       nu->type = CU_BEZIER;
-                       nu->pntsu = onpoints[j];
-                       nu->resolu = 8;
-                       nu->flag = CU_2D;
-                       nu->flagu = CU_NURB_CYCLIC;
-                       nu->bezt = bezt;
-
-                       /* individual curve loop, start-end */
-                       for (k = 0; k < n; k++) {
-                               l = (j > 0) ? (k + ftoutline.contours[j - 1] + 1) : k;
-                               if (k == 0) l_first = l;
-
-                               /* virtual conic on-curve points */
-                               {
-                                       const int l_next = (k < n - 1) ? (l + 1) : l_first;
-                                       if (ftoutline.tags[l]      == FT_Curve_Tag_Conic &&
-                                           ftoutline.tags[l_next] == FT_Curve_Tag_Conic)
-                                       {
-                                               dx = (ftoutline.points[l].x + ftoutline.points[l_next].x) * scale / 2.0f;
-                                               dy = (ftoutline.points[l].y + ftoutline.points[l_next].y) * scale / 2.0f;
-
-                                               /* left handle */
-                                               bezt->vec[0][0] = (dx + (2 * ftoutline.points[l].x) * scale) / 3.0f;
-                                               bezt->vec[0][1] = (dy + (2 * ftoutline.points[l].y) * scale) / 3.0f;
-
-                                               /* midpoint (virtual on-curve point) */
-                                               bezt->vec[1][0] = dx;
-                                               bezt->vec[1][1] = dy;
-
-                                               /* right handle */
-                                               bezt->vec[2][0] = (dx + (2 * ftoutline.points[l_next].x) * scale) / 3.0f;
-                                               bezt->vec[2][1] = (dy + (2 * ftoutline.points[l_next].y) * scale) / 3.0f;
-
-                                               bezt->h1 = bezt->h2 = HD_ALIGN;
-                                               bezt->radius = 1.0f;
-                                               bezt++;
-                                       }
-                               }
-
-                               /* on-curve points */
-                               if (ftoutline.tags[l] == FT_Curve_Tag_On) {
-                                       const int l_prev = (k > 0)     ? (l - 1) : ftoutline.contours[j];
-                                       const int l_next = (k < n - 1) ? (l + 1) : l_first;
-
-                                       /* left handle */
-                                       if (ftoutline.tags[l_prev] == FT_Curve_Tag_Cubic) {
-                                               bezt->vec[0][0] = ftoutline.points[l_prev].x * scale;
-                                               bezt->vec[0][1] = ftoutline.points[l_prev].y * scale;
-                                               bezt->h1 = HD_FREE;
-                                       }
-                                       else if (ftoutline.tags[l_prev] == FT_Curve_Tag_Conic) {
-                                               bezt->vec[0][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l_prev].x)) * scale / 3.0f;
-                                               bezt->vec[0][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l_prev].y)) * scale / 3.0f;
-                                               bezt->h1 = HD_FREE;
-                                       }
-                                       else {
-                                               bezt->vec[0][0] = ftoutline.points[l].x * scale - (ftoutline.points[l].x - ftoutline.points[l_prev].x) * scale / 3.0f;
-                                               bezt->vec[0][1] = ftoutline.points[l].y * scale - (ftoutline.points[l].y - ftoutline.points[l_prev].y) * scale / 3.0f;
-                                               bezt->h1 = HD_VECT;
-                                       }
-
-                                       /* midpoint (on-curve point) */
-                                       bezt->vec[1][0] = ftoutline.points[l].x * scale;
-                                       bezt->vec[1][1] = ftoutline.points[l].y * scale;
-
-                                       /* right handle */
-                                       if (ftoutline.tags[l_next] == FT_Curve_Tag_Cubic) {
-                                               bezt->vec[2][0] = ftoutline.points[l_next].x * scale;
-                                               bezt->vec[2][1] = ftoutline.points[l_next].y * scale;
-                                               bezt->h2 = HD_FREE;
-                                       }
-                                       else if (ftoutline.tags[l_next] == FT_Curve_Tag_Conic) {
-                                               bezt->vec[2][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l_next].x)) * scale / 3.0f;
-                                               bezt->vec[2][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l_next].y)) * scale / 3.0f;
-                                               bezt->h2 = HD_FREE;
-                                       }
-                                       else {
-                                               bezt->vec[2][0] = ftoutline.points[l].x * scale - (ftoutline.points[l].x - ftoutline.points[l_next].x) * scale / 3.0f;
-                                               bezt->vec[2][1] = ftoutline.points[l].y * scale - (ftoutline.points[l].y - ftoutline.points[l_next].y) * scale / 3.0f;
-                                               bezt->h2 = HD_VECT;
-                                       }
-
-                                       /* get the handles that are aligned, tricky...
-                                        * - check if one of them is a vector handle.
-                                        * - dist_squared_to_line_v2, check if the three beztriple points are on one line
-                                        * - len_squared_v2v2, see if there's a distance between the three points
-                                        * - len_squared_v2v2 again, to check the angle between the handles
-                                        */
-                                       if ((bezt->h1 != HD_VECT && bezt->h2 != HD_VECT) &&
-                                           (dist_squared_to_line_v2(bezt->vec[0], bezt->vec[1], bezt->vec[2]) < (0.001f * 0.001f)) &&
-                                           (len_squared_v2v2(bezt->vec[0], bezt->vec[1]) > eps_sq) &&
-                                           (len_squared_v2v2(bezt->vec[1], bezt->vec[2]) > eps_sq) &&
-                                           (len_squared_v2v2(bezt->vec[0], bezt->vec[2]) > eps_sq) &&
-                                           (len_squared_v2v2(bezt->vec[0], bezt->vec[2]) >
-                                            max_ff(len_squared_v2v2(bezt->vec[0], bezt->vec[1]),
-                                                   len_squared_v2v2(bezt->vec[1], bezt->vec[2]))))
-                                       {
-                                               bezt->h1 = bezt->h2 = HD_ALIGN;
-                                       }
-                                       bezt->radius = 1.0f;
-                                       bezt++;
-                               }
-                       }
-               }
-
-               MEM_freeN(onpoints);
-
-               return che;
-       }
-
-       return NULL;
+  const float scale = vfd->scale;
+  const float eps = 0.0001f;
+  const float eps_sq = eps * eps;
+  /* Blender */
+  struct Nurb *nu;
+  struct VChar *che;
+  struct BezTriple *bezt;
+
+  /* Freetype2 */
+  FT_GlyphSlot glyph;
+  FT_UInt glyph_index;
+  FT_Outline ftoutline;
+  float dx, dy;
+  int j, k, l, l_first = 0;
+
+  /*
+   * Generate the character 3D data
+   *
+   * Get the FT Glyph index and load the Glyph */
+  glyph_index = FT_Get_Char_Index(face, charcode);
+  err = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP);
+
+  /* If loading succeeded, convert the FT glyph to the internal format */
+  if (!err) {
+    /* initialize as -1 to add 1 on first loop each time */
+    int contour_prev;
+    int *onpoints;
+
+    /* First we create entry for the new character to the character list */
+    che = (VChar *)MEM_callocN(sizeof(struct VChar), "objfnt_char");
+
+    /* Take some data for modifying purposes */
+    glyph = face->glyph;
+    ftoutline = glyph->outline;
+
+    /* Set the width and character code */
+    che->index = charcode;
+    che->width = glyph->advance.x * scale;
+
+    BLI_ghash_insert(vfd->characters, POINTER_FROM_UINT(che->index), che);
+
+    /* Start converting the FT data */
+    onpoints = (int *)MEM_callocN((ftoutline.n_contours) * sizeof(int), "onpoints");
+
+    /* get number of on-curve points for beziertriples (including conic virtual on-points) */
+    for (j = 0, contour_prev = -1; j < ftoutline.n_contours; j++) {
+      const int n = ftoutline.contours[j] - contour_prev;
+      contour_prev = ftoutline.contours[j];
+
+      for (k = 0; k < n; k++) {
+        l = (j > 0) ? (k + ftoutline.contours[j - 1] + 1) : k;
+        if (k == 0) {
+          l_first = l;
+        }
+
+        if (ftoutline.tags[l] == FT_Curve_Tag_On) {
+          onpoints[j]++;
+        }
+
+        {
+          const int l_next = (k < n - 1) ? (l + 1) : l_first;
+          if (ftoutline.tags[l] == FT_Curve_Tag_Conic &&
+              ftoutline.tags[l_next] == FT_Curve_Tag_Conic) {
+            onpoints[j]++;
+          }
+        }
+      }
+    }
+
+    /* contour loop, bezier & conic styles merged */
+    for (j = 0, contour_prev = -1; j < ftoutline.n_contours; j++) {
+      const int n = ftoutline.contours[j] - contour_prev;
+      contour_prev = ftoutline.contours[j];
+
+      /* add new curve */
+      nu = (Nurb *)MEM_callocN(sizeof(struct Nurb), "objfnt_nurb");
+      bezt = (BezTriple *)MEM_callocN((onpoints[j]) * sizeof(BezTriple), "objfnt_bezt");
+      BLI_addtail(&che->nurbsbase, nu);
+
+      nu->type = CU_BEZIER;
+      nu->pntsu = onpoints[j];
+      nu->resolu = 8;
+      nu->flag = CU_2D;
+      nu->flagu = CU_NURB_CYCLIC;
+      nu->bezt = bezt;
+
+      /* individual curve loop, start-end */
+      for (k = 0; k < n; k++) {
+        l = (j > 0) ? (k + ftoutline.contours[j - 1] + 1) : k;
+        if (k == 0) {
+          l_first = l;
+        }
+
+        /* virtual conic on-curve points */
+        {
+          const int l_next = (k < n - 1) ? (l + 1) : l_first;
+          if (ftoutline.tags[l] == FT_Curve_Tag_Conic &&
+              ftoutline.tags[l_next] == FT_Curve_Tag_Conic) {
+            dx = (ftoutline.points[l].x + ftoutline.points[l_next].x) * scale / 2.0f;
+            dy = (ftoutline.points[l].y + ftoutline.points[l_next].y) * scale / 2.0f;
+
+            /* left handle */
+            bezt->vec[0][0] = (dx + (2 * ftoutline.points[l].x) * scale) / 3.0f;
+            bezt->vec[0][1] = (dy + (2 * ftoutline.points[l].y) * scale) / 3.0f;
+
+            /* midpoint (virtual on-curve point) */
+            bezt->vec[1][0] = dx;
+            bezt->vec[1][1] = dy;
+
+            /* right handle */
+            bezt->vec[2][0] = (dx + (2 * ftoutline.points[l_next].x) * scale) / 3.0f;
+            bezt->vec[2][1] = (dy + (2 * ftoutline.points[l_next].y) * scale) / 3.0f;
+
+            bezt->h1 = bezt->h2 = HD_ALIGN;
+            bezt->radius = 1.0f;
+            bezt++;
+          }
+        }
+
+        /* on-curve points */
+        if (ftoutline.tags[l] == FT_Curve_Tag_On) {
+          const int l_prev = (k > 0) ? (l - 1) : ftoutline.contours[j];
+          const int l_next = (k < n - 1) ? (l + 1) : l_first;
+
+          /* left handle */
+          if (ftoutline.tags[l_prev] == FT_Curve_Tag_Cubic) {
+            bezt->vec[0][0] = ftoutline.points[l_prev].x * scale;
+            bezt->vec[0][1] = ftoutline.points[l_prev].y * scale;
+            bezt->h1 = HD_FREE;
+          }
+          else if (ftoutline.tags[l_prev] == FT_Curve_Tag_Conic) {
+            bezt->vec[0][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l_prev].x)) * scale /
+                              3.0f;
+            bezt->vec[0][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l_prev].y)) * scale /
+                              3.0f;
+            bezt->h1 = HD_FREE;
+          }
+          else {
+            bezt->vec[0][0] = ftoutline.points[l].x * scale -
+                              (ftoutline.points[l].x - ftoutline.points[l_prev].x) * scale / 3.0f;
+            bezt->vec[0][1] = ftoutline.points[l].y * scale -
+                              (ftoutline.points[l].y - ftoutline.points[l_prev].y) * scale / 3.0f;
+            bezt->h1 = HD_VECT;
+          }
+
+          /* midpoint (on-curve point) */
+          bezt->vec[1][0] = ftoutline.points[l].x * scale;
+          bezt->vec[1][1] = ftoutline.points[l].y * scale;
+
+          /* right handle */
+          if (ftoutline.tags[l_next] == FT_Curve_Tag_Cubic) {
+            bezt->vec[2][0] = ftoutline.points[l_next].x * scale;
+            bezt->vec[2][1] = ftoutline.points[l_next].y * scale;
+            bezt->h2 = HD_FREE;
+          }
+          else if (ftoutline.tags[l_next] == FT_Curve_Tag_Conic) {
+            bezt->vec[2][0] = (ftoutline.points[l].x + (2 * ftoutline.points[l_next].x)) * scale /
+                              3.0f;
+            bezt->vec[2][1] = (ftoutline.points[l].y + (2 * ftoutline.points[l_next].y)) * scale /
+                              3.0f;
+            bezt->h2 = HD_FREE;
+          }
+          else {
+            bezt->vec[2][0] = ftoutline.points[l].x * scale -
+                              (ftoutline.points[l].x - ftoutline.points[l_next].x) * scale / 3.0f;
+            bezt->vec[2][1] = ftoutline.points[l].y * scale -
+                              (ftoutline.points[l].y - ftoutline.points[l_next].y) * scale / 3.0f;
+            bezt->h2 = HD_VECT;
+          }
+
+          /* get the handles that are aligned, tricky...
+           * - check if one of them is a vector handle.
+           * - dist_squared_to_line_v2, check if the three beztriple points are on one line
+           * - len_squared_v2v2, see if there's a distance between the three points
+           * - len_squared_v2v2 again, to check the angle between the handles
+           */
+          if ((bezt->h1 != HD_VECT && bezt->h2 != HD_VECT) &&
+              (dist_squared_to_line_v2(bezt->vec[0], bezt->vec[1], bezt->vec[2]) <
+               (0.001f * 0.001f)) &&
+              (len_squared_v2v2(bezt->vec[0], bezt->vec[1]) > eps_sq) &&
+              (len_squared_v2v2(bezt->vec[1], bezt->vec[2]) > eps_sq) &&
+              (len_squared_v2v2(bezt->vec[0], bezt->vec[2]) > eps_sq) &&
+              (len_squared_v2v2(bezt->vec[0], bezt->vec[2]) >
+               max_ff(len_squared_v2v2(bezt->vec[0], bezt->vec[1]),
+                      len_squared_v2v2(bezt->vec[1], bezt->vec[2])))) {
+            bezt->h1 = bezt->h2 = HD_ALIGN;
+          }
+          bezt->radius = 1.0f;
+          bezt++;
+        }
+      }
+    }
+
+    MEM_freeN(onpoints);
+
+    return che;
+  }
+
+  return NULL;
 }
 
 static VChar *objchr_to_ftvfontdata(VFont *vfont, FT_ULong charcode)
 {
-       VChar *che;
-
-       /* Freetype2 */
-       FT_Face face;
-
-       /* Load the font to memory */
-       if (vfont->temp_pf) {
-               err = FT_New_Memory_Face(library,
-                                        vfont->temp_pf->data,
-                                        vfont->temp_pf->size,
-                                        0,
-                                        &face);
-               if (err) {
-                       return NULL;
-               }
-       }
-       else {
-               err = true;
-               return NULL;
-       }
-
-       /* Read the char */
-       che = freetypechar_to_vchar(face, charcode, vfont->data);
-
-       /* And everything went ok */
-       return che;
+  VChar *che;
+
+  /* Freetype2 */
+  FT_Face face;
+
+  /* Load the font to memory */
+  if (vfont->temp_pf) {
+    err = FT_New_Memory_Face(library, vfont->temp_pf->data, vfont->temp_pf->size, 0, &face);
+    if (err) {
+      return NULL;
+    }
+  }
+  else {
+    err = true;
+    return NULL;
+  }
+
+  /* Read the char */
+  che = freetypechar_to_vchar(face, charcode, vfont->data);
+
+  /* And everything went ok */
+  return che;
 }
 
-
 static VFontData *objfnt_to_ftvfontdata(PackedFile *pf)
 {
-       /* Variables */
-       FT_Face face;
-       const FT_ULong charcode_reserve = 256;
-       FT_ULong charcode = 0, lcode;
-       FT_UInt glyph_index;
-       const char *fontname;
-       VFontData *vfd;
-
-       /* load the freetype font */
-       err = FT_New_Memory_Face(library,
-                                pf->data,
-                                pf->size,
-                                0,
-                                &face);
-
-       if (err) return NULL;
-
-       /* allocate blender font */
-       vfd = MEM_callocN(sizeof(*vfd), "FTVFontData");
-
-       /* get the name */
-       fontname = FT_Get_Postscript_Name(face);
-       BLI_strncpy(vfd->name, (fontname == NULL) ? "" : fontname, sizeof(vfd->name));
-
-       /* Extract the first 256 character from TTF */
-       lcode = charcode = FT_Get_First_Char(face, &glyph_index);
-
-       /* No charmap found from the ttf so we need to figure it out */
-       if (glyph_index == 0) {
-               FT_CharMap found = NULL;
-               FT_CharMap charmap;
-               int n;
-
-               for (n = 0; n < face->num_charmaps; n++) {
-                       charmap = face->charmaps[n];
-                       if (charmap->encoding == FT_ENCODING_APPLE_ROMAN) {
-                               found = charmap;
-                               break;
-                       }
-               }
-
-               err = FT_Set_Charmap(face, found);
-
-               if (err)
-                       return NULL;
-
-               lcode = charcode = FT_Get_First_Char(face, &glyph_index);
-       }
-
-       /* Blender default BFont is not "complete". */
-       const bool complete_font = (face->ascender != 0) && (face->descender != 0) &&
-                                  (face->ascender != face->descender);
-
-       if (complete_font) {
-               /* We can get descender as well, but we simple store descender in relation to the ascender.
-                * Also note that descender is stored as a negative number. */
-               vfd->ascender = (float)face->ascender / (face->ascender - face->descender);
-       }
-       else {
-               vfd->ascender = 0.8f;
-               vfd->em_height = 1.0f;
-       }
-
-       /* Adjust font size */
-       if (face->bbox.yMax != face->bbox.yMin) {
-               vfd->scale = (float)(1.0 / (double)(face->bbox.yMax - face->bbox.yMin));
-
-               if (complete_font) {
-                       vfd->em_height = (float)(face->ascender - face->descender) / (face->bbox.yMax - face->bbox.yMin);
-               }
-       }
-       else {
-               vfd->scale = 1.0f / 1000.0f;
-       }
-
-       /* Load characters */
-       vfd->characters = BLI_ghash_int_new_ex(__func__, charcode_reserve);
-
-       while (charcode < charcode_reserve) {
-               /* Generate the font data */
-               freetypechar_to_vchar(face, charcode, vfd);
-
-               /* Next glyph */
-               charcode = FT_Get_Next_Char(face, charcode, &glyph_index);
-
-               /* Check that we won't start infinite loop */
-               if (charcode <= lcode)
-                       break;
-               lcode = charcode;
-       }
-
-       return vfd;
+  /* Variables */
+  FT_Face face;
+  const FT_ULong charcode_reserve = 256;
+  FT_ULong charcode = 0, lcode;
+  FT_UInt glyph_index;
+  const char *fontname;
+  VFontData *vfd;
+
+  /* load the freetype font */
+  err = FT_New_Memory_Face(library, pf->data, pf->size, 0, &face);
+
+  if (err) {
+    return NULL;
+  }
+
+  /* allocate blender font */
+  vfd = MEM_callocN(sizeof(*vfd), "FTVFontData");
+
+  /* get the name */
+  fontname = FT_Get_Postscript_Name(face);
+  BLI_strncpy(vfd->name, (fontname == NULL) ? "" : fontname, sizeof(vfd->name));
+
+  /* Extract the first 256 character from TTF */
+  lcode = charcode = FT_Get_First_Char(face, &glyph_index);
+
+  /* No charmap found from the ttf so we need to figure it out */
+  if (glyph_index == 0) {
+    FT_CharMap found = NULL;
+    FT_CharMap charmap;
+    int n;
+
+    for (n = 0; n < face->num_charmaps; n++) {
+      charmap = face->charmaps[n];
+      if (charmap->encoding == FT_ENCODING_APPLE_ROMAN) {
+        found = charmap;
+        break;
+      }
+    }
+
+    err = FT_Set_Charmap(face, found);
+
+    if (err) {
+      return NULL;
+    }
+
+    lcode = charcode = FT_Get_First_Char(face, &glyph_index);
+  }
+
+  /* Blender default BFont is not "complete". */
+  const bool complete_font = (face->ascender != 0) && (face->descender != 0) &&
+                             (face->ascender != face->descender);
+
+  if (complete_font) {
+    /* We can get descender as well, but we simple store descender in relation to the ascender.
+     * Also note that descender is stored as a negative number. */
+    vfd->ascender = (float)face->ascender / (face->ascender - face->descender);
+  }
+  else {
+    vfd->ascender = 0.8f;
+    vfd->em_height = 1.0f;
+  }
+
+  /* Adjust font size */
+  if (face->bbox.yMax != face->bbox.yMin) {
+    vfd->scale = (float)(1.0 / (double)(face->bbox.yMax - face->bbox.yMin));
+
+    if (complete_font) {
+      vfd->em_height = (float)(face->ascender - face->descender) /
+                       (face->bbox.yMax - face->bbox.yMin);
+    }
+  }
+  else {
+    vfd->scale = 1.0f / 1000.0f;
+  }
+
+  /* Load characters */
+  vfd->characters = BLI_ghash_int_new_ex(__func__, charcode_reserve);
+
+  while (charcode < charcode_reserve) {
+    /* Generate the font data */
+    freetypechar_to_vchar(face, charcode, vfd);
+
+    /* Next glyph */
+    charcode = FT_Get_Next_Char(face, charcode, &glyph_index);
+
+    /* Check that we won't start infinite loop */
+    if (charcode <= lcode) {
+      break;
+    }
+    lcode = charcode;
+  }
+
+  return vfd;
 }
 
-
 static int check_freetypefont(PackedFile *pf)
 {
-       FT_Face face;
-       FT_GlyphSlot glyph;
-       FT_UInt glyph_index;
-       int success = 0;
-
-       err = FT_New_Memory_Face(library,
-                                pf->data,
-                                pf->size,
-                                0,
-                                &face);
-       if (err) {
-               success = 0;
-               //XXX error("This is not a valid font");
-       }
-       else {
-               glyph_index = FT_Get_Char_Index(face, 'A');
-               err = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP);
-               if (err) {
-                       success = 0;
-               }
-               else {
-                       glyph = face->glyph;
-                       if (glyph->format == ft_glyph_format_outline) {
-                               success = 1;
-                       }
-                       else {
-                               //XXX error("Selected Font has no outline data");
-                               success = 0;
-                       }
-               }
-       }
-
-       return success;
+  FT_Face face;
+  FT_GlyphSlot glyph;
+  FT_UInt glyph_index;
+  int success = 0;
+
+  err = FT_New_Memory_Face(library, pf->data, pf->size, 0, &face);
+  if (err) {
+    success = 0;
+    //XXX error("This is not a valid font");
+  }
+  else {
+    glyph_index = FT_Get_Char_Index(face, 'A');
+    err = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP);
+    if (err) {
+      success = 0;
+    }
+    else {
+      glyph = face->glyph;
+      if (glyph->format == ft_glyph_format_outline) {
+        success = 1;
+      }
+      else {
+        //XXX error("Selected Font has no outline data");
+        success = 0;
+      }
+    }
+  }
+
+  return success;
 }
 
 /**
@@ -418,64 +419,67 @@ static int check_freetypefont(PackedFile *pf)
  */
 VFontData *BLI_vfontdata_from_freetypefont(PackedFile *pf)
 {
-       VFontData *vfd = NULL;
-       int success = 0;
+  VFontData *vfd = NULL;
+  int success = 0;
 
-       /* init Freetype */
-       err = FT_Init_FreeType(&library);
-       if (err) {
-               /* XXX error("Failed to load the Freetype font library"); */
-               return NULL;
-       }
+  /* init Freetype */
+  err = FT_Init_FreeType(&library);
+  if (err) {
+    /* XXX error("Failed to load the Freetype font library"); */
+    return NULL;
+  }
 
-       success = check_freetypefont(pf);
+  success = check_freetypefont(pf);
 
-       if (success) {
-               vfd = objfnt_to_ftvfontdata(pf);
-       }
+  if (success) {
+    vfd = objfnt_to_ftvfontdata(pf);
+  }
 
-       /* free Freetype */
-       FT_Done_FreeType(library);
+  /* free Freetype */
+  FT_Done_FreeType(library);
 
-       return vfd;
+  return vfd;
 }
 
 static void *vfontdata_copy_characters_value_cb(const void *src)
 {
-       return BLI_vfontchar_copy(src, 0);
+  return BLI_vfontchar_copy(src, 0);
 }
 
 VFontData *BLI_vfontdata_copy(const VFontData *vfont_src, const int UNUSED(flag))
 {
-       VFontData *vfont_dst = MEM_dupallocN(vfont_src);
+  VFontData *vfont_dst = MEM_dupallocN(vfont_src);
 
-       if (vfont_src->characters != NULL) {
-               vfont_dst->characters = BLI_ghash_copy(vfont_src->characters, NULL, vfontdata_copy_characters_value_cb);
-       }
+  if (vfont_src->characters != NULL) {
+    vfont_dst->characters = BLI_ghash_copy(
+        vfont_src->characters, NULL, vfontdata_copy_characters_value_cb);
+  }
 
-       return vfont_dst;
+  return vfont_dst;
 }
 
 VChar *BLI_vfontchar_from_freetypefont(VFont *vfont, unsigned long character)
 {
-       VChar *che = NULL;
+  VChar *che = NULL;
 
-       if (!vfont) return NULL;
+  if (!vfont) {
+    return NULL;
+  }
 
-       /* Init Freetype */
-       err = FT_Init_FreeType(&library);
-       if (err) {
-               /* XXX error("Failed to load the Freetype font library"); */
-               return NULL;
-       }
+  /* Init Freetype */
+  err = FT_Init_FreeType(&library);
+  if (err) {
+    /* XXX error("Failed to load the Freetype font library"); */
+    return NULL;
+  }
 
-       /* Load the character */
-       che = objchr_to_ftvfontdata(vfont, character);
+  /* Load the character */
+  che = objchr_to_ftvfontdata(vfont, character);
 
-       /* Free Freetype */
-       FT_Done_FreeType(library);
+  /* Free Freetype */
+  FT_Done_FreeType(library);
 
-       return che;
+  return che;
 }
 
 /* Yeah, this is very bad... But why is this in BLI in the first place, since it uses Nurb data?
@@ -485,16 +489,15 @@ VChar *BLI_vfontchar_from_freetypefont(VFont *vfont, unsigned long character)
 
 VChar *BLI_vfontchar_copy(const VChar *vchar_src, const int UNUSED(flag))
 {
-       VChar *vchar_dst = MEM_dupallocN(vchar_src);
+  VChar *vchar_dst = MEM_dupallocN(vchar_src);
 
-       BLI_listbase_clear(&vchar_dst->nurbsbase);
-       BKE_nurbList_duplicate(&vchar_dst->nurbsbase, &vchar_src->nurbsbase);
+  BLI_listbase_clear(&vchar_dst->nurbsbase);
+  BKE_nurbList_duplicate(&vchar_dst->nurbsbase, &vchar_src->nurbsbase);
 
-       return vchar_dst;
+  return vchar_dst;
 }
 
-
-/*
+/**
  * from: http://www.freetype.org/freetype2/docs/glyphs/glyphs-6.html#section-1
  *
  * Vectorial representation of Freetype glyphs
@@ -505,27 +508,30 @@ VChar *BLI_vfontchar_copy(const VChar *vchar_src, const int UNUSED(flag))
  * they come from the TrueType format. The latter are called cubic arcs and mostly come from the
  * Type1 format.
  *
- * Each arc is described through a series of start, end and control points. Each point of the outline
- * has a specific tag which indicates whether it is used to describe a line segment or an arc.
+ * Each arc is described through a series of start, end and control points.
+ * Each point of the outline has a specific tag which indicates whether it is
+ * used to describe a line segment or an arc.
  * The following rules are applied to decompose the contour's points into segments and arcs :
  *
  * # two successive "on" points indicate a line segment joining them.
  *
- * # one conic "off" point amidst two "on" points indicates a conic bezier arc, the "off" point being
- *   the control point, and the "on" ones the start and end points.
+ * # one conic "off" point amidst two "on" points indicates a conic bezier arc,
+ *   the "off" point being the control point, and the "on" ones the start and end points.
  *
- * # Two successive cubic "off" points amidst two "on" points indicate a cubic bezier arc. There must
- *   be exactly two cubic control points and two on points for each cubic arc (using a single cubic
- *   "off" point between two "on" points is forbidden, for example).
+ * # Two successive cubic "off" points amidst two "on" points indicate a cubic bezier arc.
+ *   There must be exactly two cubic control points and two on points for each cubic arc
+ *   (using a single cubic "off" point between two "on" points is forbidden, for example).
  *
- * # finally, two successive conic "off" points forces the rasterizer to create (during the scan-line
- *   conversion process exclusively) a virtual "on" point amidst them, at their exact middle. This
- *   greatly facilitates the definition of successive conic bezier arcs. Moreover, it's the way
- *   outlines are described in the TrueType specification.
+ * # finally, two successive conic "off" points forces the rasterizer to create
+ *   (during the scan-line conversion process exclusively) a virtual "on" point amidst them,
+ *   at their exact middle.
+ *   This greatly facilitates the definition of successive conic bezier arcs.
+ *   Moreover, it's the way outlines are described in the TrueType specification.
  *
  * Note that it is possible to mix conic and cubic arcs in a single contour, even though no current
  * font driver produces such outlines.
  *
+ * <pre>
  *                                   *            # on
  *                                                * off
  *                                __---__
@@ -557,9 +563,11 @@ VChar *BLI_vfontchar_copy(const VChar *vchar_src, const int UNUSED(flag))
  *      Two "on" points
  *    and two "cubic" point
  *       between them
- * Each glyph's original outline points are located on a grid of indivisible units. The points are stored
- * in the font file as 16-bit integer grid coordinates, with the grid origin's being at (0, 0); they thus
- * range from -16384 to 16383.
+ * </pre>
+ *
+ * Each glyph's original outline points are located on a grid of indivisible units.
+ * The points are stored in the font file as 16-bit integer grid coordinates,
+ * with the grid origin's being at (0, 0); they thus range from -16384 to 16383.
  *
  * Convert conic to bezier arcs:
  * Conic P0 P1 P2