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