#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <ctype.h>
#include <X11/fonts/fntfilst.h>
#include <X11/fonts/fontutil.h>
#include <X11/fonts/bitmap.h>
#include <X11/fonts/bdfint.h>
#if HAVE_STDINT_H
#include <stdint.h>
#elif !defined(INT32_MAX)
#define INT32_MAX 0x7fffffff
#endif
#define INDICES 256
#define MAXENCODING 0xFFFF
#define BDFLINELEN 1024
static Bool bdfPadToTerminal(FontPtr pFont);
extern int bdfFileLineNum;
static Bool
bdfReadBitmap(CharInfoPtr pCI, FontFilePtr file, int bit, int byte,
int glyph, int scan, CARD32 *sizes)
{
int widthBits,
widthBytes,
widthHexChars;
int height,
row;
int i,
inLineLen,
nextByte;
unsigned char *pInBits,
*picture,
*line = NULL;
unsigned char lineBuf[BDFLINELEN];
widthBits = GLYPHWIDTHPIXELS(pCI);
height = GLYPHHEIGHTPIXELS(pCI);
widthBytes = BYTES_PER_ROW(widthBits, glyph);
if (widthBytes * height > 0) {
picture = malloc(widthBytes * height);
if (!picture) {
bdfError("Couldn't allocate picture (%d*%d)\n", widthBytes, height);
goto BAILOUT;
}
} else
picture = NULL;
pCI->bits = (char *) picture;
if (sizes) {
for (i = 0; i < GLYPHPADOPTIONS; i++)
sizes[i] += BYTES_PER_ROW(widthBits, (1 << i)) * height;
}
nextByte = 0;
widthHexChars = BYTES_PER_ROW(widthBits, 1);
for (row = 0; row < height; row++) {
line = bdfGetLine(file, lineBuf, BDFLINELEN);
if (!line)
break;
if (widthBits == 0) {
if ((!line) || (bdfIsPrefix(line, "ENDCHAR")))
break;
else
continue;
}
pInBits = line;
inLineLen = strlen((char *) pInBits);
if (inLineLen & 1) {
bdfError("odd number of characters in hex encoding\n");
line[inLineLen++] = '0';
line[inLineLen] = '\0';
}
inLineLen >>= 1;
i = inLineLen;
if (i > widthHexChars)
i = widthHexChars;
for (; i > 0; i--, pInBits += 2)
picture[nextByte++] = bdfHexByte(pInBits);
if (inLineLen < widthHexChars) {
for (i = widthHexChars - inLineLen; i > 0; i--)
picture[nextByte++] = 0;
} else {
unsigned char mask;
mask = 0xff << (8 - (widthBits & 0x7));
if (mask && picture[nextByte - 1] & ~mask) {
picture[nextByte - 1] &= mask;
}
}
if (widthBytes > widthHexChars) {
i = widthBytes - widthHexChars;
while (i-- > 0)
picture[nextByte++] = 0;
}
}
if ((line && (!bdfIsPrefix(line, "ENDCHAR"))) || (height == 0))
line = bdfGetLine(file, lineBuf, BDFLINELEN);
if ((!line) || (!bdfIsPrefix(line, "ENDCHAR"))) {
bdfError("missing 'ENDCHAR'\n");
goto BAILOUT;
}
if (nextByte != height * widthBytes) {
bdfError("bytes != rows * bytes_per_row (%d != %d * %d)\n",
nextByte, height, widthBytes);
goto BAILOUT;
}
if (picture != NULL) {
if (bit == LSBFirst)
BitOrderInvert(picture, nextByte);
if (bit != byte) {
if (scan == 2)
TwoByteSwap(picture, nextByte);
else if (scan == 4)
FourByteSwap(picture, nextByte);
}
}
return (TRUE);
BAILOUT:
if (picture)
free(picture);
pCI->bits = NULL;
return (FALSE);
}
static Bool
bdfSkipBitmap(FontFilePtr file, int height)
{
unsigned char *line;
int i = 0;
unsigned char lineBuf[BDFLINELEN];
do {
line = bdfGetLine(file, lineBuf, BDFLINELEN);
i++;
} while (line && !bdfIsPrefix(line, "ENDCHAR") && i <= height);
if (i > 1 && line && !bdfIsPrefix(line, "ENDCHAR")) {
bdfError("Error in bitmap, missing 'ENDCHAR'\n");
return (FALSE);
}
return (TRUE);
}
static void
bdfFreeFontBits(FontPtr pFont)
{
BitmapFontPtr bitmapFont;
BitmapExtraPtr bitmapExtra;
int i, nencoding;
bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
bitmapExtra = (BitmapExtraPtr) bitmapFont->bitmapExtra;
free(bitmapFont->ink_metrics);
if(bitmapFont->encoding) {
nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) *
(pFont->info.lastRow - pFont->info.firstRow + 1);
for(i=0; i<NUM_SEGMENTS(nencoding); i++)
free(bitmapFont->encoding[i]);
}
free(bitmapFont->encoding);
for (i = 0; i < bitmapFont->num_chars; i++)
free(bitmapFont->metrics[i].bits);
free(bitmapFont->metrics);
if (bitmapExtra)
{
free (bitmapExtra->glyphNames);
free (bitmapExtra->sWidths);
free (bitmapExtra);
}
free(pFont->info.props);
free(bitmapFont);
}
static Bool
bdfReadCharacters(FontFilePtr file, FontPtr pFont, bdfFileState *pState,
int bit, int byte, int glyph, int scan)
{
unsigned char *line;
register CharInfoPtr ci;
int i,
ndx,
nchars,
nignored;
unsigned int char_row, char_col;
int numEncodedGlyphs = 0;
CharInfoPtr *bdfEncoding[256];
BitmapFontPtr bitmapFont;
BitmapExtraPtr bitmapExtra;
CARD32 *bitmapsSizes;
unsigned char lineBuf[BDFLINELEN];
int nencoding;
bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
bitmapExtra = (BitmapExtraPtr) bitmapFont->bitmapExtra;
if (bitmapExtra) {
bitmapsSizes = bitmapExtra->bitmapsSizes;
for (i = 0; i < GLYPHPADOPTIONS; i++)
bitmapsSizes[i] = 0;
} else
bitmapsSizes = NULL;
bzero(bdfEncoding, sizeof(bdfEncoding));
bitmapFont->metrics = NULL;
ndx = 0;
line = bdfGetLine(file, lineBuf, BDFLINELEN);
if ((!line) || (sscanf((char *) line, "CHARS %d", &nchars) != 1)) {
bdfError("bad 'CHARS' in bdf file\n");
return (FALSE);
}
if (nchars < 1) {
bdfError("invalid number of CHARS in BDF file\n");
return (FALSE);
}
if (nchars > INT32_MAX / sizeof(CharInfoRec)) {
bdfError("Couldn't allocate pCI (%d*%d)\n", nchars,
sizeof(CharInfoRec));
goto BAILOUT;
}
ci = calloc(nchars, sizeof(CharInfoRec));
if (!ci) {
bdfError("Couldn't allocate pCI (%d*%d)\n", nchars,
sizeof(CharInfoRec));
goto BAILOUT;
}
bitmapFont->metrics = ci;
if (bitmapExtra) {
bitmapExtra->glyphNames = malloc(nchars * sizeof(Atom));
if (!bitmapExtra->glyphNames) {
bdfError("Couldn't allocate glyphNames (%d*%d)\n",
nchars, sizeof(Atom));
goto BAILOUT;
}
}
if (bitmapExtra) {
bitmapExtra->sWidths = malloc(nchars * sizeof(int));
if (!bitmapExtra->sWidths) {
bdfError("Couldn't allocate sWidth (%d *%d)\n",
nchars, sizeof(int));
return FALSE;
}
}
line = bdfGetLine(file, lineBuf, BDFLINELEN);
pFont->info.firstRow = 256;
pFont->info.lastRow = 0;
pFont->info.firstCol = 256;
pFont->info.lastCol = 0;
nignored = 0;
for (ndx = 0; (ndx < nchars) && (line) && (bdfIsPrefix(line, "STARTCHAR"));) {
int t;
int wx;
int wy;
int bw;
int bh;
int bl;
int bb;
int enc,
enc2;
unsigned char *p;
char charName[100];
int ignore;
if (sscanf((char *) line, "STARTCHAR %s", charName) != 1) {
bdfError("bad character name in BDF file\n");
goto BAILOUT;
}
if (bitmapExtra)
bitmapExtra->glyphNames[ndx] = bdfForceMakeAtom(charName, NULL);
line = bdfGetLine(file, lineBuf, BDFLINELEN);
if (!line || (t = sscanf((char *) line, "ENCODING %d %d", &enc, &enc2)) < 1) {
bdfError("bad 'ENCODING' in BDF file\n");
goto BAILOUT;
}
if (enc < -1 || (t == 2 && enc2 < -1)) {
bdfError("bad ENCODING value");
goto BAILOUT;
}
if (t == 2 && enc == -1)
enc = enc2;
ignore = 0;
if (enc == -1) {
if (!bitmapExtra) {
nignored++;
ignore = 1;
}
} else if (enc > MAXENCODING) {
bdfError("char '%s' has encoding too large (%d)\n",
charName, enc);
} else {
char_row = (enc >> 8) & 0xFF;
char_col = enc & 0xFF;
if (char_row < pFont->info.firstRow)
pFont->info.firstRow = char_row;
if (char_row > pFont->info.lastRow)
pFont->info.lastRow = char_row;
if (char_col < pFont->info.firstCol)
pFont->info.firstCol = char_col;
if (char_col > pFont->info.lastCol)
pFont->info.lastCol = char_col;
if (bdfEncoding[char_row] == (CharInfoPtr *) NULL) {
bdfEncoding[char_row] = malloc(256 * sizeof(CharInfoPtr));
if (!bdfEncoding[char_row]) {
bdfError("Couldn't allocate row %d of encoding (%d*%d)\n",
char_row, INDICES, sizeof(CharInfoPtr));
goto BAILOUT;
}
for (i = 0; i < 256; i++)
bdfEncoding[char_row][i] = (CharInfoPtr) NULL;
}
if (bdfEncoding[char_row] != NULL) {
bdfEncoding[char_row][char_col] = ci;
numEncodedGlyphs++;
}
}
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;
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;
}
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;
}
if ((bh < 0) || (bw < 0)) {
bdfError("character '%s' has a negative sized bitmap, %dx%d\n",
charName, bw, bh);
goto BAILOUT;
}
line = bdfGetLine(file, lineBuf, BDFLINELEN);
if ((line) && (bdfIsPrefix(line, "ATTRIBUTES"))) {
for (p = line + strlen("ATTRIBUTES ");
(*p == ' ') || (*p == '\t');
p++)
;
ci->metrics.attributes = (bdfHexByte(p) << 8) + bdfHexByte(p + 2);
line = bdfGetLine(file, lineBuf, BDFLINELEN);
} else
ci->metrics.attributes = 0;
if (!line || !bdfIsPrefix(line, "BITMAP")) {
bdfError("missing 'BITMAP'\n");
goto BAILOUT;
}
if ((strlen(charName) == 1)) {
if ((charName[0] >= '0') && (charName[0] <= '9')) {
pState->digitWidths += wx;
pState->digitCount++;
} else if (charName[0] == 'x') {
pState->exHeight = (bh + bb) <= 0 ? bh : bh + bb;
}
}
if (!ignore) {
ci->metrics.leftSideBearing = bl;
ci->metrics.rightSideBearing = bl + bw;
ci->metrics.ascent = bh + bb;
ci->metrics.descent = -bb;
ci->metrics.characterWidth = wx;
ci->bits = NULL;
bdfReadBitmap(ci, file, bit, byte, glyph, scan, bitmapsSizes);
ci++;
ndx++;
} else
bdfSkipBitmap(file, bh);
line = bdfGetLine(file, lineBuf, BDFLINELEN);
}
if (ndx + nignored != nchars) {
bdfError("%d too few characters\n", nchars - (ndx + nignored));
goto BAILOUT;
}
nchars = ndx;
bitmapFont->num_chars = nchars;
if ((line) && (bdfIsPrefix(line, "STARTCHAR"))) {
bdfError("more characters than specified\n");
goto BAILOUT;
}
if ((!line) || (!bdfIsPrefix(line, "ENDFONT"))) {
bdfError("missing 'ENDFONT'\n");
goto BAILOUT;
}
if (numEncodedGlyphs == 0)
bdfWarning("No characters with valid encodings\n");
nencoding = (pFont->info.lastRow - pFont->info.firstRow + 1) *
(pFont->info.lastCol - pFont->info.firstCol + 1);
bitmapFont->encoding = calloc(NUM_SEGMENTS(nencoding),sizeof(CharInfoPtr*));
if (!bitmapFont->encoding) {
bdfError("Couldn't allocate ppCI (%d,%d)\n",
NUM_SEGMENTS(nencoding),
sizeof(CharInfoPtr*));
goto BAILOUT;
}
pFont->info.allExist = TRUE;
i = 0;
for (char_row = pFont->info.firstRow;
char_row <= pFont->info.lastRow;
char_row++) {
if (bdfEncoding[char_row] == (CharInfoPtr *) NULL) {
pFont->info.allExist = FALSE;
i += pFont->info.lastCol - pFont->info.firstCol + 1;
} else {
for (char_col = pFont->info.firstCol;
char_col <= pFont->info.lastCol;
char_col++) {
if (!bdfEncoding[char_row][char_col])
pFont->info.allExist = FALSE;
else {
if (!bitmapFont->encoding[SEGMENT_MAJOR(i)]) {
bitmapFont->encoding[SEGMENT_MAJOR(i)]=
calloc(BITMAP_FONT_SEGMENT_SIZE,
sizeof(CharInfoPtr));
if (!bitmapFont->encoding[SEGMENT_MAJOR(i)])
goto BAILOUT;
}
ACCESSENCODINGL(bitmapFont->encoding,i) =
bdfEncoding[char_row][char_col];
}
i++;
}
}
}
for (i = 0; i < 256; i++)
if (bdfEncoding[i])
free(bdfEncoding[i]);
return (TRUE);
BAILOUT:
for (i = 0; i < 256; i++)
if (bdfEncoding[i])
free(bdfEncoding[i]);
return (FALSE);
}
static Bool
bdfReadHeader(FontFilePtr file, bdfFileState *pState)
{
unsigned char *line;
char namebuf[BDFLINELEN];
unsigned char lineBuf[BDFLINELEN];
line = bdfGetLine(file, lineBuf, BDFLINELEN);
if (!line || sscanf((char *) line, "STARTFONT %s", namebuf) != 1 ||
!bdfStrEqual(namebuf, "2.1")) {
bdfError("bad 'STARTFONT'\n");
return (FALSE);
}
line = bdfGetLine(file, lineBuf, BDFLINELEN);
if (!line || sscanf((char *) line, "FONT %[^\n]", pState->fontName) != 1) {
bdfError("bad 'FONT'\n");
return (FALSE);
}
line = bdfGetLine(file, lineBuf, BDFLINELEN);
if (!line || !bdfIsPrefix(line, "SIZE")) {
bdfError("missing 'SIZE'\n");
return (FALSE);
}
if (sscanf((char *) line, "SIZE %f%d%d", &pState->pointSize,
&pState->resolution_x, &pState->resolution_y) != 3) {
bdfError("bad 'SIZE'\n");
return (FALSE);
}
if (pState->pointSize < 1 ||
pState->resolution_x < 1 || pState->resolution_y < 1) {
bdfError("SIZE values must be > 0\n");
return (FALSE);
}
line = bdfGetLine(file, lineBuf, BDFLINELEN);
if (!line || !bdfIsPrefix(line, "FONTBOUNDINGBOX")) {
bdfError("missing 'FONTBOUNDINGBOX'\n");
return (FALSE);
}
return (TRUE);
}
static Bool
bdfReadProperties(FontFilePtr file, FontPtr pFont, bdfFileState *pState)
{
int nProps, props_left,
nextProp;
char *stringProps;
FontPropPtr props;
char namebuf[BDFLINELEN],
secondbuf[BDFLINELEN],
thirdbuf[BDFLINELEN];
unsigned char *line;
unsigned char lineBuf[BDFLINELEN];
BitmapFontPtr bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
line = bdfGetLine(file, lineBuf, BDFLINELEN);
if (!line || !bdfIsPrefix(line, "STARTPROPERTIES")) {
bdfError("missing 'STARTPROPERTIES'\n");
return (FALSE);
}
if (sscanf((char *) line, "STARTPROPERTIES %d", &nProps) != 1) {
bdfError("bad 'STARTPROPERTIES'\n");
return (FALSE);
}
pFont->info.isStringProp = NULL;
pFont->info.props = NULL;
pFont->info.nprops = 0;
stringProps = malloc((nProps + BDF_GENPROPS) * sizeof(char));
pFont->info.isStringProp = stringProps;
if (stringProps == NULL) {
bdfError("Couldn't allocate stringProps (%d*%d)\n",
(nProps + BDF_GENPROPS), sizeof(Bool));
goto BAILOUT;
}
pFont->info.props = props = calloc(nProps + BDF_GENPROPS,
sizeof(FontPropRec));
if (props == NULL) {
bdfError("Couldn't allocate props (%d*%d)\n", nProps + BDF_GENPROPS,
sizeof(FontPropRec));
goto BAILOUT;
}
nextProp = 0;
props_left = nProps;
while (props_left-- > 0) {
line = bdfGetLine(file, lineBuf, BDFLINELEN);
if (line == NULL || bdfIsPrefix(line, "ENDPROPERTIES")) {
bdfError("\"STARTPROPERTIES %d\" followed by only %d properties\n",
nProps, nProps - props_left - 1);
goto BAILOUT;
}
while (*line && isspace(*line))
line++;
switch (sscanf((char *) line, "%s%s%s", namebuf, secondbuf, thirdbuf)) {
default:
bdfError("missing '%s' parameter value\n", namebuf);
goto BAILOUT;
case 2:
if (secondbuf[0] == '"') {
stringProps[nextProp] = TRUE;
props[nextProp].value =
bdfGetPropertyValue((char *)line + strlen(namebuf) + 1);
if (!props[nextProp].value)
goto BAILOUT;
break;
} else if (bdfIsInteger(secondbuf)) {
stringProps[nextProp] = FALSE;
props[nextProp].value = atoi(secondbuf);
break;
} else {
bdfError("invalid '%s' parameter value\n", namebuf);
goto BAILOUT;
}
case 3:
if (secondbuf[0] == '"') {
stringProps[nextProp] = TRUE;
props[nextProp].value =
bdfGetPropertyValue((char *)line + strlen(namebuf) + 1);
if (!props[nextProp].value)
goto BAILOUT;
break;
} else {
bdfError("invalid '%s' parameter value\n", namebuf);
goto BAILOUT;
}
}
props[nextProp].name = bdfForceMakeAtom(namebuf, NULL);
if (props[nextProp].name == None) {
bdfError("Empty property name.\n");
goto BAILOUT;
}
if (!bdfSpecialProperty(pFont, &props[nextProp],
stringProps[nextProp], pState))
nextProp++;
}
line = bdfGetLine(file, lineBuf, BDFLINELEN);
if (!line || !bdfIsPrefix(line, "ENDPROPERTIES")) {
bdfError("missing 'ENDPROPERTIES'\n");
goto BAILOUT;
}
if (!pState->haveFontAscent || !pState->haveFontDescent) {
bdfError("missing 'FONT_ASCENT' or 'FONT_DESCENT' properties\n");
goto BAILOUT;
}
if (bitmapFont->bitmapExtra) {
bitmapFont->bitmapExtra->info.fontAscent = pFont->info.fontAscent;
bitmapFont->bitmapExtra->info.fontDescent = pFont->info.fontDescent;
}
if (!pState->pointSizeProp) {
props[nextProp].name = bdfForceMakeAtom("POINT_SIZE", NULL);
props[nextProp].value = (INT32) (pState->pointSize * 10.0);
stringProps[nextProp] = FALSE;
pState->pointSizeProp = &props[nextProp];
nextProp++;
}
if (!pState->fontProp) {
props[nextProp].name = bdfForceMakeAtom("FONT", NULL);
props[nextProp].value = (INT32) bdfForceMakeAtom(pState->fontName, NULL);
stringProps[nextProp] = TRUE;
pState->fontProp = &props[nextProp];
nextProp++;
}
if (!pState->weightProp) {
props[nextProp].name = bdfForceMakeAtom("WEIGHT", NULL);
props[nextProp].value = -1;
stringProps[nextProp] = FALSE;
pState->weightProp = &props[nextProp];
nextProp++;
}
if (!pState->resolutionProp &&
pState->resolution_x == pState->resolution_y) {
props[nextProp].name = bdfForceMakeAtom("RESOLUTION", NULL);
props[nextProp].value = (INT32) ((pState->resolution_x * 100.0) / 72.27);
stringProps[nextProp] = FALSE;
pState->resolutionProp = &props[nextProp];
nextProp++;
}
if (!pState->resolutionXProp) {
props[nextProp].name = bdfForceMakeAtom("RESOLUTION_X", NULL);
props[nextProp].value = (INT32) pState->resolution_x;
stringProps[nextProp] = FALSE;
pState->resolutionProp = &props[nextProp];
nextProp++;
}
if (!pState->resolutionYProp) {
props[nextProp].name = bdfForceMakeAtom("RESOLUTION_Y", NULL);
props[nextProp].value = (INT32) pState->resolution_y;
stringProps[nextProp] = FALSE;
pState->resolutionProp = &props[nextProp];
nextProp++;
}
if (!pState->xHeightProp) {
props[nextProp].name = bdfForceMakeAtom("X_HEIGHT", NULL);
props[nextProp].value = -1;
stringProps[nextProp] = FALSE;
pState->xHeightProp = &props[nextProp];
nextProp++;
}
if (!pState->quadWidthProp) {
props[nextProp].name = bdfForceMakeAtom("QUAD_WIDTH", NULL);
props[nextProp].value = -1;
stringProps[nextProp] = FALSE;
pState->quadWidthProp = &props[nextProp];
nextProp++;
}
pFont->info.nprops = nextProp;
return (TRUE);
BAILOUT:
if (pFont->info.isStringProp) {
free(pFont->info.isStringProp);
pFont->info.isStringProp = NULL;
}
if (pFont->info.props) {
free(pFont->info.props);
pFont->info.props = NULL;
}
while (line && bdfIsPrefix(line, "ENDPROPERTIES"))
line = bdfGetLine(file, lineBuf, BDFLINELEN);
return (FALSE);
}
static void
bdfUnloadFont(FontPtr pFont)
{
bdfFreeFontBits (pFont);
DestroyFontRec(pFont);
}
int
bdfReadFont(FontPtr pFont, FontFilePtr file,
int bit, int byte, int glyph, int scan)
{
bdfFileState state;
xCharInfo *min,
*max;
BitmapFontPtr bitmapFont;
pFont->fontPrivate = 0;
bzero(&state, sizeof(bdfFileState));
bdfFileLineNum = 0;
if (!bdfReadHeader(file, &state))
goto BAILOUT;
bitmapFont = calloc(1, sizeof(BitmapFontRec));
if (!bitmapFont) {
bdfError("Couldn't allocate bitmapFontRec (%d)\n", sizeof(BitmapFontRec));
goto BAILOUT;
}
pFont->fontPrivate = (pointer) bitmapFont;
bitmapFont->metrics = 0;
bitmapFont->ink_metrics = 0;
bitmapFont->bitmaps = 0;
bitmapFont->encoding = 0;
bitmapFont->pDefault = NULL;
bitmapFont->bitmapExtra = calloc(1, sizeof(BitmapExtraRec));
if (!bitmapFont->bitmapExtra) {
bdfError("Couldn't allocate bitmapExtra (%d)\n", sizeof(BitmapExtraRec));
goto BAILOUT;
}
bitmapFont->bitmapExtra->glyphNames = 0;
bitmapFont->bitmapExtra->sWidths = 0;
if (!bdfReadProperties(file, pFont, &state))
goto BAILOUT;
if (!bdfReadCharacters(file, pFont, &state, bit, byte, glyph, scan))
goto BAILOUT;
if (state.haveDefaultCh) {
unsigned int r, c, cols;
r = pFont->info.defaultCh >> 8;
c = pFont->info.defaultCh & 0xFF;
if (pFont->info.firstRow <= r && r <= pFont->info.lastRow &&
pFont->info.firstCol <= c && c <= pFont->info.lastCol) {
cols = pFont->info.lastCol - pFont->info.firstCol + 1;
r = r - pFont->info.firstRow;
c = c - pFont->info.firstCol;
bitmapFont->pDefault = ACCESSENCODING(bitmapFont->encoding,
r * cols + c);
}
}
pFont->bit = bit;
pFont->byte = byte;
pFont->glyph = glyph;
pFont->scan = scan;
pFont->info.anamorphic = FALSE;
pFont->info.cachable = TRUE;
bitmapComputeFontBounds(pFont);
if (FontCouldBeTerminal(&pFont->info)) {
bdfPadToTerminal(pFont);
bitmapComputeFontBounds(pFont);
}
FontComputeInfoAccelerators(&pFont->info);
if (bitmapFont->bitmapExtra)
FontComputeInfoAccelerators(&bitmapFont->bitmapExtra->info);
if (pFont->info.constantMetrics) {
if (!bitmapAddInkMetrics(pFont)) {
bdfError("Failed to add bitmap ink metrics\n");
goto BAILOUT;
}
}
if (bitmapFont->bitmapExtra)
bitmapFont->bitmapExtra->info.inkMetrics = pFont->info.inkMetrics;
bitmapComputeFontInkBounds(pFont);
min = &pFont->info.ink_minbounds;
max = &pFont->info.ink_maxbounds;
if (state.xHeightProp && (state.xHeightProp->value == -1))
state.xHeightProp->value = state.exHeight ?
state.exHeight : min->ascent;
if (state.quadWidthProp && (state.quadWidthProp->value == -1))
state.quadWidthProp->value = state.digitCount ?
(INT32) (state.digitWidths / state.digitCount) :
(min->characterWidth + max->characterWidth) / 2;
if (state.weightProp && (state.weightProp->value == -1))
state.weightProp->value = bitmapComputeWeight(pFont);
pFont->get_glyphs = bitmapGetGlyphs;
pFont->get_metrics = bitmapGetMetrics;
pFont->unload_font = bdfUnloadFont;
pFont->unload_glyphs = NULL;
return Successful;
BAILOUT:
if (pFont->fontPrivate)
bdfFreeFontBits (pFont);
return AllocError;
}
int
bdfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file)
{
FontRec font;
int ret;
bzero(&font, sizeof (FontRec));
ret = bdfReadFont(&font, file, MSBFirst, LSBFirst, 1, 1);
if (ret == Successful) {
*pFontInfo = font.info;
font.info.props = 0;
font.info.isStringProp = 0;
font.info.nprops = 0;
bdfFreeFontBits (&font);
}
return ret;
}
static Bool
bdfPadToTerminal(FontPtr pFont)
{
BitmapFontPtr bitmapFont;
BitmapExtraPtr bitmapExtra;
int i;
int new_size;
CharInfoRec new;
int w,
h;
bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
bzero(&new, sizeof(CharInfoRec));
new.metrics.ascent = pFont->info.fontAscent;
new.metrics.descent = pFont->info.fontDescent;
new.metrics.leftSideBearing = 0;
new.metrics.rightSideBearing = pFont->info.minbounds.characterWidth;
new.metrics.characterWidth = new.metrics.rightSideBearing;
new_size = BYTES_FOR_GLYPH(&new, pFont->glyph);
for (i = 0; i < bitmapFont->num_chars; i++) {
new.bits = malloc(new_size);
if (!new.bits) {
bdfError("Couldn't allocate bits (%d)\n", new_size);
return FALSE;
}
FontCharReshape(pFont, &bitmapFont->metrics[i], &new);
new.metrics.attributes = bitmapFont->metrics[i].metrics.attributes;
free(bitmapFont->metrics[i].bits);
bitmapFont->metrics[i] = new;
}
bitmapExtra = bitmapFont->bitmapExtra;
if (bitmapExtra) {
w = GLYPHWIDTHPIXELS(&new);
h = GLYPHHEIGHTPIXELS(&new);
for (i = 0; i < GLYPHPADOPTIONS; i++)
bitmapExtra->bitmapsSizes[i] = bitmapFont->num_chars *
(BYTES_PER_ROW(w, 1 << i) * h);
}
return TRUE;
}