pcfread.c revision fd60135f
1a96d7823Smrg/*
2a96d7823Smrg
3a96d7823SmrgCopyright 1990, 1998  The Open Group
4a96d7823Smrg
5a96d7823SmrgPermission to use, copy, modify, distribute, and sell this software and its
6a96d7823Smrgdocumentation for any purpose is hereby granted without fee, provided that
7a96d7823Smrgthe above copyright notice appear in all copies and that both that
8a96d7823Smrgcopyright notice and this permission notice appear in supporting
9a96d7823Smrgdocumentation.
10a96d7823Smrg
11a96d7823SmrgThe above copyright notice and this permission notice shall be included
12a96d7823Smrgin all copies or substantial portions of the Software.
13a96d7823Smrg
14a96d7823SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15a96d7823SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16a96d7823SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17a96d7823SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18a96d7823SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19a96d7823SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20a96d7823SmrgOTHER DEALINGS IN THE SOFTWARE.
21a96d7823Smrg
22a96d7823SmrgExcept as contained in this notice, the name of The Open Group shall
23a96d7823Smrgnot be used in advertising or otherwise to promote the sale, use or
24a96d7823Smrgother dealings in this Software without prior written authorization
25a96d7823Smrgfrom The Open Group.
26a96d7823Smrg
27a96d7823Smrg*/
28a96d7823Smrg
29a96d7823Smrg/*
30a96d7823Smrg * Author:  Keith Packard, MIT X Consortium
31a96d7823Smrg */
32a96d7823Smrg
33a96d7823Smrg#ifdef HAVE_CONFIG_H
34a96d7823Smrg#include <config.h>
35a96d7823Smrg#endif
36a96d7823Smrg#include "libxfontint.h"
37a96d7823Smrg
38a96d7823Smrg#include <X11/fonts/fntfilst.h>
39a96d7823Smrg#include <X11/fonts/bitmap.h>
40a96d7823Smrg#include <X11/fonts/pcf.h>
41a96d7823Smrg
42a96d7823Smrg#ifndef MAX
43a96d7823Smrg#define   MAX(a,b)    (((a)>(b)) ? a : b)
44a96d7823Smrg#endif
45a96d7823Smrg
46a96d7823Smrg#include <stdarg.h>
47a96d7823Smrg#include <stdint.h>
48fd60135fSmrg#include <string.h>
49a96d7823Smrg
50a96d7823Smrgvoid
51a96d7823SmrgpcfError(const char* message, ...)
52a96d7823Smrg{
53a96d7823Smrg    va_list args;
54a96d7823Smrg
55a96d7823Smrg    va_start(args, message);
56a96d7823Smrg
57a96d7823Smrg    fprintf(stderr, "PCF Error: ");
58a96d7823Smrg    vfprintf(stderr, message, args);
59a96d7823Smrg    va_end(args);
60a96d7823Smrg}
61a96d7823Smrg
62a96d7823Smrg/* Read PCF font files */
63a96d7823Smrg
64a96d7823Smrgstatic void pcfUnloadFont ( FontPtr pFont );
65a96d7823Smrgstatic int  position;
66a96d7823Smrg
67a96d7823Smrg
68a96d7823Smrg#define IS_EOF(file) ((file)->eof == BUFFILEEOF)
69a96d7823Smrg
70a96d7823Smrg#define FONT_FILE_GETC_ERR(f)  (tmp = FontFileGetc(f), BAIL_ON_EOF)
71a96d7823Smrg
72a96d7823Smrgstatic int
73a96d7823SmrgpcfGetLSB32(FontFilePtr file)
74a96d7823Smrg{
75a96d7823Smrg    int         c;
76a96d7823Smrg
77a96d7823Smrg    c = FontFileGetc(file);
78a96d7823Smrg    c |= FontFileGetc(file) << 8;
79a96d7823Smrg    c |= FontFileGetc(file) << 16;
80a96d7823Smrg    c |= FontFileGetc(file) << 24;
81a96d7823Smrg    position += 4;
82a96d7823Smrg    return c;
83a96d7823Smrg}
84a96d7823Smrg
85a96d7823Smrgstatic int
86a96d7823SmrgpcfGetINT32(FontFilePtr file, CARD32 format)
87a96d7823Smrg{
88a96d7823Smrg    int         c;
89a96d7823Smrg
90a96d7823Smrg    if (PCF_BYTE_ORDER(format) == MSBFirst) {
91a96d7823Smrg	c = FontFileGetc(file) << 24;
92a96d7823Smrg	c |= FontFileGetc(file) << 16;
93a96d7823Smrg	c |= FontFileGetc(file) << 8;
94a96d7823Smrg	c |= FontFileGetc(file);
95a96d7823Smrg    } else {
96a96d7823Smrg	c = FontFileGetc(file);
97a96d7823Smrg	c |= FontFileGetc(file) << 8;
98a96d7823Smrg	c |= FontFileGetc(file) << 16;
99a96d7823Smrg	c |= FontFileGetc(file) << 24;
100a96d7823Smrg    }
101a96d7823Smrg    position += 4;
102a96d7823Smrg    return c;
103a96d7823Smrg}
104a96d7823Smrg
105a96d7823Smrgstatic int
106a96d7823SmrgpcfGetINT16(FontFilePtr file, CARD32 format)
107a96d7823Smrg{
108a96d7823Smrg    int         c;
109a96d7823Smrg
110a96d7823Smrg    if (PCF_BYTE_ORDER(format) == MSBFirst) {
111a96d7823Smrg	c = FontFileGetc(file) << 8;
112a96d7823Smrg	c |= FontFileGetc(file);
113a96d7823Smrg    } else {
114a96d7823Smrg	c = FontFileGetc(file);
115a96d7823Smrg	c |= FontFileGetc(file) << 8;
116a96d7823Smrg    }
117a96d7823Smrg    position += 2;
118a96d7823Smrg    return c;
119a96d7823Smrg}
120a96d7823Smrg
121a96d7823Smrg#define pcfGetINT8(file, format) (position++, FontFileGetc(file))
122a96d7823Smrg
123a96d7823Smrgstatic      PCFTablePtr
124a96d7823SmrgpcfReadTOC(FontFilePtr file, int *countp)
125a96d7823Smrg{
126a96d7823Smrg    CARD32      version;
127a96d7823Smrg    PCFTablePtr tables;
128a96d7823Smrg    int         count;
129a96d7823Smrg    int         i;
130a96d7823Smrg
131a96d7823Smrg    position = 0;
132a96d7823Smrg    version = pcfGetLSB32(file);
133a96d7823Smrg    if (version != PCF_FILE_VERSION)
134a96d7823Smrg	return (PCFTablePtr) NULL;
135a96d7823Smrg    count = pcfGetLSB32(file);
136a96d7823Smrg    if (IS_EOF(file)) return (PCFTablePtr) NULL;
137a96d7823Smrg    if (count < 0 || count > INT32_MAX / sizeof(PCFTableRec)) {
138a96d7823Smrg	pcfError("pcfReadTOC(): invalid file format\n");
139a96d7823Smrg	return NULL;
140a96d7823Smrg    }
141a96d7823Smrg    tables = malloc(count * sizeof(PCFTableRec));
142a96d7823Smrg    if (!tables) {
143a96d7823Smrg	pcfError("pcfReadTOC(): Couldn't allocate tables (%d*%d)\n",
144a96d7823Smrg		 count, (int) sizeof(PCFTableRec));
145a96d7823Smrg	return (PCFTablePtr) NULL;
146a96d7823Smrg    }
147a96d7823Smrg    for (i = 0; i < count; i++) {
148a96d7823Smrg	tables[i].type = pcfGetLSB32(file);
149a96d7823Smrg	tables[i].format = pcfGetLSB32(file);
150a96d7823Smrg	tables[i].size = pcfGetLSB32(file);
151a96d7823Smrg	tables[i].offset = pcfGetLSB32(file);
152a96d7823Smrg	if (IS_EOF(file)) goto Bail;
153a96d7823Smrg    }
154a96d7823Smrg
155a96d7823Smrg    *countp = count;
156a96d7823Smrg    return tables;
157a96d7823Smrg
158a96d7823Smrg Bail:
159a96d7823Smrg    free(tables);
160a96d7823Smrg    return (PCFTablePtr) NULL;
161a96d7823Smrg}
162a96d7823Smrg
163a96d7823Smrg/*
164a96d7823Smrg * PCF supports two formats for metrics, both the regular
165a96d7823Smrg * jumbo size, and 'lite' metrics, which are useful
166a96d7823Smrg * for most fonts which have even vaguely reasonable
167a96d7823Smrg * metrics
168a96d7823Smrg */
169a96d7823Smrg
170a96d7823Smrgstatic Bool
171a96d7823SmrgpcfGetMetric(FontFilePtr file, CARD32 format, xCharInfo *metric)
172a96d7823Smrg{
173a96d7823Smrg    metric->leftSideBearing = pcfGetINT16(file, format);
174a96d7823Smrg    metric->rightSideBearing = pcfGetINT16(file, format);
175a96d7823Smrg    metric->characterWidth = pcfGetINT16(file, format);
176a96d7823Smrg    metric->ascent = pcfGetINT16(file, format);
177a96d7823Smrg    metric->descent = pcfGetINT16(file, format);
178a96d7823Smrg    metric->attributes = pcfGetINT16(file, format);
179a96d7823Smrg    if (IS_EOF(file)) return FALSE;
180a96d7823Smrg
181a96d7823Smrg    return TRUE;
182a96d7823Smrg}
183a96d7823Smrg
184a96d7823Smrgstatic Bool
185a96d7823SmrgpcfGetCompressedMetric(FontFilePtr file, CARD32 format, xCharInfo *metric)
186a96d7823Smrg{
187a96d7823Smrg    metric->leftSideBearing = pcfGetINT8(file, format) - 0x80;
188a96d7823Smrg    metric->rightSideBearing = pcfGetINT8(file, format) - 0x80;
189a96d7823Smrg    metric->characterWidth = pcfGetINT8(file, format) - 0x80;
190a96d7823Smrg    metric->ascent = pcfGetINT8(file, format) - 0x80;
191a96d7823Smrg    metric->descent = pcfGetINT8(file, format) - 0x80;
192a96d7823Smrg    metric->attributes = 0;
193a96d7823Smrg    if (IS_EOF(file)) return FALSE;
194a96d7823Smrg
195a96d7823Smrg    return TRUE;
196a96d7823Smrg}
197a96d7823Smrg
198a96d7823Smrg/*
199a96d7823Smrg * Position the file to the begining of the specified table
200a96d7823Smrg * in the font file
201a96d7823Smrg */
202a96d7823Smrgstatic Bool
203a96d7823SmrgpcfSeekToType(FontFilePtr file, PCFTablePtr tables, int ntables,
204a96d7823Smrg	      CARD32 type, CARD32 *formatp, CARD32 *sizep)
205a96d7823Smrg{
206a96d7823Smrg    int         i;
207a96d7823Smrg
208a96d7823Smrg    for (i = 0; i < ntables; i++)
209a96d7823Smrg	if (tables[i].type == type) {
210a96d7823Smrg	    if (position > tables[i].offset)
211a96d7823Smrg		return FALSE;
212a96d7823Smrg	    if (!FontFileSkip(file, tables[i].offset - position))
213a96d7823Smrg		return FALSE;
214a96d7823Smrg	    position = tables[i].offset;
215a96d7823Smrg	    *sizep = tables[i].size;
216a96d7823Smrg	    *formatp = tables[i].format;
217a96d7823Smrg	    return TRUE;
218a96d7823Smrg	}
219a96d7823Smrg    return FALSE;
220a96d7823Smrg}
221a96d7823Smrg
222a96d7823Smrgstatic Bool
223a96d7823SmrgpcfHasType (PCFTablePtr tables, int ntables, CARD32 type)
224a96d7823Smrg{
225a96d7823Smrg    int         i;
226a96d7823Smrg
227a96d7823Smrg    for (i = 0; i < ntables; i++)
228a96d7823Smrg	if (tables[i].type == type)
229a96d7823Smrg	    return TRUE;
230a96d7823Smrg    return FALSE;
231a96d7823Smrg}
232a96d7823Smrg
233a96d7823Smrg/*
234a96d7823Smrg * pcfGetProperties
235a96d7823Smrg *
236a96d7823Smrg * Reads the font properties from the font file, filling in the FontInfo rec
237a96d7823Smrg * supplied.  Used by by both ReadFont and ReadFontInfo routines.
238a96d7823Smrg */
239a96d7823Smrg
240a96d7823Smrgstatic Bool
241a96d7823SmrgpcfGetProperties(FontInfoPtr pFontInfo, FontFilePtr file,
242a96d7823Smrg		 PCFTablePtr tables, int ntables)
243a96d7823Smrg{
244a96d7823Smrg    FontPropPtr props = 0;
245a96d7823Smrg    int         nprops;
246a96d7823Smrg    char       *isStringProp = 0;
247a96d7823Smrg    CARD32      format;
248a96d7823Smrg    int         i;
249a96d7823Smrg    CARD32      size;
250a96d7823Smrg    int         string_size;
251a96d7823Smrg    char       *strings;
252a96d7823Smrg
253a96d7823Smrg    /* font properties */
254a96d7823Smrg
255a96d7823Smrg    if (!pcfSeekToType(file, tables, ntables, PCF_PROPERTIES, &format, &size))
256a96d7823Smrg	goto Bail;
257a96d7823Smrg    format = pcfGetLSB32(file);
258a96d7823Smrg    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
259a96d7823Smrg	goto Bail;
260a96d7823Smrg    nprops = pcfGetINT32(file, format);
261a96d7823Smrg    if (nprops <= 0 || nprops > INT32_MAX / sizeof(FontPropRec)) {
262a96d7823Smrg	pcfError("pcfGetProperties(): invalid nprops value (%d)\n", nprops);
263a96d7823Smrg	goto Bail;
264a96d7823Smrg    }
265a96d7823Smrg    if (IS_EOF(file)) goto Bail;
266a96d7823Smrg    props = malloc(nprops * sizeof(FontPropRec));
267a96d7823Smrg    if (!props) {
268a96d7823Smrg	pcfError("pcfGetProperties(): Couldn't allocate props (%d*%d)\n",
269a96d7823Smrg	       nprops, (int) sizeof(FontPropRec));
270a96d7823Smrg	goto Bail;
271a96d7823Smrg    }
272a96d7823Smrg    isStringProp = malloc(nprops * sizeof(char));
273a96d7823Smrg    if (!isStringProp) {
274a96d7823Smrg	pcfError("pcfGetProperties(): Couldn't allocate isStringProp (%d*%d)\n",
275a96d7823Smrg	       nprops, (int) sizeof(char));
276a96d7823Smrg	goto Bail;
277a96d7823Smrg    }
278a96d7823Smrg    for (i = 0; i < nprops; i++) {
279a96d7823Smrg	props[i].name = pcfGetINT32(file, format);
280a96d7823Smrg	isStringProp[i] = pcfGetINT8(file, format);
281a96d7823Smrg	props[i].value = pcfGetINT32(file, format);
282a96d7823Smrg	if (props[i].name < 0
283a96d7823Smrg	    || (isStringProp[i] != 0 && isStringProp[i] != 1)
284a96d7823Smrg	    || (isStringProp[i] && props[i].value < 0)) {
285a96d7823Smrg	    pcfError("pcfGetProperties(): invalid file format %ld %d %ld\n",
286a96d7823Smrg		     props[i].name, isStringProp[i], props[i].value);
287a96d7823Smrg	    goto Bail;
288a96d7823Smrg	}
289a96d7823Smrg	if (IS_EOF(file)) goto Bail;
290a96d7823Smrg    }
291a96d7823Smrg    /* pad the property array */
292a96d7823Smrg    /*
293a96d7823Smrg     * clever here - nprops is the same as the number of odd-units read, as
294a96d7823Smrg     * only isStringProp are odd length
295a96d7823Smrg     */
296a96d7823Smrg    if (nprops & 3)
297a96d7823Smrg    {
298a96d7823Smrg	i = 4 - (nprops & 3);
299a96d7823Smrg	(void)FontFileSkip(file, i);
300a96d7823Smrg	position += i;
301a96d7823Smrg    }
302a96d7823Smrg    if (IS_EOF(file)) goto Bail;
303a96d7823Smrg    string_size = pcfGetINT32(file, format);
304a96d7823Smrg    if (string_size < 0) goto Bail;
305a96d7823Smrg    if (IS_EOF(file)) goto Bail;
306a96d7823Smrg    strings = malloc(string_size);
307a96d7823Smrg    if (!strings) {
308a96d7823Smrg      pcfError("pcfGetProperties(): Couldn't allocate strings (%d)\n", string_size);
309a96d7823Smrg	goto Bail;
310a96d7823Smrg    }
311a96d7823Smrg    FontFileRead(file, strings, string_size);
312a96d7823Smrg    if (IS_EOF(file)) goto Bail;
313a96d7823Smrg    position += string_size;
314a96d7823Smrg    for (i = 0; i < nprops; i++) {
315fd60135fSmrg	if (props[i].name >= string_size) {
316fd60135fSmrg	    pcfError("pcfGetProperties(): String starts out of bounds (%ld/%d)\n", props[i].name, string_size);
317fd60135fSmrg	    goto Bail;
318fd60135fSmrg	}
319a96d7823Smrg	props[i].name = MakeAtom(strings + props[i].name,
320fd60135fSmrg				 strnlen(strings + props[i].name, string_size - props[i].name), TRUE);
321a96d7823Smrg	if (isStringProp[i]) {
322fd60135fSmrg	    if (props[i].value >= string_size) {
323fd60135fSmrg		pcfError("pcfGetProperties(): String starts out of bounds (%ld/%d)\n", props[i].value, string_size);
324fd60135fSmrg		goto Bail;
325fd60135fSmrg	    }
326a96d7823Smrg	    props[i].value = MakeAtom(strings + props[i].value,
327fd60135fSmrg				      strnlen(strings + props[i].value, string_size - props[i].value), TRUE);
328a96d7823Smrg	}
329a96d7823Smrg    }
330a96d7823Smrg    free(strings);
331a96d7823Smrg    pFontInfo->isStringProp = isStringProp;
332a96d7823Smrg    pFontInfo->props = props;
333a96d7823Smrg    pFontInfo->nprops = nprops;
334a96d7823Smrg    return TRUE;
335a96d7823SmrgBail:
336a96d7823Smrg    free(isStringProp);
337a96d7823Smrg    free(props);
338a96d7823Smrg    return FALSE;
339a96d7823Smrg}
340a96d7823Smrg
341a96d7823Smrg
342a96d7823Smrg/*
343a96d7823Smrg * pcfReadAccel
344a96d7823Smrg *
345a96d7823Smrg * Fill in the accelerator information from the font file; used
346a96d7823Smrg * to read both BDF_ACCELERATORS and old style ACCELERATORS
347a96d7823Smrg */
348a96d7823Smrg
349a96d7823Smrgstatic Bool
350a96d7823SmrgpcfGetAccel(FontInfoPtr pFontInfo, FontFilePtr file,
351a96d7823Smrg	    PCFTablePtr tables, int ntables, CARD32 type)
352a96d7823Smrg{
353a96d7823Smrg    CARD32      format;
354a96d7823Smrg    CARD32	size;
355a96d7823Smrg
356a96d7823Smrg    if (!pcfSeekToType(file, tables, ntables, type, &format, &size) ||
357a96d7823Smrg	IS_EOF(file))
358a96d7823Smrg	goto Bail;
359a96d7823Smrg    format = pcfGetLSB32(file);
360a96d7823Smrg    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) &&
361a96d7823Smrg	!PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS))
362a96d7823Smrg    {
363a96d7823Smrg	goto Bail;
364a96d7823Smrg    }
365a96d7823Smrg    pFontInfo->noOverlap = pcfGetINT8(file, format);
366a96d7823Smrg    pFontInfo->constantMetrics = pcfGetINT8(file, format);
367a96d7823Smrg    pFontInfo->terminalFont = pcfGetINT8(file, format);
368a96d7823Smrg    pFontInfo->constantWidth = pcfGetINT8(file, format);
369a96d7823Smrg    pFontInfo->inkInside = pcfGetINT8(file, format);
370a96d7823Smrg    pFontInfo->inkMetrics = pcfGetINT8(file, format);
371a96d7823Smrg    pFontInfo->drawDirection = pcfGetINT8(file, format);
372a96d7823Smrg    pFontInfo->anamorphic = FALSE;
373a96d7823Smrg    pFontInfo->cachable = TRUE;
374a96d7823Smrg     /* natural alignment */ pcfGetINT8(file, format);
375a96d7823Smrg    pFontInfo->fontAscent = pcfGetINT32(file, format);
376a96d7823Smrg    pFontInfo->fontDescent = pcfGetINT32(file, format);
377a96d7823Smrg    pFontInfo->maxOverlap = pcfGetINT32(file, format);
378a96d7823Smrg    if (IS_EOF(file)) goto Bail;
379a96d7823Smrg    if (!pcfGetMetric(file, format, &pFontInfo->minbounds))
380a96d7823Smrg	goto Bail;
381a96d7823Smrg    if (!pcfGetMetric(file, format, &pFontInfo->maxbounds))
382a96d7823Smrg	goto Bail;
383a96d7823Smrg    if (PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) {
384a96d7823Smrg	if (!pcfGetMetric(file, format, &pFontInfo->ink_minbounds))
385a96d7823Smrg	    goto Bail;
386a96d7823Smrg	if (!pcfGetMetric(file, format, &pFontInfo->ink_maxbounds))
387a96d7823Smrg	    goto Bail;
388a96d7823Smrg    } else {
389a96d7823Smrg	pFontInfo->ink_minbounds = pFontInfo->minbounds;
390a96d7823Smrg	pFontInfo->ink_maxbounds = pFontInfo->maxbounds;
391a96d7823Smrg    }
392a96d7823Smrg    return TRUE;
393a96d7823SmrgBail:
394a96d7823Smrg    return FALSE;
395a96d7823Smrg}
396a96d7823Smrg
397a96d7823Smrgint
398a96d7823SmrgpcfReadFont(FontPtr pFont, FontFilePtr file,
399a96d7823Smrg	    int bit, int byte, int glyph, int scan)
400a96d7823Smrg{
401a96d7823Smrg    CARD32      format;
402a96d7823Smrg    CARD32      size;
403a96d7823Smrg    BitmapFontPtr  bitmapFont = 0;
404a96d7823Smrg    int         i;
405a96d7823Smrg    PCFTablePtr tables = 0;
406a96d7823Smrg    int         ntables;
407a96d7823Smrg    int         nmetrics;
408a96d7823Smrg    int         nbitmaps;
409a96d7823Smrg    int         sizebitmaps;
410a96d7823Smrg    int         nink_metrics;
411a96d7823Smrg    CharInfoPtr metrics = 0;
412a96d7823Smrg    xCharInfo  *ink_metrics = 0;
413a96d7823Smrg    char       *bitmaps = 0;
414a96d7823Smrg    CharInfoPtr **encoding = 0;
415a96d7823Smrg    int         nencoding = 0;
416a96d7823Smrg    int         encodingOffset;
417a96d7823Smrg    CARD32      bitmapSizes[GLYPHPADOPTIONS];
418a96d7823Smrg    CARD32     *offsets = 0;
419a96d7823Smrg    Bool	hasBDFAccelerators;
420a96d7823Smrg
421a96d7823Smrg    pFont->info.nprops = 0;
422a96d7823Smrg    pFont->info.props = 0;
423a96d7823Smrg    pFont->info.isStringProp=0;
424a96d7823Smrg
425a96d7823Smrg    if (!(tables = pcfReadTOC(file, &ntables)))
426a96d7823Smrg	goto Bail;
427a96d7823Smrg
428a96d7823Smrg    /* properties */
429a96d7823Smrg
430a96d7823Smrg    if (!pcfGetProperties(&pFont->info, file, tables, ntables))
431a96d7823Smrg	goto Bail;
432a96d7823Smrg
433a96d7823Smrg    /* Use the old accelerators if no BDF accelerators are in the file */
434a96d7823Smrg
435a96d7823Smrg    hasBDFAccelerators = pcfHasType (tables, ntables, PCF_BDF_ACCELERATORS);
436a96d7823Smrg    if (!hasBDFAccelerators)
437a96d7823Smrg	if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_ACCELERATORS))
438a96d7823Smrg	    goto Bail;
439a96d7823Smrg
440a96d7823Smrg    /* metrics */
441a96d7823Smrg
442a96d7823Smrg    if (!pcfSeekToType(file, tables, ntables, PCF_METRICS, &format, &size)) {
443a96d7823Smrg	goto Bail;
444a96d7823Smrg    }
445a96d7823Smrg    format = pcfGetLSB32(file);
446a96d7823Smrg    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) &&
447a96d7823Smrg	    !PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) {
448a96d7823Smrg	goto Bail;
449a96d7823Smrg    }
450a96d7823Smrg    if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
451a96d7823Smrg	nmetrics = pcfGetINT32(file, format);
452a96d7823Smrg    else
453a96d7823Smrg	nmetrics = pcfGetINT16(file, format);
454a96d7823Smrg    if (IS_EOF(file)) goto Bail;
455a96d7823Smrg    if (nmetrics < 0 || nmetrics > INT32_MAX / sizeof(CharInfoRec)) {
456a96d7823Smrg	pcfError("pcfReadFont(): invalid file format\n");
457a96d7823Smrg	goto Bail;
458a96d7823Smrg    }
459a96d7823Smrg    metrics = malloc(nmetrics * sizeof(CharInfoRec));
460a96d7823Smrg    if (!metrics) {
461a96d7823Smrg	pcfError("pcfReadFont(): Couldn't allocate metrics (%d*%d)\n",
462a96d7823Smrg		 nmetrics, (int) sizeof(CharInfoRec));
463a96d7823Smrg	goto Bail;
464a96d7823Smrg    }
465a96d7823Smrg    for (i = 0; i < nmetrics; i++)
466a96d7823Smrg	if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) {
467a96d7823Smrg	    if (!pcfGetMetric(file, format, &(metrics + i)->metrics))
468a96d7823Smrg		goto Bail;
469a96d7823Smrg	} else {
470a96d7823Smrg	    if (!pcfGetCompressedMetric(file, format, &(metrics + i)->metrics))
471a96d7823Smrg		goto Bail;
472a96d7823Smrg	}
473a96d7823Smrg
474a96d7823Smrg    /* bitmaps */
475a96d7823Smrg
476a96d7823Smrg    if (!pcfSeekToType(file, tables, ntables, PCF_BITMAPS, &format, &size))
477a96d7823Smrg	goto Bail;
478a96d7823Smrg    format = pcfGetLSB32(file);
479a96d7823Smrg    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
480a96d7823Smrg	goto Bail;
481a96d7823Smrg
482a96d7823Smrg    nbitmaps = pcfGetINT32(file, format);
483a96d7823Smrg    if (nbitmaps != nmetrics || IS_EOF(file))
484a96d7823Smrg	goto Bail;
485a96d7823Smrg    /* nmetrics is already ok, so nbitmap also is */
486a96d7823Smrg    offsets = malloc(nbitmaps * sizeof(CARD32));
487a96d7823Smrg    if (!offsets) {
488a96d7823Smrg	pcfError("pcfReadFont(): Couldn't allocate offsets (%d*%d)\n",
489a96d7823Smrg		 nbitmaps, (int) sizeof(CARD32));
490a96d7823Smrg	goto Bail;
491a96d7823Smrg    }
492a96d7823Smrg    for (i = 0; i < nbitmaps; i++) {
493a96d7823Smrg	offsets[i] = pcfGetINT32(file, format);
494a96d7823Smrg	if (IS_EOF(file)) goto Bail;
495a96d7823Smrg    }
496a96d7823Smrg
497a96d7823Smrg    for (i = 0; i < GLYPHPADOPTIONS; i++) {
498a96d7823Smrg	bitmapSizes[i] = pcfGetINT32(file, format);
499a96d7823Smrg	if (IS_EOF(file)) goto Bail;
500a96d7823Smrg    }
501a96d7823Smrg
502a96d7823Smrg    sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX(format)];
503a96d7823Smrg    /* guard against completely empty font */
504a96d7823Smrg    bitmaps = malloc(sizebitmaps ? sizebitmaps : 1);
505a96d7823Smrg    if (!bitmaps) {
506a96d7823Smrg      pcfError("pcfReadFont(): Couldn't allocate bitmaps (%d)\n", sizebitmaps ? sizebitmaps : 1);
507a96d7823Smrg	goto Bail;
508a96d7823Smrg    }
509a96d7823Smrg    FontFileRead(file, bitmaps, sizebitmaps);
510a96d7823Smrg    if (IS_EOF(file)) goto Bail;
511a96d7823Smrg    position += sizebitmaps;
512a96d7823Smrg
513a96d7823Smrg    if (PCF_BIT_ORDER(format) != bit)
514a96d7823Smrg	BitOrderInvert((unsigned char *)bitmaps, sizebitmaps);
515a96d7823Smrg    if ((PCF_BYTE_ORDER(format) == PCF_BIT_ORDER(format)) != (bit == byte)) {
516a96d7823Smrg	switch (bit == byte ? PCF_SCAN_UNIT(format) : scan) {
517a96d7823Smrg	case 1:
518a96d7823Smrg	    break;
519a96d7823Smrg	case 2:
520a96d7823Smrg	    TwoByteSwap((unsigned char *)bitmaps, sizebitmaps);
521a96d7823Smrg	    break;
522a96d7823Smrg	case 4:
523a96d7823Smrg	    FourByteSwap((unsigned char *)bitmaps, sizebitmaps);
524a96d7823Smrg	    break;
525a96d7823Smrg	}
526a96d7823Smrg    }
527a96d7823Smrg    if (PCF_GLYPH_PAD(format) != glyph) {
528a96d7823Smrg	char       *padbitmaps;
529a96d7823Smrg	int         sizepadbitmaps;
530a96d7823Smrg	int         old,
531a96d7823Smrg	            new;
532a96d7823Smrg	xCharInfo  *metric;
533a96d7823Smrg
534a96d7823Smrg	sizepadbitmaps = bitmapSizes[PCF_SIZE_TO_INDEX(glyph)];
535a96d7823Smrg	padbitmaps = malloc(sizepadbitmaps);
536a96d7823Smrg	if (!padbitmaps) {
537a96d7823Smrg          pcfError("pcfReadFont(): Couldn't allocate padbitmaps (%d)\n", sizepadbitmaps);
538a96d7823Smrg	    goto Bail;
539a96d7823Smrg	}
540a96d7823Smrg	new = 0;
541a96d7823Smrg	for (i = 0; i < nbitmaps; i++) {
542a96d7823Smrg	    old = offsets[i];
543a96d7823Smrg	    metric = &metrics[i].metrics;
544a96d7823Smrg	    offsets[i] = new;
545a96d7823Smrg	    new += RepadBitmap(bitmaps + old, padbitmaps + new,
546a96d7823Smrg			       PCF_GLYPH_PAD(format), glyph,
547a96d7823Smrg			  metric->rightSideBearing - metric->leftSideBearing,
548a96d7823Smrg			       metric->ascent + metric->descent);
549a96d7823Smrg	}
550a96d7823Smrg	free(bitmaps);
551a96d7823Smrg	bitmaps = padbitmaps;
552a96d7823Smrg    }
553a96d7823Smrg    for (i = 0; i < nbitmaps; i++)
554a96d7823Smrg	metrics[i].bits = bitmaps + offsets[i];
555a96d7823Smrg
556a96d7823Smrg    free(offsets);
557a96d7823Smrg    offsets = NULL;
558a96d7823Smrg
559a96d7823Smrg    /* ink metrics ? */
560a96d7823Smrg
561a96d7823Smrg    ink_metrics = NULL;
562a96d7823Smrg    if (pcfSeekToType(file, tables, ntables, PCF_INK_METRICS, &format, &size)) {
563a96d7823Smrg	format = pcfGetLSB32(file);
564a96d7823Smrg	if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) &&
565a96d7823Smrg		!PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) {
566a96d7823Smrg	    goto Bail;
567a96d7823Smrg	}
568a96d7823Smrg	if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
569a96d7823Smrg	    nink_metrics = pcfGetINT32(file, format);
570a96d7823Smrg	else
571a96d7823Smrg	    nink_metrics = pcfGetINT16(file, format);
572a96d7823Smrg	if (IS_EOF(file)) goto Bail;
573a96d7823Smrg	if (nink_metrics != nmetrics)
574a96d7823Smrg	    goto Bail;
575a96d7823Smrg	/* nmetrics already checked */
576a96d7823Smrg	ink_metrics = malloc(nink_metrics * sizeof(xCharInfo));
577a96d7823Smrg	if (!ink_metrics) {
578a96d7823Smrg            pcfError("pcfReadFont(): Couldn't allocate ink_metrics (%d*%d)\n",
579a96d7823Smrg		     nink_metrics, (int) sizeof(xCharInfo));
580a96d7823Smrg	    goto Bail;
581a96d7823Smrg	}
582a96d7823Smrg	for (i = 0; i < nink_metrics; i++)
583a96d7823Smrg	    if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) {
584a96d7823Smrg		if (!pcfGetMetric(file, format, ink_metrics + i))
585a96d7823Smrg		    goto Bail;
586a96d7823Smrg	    } else {
587a96d7823Smrg		if (!pcfGetCompressedMetric(file, format, ink_metrics + i))
588a96d7823Smrg		    goto Bail;
589a96d7823Smrg	    }
590a96d7823Smrg    }
591a96d7823Smrg
592a96d7823Smrg    /* encoding */
593a96d7823Smrg
594a96d7823Smrg    if (!pcfSeekToType(file, tables, ntables, PCF_BDF_ENCODINGS, &format, &size))
595a96d7823Smrg	goto Bail;
596a96d7823Smrg    format = pcfGetLSB32(file);
597a96d7823Smrg    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
598a96d7823Smrg	goto Bail;
599a96d7823Smrg
600a96d7823Smrg    pFont->info.firstCol = pcfGetINT16(file, format);
601a96d7823Smrg    pFont->info.lastCol = pcfGetINT16(file, format);
602a96d7823Smrg    pFont->info.firstRow = pcfGetINT16(file, format);
603a96d7823Smrg    pFont->info.lastRow = pcfGetINT16(file, format);
604a96d7823Smrg    pFont->info.defaultCh = pcfGetINT16(file, format);
605a96d7823Smrg    if (IS_EOF(file)) goto Bail;
606a96d7823Smrg    if (pFont->info.firstCol > pFont->info.lastCol ||
607a96d7823Smrg       pFont->info.firstRow > pFont->info.lastRow ||
608a96d7823Smrg       pFont->info.lastCol-pFont->info.firstCol > 255) goto Bail;
609a96d7823Smrg
610a96d7823Smrg    nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) *
611a96d7823Smrg	(pFont->info.lastRow - pFont->info.firstRow + 1);
612a96d7823Smrg
613a96d7823Smrg    encoding = calloc(NUM_SEGMENTS(nencoding), sizeof(CharInfoPtr*));
614a96d7823Smrg    if (!encoding) {
615a96d7823Smrg	pcfError("pcfReadFont(): Couldn't allocate encoding (%d*%d)\n",
616a96d7823Smrg		 nencoding, (int) sizeof(CharInfoPtr));
617a96d7823Smrg	goto Bail;
618a96d7823Smrg    }
619a96d7823Smrg
620a96d7823Smrg    pFont->info.allExist = TRUE;
621a96d7823Smrg    for (i = 0; i < nencoding; i++) {
622a96d7823Smrg	encodingOffset = pcfGetINT16(file, format);
623a96d7823Smrg	if (IS_EOF(file)) goto Bail;
624a96d7823Smrg	if (encodingOffset == 0xFFFF) {
625a96d7823Smrg	    pFont->info.allExist = FALSE;
626a96d7823Smrg	} else {
627a96d7823Smrg            if(!encoding[SEGMENT_MAJOR(i)]) {
628a96d7823Smrg                encoding[SEGMENT_MAJOR(i)]=
629a96d7823Smrg                    calloc(BITMAP_FONT_SEGMENT_SIZE, sizeof(CharInfoPtr));
630a96d7823Smrg                if(!encoding[SEGMENT_MAJOR(i)])
631a96d7823Smrg                    goto Bail;
632a96d7823Smrg            }
633a96d7823Smrg	    ACCESSENCODINGL(encoding, i) = metrics + encodingOffset;
634a96d7823Smrg        }
635a96d7823Smrg    }
636a96d7823Smrg
637a96d7823Smrg    /* BDF style accelerators (i.e. bounds based on encoded glyphs) */
638a96d7823Smrg
639a96d7823Smrg    if (hasBDFAccelerators)
640a96d7823Smrg	if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_BDF_ACCELERATORS))
641a96d7823Smrg	    goto Bail;
642a96d7823Smrg
643a96d7823Smrg    bitmapFont = malloc(sizeof *bitmapFont);
644a96d7823Smrg    if (!bitmapFont) {
645a96d7823Smrg	pcfError("pcfReadFont(): Couldn't allocate bitmapFont (%d)\n",
646a96d7823Smrg		 (int) sizeof *bitmapFont);
647a96d7823Smrg	goto Bail;
648a96d7823Smrg    }
649a96d7823Smrg
650a96d7823Smrg    bitmapFont->version_num = PCF_FILE_VERSION;
651a96d7823Smrg    bitmapFont->num_chars = nmetrics;
652a96d7823Smrg    bitmapFont->num_tables = ntables;
653a96d7823Smrg    bitmapFont->metrics = metrics;
654a96d7823Smrg    bitmapFont->ink_metrics = ink_metrics;
655a96d7823Smrg    bitmapFont->bitmaps = bitmaps;
656a96d7823Smrg    bitmapFont->encoding = encoding;
657a96d7823Smrg    bitmapFont->pDefault = (CharInfoPtr) 0;
658a96d7823Smrg    if (pFont->info.defaultCh != (unsigned short) NO_SUCH_CHAR) {
659a96d7823Smrg	unsigned int r,
660a96d7823Smrg	            c,
661a96d7823Smrg	            cols;
662a96d7823Smrg
663a96d7823Smrg	r = pFont->info.defaultCh >> 8;
664a96d7823Smrg	c = pFont->info.defaultCh & 0xFF;
665a96d7823Smrg	if (pFont->info.firstRow <= r && r <= pFont->info.lastRow &&
666a96d7823Smrg		pFont->info.firstCol <= c && c <= pFont->info.lastCol) {
667a96d7823Smrg	    cols = pFont->info.lastCol - pFont->info.firstCol + 1;
668a96d7823Smrg	    r = r - pFont->info.firstRow;
669a96d7823Smrg	    c = c - pFont->info.firstCol;
670a96d7823Smrg	    bitmapFont->pDefault = ACCESSENCODING(encoding, r * cols + c);
671a96d7823Smrg	}
672a96d7823Smrg    }
673a96d7823Smrg    bitmapFont->bitmapExtra = (BitmapExtraPtr) 0;
674a96d7823Smrg    pFont->fontPrivate = (pointer) bitmapFont;
675a96d7823Smrg    pFont->get_glyphs = bitmapGetGlyphs;
676a96d7823Smrg    pFont->get_metrics = bitmapGetMetrics;
677a96d7823Smrg    pFont->unload_font = pcfUnloadFont;
678a96d7823Smrg    pFont->unload_glyphs = NULL;
679a96d7823Smrg    pFont->bit = bit;
680a96d7823Smrg    pFont->byte = byte;
681a96d7823Smrg    pFont->glyph = glyph;
682a96d7823Smrg    pFont->scan = scan;
683a96d7823Smrg    free(tables);
684a96d7823Smrg    return Successful;
685a96d7823SmrgBail:
686a96d7823Smrg    free(ink_metrics);
687a96d7823Smrg    if(encoding) {
688a96d7823Smrg        for(i=0; i<NUM_SEGMENTS(nencoding); i++)
689a96d7823Smrg            free(encoding[i]);
690a96d7823Smrg    }
691a96d7823Smrg    free(encoding);
692a96d7823Smrg    free(bitmaps);
693a96d7823Smrg    free(metrics);
694a96d7823Smrg    free(pFont->info.props);
695a96d7823Smrg    pFont->info.nprops = 0;
696a96d7823Smrg    pFont->info.props = 0;
697a96d7823Smrg    free (pFont->info.isStringProp);
698a96d7823Smrg    free(bitmapFont);
699a96d7823Smrg    free(tables);
700a96d7823Smrg    free(offsets);
701a96d7823Smrg    return AllocError;
702a96d7823Smrg}
703a96d7823Smrg
704a96d7823Smrgint
705a96d7823SmrgpcfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file)
706a96d7823Smrg{
707a96d7823Smrg    PCFTablePtr tables;
708a96d7823Smrg    int         ntables;
709a96d7823Smrg    CARD32      format;
710a96d7823Smrg    CARD32      size;
711a96d7823Smrg    int         nencoding;
712a96d7823Smrg    Bool	hasBDFAccelerators;
713a96d7823Smrg
714a96d7823Smrg    pFontInfo->isStringProp = NULL;
715a96d7823Smrg    pFontInfo->props = NULL;
716a96d7823Smrg    pFontInfo->nprops = 0;
717a96d7823Smrg
718a96d7823Smrg    if (!(tables = pcfReadTOC(file, &ntables)))
719a96d7823Smrg	goto Bail;
720a96d7823Smrg
721a96d7823Smrg    /* properties */
722a96d7823Smrg
723a96d7823Smrg    if (!pcfGetProperties(pFontInfo, file, tables, ntables))
724a96d7823Smrg	goto Bail;
725a96d7823Smrg
726a96d7823Smrg    /* Use the old accelerators if no BDF accelerators are in the file */
727a96d7823Smrg
728a96d7823Smrg    hasBDFAccelerators = pcfHasType (tables, ntables, PCF_BDF_ACCELERATORS);
729a96d7823Smrg    if (!hasBDFAccelerators)
730a96d7823Smrg	if (!pcfGetAccel (pFontInfo, file, tables, ntables, PCF_ACCELERATORS))
731a96d7823Smrg	    goto Bail;
732a96d7823Smrg
733a96d7823Smrg    /* encoding */
734a96d7823Smrg
735a96d7823Smrg    if (!pcfSeekToType(file, tables, ntables, PCF_BDF_ENCODINGS, &format, &size))
736a96d7823Smrg	goto Bail;
737a96d7823Smrg    format = pcfGetLSB32(file);
738a96d7823Smrg    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
739a96d7823Smrg	goto Bail;
740a96d7823Smrg
741a96d7823Smrg    pFontInfo->firstCol = pcfGetINT16(file, format);
742a96d7823Smrg    pFontInfo->lastCol = pcfGetINT16(file, format);
743a96d7823Smrg    pFontInfo->firstRow = pcfGetINT16(file, format);
744a96d7823Smrg    pFontInfo->lastRow = pcfGetINT16(file, format);
745a96d7823Smrg    pFontInfo->defaultCh = pcfGetINT16(file, format);
746a96d7823Smrg    if (IS_EOF(file)) goto Bail;
747a96d7823Smrg    if (pFontInfo->firstCol > pFontInfo->lastCol ||
748a96d7823Smrg       pFontInfo->firstRow > pFontInfo->lastRow ||
749a96d7823Smrg       pFontInfo->lastCol-pFontInfo->firstCol > 255) goto Bail;
750a96d7823Smrg
751a96d7823Smrg    nencoding = (pFontInfo->lastCol - pFontInfo->firstCol + 1) *
752a96d7823Smrg	(pFontInfo->lastRow - pFontInfo->firstRow + 1);
753a96d7823Smrg
754a96d7823Smrg    pFontInfo->allExist = TRUE;
755a96d7823Smrg    while (nencoding--) {
756a96d7823Smrg	if (pcfGetINT16(file, format) == 0xFFFF)
757a96d7823Smrg	    pFontInfo->allExist = FALSE;
758a96d7823Smrg	if (IS_EOF(file)) goto Bail;
759a96d7823Smrg    }
760a96d7823Smrg    if (IS_EOF(file)) goto Bail;
761a96d7823Smrg
762a96d7823Smrg    /* BDF style accelerators (i.e. bounds based on encoded glyphs) */
763a96d7823Smrg
764a96d7823Smrg    if (hasBDFAccelerators)
765a96d7823Smrg	if (!pcfGetAccel (pFontInfo, file, tables, ntables, PCF_BDF_ACCELERATORS))
766a96d7823Smrg	    goto Bail;
767a96d7823Smrg
768a96d7823Smrg    free(tables);
769a96d7823Smrg    return Successful;
770a96d7823SmrgBail:
771a96d7823Smrg    pFontInfo->nprops = 0;
772a96d7823Smrg    free (pFontInfo->props);
773a96d7823Smrg    free (pFontInfo->isStringProp);
774a96d7823Smrg    free(tables);
775a96d7823Smrg    return AllocError;
776a96d7823Smrg}
777a96d7823Smrg
778a96d7823Smrgstatic void
779a96d7823SmrgpcfUnloadFont(FontPtr pFont)
780a96d7823Smrg{
781a96d7823Smrg    BitmapFontPtr  bitmapFont;
782a96d7823Smrg    int i,nencoding;
783a96d7823Smrg
784a96d7823Smrg    bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
785a96d7823Smrg    free(bitmapFont->ink_metrics);
786a96d7823Smrg    if(bitmapFont->encoding) {
787a96d7823Smrg        nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) *
788a96d7823Smrg	    (pFont->info.lastRow - pFont->info.firstRow + 1);
789a96d7823Smrg        for(i=0; i<NUM_SEGMENTS(nencoding); i++)
790a96d7823Smrg            free(bitmapFont->encoding[i]);
791a96d7823Smrg    }
792a96d7823Smrg    free(bitmapFont->encoding);
793a96d7823Smrg    free(bitmapFont->bitmaps);
794a96d7823Smrg    free(bitmapFont->metrics);
795a96d7823Smrg    free(pFont->info.isStringProp);
796a96d7823Smrg    free(pFont->info.props);
797a96d7823Smrg    free(bitmapFont);
798a96d7823Smrg    DestroyFontRec(pFont);
799a96d7823Smrg}
800