From 750e90e627584040ea14ae9a62d652cb01919d81 Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Tue, 5 Jan 2021 14:29:34 -0600 Subject: [PATCH] Reader: partially accomodate the BDF 2.2 format At least for some CJK character sets, FontForge writes a font which includes a METRICSSET section in the preamble, and later in some glyphs skips the SWIDTH/DWIDTH lines in preference to the default values specified in the METRICSSET. According to the Adobe document describing the 2.2 format, this is ia size optimization for storing bdf fonts because many glyphs have the same metrics, particular for vertical text layouts. X's bdftopcf never accepted these extensions not present in BDF 2.1, but fontforge writes them anyway. (I'm not sure who is using fontforge's BDF output, given this fact) This adds minimal support for these elements of the font. Testing performed: * converted yasa-200.bdf to pcf, then rendered with Adafruit_CircuitPython_BitmapFont's simpletest on a host computer with https://github.com/adafruit/Adafruit_CircuitPython_Bitmap_Font/pull/34 applied. (this was broken before this PR) * converted a bdf file produced by otf2bdf and displayed it similarly (this was working before) --- bdfint.h | 2 ++ bdfread.c | 92 ++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 72 insertions(+), 22 deletions(-) diff --git a/bdfint.h b/bdfint.h index cc464cb..c0ccdf9 100644 --- a/bdfint.h +++ b/bdfint.h @@ -51,6 +51,8 @@ typedef struct BDFSTAT { int digitCount; int digitWidths; int exHeight; + int sWidthDefault; + int dWidthDefault; FontPropPtr fontProp; FontPropPtr pointSizeProp; diff --git a/bdfread.c b/bdfread.c index c168a31..81d9f42 100644 --- a/bdfread.c +++ b/bdfread.c @@ -402,36 +402,39 @@ bdfReadCharacters(FontFilePtr file, FontPtr pFont, bdfFileState *pState, } line = bdfGetLine(file, lineBuf, BDFLINELEN); - if ((!line) || (sscanf((char *) line, "SWIDTH %d %d", &wx, &wy) != 2)) { - bdfError("bad 'SWIDTH'\n"); - goto BAILOUT; - } - if (wy != 0) { - bdfError("SWIDTH y value must be zero\n"); - goto BAILOUT; - } - if (bitmapExtra) - bitmapExtra->sWidths[ndx] = wx; + if (line && bdfIsPrefix(line, "SWIDTH")) { + if ((!line) || (sscanf((char *) line, "SWIDTH %d %d", &wx, &wy) != 2)) { + bdfError("bad 'SWIDTH'\n"); + goto BAILOUT; + } + if (wy != 0) { + bdfError("SWIDTH y value must be zero\n"); + goto BAILOUT; + } + line = bdfGetLine(file, lineBuf, BDFLINELEN); + } else { + wx = pState->sWidthDefault; + } + if (bitmapExtra) + bitmapExtra->sWidths[ndx] = wx; -/* 5/31/89 (ef) -- we should be able to ditch the character and recover */ -/* from all of these. */ + if (line && bdfIsPrefix(line, "DWIDTH")) { + if (sscanf((char *) line, "DWIDTH %d %d", &wx, &wy) != 2) { + bdfError("bad 'DWIDTH'\n"); + goto BAILOUT; + } + line = bdfGetLine(file, lineBuf, BDFLINELEN); + } else { + wx = pState->dWidthDefault; + } - line = bdfGetLine(file, lineBuf, BDFLINELEN); - if ((!line) || (sscanf((char *) line, "DWIDTH %d %d", &wx, &wy) != 2)) { - bdfError("bad 'DWIDTH'\n"); - goto BAILOUT; - } - if (wy != 0) { - bdfError("DWIDTH y value must be zero\n"); - goto BAILOUT; - } /* xCharInfo metrics are stored as INT16 */ if ((wx < INT16_MIN) || (wx > INT16_MAX)) { bdfError("character '%s' has out of range width, %d\n", charName, wx); goto BAILOUT; } - line = bdfGetLine(file, lineBuf, BDFLINELEN); + if ((!line) || (sscanf((char *) line, "BBX %d %d %d %d", &bw, &bh, &bl, &bb) != 4)) { bdfError("bad 'BBX'\n"); goto BAILOUT; @@ -612,6 +615,48 @@ bdfReadHeader(FontFilePtr file, bdfFileState *pState) /***====================================================================***/ +static Bool +bdfReadMetricsSet(FontFilePtr file, FontPtr pFont, bdfFileState *pState, + unsigned char *line, unsigned char *lineBuf, size_t lineLen) +{ + int metricsSet, wx, wy; + if (sscanf((char *) line, "METRICSSET %d", &metricsSet) != 1) { + bdfError("bad 'METRICSSET'\n"); + goto BAILOUT; + } + + do { + line = bdfGetLine(file, lineBuf, lineLen); + if (!line) goto BAILOUT; + + if (bdfIsPrefix(line, "SWIDTH")) { + if ((!line) || (sscanf((char *) line, "SWIDTH %d %d", &wx, &wy) != 2)) { + bdfError("bad 'SWIDTH'\n"); + goto BAILOUT; + } + pState->sWidthDefault = wx; + } + if (bdfIsPrefix(line, "DWIDTH")) { + if ((!line) || (sscanf((char *) line, "DWIDTH %d %d", &wx, &wy) != 2)) { + bdfError("bad 'DWIDTH'\n"); + goto BAILOUT; + } + pState->dWidthDefault = wx; + } + } while( + bdfIsPrefix(line, "SWIDTH") || + bdfIsPrefix(line, "DWIDTH") || + bdfIsPrefix(line, "SWIDTH1") || + bdfIsPrefix(line, "DWIDTH1") || + bdfIsPrefix(line, "VVECTOR")); + return (TRUE); + + BAILOUT: + return (FALSE); +} + +/***====================================================================***/ + static Bool bdfReadProperties(FontFilePtr file, FontPtr pFont, bdfFileState *pState) { @@ -627,6 +672,9 @@ bdfReadProperties(FontFilePtr file, FontPtr pFont, bdfFileState *pState) BitmapFontPtr bitmapFont = (BitmapFontPtr) pFont->fontPrivate; line = bdfGetLine(file, lineBuf, BDFLINELEN); + if (line && bdfIsPrefix(line, "METRICSSET")) { + bdfReadMetricsSet(file, pFont, pState, line, lineBuf, BDFLINELEN); + } if (!line || !bdfIsPrefix(line, "STARTPROPERTIES")) { bdfError("missing 'STARTPROPERTIES'\n"); return (FALSE);