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)
This commit is contained in:
Jeff Epler 2021-01-05 14:29:34 -06:00
parent 9f4ab8c373
commit 750e90e627
2 changed files with 72 additions and 22 deletions

View file

@ -51,6 +51,8 @@ typedef struct BDFSTAT {
int digitCount;
int digitWidths;
int exHeight;
int sWidthDefault;
int dWidthDefault;
FontPropPtr fontProp;
FontPropPtr pointSizeProp;

View file

@ -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);