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