Hi Matthieu,

you already gave an ok some time ago to merge changes to fonttosfnt. Now that my changes have been tested and merged upstream I'd like to integrate them into xenocara. May I ask for another ok?

Christopher


Index: fonttosfnt.c
===================================================================
RCS file: /cvs/xenocara/app/fonttosfnt/fonttosfnt.c,v
retrieving revision 1.3
diff -u -p -r1.3 fonttosfnt.c
--- fonttosfnt.c        14 Jan 2020 20:52:17 -0000      1.3
+++ fonttosfnt.c        9 Oct 2020 07:27:19 -0000
@@ -106,6 +106,12 @@ main(int argc, char **argv)
font = makeFont(); + if(argc - i > 1)
+       fprintf(stderr,
+           "You are requesting to put more than one font into a single OpenType 
font.\n"
+           "This is not recommended. The global font metrics will not match every 
font face.\n"
+           "The creation of an OpenType font collection is recommended.\n");
+
     if(i == argc) {
         rc = readFile(NULL, font);
         if(rc != 0)
Index: fonttosfnt.h
===================================================================
RCS file: /cvs/xenocara/app/fonttosfnt/fonttosfnt.h,v
retrieving revision 1.3
diff -u -p -r1.3 fonttosfnt.h
--- fonttosfnt.h        15 Aug 2019 16:57:57 -0000      1.3
+++ fonttosfnt.h        9 Oct 2020 07:27:19 -0000
@@ -29,6 +29,7 @@ THE SOFTWARE.
 #endif
#include <stdarg.h>
+#include <math.h>
 #include <ft2build.h>
 #include FT_FREETYPE_H
@@ -69,17 +70,15 @@ extern int reencode_flag; #define UNITS_PER_EM 2048 -#define EPSILON 0.000000001
-#define FLOOR(x) ((x) < 0.0 ? -(int)(-(x)) : (x))
-#define CEIL(x) FLOOR((x) + 1.0 - EPSILON)
+#define UNDEF 0x80000000
/* Convert a fixed-point value into FUnits */
 #define FONT_UNITS(x) \
-  FLOOR(((double)(x)) / TWO_SIXTEENTH * UNITS_PER_EM + 0.5)
+  round(((double)(x)) / TWO_SIXTEENTH * UNITS_PER_EM)
 #define FONT_UNITS_FLOOR(x) \
-  FLOOR(((double)(x)) / TWO_SIXTEENTH * UNITS_PER_EM)
+  floor(((double)(x)) / TWO_SIXTEENTH * UNITS_PER_EM)
 #define FONT_UNITS_CEIL(x) \
-  CEIL(((double)(x)) / TWO_SIXTEENTH * UNITS_PER_EM)
+  ceil(((double)(x)) / TWO_SIXTEENTH * UNITS_PER_EM)
typedef struct _FontNameEntry {
     int nid;                    /* name id */
@@ -87,6 +86,23 @@ typedef struct _FontNameEntry {
     char *value;
 } FontNameEntryRec, *FontNameEntryPtr;
+typedef struct _Metrics {
+    int height;
+    int size;
+    int maxX;
+    int minX;
+    int maxY;
+    int minY;
+    int xHeight;
+    int capHeight;
+    int maxAwidth;
+    int awidth;
+    int ascent;
+    int descent;
+    int underlinePosition;
+    int underlineThickness;
+} MetricsRec, *MetricsPtr;
+
 typedef struct _Font {
     int numNames;
     struct _FontNameEntry *names;
@@ -94,8 +110,8 @@ typedef struct _Font {
     int weight;                 /* as in the OS/2 table */
     int width;                  /* as in the OS/2 table */
     int italicAngle;            /* degrees c-clockwise from the vertical */
-    int underlinePosition;
-    int underlineThickness;
+    MetricsRec pxMetrics;
+    MetricsRec metrics;
     unsigned foundry;
     struct _Strike *strikes;
 } FontRec, *FontPtr;
@@ -152,9 +168,9 @@ CmapPtr makeCmap(FontPtr);
 int findIndex(CmapPtr, int);
 int findCode(CmapPtr, int);
 BitmapPtr strikeBitmapIndex(StrikePtr, CmapPtr, int);
-void strikeMetrics(StrikePtr, int*, int*, int*, int*, int*);
+int strikeMaxWidth(StrikePtr);
 int glyphMetrics(FontPtr, int, int*, int*, int*, int*, int*);
-void fontMetrics(FontPtr, int*, int*, int*, int*, int*);
+void fontMetrics(FontPtr);
 int maxIndex(CmapPtr);
int readFile(char *filename, FontPtr);
@@ -174,6 +190,7 @@ int macTime(int *, unsigned *);
 unsigned faceFoundry(FT_Face);
 char *faceEncoding(FT_Face);
 int faceFlags(FT_Face);
+int faceIntProp(FT_Face, const char *);
 int faceWeight(FT_Face);
 int faceWidth(FT_Face);
 int faceItalicAngle(FT_Face);
Index: read.c
===================================================================
RCS file: /cvs/xenocara/app/fonttosfnt/read.c,v
retrieving revision 1.4
diff -u -p -r1.4 read.c
--- read.c      14 Jan 2020 20:52:17 -0000      1.4
+++ read.c      9 Oct 2020 07:27:20 -0000
@@ -29,6 +29,7 @@ THE SOFTWARE.
 #include FT_FREETYPE_H
 #include FT_MODULE_H
 #include FT_BDF_H
+#include FT_FONT_FORMATS_H
 #include "X11/Xos.h"
 #include "fonttosfnt.h"
 #include "X11/fonts/fontenc.h"
@@ -102,7 +103,7 @@ readFile(char *filename, FontPtr font)
     BitmapPtr bitmap;
     int symbol = 0;
     int force_unicode = 1;
-    char *encoding_name = NULL;
+    const char *encoding_name, *file_format;
     FontMapPtr mapping = NULL;
     FontMapReversePtr reverse = NULL;
@@ -133,6 +134,15 @@ readFile(char *filename, FontPtr font)
         return -1;
     }
+ file_format = FT_Get_Font_Format(face);
+    if(strcmp(file_format, "BDF") != 0)
+       fprintf(stderr,
+               "font file %s is of format %s.\n"
+               "It's recommended to convert directly from a BDF font.\n"
+               "Some font properties may get lost when converting via a PCF 
font.\n",
+               filename ? filename : "<stdin>",
+               file_format);
+
     /* FreeType will insist on encodings which are simple subsets of unicode
      * to be read as unicode regardless of what we call them. */
     for(j = 0; j < face->num_charmaps; ++j) {
@@ -258,30 +268,6 @@ readFile(char *filename, FontPtr font)
         i++;
 #endif
         font->numNames = i;
-
-        font->flags = faceFlags(face) | (symbol ? FACE_SYMBOL : 0);
-        font->weight = faceWeight(face);
-        font->width = faceWidth(face);
-        font->foundry = faceFoundry(face);
-        font->italicAngle = faceItalicAngle(face);
-
-        rc = FT_Get_BDF_Property(face, "UNDERLINE_POSITION", &prop);
-        if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
- font->underlinePosition = - (double)prop.u.integer / face->available_sizes[0].height *
-                TWO_SIXTEENTH;
-        else
-            font->underlinePosition =
-                - 1.5 / face->available_sizes[0].height * TWO_SIXTEENTH;
-
-        rc = FT_Get_BDF_Property(face, "UNDERLINE_THICKNESS", &prop);
-        if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
- font->underlineThickness = - (double)prop.u.integer / face->available_sizes[0].height *
-                TWO_SIXTEENTH;
-        else
-            font->underlineThickness =
-                1.0 / face->available_sizes[0].height * TWO_SIXTEENTH;
     }
if(face->num_fixed_sizes == 0) {
@@ -303,6 +289,20 @@ readFile(char *filename, FontPtr font)
         fprintf(stderr, "Couldn't select character map: %x.\n", rc);
         return -1;
     }
+
+    font->flags = faceFlags(face) | (symbol ? FACE_SYMBOL : 0);
+    font->weight = faceWeight(face);
+    font->width = faceWidth(face);
+    font->foundry = faceFoundry(face);
+    font->italicAngle = faceItalicAngle(face);
+    font->pxMetrics.height = face->available_sizes[0].height;
+    font->pxMetrics.size = faceIntProp(face, "PIXEL_SIZE");
+    font->pxMetrics.xHeight = faceIntProp(face, "X_HEIGHT");
+    font->pxMetrics.capHeight = faceIntProp(face, "CAP_HEIGHT");
+    font->pxMetrics.ascent = faceIntProp(face, "FONT_ASCENT");
+    font->pxMetrics.descent = faceIntProp(face, "FONT_DESCENT");
+    font->pxMetrics.underlinePosition = faceIntProp(face, 
"UNDERLINE_POSITION");
+    font->pxMetrics.underlineThickness = faceIntProp(face, 
"UNDERLINE_THICKNESS");
for(int i = 0; i < face->num_fixed_sizes; i++) {
         if(verbose_flag)
Index: struct.c
===================================================================
RCS file: /cvs/xenocara/app/fonttosfnt/struct.c,v
retrieving revision 1.3
diff -u -p -r1.3 struct.c
--- struct.c    14 Jan 2020 20:52:17 -0000      1.3
+++ struct.c    9 Oct 2020 07:27:20 -0000
@@ -42,8 +42,32 @@ makeFont(void)
     font->weight = 500;
     font->width = 5;
     font->italicAngle = 0;
-    font->underlinePosition = - TWO_SIXTEENTH;
-    font->underlineThickness = TWO_SIXTEENTH;
+    font->pxMetrics.height = UNDEF;
+    font->pxMetrics.maxX = UNDEF;
+    font->pxMetrics.minX = UNDEF;
+    font->pxMetrics.maxY = UNDEF;
+    font->pxMetrics.minY = UNDEF;
+    font->pxMetrics.xHeight = UNDEF;
+    font->pxMetrics.capHeight = UNDEF;
+    font->pxMetrics.maxAwidth = UNDEF;
+    font->pxMetrics.awidth = UNDEF;
+    font->pxMetrics.ascent = UNDEF;
+    font->pxMetrics.descent = UNDEF;
+    font->pxMetrics.underlinePosition = UNDEF;
+    font->pxMetrics.underlineThickness = UNDEF;
+    font->metrics.height = UNDEF;
+    font->metrics.maxX = UNDEF;
+    font->metrics.minX = UNDEF;
+    font->metrics.maxY = UNDEF;
+    font->metrics.minY = UNDEF;
+    font->metrics.xHeight = UNDEF;
+    font->metrics.capHeight = UNDEF;
+    font->metrics.maxAwidth = UNDEF;
+    font->metrics.awidth = UNDEF;
+    font->metrics.ascent = UNDEF;
+    font->metrics.descent = UNDEF;
+    font->metrics.underlinePosition = UNDEF;
+    font->metrics.underlineThickness = UNDEF;
     font->foundry = makeName("UNKN");
     font->strikes = NULL;
     return font;
@@ -401,19 +425,12 @@ strikeBitmapIndex(StrikePtr strike, Cmap
     return STRIKE_BITMAP(strike, code);
 }
-void
-strikeMetrics(StrikePtr strike,
- int *width_max_return, - int *x_min_return, int *y_min_return,
-              int *x_max_return, int *y_max_return)
+int
+strikeMaxWidth(StrikePtr strike)
 {
     BitmapPtr bitmap;
     int i;
     int width_max = 0;
-    int x_min = 10000;
-    int y_min = 10000;
-    int x_max = -10000;
-    int y_max = -10000;
for(i = 0; i < FONT_CODES; i++) {
         bitmap = STRIKE_BITMAP(strike, i);
@@ -421,21 +438,9 @@ strikeMetrics(StrikePtr strike,
             continue;
         if(bitmap->advanceWidth > width_max)
             width_max = bitmap->advanceWidth;
-        if(bitmap->horiBearingX < x_min)
-            x_min = bitmap->horiBearingX;
-        if(bitmap->horiBearingY > y_max)
-            y_max = bitmap->horiBearingY;
-        if(bitmap->horiBearingX + bitmap->width > x_max)
-            x_max = bitmap->horiBearingX + bitmap->width;
-        if(bitmap->horiBearingY - bitmap->height < y_min)
-            y_min = bitmap->horiBearingY - bitmap->height;
     }
- if(width_max_return) *width_max_return = width_max;
-    if(x_min_return) *x_min_return = x_min;
-    if(y_min_return) *y_min_return = y_min;
-    if(x_max_return) *x_max_return = x_max;
-    if(y_max_return) *y_max_return = y_max;
+    return width_max;
 }
int
@@ -453,7 +458,7 @@ glyphMetrics(FontPtr font, int code,
         if(bitmap) {
             if(width_return)
*width_return = - (((float)bitmap->advanceWidth + 0.5) / strike->sizeX) *
+                    (((float)bitmap->advanceWidth) / strike->sizeX) *
                     TWO_SIXTEENTH;
             if(x_min_return)
                 *x_min_return =
@@ -463,17 +468,13 @@ glyphMetrics(FontPtr font, int code,
                 *y_min_return =
(((float)bitmap->horiBearingY - bitmap->height) / strike->sizeY) * TWO_SIXTEENTH;
-            /* For the following two, 0.9 instead of 0.5 might make
-               more sense.  However, using different rounding rules
-               for x_max and awidth causes problems for detecting
-               charcell fonts. */
             if(x_max_return)
                 *x_max_return =
-                    (((float)bitmap->horiBearingX + bitmap->width + 0.5)
+                    (((float)bitmap->horiBearingX + bitmap->width)
                      / strike->sizeX) * TWO_SIXTEENTH;
             if(y_max_return)
                 *y_max_return =
-                    (((float)bitmap->horiBearingY + 0.5) / strike->sizeY) *
+                    (((float)bitmap->horiBearingY) / strike->sizeY) *
                     TWO_SIXTEENTH;
             return 1;
         }
@@ -482,33 +483,3 @@ glyphMetrics(FontPtr font, int code,
return -1;
 }
-
-void
-fontMetrics(FontPtr font,
-            int *max_awidth_return,
-            int *min_x_return, int *min_y_return,
-            int *max_x_return, int *max_y_return)
-{
-    int i, rc;
-    int max_awidth = 0;
-    int min_x = 10000 * 65536, min_y = 10000 * 65536;
-    int max_x = -10000 * 65536, max_y = -10000 * 65536;
-    for(i = 0; i < FONT_CODES; i++) {
-        int awidth, x0, y0, x1, y1;
-        rc = glyphMetrics(font, i, &awidth, &x0, &y0, &x1, &y1);
-        if(rc < 0)
-            continue;
-        if(awidth > max_awidth)
-            max_awidth = awidth;
-        if(x0 < min_x) min_x = x0;
-        if(y0 < min_y) min_y = y0;
-        if(x1 > max_x) max_x = x1;
-        if(y1 > max_y) max_y = y1;
-    }
-    if(max_awidth_return) *max_awidth_return = max_awidth;
-    if(min_x_return) *min_x_return = min_x;
-    if(min_y_return) *min_y_return = min_y;
-    if(max_x_return) *max_x_return = max_x;
-    if(max_y_return) *max_y_return = max_y;
-}
-
Index: util.c
===================================================================
RCS file: /cvs/xenocara/app/fonttosfnt/util.c,v
retrieving revision 1.4
diff -u -p -r1.4 util.c
--- util.c      14 Jan 2020 20:52:17 -0000      1.4
+++ util.c      9 Oct 2020 07:27:20 -0000
@@ -213,10 +213,10 @@ macTime(int *hi, unsigned *lo)
     tm.tm_isdst = -1;
macEpoch = mktime_gmt(&tm);
-    if(macEpoch < 0) return -1;
+    if(macEpoch == -1) return -1;
current = time(NULL);
-    if(current < 0)
+    if(current == -1)
         return -1;
if(current < macEpoch) {
@@ -280,8 +280,11 @@ faceFoundry(FT_Face face)
             return makeName("URW ");
         else if(strcasecmp(prop.u.atom, "y&y") == 0)
             return makeName("Y&Y ");
-        else
-            return makeName("UNKN");
+        else {
+           char buf[5];
+           snprintf(buf, sizeof(buf), "%-4s", prop.u.atom);
+            return makeName(buf);
+       }
     }
     /* For now */
     return makeName("UNKN");
@@ -302,7 +305,7 @@ faceWeight(FT_Face face)
         else if(strcasecmp(prop.u.atom, "light") == 0)
             return 300;
         else if(strcasecmp(prop.u.atom, "medium") == 0)
-            return 500;
+            return 400;
         else if(strcasecmp(prop.u.atom, "semibold") == 0)
             return 600;
         else if(strcasecmp(prop.u.atom, "bold") == 0)
@@ -312,9 +315,9 @@ faceWeight(FT_Face face)
         else if(strcasecmp(prop.u.atom, "black") == 0)
             return 900;
         else
-            return 500;
+            return 400;
     } else
-        return 500;             /* for now */
+        return 400;             /* for now */
 }
int
@@ -386,6 +389,19 @@ faceFlags(FT_Face face)
             flags |= FACE_ITALIC;
     }
     return flags;
+}
+
+int
+faceIntProp(FT_Face face, const char *name)
+{
+    int rc;
+    BDF_PropertyRec prop;
+
+    rc = FT_Get_BDF_Property(face, name, &prop);
+    if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
+       return prop.u.integer;
+    else
+       return UNDEF;
 }
char *
Index: write.c
===================================================================
RCS file: /cvs/xenocara/app/fonttosfnt/write.c,v
retrieving revision 1.2
diff -u -p -r1.2 write.c
--- write.c     13 Jun 2008 00:04:06 -0000      1.2
+++ write.c     9 Oct 2020 07:27:20 -0000
@@ -61,7 +61,6 @@ static int writemaxp(FILE*, FontPtr);
 static int writename(FILE*, FontPtr);
 static int writepost(FILE*, FontPtr);
-int max_awidth, min_x, min_y, max_x, max_y;
 static CmapPtr current_cmap = NULL;
 static int numglyphs, nummetrics;
 static int write_error_occurred, read_error_occurred;
@@ -206,6 +205,117 @@ readULONG(FILE *out)
     return ntohl(val);
 }
+void
+fontMetrics(FontPtr font)
+{
+    int i, rc;
+    double sumAwidth = 0;
+    unsigned count = 0;
+
+    font->metrics.maxAwidth = 0;
+    font->metrics.maxX = -10000 * TWO_SIXTEENTH;
+    font->metrics.maxY = -10000 * TWO_SIXTEENTH;
+    font->metrics.minX = 10000 * TWO_SIXTEENTH;
+    font->metrics.minY = 10000 * TWO_SIXTEENTH;
+
+    for(i = 0; i < FONT_CODES; i++) {
+        int awidth, x0, y0, x1, y1;
+        rc = glyphMetrics(font, i, &awidth, &x0, &y0, &x1, &y1);
+        if(rc < 0)
+            continue;
+
+        if(awidth > font->metrics.maxAwidth) font->metrics.maxAwidth = awidth;
+        if(x0 < font->metrics.minX) font->metrics.minX = x0;
+        if(y0 < font->metrics.minY) font->metrics.minY = y0;
+        if(x1 > font->metrics.maxX) font->metrics.maxX = x1;
+        if(y1 > font->metrics.maxY) font->metrics.maxY = y1;
+
+       if(awidth > 0) {
+           sumAwidth += awidth;
+           count++;
+       }
+    }
+
+    if (count) font->metrics.awidth = sumAwidth / count;
+
+    font->metrics.height = TWO_SIXTEENTH;
+
+    if(font->pxMetrics.size == UNDEF) {
+       font->pxMetrics.size = font->pxMetrics.height;
+       font->metrics.size = font->metrics.height;
+    }
+
+    font->metrics.size = font->pxMetrics.size
+           * TWO_SIXTEENTH / font->pxMetrics.height;
+
+    if(font->pxMetrics.ascent == UNDEF) {
+       font->metrics.ascent = font->metrics.maxY;
+       font->pxMetrics.ascent =
+           font->metrics.ascent
+           * font->pxMetrics.height / TWO_SIXTEENTH;
+    }
+    else
+       font->metrics.ascent =
+           font->pxMetrics.ascent
+           * TWO_SIXTEENTH / font->pxMetrics.height;
+
+    if(font->pxMetrics.descent == UNDEF) {
+       font->metrics.descent = font->metrics.minY;
+       font->pxMetrics.descent =
+           font->metrics.descent
+           * font->pxMetrics.height / TWO_SIXTEENTH;
+    }
+    else
+       font->metrics.descent =
+           font->pxMetrics.descent
+           * TWO_SIXTEENTH / font->pxMetrics.height;
+
+    if(font->pxMetrics.capHeight == UNDEF) {
+       if(glyphMetrics(font, 'X', NULL, NULL, NULL, NULL, 
&font->metrics.capHeight) != 1)
+           font->metrics.capHeight = font->metrics.ascent;
+       font->pxMetrics.capHeight =
+           font->metrics.capHeight * font->pxMetrics.height / TWO_SIXTEENTH;
+    }
+    else
+       font->metrics.capHeight =
+           font->pxMetrics.capHeight
+           * TWO_SIXTEENTH / font->pxMetrics.height;
+
+    if(font->pxMetrics.xHeight == UNDEF) {
+       if(glyphMetrics(font, 'x', NULL, NULL, NULL, NULL, 
&font->metrics.xHeight) != 1)
+           font->metrics.xHeight = font->metrics.capHeight * 2 / 3;
+       font->pxMetrics.xHeight =
+           font->metrics.xHeight * font->pxMetrics.height / TWO_SIXTEENTH;
+    }
+    else
+       font->metrics.xHeight =
+           font->pxMetrics.xHeight
+           * TWO_SIXTEENTH / font->pxMetrics.height;
+
+    if(font->pxMetrics.underlinePosition == UNDEF)
+       font->metrics.underlinePosition = - font->metrics.descent * 2;
+    else {
+       fprintf(stderr, "Setting underlinePosition. pxMetrics.underlinePosition is 
%d. height is %d\n",
+               font->pxMetrics.underlinePosition, font->pxMetrics.height);
+       font->metrics.underlinePosition =
+           font->pxMetrics.underlinePosition
+           * TWO_SIXTEENTH / font->pxMetrics.height;
+    }
+
+    if(font->pxMetrics.underlineThickness == UNDEF)
+       /* make sure thickness is at least one pixel. */
+       /* TODO: this could be refined according to
+        * X Logical Font Description Conventions (xlfd.txt)
+        * by also considering the font weight. */
+       font->metrics.underlineThickness =
+           TWO_SIXTEENTH
+           / (font->pxMetrics.height < 9 ? font->pxMetrics.height : 9);
+    else
+       font->metrics.underlineThickness =
+           font->pxMetrics.underlineThickness
+           * TWO_SIXTEENTH / font->pxMetrics.height;
+}
+
int writeFile(char *filename, FontPtr font)
 {
@@ -219,8 +329,6 @@ writeFile(char *filename, FontPtr font)
     int offset[15], length[15];
     StrikePtr strike;
- fontMetrics(font, &max_awidth, &min_x, &min_y, &max_x, &max_y);
-
     out = fopen(filename, "wb+");
     if(out == NULL)
         return -1;
@@ -231,6 +339,8 @@ writeFile(char *filename, FontPtr font)
         return -1;
     }
+ fontMetrics(font);
+
     write_error_occurred = 0;
     read_error_occurred = 0;
@@ -434,8 +544,8 @@ fixupChecksum(FILE *out, int full_length static int writehead(FILE* out, FontPtr font)
 {
-    int time_hi;
-    unsigned time_lo;
+    int time_hi = 0;
+    unsigned time_lo = 0;
macTime(&time_hi, &time_lo); @@ -451,10 +561,12 @@ writehead(FILE* out, FontPtr font)
     writeLONG(out, time_hi);    /* modified */
     writeULONG(out, time_lo);
- writeUSHORT(out, FONT_UNITS_FLOOR(min_x));
-    writeUSHORT(out, FONT_UNITS_FLOOR(min_y));
-    writeUSHORT(out, FONT_UNITS_CEIL(max_x));
-    writeUSHORT(out, FONT_UNITS_CEIL(max_y));
+    /* bounding box for all glyphs */
+    writeUSHORT(out, FONT_UNITS_FLOOR(font->metrics.minX));
+    writeUSHORT(out, FONT_UNITS_FLOOR(font->metrics.minY));
+    writeUSHORT(out, FONT_UNITS_CEIL(font->metrics.maxX));
+    writeUSHORT(out, FONT_UNITS_CEIL(font->metrics.maxY));
+
     writeUSHORT(out, font->flags); /* macStyle */
     writeUSHORT(out, 1);        /* lowestRecPPEM */
     writeSHORT(out, 0);         /* fontDirectionHint */
@@ -549,27 +661,6 @@ writeEBDT(FILE* out, FontPtr font)
     return 0;
 }
-static int
-writeSbitLineMetrics(FILE *out, StrikePtr strike, int num, int den)
-{
-    int width_max, x_min, y_min, x_max, y_max;
-    strikeMetrics(strike, &width_max, &x_min, &y_min, &x_max, &y_max);
-
-    writeCHAR(out, y_max);      /* ascender */
-    writeCHAR(out, y_min);      /* descender */
-    writeBYTE(out, width_max);  /* widthMax */
-    writeCHAR(out, num);          /* caretSlopeNumerator */
-    writeCHAR(out, den);          /* caretSlopeDenominator */
-    writeCHAR(out, 0);          /* caretOffset */
-    writeCHAR(out, 0);          /* minOriginSB */
-    writeCHAR(out, 0);          /* minAdvanceSB */
-    writeCHAR(out, 0);          /* maxBeforeBL */
-    writeCHAR(out, 0);          /* minAfterBL */
-    writeCHAR(out, 0);          /* pad1 */
-    writeCHAR(out, 0);          /* pad2 */
-    return 0;
-}
-
static int writeEBLC(FILE* out, FontPtr font)
 {
@@ -599,8 +690,20 @@ writeEBLC(FILE* out, FontPtr font)
         writeULONG(out, 0xDEADFACE); /* indexTablesSize */
         writeULONG(out, 0xDEADFACE); /* numberOfIndexSubTables */
         writeULONG(out, 0);     /* colorRef */
-        writeSbitLineMetrics(out, strike, num, den);
-        writeSbitLineMetrics(out, strike, num, den);
+       for (i = 0; i <= 1; i++) {
+         writeCHAR(out, font->pxMetrics.ascent);    /* ascender */
+         writeCHAR(out, -font->pxMetrics.descent);  /* descender */
+         writeBYTE(out, strikeMaxWidth(strike));       /* widthMax */
+         writeCHAR(out, num);                          /* caretSlopeNumerator 
*/
+         writeCHAR(out, den);                          /* 
caretSlopeDenominator */
+         writeCHAR(out, 0);                            /* caretOffset */
+         writeCHAR(out, 0);                            /* minOriginSB */
+         writeCHAR(out, 0);                            /* minAdvanceSB */
+         writeCHAR(out, 0);                            /* maxBeforeBL */
+         writeCHAR(out, 0);                            /* minAfterBL */
+         writeCHAR(out, 0);                            /* pad1 */
+         writeCHAR(out, 0);                            /* pad2 */
+       }
         writeUSHORT(out, 0);    /* startGlyphIndex */
         writeUSHORT(out, 0xFFFD); /* endGlyphIndex */
         writeBYTE(out, strike->sizeX); /* ppemX */
@@ -648,9 +751,6 @@ writeEBLC(FILE* out, FontPtr font)
     /* actual indexSubTables */
     strike = font->strikes;
     while(strike) {
-        int vertAdvance, y_min, y_max;
-        strikeMetrics(strike, NULL, NULL, &y_min, NULL, &y_max);
-        vertAdvance = y_max - y_min;
         table = strike->indexSubTables;
         while(table) {
             int location;
@@ -718,7 +818,7 @@ writeEBLC(FILE* out, FontPtr font)
                 writeBYTE(out, bitmap->advanceWidth);
                 writeCHAR(out, bitmap->horiBearingX); /* vertBearingX */
                 writeCHAR(out, bitmap->horiBearingY); /* vertBearingY */
-                writeBYTE(out, vertAdvance); /* vertAdvance */
+                writeBYTE(out, font->metrics.maxAwidth); /* vertAdvance */
             } else {
for(i = table->firstGlyphIndex; i <= table->lastGlyphIndex; i++) {
@@ -849,13 +949,15 @@ writehhea(FILE* out, FontPtr font)
     degreesToFraction(font->italicAngle, &num, &den);
writeULONG(out, 0x00010000); /* version */
-    writeSHORT(out, FONT_UNITS_CEIL(max_y)); /* ascender */
-    writeSHORT(out, FONT_UNITS_FLOOR(min_y)); /* descender */
-    writeSHORT(out, FONT_UNITS(TWO_SIXTEENTH / 20)); /* lineGap */
-    writeUSHORT(out, FONT_UNITS(max_awidth)); /* advanceWidthMax */
-    writeSHORT(out, FONT_UNITS_FLOOR(min_x)); /* minLeftSideBearing */
-    writeSHORT(out, FONT_UNITS_FLOOR(min_x)); /* minRightSideBearing */
-    writeSHORT(out, FONT_UNITS_CEIL(max_x)); /* xMaxExtent */
+    writeSHORT(out, FONT_UNITS_CEIL(font->metrics.ascent)); /* ascender */
+    writeSHORT(out, -FONT_UNITS_CEIL(font->metrics.descent)); /* descender */
+    writeSHORT(out, FONT_UNITS(font->metrics.size - font->metrics.ascent - 
font->metrics.descent));   /* lineGap */
+    writeUSHORT(out, FONT_UNITS(font->metrics.maxAwidth)); /* advanceWidthMax 
*/
+    /* TODO: the next three are not calculated according to spec, are they ?
+     * https://docs.microsoft.com/en-us/typography/opentype/spec/hhea */
+    writeSHORT(out, FONT_UNITS_FLOOR(font->metrics.minX)); /* 
minLeftSideBearing */
+    writeSHORT(out, FONT_UNITS_FLOOR(font->metrics.minX)); /* 
minRightSideBearing */
+    writeSHORT(out, FONT_UNITS_CEIL(font->metrics.maxX)); /* xMaxExtent */
     writeSHORT(out, den);       /* caretSlopeRise */
     writeSHORT(out, num);       /* caretSlopeRun */
     writeSHORT(out, 0);         /* reserved */
@@ -974,8 +1076,8 @@ writepost(FILE* out, FontPtr font)
writeULONG(out, 0x00030000); /* FormatType */
     writeULONG(out, font->italicAngle); /* italicAngle */
-    writeSHORT(out, FONT_UNITS(font->underlinePosition));
-    writeSHORT(out, FONT_UNITS(font->underlineThickness));
+    writeSHORT(out, FONT_UNITS(font->metrics.underlinePosition));
+    writeSHORT(out, FONT_UNITS(font->metrics.underlineThickness));
     writeULONG(out, fixed_pitch); /* isFixedPitch */
     writeULONG(out, 0);         /* minMemType42 */
     writeULONG(out, 0);         /* maxMemType42 */
@@ -989,8 +1091,8 @@ writeOS2(FILE* out, FontPtr font)
 {
     int i;
- writeUSHORT(out, 0x0001);
-    writeSHORT(out, FONT_UNITS(max_awidth / 2)); /* xAvgCharWidth; */
+    writeUSHORT(out, 5); /* version */
+    writeSHORT(out, FONT_UNITS(font->metrics.awidth)); /* xAvgCharWidth; */
     writeUSHORT(out, font->weight);  /* usWeightClass; */
     writeUSHORT(out, font->width); /* usWidthClass; */
     writeSHORT(out, 0);         /* fsType; */
@@ -1002,7 +1104,7 @@ writeOS2(FILE* out, FontPtr font)
     writeSHORT(out, UNITS_PER_EM / 5); /* ySuperscriptYSize; */
     writeSHORT(out, 0);         /* ySuperscriptXOffset; */
     writeSHORT(out, UNITS_PER_EM / 5); /* ySuperscriptYOffset; */
- writeSHORT(out, FONT_UNITS(font->underlineThickness)); + writeSHORT(out, FONT_UNITS(font->metrics.underlineThickness));
     /* yStrikeoutSize; */
     writeSHORT(out, UNITS_PER_EM / 4); /* yStrikeoutPosition; */
     writeSHORT(out, 0);         /* sFamilyClass; */
@@ -1013,17 +1115,38 @@ writeOS2(FILE* out, FontPtr font)
     writeULONG(out, 0x03FF);    /* ulUnicodeRange3; */
     writeULONG(out, 0U);        /* ulUnicodeRange4; */
     writeULONG(out, font->foundry); /* achVendID[4]; */
-    writeUSHORT(out, 0x0040);   /* fsSelection; */
+    i = 0;
+    if (font->flags & FACE_ITALIC)
+       i |= 1 << 0;
+    if (font->flags & FACE_BOLD)
+       i |= 1 << 5;
+    if (!i)
+       i |= 1 << 6;
+#ifndef NO_TYPO_METRICS
+    i |= 1 << 7; /* USE_TYPO_METRICS instead usWin metrics for line spacing. */
+#endif
+    writeUSHORT(out, i);       /* fsSelection; */
     writeUSHORT(out, 0x20);     /* usFirstCharIndex; */
     writeUSHORT(out, 0xFFFD);   /* usLastCharIndex; */
-    writeUSHORT(out, FONT_UNITS_CEIL(max_y)); /* sTypoAscender; */
-    writeUSHORT(out, -FONT_UNITS_FLOOR(min_y)); /* sTypoDescender; */
-    writeUSHORT(out, FONT_UNITS(max_y - min_y));
-    /* sTypoLineGap; */
-    writeUSHORT(out, FONT_UNITS_CEIL(max_y)); /* usWinAscent; */
-    writeUSHORT(out, -FONT_UNITS_FLOOR(min_y)); /* usWinDescent; */
-    writeULONG(out, 3);         /* ulCodePageRange1; */
-    writeULONG(out, 0);         /* ulCodePageRange2; */
+    writeUSHORT(out, FONT_UNITS_CEIL(font->metrics.ascent)); /* sTypoAscender; 
*/
+    writeSHORT(out, -FONT_UNITS_CEIL(font->metrics.descent)); /* 
sTypoDescender; */
+    writeSHORT(out, FONT_UNITS(font->metrics.size - font->metrics.ascent - 
font->metrics.descent));   /* sTypoLineGap */
+#ifdef NO_TYPO_METRICS
+    writeUSHORT(out, FONT_UNITS_CEIL(font->metrics.ascent)); /* usWinAscent; */
+    writeUSHORT(out, FONT_UNITS_CEIL(font->metrics.descent)); /* usWinDescent; 
*/
+#else
+    writeUSHORT(out, FONT_UNITS_CEIL(font->metrics.maxY)); /* usWinAscent; */
+    writeUSHORT(out, -FONT_UNITS_FLOOR(font->metrics.minY)); /* usWinDescent; 
*/
+#endif
+    writeULONG(out, 3);                                                /* 
ulCodePageRange1; */
+    writeULONG(out, 0);                                        /* 
ulCodePageRange2; */
+    writeSHORT(out, FONT_UNITS_CEIL(font->metrics.xHeight));        /* 
sxHeight; */
+    writeSHORT(out, FONT_UNITS_CEIL(font->metrics.capHeight));      /* 
sCapHeight; */
+    writeUSHORT(out, 0);                                       /* 
usDefaultChar; */
+    writeUSHORT(out, 20);                                      /* usBreakChar; 
*/
+    writeUSHORT(out, 0);                                       /* 
usMaxContext; */
+    writeUSHORT(out, 0);                                       /* 
usLowerOpticalPointSize; */
+    writeUSHORT(out, 0xffff);                                  /* 
usUpperOpticalPointSize; */
     return 0;
 }
@@ -1061,11 +1184,11 @@ writePCLT(FILE* out, FontPtr font) writeULONG(out, 0x00010000); /* version */
     writeULONG(out, 0);         /* FontNumber */
-    writeUSHORT(out, FONT_UNITS(max_awidth)); /* pitch */
-    writeUSHORT(out, FONT_UNITS(max_y));    /* xHeight */
+    writeUSHORT(out, FONT_UNITS(font->metrics.maxAwidth)); /* pitch */
+    writeUSHORT(out, FONT_UNITS(font->metrics.xHeight));    /* xHeight */
     writeUSHORT(out, style);    /* style */
     writeUSHORT(out, 6 << 12);  /* TypeFamily */
-    writeUSHORT(out, FONT_UNITS(max_y)); /* CapHeight */
+    writeUSHORT(out, FONT_UNITS(font->metrics.xHeight)); /* CapHeight */
     writeUSHORT(out, 0);        /* SymbolSet */
     writeCHARs(out, name, 16);  /* TypeFace */
     writeBYTEs(out, charComplement, 8); /* CharacterComplement */


--
http://gmerlin.de
OpenPGP: http://gmerlin.de/christopher.pub
CB07 DA40 B0B6 571D 35E2  0DEF 87E2 92A7 13E5 DEE1

Reply via email to