summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fonttosfnt.h23
-rw-r--r--read.c37
-rw-r--r--struct.c125
-rw-r--r--util.c13
-rw-r--r--write.c49
5 files changed, 176 insertions, 71 deletions
diff --git a/fonttosfnt.h b/fonttosfnt.h
index 202ab5a..a05e036 100644
--- a/fonttosfnt.h
+++ b/fonttosfnt.h
@@ -86,6 +86,22 @@ typedef struct _FontNameEntry {
char *value;
} FontNameEntryRec, *FontNameEntryPtr;
+typedef struct _Metrics {
+ int height;
+ 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;
@@ -93,8 +109,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;
@@ -153,7 +169,7 @@ int findCode(CmapPtr, int);
BitmapPtr strikeBitmapIndex(StrikePtr, CmapPtr, int);
void strikeMetrics(StrikePtr, int*, int*, int*, int*, int*);
int glyphMetrics(FontPtr, int, int*, int*, int*, int*, int*);
-void fontMetrics(FontPtr, int*, int*, int*, int*, int*);
+void fontMetrics(FontPtr, MetricsPtr);
int maxIndex(CmapPtr);
int readFile(char *filename, FontPtr);
@@ -173,6 +189,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);
diff --git a/read.c b/read.c
index a22ce41..db79a59 100644
--- a/read.c
+++ b/read.c
@@ -258,30 +258,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) {
@@ -304,6 +280,19 @@ readFile(char *filename, FontPtr font)
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.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)
fprintf(stderr, "size %d: %dx%d\n",
diff --git a/struct.c b/struct.c
index bcb07ba..1c14931 100644
--- a/struct.c
+++ b/struct.c
@@ -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;
@@ -480,31 +504,90 @@ glyphMetrics(FontPtr font, int code,
}
void
-fontMetrics(FontPtr font,
- int *max_awidth_return,
- int *min_x_return, int *min_y_return,
- int *max_x_return, int *max_y_return)
+fontMetrics(FontPtr font, MetricsPtr metrics)
{
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;
+ double sumAwidth = 0;
+ unsigned count = 0;
+
+ metrics->height = UNDEF /* TODO */;
+ metrics->maxAwidth = 0;
+ metrics->maxX = -10000 * TWO_SIXTEENTH;
+ metrics->maxY = -10000 * TWO_SIXTEENTH;
+ metrics->minX = 10000 * TWO_SIXTEENTH;
+ metrics->minY = 10000 * TWO_SIXTEENTH;
+ metrics->ascent = UNDEF;
+ metrics->descent = UNDEF;
+ metrics->underlinePosition = UNDEF;
+ metrics->underlineThickness = UNDEF;
+
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(awidth > metrics->maxAwidth) metrics->maxAwidth = awidth;
+ if(x0 < metrics->minX) metrics->minX = x0;
+ if(y0 < metrics->minY) metrics->minY = y0;
+ if(x1 > metrics->maxX) metrics->maxX = x1;
+ if(y1 > metrics->maxY) metrics->maxY = y1;
+
+ if(awidth > 0) {
+ sumAwidth += awidth;
+ count++;
+ }
}
- 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;
-}
+ if (count) metrics->awidth = sumAwidth / count;
+
+ if(font->pxMetrics.ascent == UNDEF)
+ metrics->ascent = metrics->maxY;
+ else
+ metrics->ascent =
+ font->pxMetrics.ascent
+ * TWO_SIXTEENTH / font->pxMetrics.height;
+
+ if(font->pxMetrics.descent == UNDEF)
+ metrics->descent = metrics->minY;
+ else
+ metrics->descent =
+ font->pxMetrics.descent
+ * TWO_SIXTEENTH / font->pxMetrics.height;
+
+ if(font->pxMetrics.capHeight == UNDEF)
+ /* TODO get ascent of letter 'X' - how to do lookups of ascii codes ? */
+ metrics->capHeight = metrics->ascent;
+ else
+ metrics->capHeight =
+ font->pxMetrics.capHeight
+ * TWO_SIXTEENTH / font->pxMetrics.height;
+
+ if(font->pxMetrics.xHeight == UNDEF)
+ /* TODO get ascent of letter 'x' - how to do lookups of ascii codes ? */
+ metrics->xHeight = metrics->ascent * 2 / 3;
+ else
+ metrics->xHeight =
+ font->pxMetrics.xHeight
+ * TWO_SIXTEENTH / font->pxMetrics.height;
+
+ if(font->pxMetrics.underlinePosition == UNDEF)
+ metrics->underlinePosition = - metrics->descent * 2;
+ else
+ metrics->underlinePosition =
+ font->pxMetrics.underlinePosition
+ * TWO_SIXTEENTH / font->pxMetrics.height;
+
+ if(font->pxMetrics.underlineThickness == UNDEF)
+ /* TODO: this could be refined according to
+ * X Logical Font Description Conventions (xlfd.txt)
+ * by also considering the font weight. */
+ /* make sure thickness is at least one pixel. */
+ metrics->underlineThickness =
+ TWO_SIXTEENTH
+ / (font->pxMetrics.height < 9 ? font->pxMetrics.height : 9);
+ else
+ metrics->underlineThickness =
+ font->pxMetrics.underlineThickness
+ * TWO_SIXTEENTH / font->pxMetrics.height;
+}
diff --git a/util.c b/util.c
index fc6eb38..ba9d096 100644
--- a/util.c
+++ b/util.c
@@ -391,6 +391,19 @@ faceFlags(FT_Face face)
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 *
faceEncoding(FT_Face face)
{
diff --git a/write.c b/write.c
index 6ad09a6..5ee0f79 100644
--- a/write.c
+++ b/write.c
@@ -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;
@@ -219,7 +218,7 @@ writeFile(char *filename, FontPtr font)
int offset[15], length[15];
StrikePtr strike;
- fontMetrics(font, &max_awidth, &min_x, &min_y, &max_x, &max_y);
+ fontMetrics(font, &font->metrics);
out = fopen(filename, "wb+");
if(out == NULL)
@@ -451,10 +450,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 */
@@ -849,13 +850,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_CEIL(font->metrics.ascent)); /* ascender */
+ writeSHORT(out, 0-FONT_UNITS_CEIL(font->metrics.descent)); /* descender */
writeSHORT(out, 0); /* 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 */
+ 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 +977,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 */
@@ -990,7 +993,7 @@ writeOS2(FILE* out, FontPtr font)
int i;
writeUSHORT(out, 0x0001);
- writeSHORT(out, FONT_UNITS(max_awidth / 2)); /* xAvgCharWidth; */
+ writeSHORT(out, FONT_UNITS(font->metrics.awidth)); /* xAvgCharWidth; */
writeUSHORT(out, font->weight); /* usWeightClass; */
writeUSHORT(out, font->width); /* usWidthClass; */
writeSHORT(out, 0); /* fsType; */
@@ -1002,7 +1005,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; */
@@ -1023,11 +1026,11 @@ writeOS2(FILE* out, FontPtr font)
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_CEIL(font->metrics.ascent)); /* sTypoAscender; */
+ writeUSHORT(out, FONT_UNITS_FLOOR(font->metrics.descent)); /* sTypoDescender; */
writeUSHORT(out, 0); /* sTypoLineGap; */
- writeUSHORT(out, FONT_UNITS_CEIL(max_y)); /* usWinAscent; */
- writeUSHORT(out, -FONT_UNITS_FLOOR(min_y)); /* usWinDescent; */
+ writeUSHORT(out, FONT_UNITS_CEIL(font->metrics.maxY)); /* usWinAscent; */
+ writeUSHORT(out, -FONT_UNITS_FLOOR(font->metrics.minY)); /* usWinDescent; */
writeULONG(out, 3); /* ulCodePageRange1; */
writeULONG(out, 0); /* ulCodePageRange2; */
return 0;
@@ -1067,11 +1070,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 */