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