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