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