recipes

packages recipes for the <noname> package manager
Log | Files | Refs

bdfread.c (29286B)


      1 /* $Xorg: bdfread.c,v 1.5 2001/02/09 02:04:01 xorgcvs Exp $ */
      2 
      3 /************************************************************************
      4 Copyright 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
      5 
      6                         All Rights Reserved
      7 
      8 Permission to use, copy, modify, and distribute this software and its
      9 documentation for any purpose and without fee is hereby granted,
     10 provided that the above copyright notice appear in all copies and that
     11 both that copyright notice and this permission notice appear in
     12 supporting documentation, and that the name of Digital not be
     13 used in advertising or publicity pertaining to distribution of the
     14 software without specific, written prior permission.
     15 
     16 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
     17 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
     18 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
     19 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
     20 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     21 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     22 SOFTWARE.
     23 
     24 ************************************************************************/
     25 
     26 /*
     27 
     28 Copyright 1994, 1998  The Open Group
     29 
     30 Permission to use, copy, modify, distribute, and sell this software and its
     31 documentation for any purpose is hereby granted without fee, provided that
     32 the above copyright notice appear in all copies and that both that
     33 copyright notice and this permission notice appear in supporting
     34 documentation.
     35 
     36 The above copyright notice and this permission notice shall be included
     37 in all copies or substantial portions of the Software.
     38 
     39 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     40 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     41 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     42 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
     43 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     44 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     45 OTHER DEALINGS IN THE SOFTWARE.
     46 
     47 Except as contained in this notice, the name of The Open Group shall
     48 not be used in advertising or otherwise to promote the sale, use or
     49 other dealings in this Software without prior written authorization
     50 from The Open Group.
     51 
     52 */
     53 /* $XFree86: xc/lib/font/bitmap/bdfread.c,v 1.11 2001/12/14 19:56:45 dawes Exp $ */
     54 
     55 #include <stdint.h>
     56 #ifndef FONTMODULE
     57 #include <ctype.h>
     58 #endif
     59 #include "../include/fntfilst.h"
     60 #include "../include/fontutil.h"
     61 /* use bitmap structure */
     62 #include "../include/bitmap.h"
     63 #include "bdfint.h"
     64 
     65 #define INDICES 256
     66 #define MAXENCODING 0xFFFF
     67 #define BDFLINELEN  1024
     68 
     69 static Bool bdfPadToTerminal(FontPtr pFont);
     70 extern int  bdfFileLineNum;
     71 
     72 /***====================================================================***/
     73 
     74 static Bool
     75 bdfReadBitmap(CharInfoPtr pCI, FontFilePtr file, int bit, int byte, 
     76 	      int glyph, int scan, CARD32 *sizes)
     77 {
     78     int         widthBits,
     79                 widthBytes,
     80                 widthHexChars;
     81     int         height,
     82                 row;
     83     int         i,
     84                 inLineLen,
     85                 nextByte;
     86     Bool        badbits;
     87     unsigned char *pInBits,
     88                *picture,
     89                *line = NULL;
     90     unsigned char        lineBuf[BDFLINELEN];
     91 
     92     widthBits = GLYPHWIDTHPIXELS(pCI);
     93     height = GLYPHHEIGHTPIXELS(pCI);
     94 
     95     widthBytes = BYTES_PER_ROW(widthBits, glyph);
     96     if (widthBytes * height > 0) {
     97 	picture = (unsigned char *) xalloc(widthBytes * height);
     98 	if (!picture) {
     99           bdfError("Couldn't allocate picture (%d*%d)\n", widthBytes, height);        
    100 	    goto BAILOUT;
    101       }
    102     } else
    103 	picture = NULL;
    104     pCI->bits = (char *) picture;
    105 
    106     if (sizes) {
    107 	for (i = 0; i < GLYPHPADOPTIONS; i++)
    108 	    sizes[i] += BYTES_PER_ROW(widthBits, (1 << i)) * height;
    109     }
    110     badbits = FALSE;
    111     nextByte = 0;
    112     widthHexChars = BYTES_PER_ROW(widthBits, 1);
    113 
    114 /* 5/31/89 (ef) -- hack, hack, hack.  what *am* I supposed to do with */
    115 /*		0 width characters? */
    116 
    117     for (row = 0; row < height; row++) {
    118 	line = bdfGetLine(file, lineBuf, BDFLINELEN);
    119 	if (!line)
    120 	    break;
    121 
    122 	if (widthBits == 0) {
    123 	    if ((!line) || (bdfIsPrefix(line, "ENDCHAR")))
    124 		break;
    125 	    else
    126 		continue;
    127 	}
    128 	pInBits = line;
    129 	inLineLen = strlen((char *) pInBits);
    130 
    131 	if (inLineLen & 1) {
    132 	    bdfError("odd number of characters in hex encoding\n");
    133 	    line[inLineLen++] = '0';
    134 	    line[inLineLen] = '\0';
    135 	}
    136 	inLineLen >>= 1;
    137 	i = inLineLen;
    138 	if (i > widthHexChars)
    139 	    i = widthHexChars;
    140 	for (; i > 0; i--, pInBits += 2)
    141 	    picture[nextByte++] = bdfHexByte(pInBits);
    142 
    143 	/* pad if line is too short */
    144 	if (inLineLen < widthHexChars) {
    145 	    for (i = widthHexChars - inLineLen; i > 0; i--)
    146 		picture[nextByte++] = 0;
    147 	} else {
    148 	    unsigned char mask;
    149 
    150 	    mask = 0xff << (8 - (widthBits & 0x7));
    151 	    if (mask && picture[nextByte - 1] & ~mask) {
    152 		picture[nextByte - 1] &= mask;
    153 		badbits = TRUE;
    154 	    } else if (inLineLen > widthHexChars)
    155 		badbits = TRUE;
    156 	}
    157 
    158 	if (widthBytes > widthHexChars) {
    159 	    i = widthBytes - widthHexChars;
    160 	    while (i-- > 0)
    161 		picture[nextByte++] = 0;
    162 	}
    163     }
    164 
    165     if ((line && (!bdfIsPrefix(line, "ENDCHAR"))) || (height == 0))
    166 	line = bdfGetLine(file, lineBuf, BDFLINELEN);
    167 
    168     if ((!line) || (!bdfIsPrefix(line, "ENDCHAR"))) {
    169 	bdfError("missing 'ENDCHAR'\n");
    170 	goto BAILOUT;
    171     }
    172     if (nextByte != height * widthBytes) {
    173 	bdfError("bytes != rows * bytes_per_row (%d != %d * %d)\n",
    174 		 nextByte, height, widthBytes);
    175 	goto BAILOUT;
    176     }
    177     if (picture != NULL) {
    178 	if (bit == LSBFirst)
    179 	    BitOrderInvert(picture, nextByte);
    180 	if (bit != byte) {
    181 	    if (scan == 2)
    182 		TwoByteSwap(picture, nextByte);
    183 	    else if (scan == 4)
    184 		FourByteSwap(picture, nextByte);
    185 	}
    186     }
    187     return (TRUE);
    188 BAILOUT:
    189     if (picture)
    190 	xfree(picture);
    191     pCI->bits = NULL;
    192     return (FALSE);
    193 }
    194 
    195 /***====================================================================***/
    196 
    197 static Bool
    198 bdfSkipBitmap(FontFilePtr file, int height)
    199 {
    200     unsigned char *line;
    201     int         i = 0;
    202     unsigned char        lineBuf[BDFLINELEN];
    203 
    204     do {
    205 	line = bdfGetLine(file, lineBuf, BDFLINELEN);
    206 	i++;
    207     } while (line && !bdfIsPrefix(line, "ENDCHAR") && i <= height);
    208 
    209     if (i > 1 && line && !bdfIsPrefix(line, "ENDCHAR")) {
    210 	bdfError("Error in bitmap, missing 'ENDCHAR'\n");
    211 	return (FALSE);
    212     }
    213     return (TRUE);
    214 }
    215 
    216 /***====================================================================***/
    217 
    218 static void
    219 bdfFreeFontBits(FontPtr pFont)
    220 {
    221     BitmapFontPtr  bitmapFont;
    222     BitmapExtraPtr bitmapExtra;
    223     int         i, nencoding;
    224 
    225     bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
    226     bitmapExtra = (BitmapExtraPtr) bitmapFont->bitmapExtra;
    227     xfree(bitmapFont->ink_metrics);
    228     if(bitmapFont->encoding) {
    229         nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) *
    230 	    (pFont->info.lastRow - pFont->info.firstRow + 1);
    231         for(i=0; i<NUM_SEGMENTS(nencoding); i++)
    232             xfree(bitmapFont->encoding[i]);
    233     }
    234     xfree(bitmapFont->encoding);
    235     for (i = 0; i < bitmapFont->num_chars; i++)
    236 	xfree(bitmapFont->metrics[i].bits);
    237     xfree(bitmapFont->metrics);
    238     if (bitmapExtra)
    239     {
    240 	xfree (bitmapExtra->glyphNames);
    241 	xfree (bitmapExtra->sWidths);
    242 	xfree (bitmapExtra);
    243     }
    244     xfree(pFont->info.props);
    245     xfree(bitmapFont);
    246 }
    247 
    248 
    249 static Bool
    250 bdfReadCharacters(FontFilePtr file, FontPtr pFont, bdfFileState *pState, 
    251 		  int bit, int byte, int glyph, int scan)
    252 {
    253     unsigned char *line;
    254     register CharInfoPtr ci;
    255     int         i,
    256                 ndx,
    257                 nchars,
    258                 nignored;
    259     unsigned int char_row, char_col;
    260     int         numEncodedGlyphs = 0;
    261     CharInfoPtr *bdfEncoding[256];
    262     BitmapFontPtr  bitmapFont;
    263     BitmapExtraPtr bitmapExtra;
    264     CARD32     *bitmapsSizes;
    265     unsigned char        lineBuf[BDFLINELEN];
    266     int         nencoding;
    267 
    268     bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
    269     bitmapExtra = (BitmapExtraPtr) bitmapFont->bitmapExtra;
    270 
    271     if (bitmapExtra) {
    272 	bitmapsSizes = bitmapExtra->bitmapsSizes;
    273 	for (i = 0; i < GLYPHPADOPTIONS; i++)
    274 	    bitmapsSizes[i] = 0;
    275     } else
    276 	bitmapsSizes = NULL;
    277 
    278     bzero(bdfEncoding, sizeof(bdfEncoding));
    279     bitmapFont->metrics = NULL;
    280     ndx = 0;
    281 
    282     line = bdfGetLine(file, lineBuf, BDFLINELEN);
    283 
    284     if ((!line) || (sscanf((char *) line, "CHARS %d", &nchars) != 1)) {
    285 	bdfError("bad 'CHARS' in bdf file\n");
    286 	return (FALSE);
    287     }
    288     if (nchars < 1) {
    289 	bdfError("invalid number of CHARS in BDF file\n");
    290 	return (FALSE);
    291     }
    292     if  ((nchars > INT32_MAX / sizeof(CharInfoRec)) || 
    293 	    (ci = (CharInfoPtr) xalloc(nchars * sizeof(CharInfoRec))) == NULL){
    294 	bdfError("Couldn't allocate pCI (%d*%d)\n", nchars,
    295 		 sizeof(CharInfoRec));
    296 	goto BAILOUT;
    297     }
    298     bzero((char *)ci, nchars * sizeof(CharInfoRec));
    299     bitmapFont->metrics = ci;
    300 
    301     if (bitmapExtra) {
    302 	bitmapExtra->glyphNames = (Atom *) xalloc(nchars * sizeof(Atom));
    303 	if (!bitmapExtra->glyphNames) {
    304 	    bdfError("Couldn't allocate glyphNames (%d*%d)\n",
    305 		     nchars, sizeof(Atom));
    306 	    goto BAILOUT;
    307 	}
    308     }
    309     if (bitmapExtra) {
    310 	bitmapExtra->sWidths = (int *) xalloc(nchars * sizeof(int));
    311 	if (!bitmapExtra->sWidths) {
    312 	    bdfError("Couldn't allocate sWidth (%d *%d)\n",
    313 		     nchars, sizeof(int));
    314 	    return FALSE;
    315 	}
    316     }
    317     line = bdfGetLine(file, lineBuf, BDFLINELEN);
    318     pFont->info.firstRow = 256;
    319     pFont->info.lastRow = 0;
    320     pFont->info.firstCol = 256;
    321     pFont->info.lastCol = 0;
    322     nignored = 0;
    323     for (ndx = 0; (ndx < nchars) && (line) && (bdfIsPrefix(line, "STARTCHAR"));) {
    324 	int         t;
    325 	int         wx;		/* x component of width */
    326 	int         wy;		/* y component of width */
    327 	int         bw;		/* bounding-box width */
    328 	int         bh;		/* bounding-box height */
    329 	int         bl;		/* bounding-box left */
    330 	int         bb;		/* bounding-box bottom */
    331 	int         enc,
    332 	            enc2;	/* encoding */
    333 	unsigned char *p;	/* temp pointer into line */
    334 	char        charName[100];
    335 	int         ignore;
    336 
    337 	if (sscanf((char *) line, "STARTCHAR %99s", charName) != 1) {
    338 	    bdfError("bad character name in BDF file\n");
    339 	    goto BAILOUT;	/* bottom of function, free and return error */
    340 	}
    341 	if (bitmapExtra)
    342 	    bitmapExtra->glyphNames[ndx] = bdfForceMakeAtom(charName, NULL);
    343 
    344 	line = bdfGetLine(file, lineBuf, BDFLINELEN);
    345 	if (!line || (t = sscanf((char *) line, "ENCODING %d %d", &enc, &enc2)) < 1) {
    346 	    bdfError("bad 'ENCODING' in BDF file\n");
    347 	    goto BAILOUT;
    348 	}
    349 	if (enc < -1 || (t == 2 && enc2 < -1)) {
    350 	    bdfError("bad ENCODING value");
    351 	    goto BAILOUT;
    352 	}
    353 	if (t == 2 && enc == -1)
    354 	    enc = enc2;
    355 	ignore = 0;
    356 	if (enc == -1) {
    357 	    if (!bitmapExtra) {
    358 		nignored++;
    359 		ignore = 1;
    360 	    }
    361 	} else if (enc > MAXENCODING) {
    362 	    bdfError("char '%s' has encoding too large (%d)\n",
    363 		     charName, enc);
    364 	} else {
    365 	    char_row = (enc >> 8) & 0xFF;
    366 	    char_col = enc & 0xFF;
    367 	    if (char_row < pFont->info.firstRow)
    368 		pFont->info.firstRow = char_row;
    369 	    if (char_row > pFont->info.lastRow)
    370 		pFont->info.lastRow = char_row;
    371 	    if (char_col < pFont->info.firstCol)
    372 		pFont->info.firstCol = char_col;
    373 	    if (char_col > pFont->info.lastCol)
    374 		pFont->info.lastCol = char_col;
    375 	    if (bdfEncoding[char_row] == (CharInfoPtr *) NULL) {
    376 		bdfEncoding[char_row] =
    377 		    (CharInfoPtr *) xalloc(256 * sizeof(CharInfoPtr));
    378 		if (!bdfEncoding[char_row]) {
    379 		    bdfError("Couldn't allocate row %d of encoding (%d*%d)\n",
    380 			     char_row, INDICES, sizeof(CharInfoPtr));
    381 		    goto BAILOUT;
    382 		}
    383 		for (i = 0; i < 256; i++)
    384 		    bdfEncoding[char_row][i] = (CharInfoPtr) NULL;
    385 	    }
    386 	    if (bdfEncoding[char_row] != NULL) {
    387 		bdfEncoding[char_row][char_col] = ci;
    388 		numEncodedGlyphs++;
    389 	    }
    390 	}
    391 
    392 	line = bdfGetLine(file, lineBuf, BDFLINELEN);
    393 	if ((!line) || (sscanf((char *) line, "SWIDTH %d %d", &wx, &wy) != 2)) {
    394 	    bdfError("bad 'SWIDTH'\n");
    395 	    goto BAILOUT;
    396 	}
    397 	if (wy != 0) {
    398 	    bdfError("SWIDTH y value must be zero\n");
    399 	    goto BAILOUT;
    400 	}
    401 	if (bitmapExtra)
    402 	    bitmapExtra->sWidths[ndx] = wx;
    403 
    404 /* 5/31/89 (ef) -- we should be able to ditch the character and recover */
    405 /*		from all of these.					*/
    406 
    407 	line = bdfGetLine(file, lineBuf, BDFLINELEN);
    408 	if ((!line) || (sscanf((char *) line, "DWIDTH %d %d", &wx, &wy) != 2)) {
    409 	    bdfError("bad 'DWIDTH'\n");
    410 	    goto BAILOUT;
    411 	}
    412 	if (wy != 0) {
    413 	    bdfError("DWIDTH y value must be zero\n");
    414 	    goto BAILOUT;
    415 	}
    416 	line = bdfGetLine(file, lineBuf, BDFLINELEN);
    417 	if ((!line) || (sscanf((char *) line, "BBX %d %d %d %d", &bw, &bh, &bl, &bb) != 4)) {
    418 	    bdfError("bad 'BBX'\n");
    419 	    goto BAILOUT;
    420 	}
    421 	if ((bh < 0) || (bw < 0)) {
    422 	    bdfError("character '%s' has a negative sized bitmap, %dx%d\n",
    423 		     charName, bw, bh);
    424 	    goto BAILOUT;
    425 	}
    426 	line = bdfGetLine(file, lineBuf, BDFLINELEN);
    427 	if ((line) && (bdfIsPrefix(line, "ATTRIBUTES"))) {
    428 	    for (p = line + strlen("ATTRIBUTES ");
    429 		    (*p == ' ') || (*p == '\t');
    430 		    p++)
    431 		 /* empty for loop */ ;
    432 	    ci->metrics.attributes = (bdfHexByte(p) << 8) + bdfHexByte(p + 2);
    433 	    line = bdfGetLine(file, lineBuf, BDFLINELEN);
    434 	} else
    435 	    ci->metrics.attributes = 0;
    436 
    437 	if (!line || !bdfIsPrefix(line, "BITMAP")) {
    438 	    bdfError("missing 'BITMAP'\n");
    439 	    goto BAILOUT;
    440 	}
    441 	/* collect data for generated properties */
    442 	if ((strlen(charName) == 1)) {
    443 	    if ((charName[0] >= '0') && (charName[0] <= '9')) {
    444 		pState->digitWidths += wx;
    445 		pState->digitCount++;
    446 	    } else if (charName[0] == 'x') {
    447 		pState->exHeight = (bh + bb) <= 0 ? bh : bh + bb;
    448 	    }
    449 	}
    450 	if (!ignore) {
    451 	    ci->metrics.leftSideBearing = bl;
    452 	    ci->metrics.rightSideBearing = bl + bw;
    453 	    ci->metrics.ascent = bh + bb;
    454 	    ci->metrics.descent = -bb;
    455 	    ci->metrics.characterWidth = wx;
    456 	    ci->bits = NULL;
    457 	    bdfReadBitmap(ci, file, bit, byte, glyph, scan, bitmapsSizes);
    458 	    ci++;
    459 	    ndx++;
    460 	} else
    461 	    bdfSkipBitmap(file, bh);
    462 
    463 	line = bdfGetLine(file, lineBuf, BDFLINELEN);	/* get STARTCHAR or
    464 							 * ENDFONT */
    465     }
    466 
    467     if (ndx + nignored != nchars) {
    468 	bdfError("%d too few characters\n", nchars - (ndx + nignored));
    469 	goto BAILOUT;
    470     }
    471     nchars = ndx;
    472     bitmapFont->num_chars = nchars;
    473     if ((line) && (bdfIsPrefix(line, "STARTCHAR"))) {
    474 	bdfError("more characters than specified\n");
    475 	goto BAILOUT;
    476     }
    477     if ((!line) || (!bdfIsPrefix(line, "ENDFONT"))) {
    478 	bdfError("missing 'ENDFONT'\n");
    479 	goto BAILOUT;
    480     }
    481     if (numEncodedGlyphs == 0)
    482 	bdfWarning("No characters with valid encodings\n");
    483 
    484     nencoding = (pFont->info.lastRow - pFont->info.firstRow + 1) *
    485 	(pFont->info.lastCol - pFont->info.firstCol + 1);
    486     bitmapFont->encoding = 
    487       (CharInfoPtr **) xcalloc(NUM_SEGMENTS(nencoding),
    488                                sizeof(CharInfoPtr*));
    489     if (!bitmapFont->encoding) {
    490 	bdfError("Couldn't allocate ppCI (%d,%d)\n",
    491                  NUM_SEGMENTS(nencoding),
    492                  sizeof(CharInfoPtr*));
    493 	goto BAILOUT;
    494     }
    495     pFont->info.allExist = TRUE;
    496     i = 0;
    497     for (char_row = pFont->info.firstRow;
    498 	    char_row <= pFont->info.lastRow;
    499 	    char_row++) {
    500 	if (bdfEncoding[char_row] == (CharInfoPtr *) NULL) {
    501 	    pFont->info.allExist = FALSE;
    502             i += pFont->info.lastCol - pFont->info.firstCol + 1;
    503 	} else {
    504 	    for (char_col = pFont->info.firstCol;
    505 		    char_col <= pFont->info.lastCol;
    506 		    char_col++) {
    507 		if (!bdfEncoding[char_row][char_col])
    508 		    pFont->info.allExist = FALSE;
    509                 else {
    510                     if (!bitmapFont->encoding[SEGMENT_MAJOR(i)]) {
    511                         bitmapFont->encoding[SEGMENT_MAJOR(i)]=
    512                             (CharInfoPtr*)xcalloc(BITMAP_FONT_SEGMENT_SIZE,
    513                                                   sizeof(CharInfoPtr));
    514                         if (!bitmapFont->encoding[SEGMENT_MAJOR(i)])
    515                             goto BAILOUT;
    516                     }
    517                     ACCESSENCODINGL(bitmapFont->encoding,i) = 
    518                         bdfEncoding[char_row][char_col];
    519                 }
    520                 i++;
    521             }
    522 	}
    523     }
    524     for (i = 0; i < 256; i++)
    525 	if (bdfEncoding[i])
    526 	    xfree(bdfEncoding[i]);
    527     return (TRUE);
    528 BAILOUT:
    529     for (i = 0; i < 256; i++)
    530 	if (bdfEncoding[i])
    531 	    xfree(bdfEncoding[i]);
    532     /* bdfFreeFontBits will clean up the rest */
    533     return (FALSE);
    534 }
    535 
    536 /***====================================================================***/
    537 
    538 static Bool
    539 bdfReadHeader(FontFilePtr file, bdfFileState *pState)
    540 {
    541     unsigned char *line;
    542     char        namebuf[BDFLINELEN];
    543     unsigned char        lineBuf[BDFLINELEN];
    544 
    545     line = bdfGetLine(file, lineBuf, BDFLINELEN);
    546     if (!line || sscanf((char *) line, "STARTFONT %s", namebuf) != 1 ||
    547 	    !bdfStrEqual(namebuf, "2.1")) {
    548 	bdfError("bad 'STARTFONT'\n");
    549 	return (FALSE);
    550     }
    551     line = bdfGetLine(file, lineBuf, BDFLINELEN);
    552     if (!line || sscanf((char *) line, "FONT %[^\n]", pState->fontName) != 1) {
    553 	bdfError("bad 'FONT'\n");
    554 	return (FALSE);
    555     }
    556     line = bdfGetLine(file, lineBuf, BDFLINELEN);
    557     if (!line || !bdfIsPrefix(line, "SIZE")) {
    558 	bdfError("missing 'SIZE'\n");
    559 	return (FALSE);
    560     }
    561     if (sscanf((char *) line, "SIZE %f%d%d", &pState->pointSize,
    562 	       &pState->resolution_x, &pState->resolution_y) != 3) {
    563 	bdfError("bad 'SIZE'\n");
    564 	return (FALSE);
    565     }
    566     if (pState->pointSize < 1 ||
    567 	pState->resolution_x < 1 || pState->resolution_y < 1) {
    568 	bdfError("SIZE values must be > 0\n");
    569 	return (FALSE);
    570     }
    571     line = bdfGetLine(file, lineBuf, BDFLINELEN);
    572     if (!line || !bdfIsPrefix(line, "FONTBOUNDINGBOX")) {
    573 	bdfError("missing 'FONTBOUNDINGBOX'\n");
    574 	return (FALSE);
    575     }
    576     return (TRUE);
    577 }
    578 
    579 /***====================================================================***/
    580 
    581 static Bool
    582 bdfReadProperties(FontFilePtr file, FontPtr pFont, bdfFileState *pState)
    583 {
    584     int         nProps, props_left,
    585                 nextProp;
    586     char       *stringProps;
    587     FontPropPtr props;
    588     char        namebuf[BDFLINELEN],
    589                 secondbuf[BDFLINELEN],
    590                 thirdbuf[BDFLINELEN];
    591     unsigned char *line;
    592     unsigned char        lineBuf[BDFLINELEN];
    593     BitmapFontPtr  bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
    594 
    595     line = bdfGetLine(file, lineBuf, BDFLINELEN);
    596     if (!line || !bdfIsPrefix(line, "STARTPROPERTIES")) {
    597 	bdfError("missing 'STARTPROPERTIES'\n");
    598 	return (FALSE);
    599     }
    600     if (sscanf((char *) line, "STARTPROPERTIES %d", &nProps) != 1) {
    601 	bdfError("bad 'STARTPROPERTIES'\n");
    602 	return (FALSE);
    603     }
    604     pFont->info.isStringProp = NULL;
    605     pFont->info.props = NULL;
    606 
    607     stringProps = (char *) xalloc((nProps + BDF_GENPROPS) * sizeof(char));
    608     pFont->info.isStringProp = stringProps;
    609     if (stringProps == NULL) {
    610 	bdfError("Couldn't allocate stringProps (%d*%d)\n",
    611 		 (nProps + BDF_GENPROPS), sizeof(Bool));
    612 	goto BAILOUT;
    613     }
    614     pFont->info.props = props = (FontPropPtr) xalloc((nProps + BDF_GENPROPS) *
    615 						     sizeof(FontPropRec));
    616     if (props == NULL) {
    617 	bdfError("Couldn't allocate props (%d*%d)\n", nProps + BDF_GENPROPS,
    618 						      sizeof(FontPropRec));
    619 	goto BAILOUT;
    620     }
    621     bzero((char *)props, (nProps + BDF_GENPROPS) * sizeof(FontPropRec));
    622 
    623     nextProp = 0;
    624     props_left = nProps;
    625     while (props_left-- > 0) {
    626 	line = bdfGetLine(file, lineBuf, BDFLINELEN);
    627 	if (line == NULL || bdfIsPrefix(line, "ENDPROPERTIES")) {
    628 	    bdfError("\"STARTPROPERTIES %d\" followed by only %d properties\n",
    629 		     nProps, nProps - props_left - 1);
    630 	    goto BAILOUT;
    631 	}
    632 	while (*line && isspace(*line))
    633 	    line++;
    634 
    635 	switch (sscanf((char *) line, "%s%s%s", namebuf, secondbuf, thirdbuf)) {
    636 	default:
    637 	    bdfError("missing '%s' parameter value\n", namebuf);
    638 	    goto BAILOUT;
    639 
    640 	case 2:
    641 	    /*
    642 	     * Possibilites include: valid quoted string with no white space
    643 	     * valid integer value invalid value
    644 	     */
    645 	    if (secondbuf[0] == '"') {
    646 		stringProps[nextProp] = TRUE;
    647 		props[nextProp].value =
    648 		    bdfGetPropertyValue((char *)line + strlen(namebuf) + 1);
    649 		if (!props[nextProp].value)
    650 		    goto BAILOUT;
    651 		break;
    652 	    } else if (bdfIsInteger(secondbuf)) {
    653 		stringProps[nextProp] = FALSE;
    654 		props[nextProp].value = atoi(secondbuf);
    655 		break;
    656 	    } else {
    657 		bdfError("invalid '%s' parameter value\n", namebuf);
    658 		goto BAILOUT;
    659 	    }
    660 
    661 	case 3:
    662 	    /*
    663 	     * Possibilites include: valid quoted string with some white space
    664 	     * invalid value (reject even if second string is integer)
    665 	     */
    666 	    if (secondbuf[0] == '"') {
    667 		stringProps[nextProp] = TRUE;
    668 		props[nextProp].value =
    669 		    bdfGetPropertyValue((char *)line + strlen(namebuf) + 1);
    670 		if (!props[nextProp].value)
    671 		    goto BAILOUT;
    672 		break;
    673 	    } else {
    674 		bdfError("invalid '%s' parameter value\n", namebuf);
    675 		goto BAILOUT;
    676 	    }
    677 	}
    678 	props[nextProp].name = bdfForceMakeAtom(namebuf, NULL);
    679 	if (props[nextProp].name == None) {
    680 	    bdfError("Empty property name.\n");
    681 	    goto BAILOUT;
    682 	}
    683 	if (!bdfSpecialProperty(pFont, &props[nextProp],
    684 				stringProps[nextProp], pState))
    685 	    nextProp++;
    686     }
    687 
    688     line = bdfGetLine(file, lineBuf, BDFLINELEN);
    689     if (!line || !bdfIsPrefix(line, "ENDPROPERTIES")) {
    690 	bdfError("missing 'ENDPROPERTIES'\n");
    691 	goto BAILOUT;
    692     }
    693     if (!pState->haveFontAscent || !pState->haveFontDescent) {
    694 	bdfError("missing 'FONT_ASCENT' or 'FONT_DESCENT' properties\n");
    695 	goto BAILOUT;
    696     }
    697     if (bitmapFont->bitmapExtra) {
    698 	bitmapFont->bitmapExtra->info.fontAscent = pFont->info.fontAscent;
    699 	bitmapFont->bitmapExtra->info.fontDescent = pFont->info.fontDescent;
    700     }
    701     if (!pState->pointSizeProp) {
    702 	props[nextProp].name = bdfForceMakeAtom("POINT_SIZE", NULL);
    703 	props[nextProp].value = (INT32) (pState->pointSize * 10.0);
    704 	stringProps[nextProp] = FALSE;
    705 	pState->pointSizeProp = &props[nextProp];
    706 	nextProp++;
    707     }
    708     if (!pState->fontProp) {
    709 	props[nextProp].name = bdfForceMakeAtom("FONT", NULL);
    710 	props[nextProp].value = (INT32) bdfForceMakeAtom(pState->fontName, NULL);
    711 	stringProps[nextProp] = TRUE;
    712 	pState->fontProp = &props[nextProp];
    713 	nextProp++;
    714     }
    715     if (!pState->weightProp) {
    716 	props[nextProp].name = bdfForceMakeAtom("WEIGHT", NULL);
    717 	props[nextProp].value = -1;	/* computed later */
    718 	stringProps[nextProp] = FALSE;
    719 	pState->weightProp = &props[nextProp];
    720 	nextProp++;
    721     }
    722     if (!pState->resolutionProp &&
    723 	pState->resolution_x == pState->resolution_y) {
    724 	props[nextProp].name = bdfForceMakeAtom("RESOLUTION", NULL);
    725 	props[nextProp].value = (INT32) ((pState->resolution_x * 100.0) / 72.27);
    726 	stringProps[nextProp] = FALSE;
    727 	pState->resolutionProp = &props[nextProp];
    728 	nextProp++;
    729     }
    730     if (!pState->resolutionXProp) {
    731 	props[nextProp].name = bdfForceMakeAtom("RESOLUTION_X", NULL);
    732 	props[nextProp].value = (INT32) pState->resolution_x;
    733 	stringProps[nextProp] = FALSE;
    734 	pState->resolutionProp = &props[nextProp];
    735 	nextProp++;
    736     }
    737     if (!pState->resolutionYProp) {
    738 	props[nextProp].name = bdfForceMakeAtom("RESOLUTION_Y", NULL);
    739 	props[nextProp].value = (INT32) pState->resolution_y;
    740 	stringProps[nextProp] = FALSE;
    741 	pState->resolutionProp = &props[nextProp];
    742 	nextProp++;
    743     }
    744     if (!pState->xHeightProp) {
    745 	props[nextProp].name = bdfForceMakeAtom("X_HEIGHT", NULL);
    746 	props[nextProp].value = -1;	/* computed later */
    747 	stringProps[nextProp] = FALSE;
    748 	pState->xHeightProp = &props[nextProp];
    749 	nextProp++;
    750     }
    751     if (!pState->quadWidthProp) {
    752 	props[nextProp].name = bdfForceMakeAtom("QUAD_WIDTH", NULL);
    753 	props[nextProp].value = -1;	/* computed later */
    754 	stringProps[nextProp] = FALSE;
    755 	pState->quadWidthProp = &props[nextProp];
    756 	nextProp++;
    757     }
    758     pFont->info.nprops = nextProp;
    759     return (TRUE);
    760 BAILOUT:
    761     if (pFont->info.isStringProp) {
    762 	xfree(pFont->info.isStringProp);
    763 	pFont->info.isStringProp = NULL;
    764     }
    765     if (pFont->info.props) {
    766 	xfree(pFont->info.props);
    767 	pFont->info.props = NULL;
    768     }
    769     while (line && bdfIsPrefix(line, "ENDPROPERTIES"))
    770 	line = bdfGetLine(file, lineBuf, BDFLINELEN);
    771     return (FALSE);
    772 }
    773 
    774 /***====================================================================***/
    775 
    776 static void
    777 bdfUnloadFont(FontPtr pFont)
    778 {
    779     bdfFreeFontBits (pFont);
    780     DestroyFontRec(pFont);
    781 }
    782 
    783 int
    784 bdfReadFont(FontPtr pFont, FontFilePtr file, 
    785 	    int bit, int byte, int glyph, int scan)
    786 {
    787     bdfFileState state;
    788     xCharInfo  *min,
    789                *max;
    790     BitmapFontPtr  bitmapFont;
    791 
    792     pFont->fontPrivate = 0;
    793 
    794     bzero(&state, sizeof(bdfFileState));
    795     bdfFileLineNum = 0;
    796 
    797     if (!bdfReadHeader(file, &state))
    798 	goto BAILOUT;
    799 
    800     bitmapFont = (BitmapFontPtr) xalloc(sizeof(BitmapFontRec));
    801     if (!bitmapFont) {
    802       bdfError("Couldn't allocate bitmapFontRec (%d)\n", sizeof(BitmapFontRec));
    803 	goto BAILOUT;
    804     }
    805     bzero((char *)bitmapFont, sizeof(BitmapFontRec));
    806 
    807     pFont->fontPrivate = (pointer) bitmapFont;
    808     bitmapFont->metrics = 0;
    809     bitmapFont->ink_metrics = 0;
    810     bitmapFont->bitmaps = 0;
    811     bitmapFont->encoding = 0;
    812     bitmapFont->pDefault = NULL;
    813 
    814     bitmapFont->bitmapExtra = (BitmapExtraPtr) xalloc(sizeof(BitmapExtraRec));
    815     if (!bitmapFont->bitmapExtra) {
    816       bdfError("Couldn't allocate bitmapExtra (%d)\n", sizeof(BitmapExtraRec));
    817         goto BAILOUT;
    818     }
    819     bzero((char *)bitmapFont->bitmapExtra, sizeof(BitmapExtraRec));
    820     
    821     bitmapFont->bitmapExtra->glyphNames = 0;
    822     bitmapFont->bitmapExtra->sWidths = 0;
    823 
    824     if (!bdfReadProperties(file, pFont, &state))
    825 	goto BAILOUT;
    826 
    827     if (!bdfReadCharacters(file, pFont, &state, bit, byte, glyph, scan))
    828 	goto BAILOUT;
    829 
    830     if (state.haveDefaultCh) {
    831 	unsigned int r, c, cols;
    832 
    833 	r = pFont->info.defaultCh >> 8;
    834 	c = pFont->info.defaultCh & 0xFF;
    835 	if (pFont->info.firstRow <= r && r <= pFont->info.lastRow &&
    836 		pFont->info.firstCol <= c && c <= pFont->info.lastCol) {
    837 	    cols = pFont->info.lastCol - pFont->info.firstCol + 1;
    838 	    r = r - pFont->info.firstRow;
    839 	    c = c - pFont->info.firstCol;
    840 	    bitmapFont->pDefault = ACCESSENCODING(bitmapFont->encoding, 
    841                                                  r * cols + c);
    842 	}
    843     }
    844     pFont->bit = bit;
    845     pFont->byte = byte;
    846     pFont->glyph = glyph;
    847     pFont->scan = scan;
    848     pFont->info.anamorphic = FALSE;
    849     pFont->info.cachable = TRUE;
    850     bitmapComputeFontBounds(pFont);
    851     if (FontCouldBeTerminal(&pFont->info)) {
    852 	bdfPadToTerminal(pFont);
    853 	bitmapComputeFontBounds(pFont);
    854     }
    855     FontComputeInfoAccelerators(&pFont->info);
    856     if (bitmapFont->bitmapExtra)
    857 	FontComputeInfoAccelerators(&bitmapFont->bitmapExtra->info);
    858     if (pFont->info.constantMetrics) {
    859       if (!bitmapAddInkMetrics(pFont)) {
    860         bdfError("Failed to add bitmap ink metrics\n");
    861         goto BAILOUT;
    862       }
    863     }    
    864     if (bitmapFont->bitmapExtra)
    865 	bitmapFont->bitmapExtra->info.inkMetrics = pFont->info.inkMetrics;
    866 
    867     bitmapComputeFontInkBounds(pFont);
    868 /*    ComputeFontAccelerators (pFont); */
    869 
    870     /* generate properties */
    871     min = &pFont->info.ink_minbounds;
    872     max = &pFont->info.ink_maxbounds;
    873     if (state.xHeightProp && (state.xHeightProp->value == -1))
    874 	state.xHeightProp->value = state.exHeight ?
    875 	    state.exHeight : min->ascent;
    876 
    877     if (state.quadWidthProp && (state.quadWidthProp->value == -1))
    878 	state.quadWidthProp->value = state.digitCount ?
    879 	    (INT32) (state.digitWidths / state.digitCount) :
    880 	    (min->characterWidth + max->characterWidth) / 2;
    881 
    882     if (state.weightProp && (state.weightProp->value == -1))
    883 	state.weightProp->value = bitmapComputeWeight(pFont);
    884 
    885     pFont->get_glyphs = bitmapGetGlyphs;
    886     pFont->get_metrics = bitmapGetMetrics;
    887     pFont->unload_font = bdfUnloadFont;
    888     pFont->unload_glyphs = NULL;
    889     return Successful;
    890 BAILOUT:
    891     if (pFont->fontPrivate)
    892 	bdfFreeFontBits (pFont);
    893     return AllocError;
    894 }
    895 
    896 int
    897 bdfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file)
    898 {
    899     FontRec     font;
    900     int         ret;
    901 
    902     bzero(&font, sizeof (FontRec));
    903 
    904     ret = bdfReadFont(&font, file, MSBFirst, LSBFirst, 1, 1);
    905     if (ret == Successful) {
    906 	*pFontInfo = font.info;
    907 	font.info.props = 0;
    908 	font.info.isStringProp = 0;
    909 	font.info.nprops = 0;
    910 	bdfFreeFontBits (&font);
    911     }
    912     return ret;
    913 }
    914 
    915 static Bool
    916 bdfPadToTerminal(FontPtr pFont)
    917 {
    918     BitmapFontPtr  bitmapFont;
    919     BitmapExtraPtr bitmapExtra;
    920     int         i;
    921     int         new_size;
    922     CharInfoRec new;
    923     int         w,
    924                 h;
    925 
    926     bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
    927 
    928     bzero(&new, sizeof(CharInfoRec)); 
    929     new.metrics.ascent = pFont->info.fontAscent;
    930     new.metrics.descent = pFont->info.fontDescent;
    931     new.metrics.leftSideBearing = 0;
    932     new.metrics.rightSideBearing = pFont->info.minbounds.characterWidth;
    933     new.metrics.characterWidth = new.metrics.rightSideBearing;
    934     new_size = BYTES_FOR_GLYPH(&new, pFont->glyph);
    935 
    936     for (i = 0; i < bitmapFont->num_chars; i++) {
    937 	new.bits = (char *) xalloc(new_size);
    938 	if (!new.bits) {
    939           bdfError("Couldn't allocate bits (%d)\n", new_size);
    940 	    return FALSE;
    941       }
    942 	FontCharReshape(pFont, &bitmapFont->metrics[i], &new);
    943         new.metrics.attributes = bitmapFont->metrics[i].metrics.attributes;
    944 	xfree(bitmapFont->metrics[i].bits);
    945 	bitmapFont->metrics[i] = new;
    946     }
    947     bitmapExtra = bitmapFont->bitmapExtra;
    948     if (bitmapExtra) {
    949 	w = GLYPHWIDTHPIXELS(&new);
    950 	h = GLYPHHEIGHTPIXELS(&new);
    951 	for (i = 0; i < GLYPHPADOPTIONS; i++)
    952 	    bitmapExtra->bitmapsSizes[i] = bitmapFont->num_chars *
    953 		(BYTES_PER_ROW(w, 1 << i) * h);
    954     }
    955     return TRUE;
    956 }