pcfread.c revision a96d7823
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#include "libxfontint.h"
37
38#include <X11/fonts/fntfilst.h>
39#include <X11/fonts/bitmap.h>
40#include <X11/fonts/pcf.h>
41
42#ifndef MAX
43#define   MAX(a,b)    (((a)>(b)) ? a : b)
44#endif
45
46#include <stdarg.h>
47#include <stdint.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	props[i].name = MakeAtom(strings + props[i].name,
315				 strlen(strings + props[i].name), TRUE);
316	if (isStringProp[i]) {
317	    props[i].value = MakeAtom(strings + props[i].value,
318				      strlen(strings + props[i].value), TRUE);
319	}
320    }
321    free(strings);
322    pFontInfo->isStringProp = isStringProp;
323    pFontInfo->props = props;
324    pFontInfo->nprops = nprops;
325    return TRUE;
326Bail:
327    free(isStringProp);
328    free(props);
329    return FALSE;
330}
331
332
333/*
334 * pcfReadAccel
335 *
336 * Fill in the accelerator information from the font file; used
337 * to read both BDF_ACCELERATORS and old style ACCELERATORS
338 */
339
340static Bool
341pcfGetAccel(FontInfoPtr pFontInfo, FontFilePtr file,
342	    PCFTablePtr tables, int ntables, CARD32 type)
343{
344    CARD32      format;
345    CARD32	size;
346
347    if (!pcfSeekToType(file, tables, ntables, type, &format, &size) ||
348	IS_EOF(file))
349	goto Bail;
350    format = pcfGetLSB32(file);
351    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) &&
352	!PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS))
353    {
354	goto Bail;
355    }
356    pFontInfo->noOverlap = pcfGetINT8(file, format);
357    pFontInfo->constantMetrics = pcfGetINT8(file, format);
358    pFontInfo->terminalFont = pcfGetINT8(file, format);
359    pFontInfo->constantWidth = pcfGetINT8(file, format);
360    pFontInfo->inkInside = pcfGetINT8(file, format);
361    pFontInfo->inkMetrics = pcfGetINT8(file, format);
362    pFontInfo->drawDirection = pcfGetINT8(file, format);
363    pFontInfo->anamorphic = FALSE;
364    pFontInfo->cachable = TRUE;
365     /* natural alignment */ pcfGetINT8(file, format);
366    pFontInfo->fontAscent = pcfGetINT32(file, format);
367    pFontInfo->fontDescent = pcfGetINT32(file, format);
368    pFontInfo->maxOverlap = pcfGetINT32(file, format);
369    if (IS_EOF(file)) goto Bail;
370    if (!pcfGetMetric(file, format, &pFontInfo->minbounds))
371	goto Bail;
372    if (!pcfGetMetric(file, format, &pFontInfo->maxbounds))
373	goto Bail;
374    if (PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) {
375	if (!pcfGetMetric(file, format, &pFontInfo->ink_minbounds))
376	    goto Bail;
377	if (!pcfGetMetric(file, format, &pFontInfo->ink_maxbounds))
378	    goto Bail;
379    } else {
380	pFontInfo->ink_minbounds = pFontInfo->minbounds;
381	pFontInfo->ink_maxbounds = pFontInfo->maxbounds;
382    }
383    return TRUE;
384Bail:
385    return FALSE;
386}
387
388int
389pcfReadFont(FontPtr pFont, FontFilePtr file,
390	    int bit, int byte, int glyph, int scan)
391{
392    CARD32      format;
393    CARD32      size;
394    BitmapFontPtr  bitmapFont = 0;
395    int         i;
396    PCFTablePtr tables = 0;
397    int         ntables;
398    int         nmetrics;
399    int         nbitmaps;
400    int         sizebitmaps;
401    int         nink_metrics;
402    CharInfoPtr metrics = 0;
403    xCharInfo  *ink_metrics = 0;
404    char       *bitmaps = 0;
405    CharInfoPtr **encoding = 0;
406    int         nencoding = 0;
407    int         encodingOffset;
408    CARD32      bitmapSizes[GLYPHPADOPTIONS];
409    CARD32     *offsets = 0;
410    Bool	hasBDFAccelerators;
411
412    pFont->info.nprops = 0;
413    pFont->info.props = 0;
414    pFont->info.isStringProp=0;
415
416    if (!(tables = pcfReadTOC(file, &ntables)))
417	goto Bail;
418
419    /* properties */
420
421    if (!pcfGetProperties(&pFont->info, file, tables, ntables))
422	goto Bail;
423
424    /* Use the old accelerators if no BDF accelerators are in the file */
425
426    hasBDFAccelerators = pcfHasType (tables, ntables, PCF_BDF_ACCELERATORS);
427    if (!hasBDFAccelerators)
428	if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_ACCELERATORS))
429	    goto Bail;
430
431    /* metrics */
432
433    if (!pcfSeekToType(file, tables, ntables, PCF_METRICS, &format, &size)) {
434	goto Bail;
435    }
436    format = pcfGetLSB32(file);
437    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) &&
438	    !PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) {
439	goto Bail;
440    }
441    if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
442	nmetrics = pcfGetINT32(file, format);
443    else
444	nmetrics = pcfGetINT16(file, format);
445    if (IS_EOF(file)) goto Bail;
446    if (nmetrics < 0 || nmetrics > INT32_MAX / sizeof(CharInfoRec)) {
447	pcfError("pcfReadFont(): invalid file format\n");
448	goto Bail;
449    }
450    metrics = malloc(nmetrics * sizeof(CharInfoRec));
451    if (!metrics) {
452	pcfError("pcfReadFont(): Couldn't allocate metrics (%d*%d)\n",
453		 nmetrics, (int) sizeof(CharInfoRec));
454	goto Bail;
455    }
456    for (i = 0; i < nmetrics; i++)
457	if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) {
458	    if (!pcfGetMetric(file, format, &(metrics + i)->metrics))
459		goto Bail;
460	} else {
461	    if (!pcfGetCompressedMetric(file, format, &(metrics + i)->metrics))
462		goto Bail;
463	}
464
465    /* bitmaps */
466
467    if (!pcfSeekToType(file, tables, ntables, PCF_BITMAPS, &format, &size))
468	goto Bail;
469    format = pcfGetLSB32(file);
470    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
471	goto Bail;
472
473    nbitmaps = pcfGetINT32(file, format);
474    if (nbitmaps != nmetrics || IS_EOF(file))
475	goto Bail;
476    /* nmetrics is already ok, so nbitmap also is */
477    offsets = malloc(nbitmaps * sizeof(CARD32));
478    if (!offsets) {
479	pcfError("pcfReadFont(): Couldn't allocate offsets (%d*%d)\n",
480		 nbitmaps, (int) sizeof(CARD32));
481	goto Bail;
482    }
483    for (i = 0; i < nbitmaps; i++) {
484	offsets[i] = pcfGetINT32(file, format);
485	if (IS_EOF(file)) goto Bail;
486    }
487
488    for (i = 0; i < GLYPHPADOPTIONS; i++) {
489	bitmapSizes[i] = pcfGetINT32(file, format);
490	if (IS_EOF(file)) goto Bail;
491    }
492
493    sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX(format)];
494    /* guard against completely empty font */
495    bitmaps = malloc(sizebitmaps ? sizebitmaps : 1);
496    if (!bitmaps) {
497      pcfError("pcfReadFont(): Couldn't allocate bitmaps (%d)\n", sizebitmaps ? sizebitmaps : 1);
498	goto Bail;
499    }
500    FontFileRead(file, bitmaps, sizebitmaps);
501    if (IS_EOF(file)) goto Bail;
502    position += sizebitmaps;
503
504    if (PCF_BIT_ORDER(format) != bit)
505	BitOrderInvert((unsigned char *)bitmaps, sizebitmaps);
506    if ((PCF_BYTE_ORDER(format) == PCF_BIT_ORDER(format)) != (bit == byte)) {
507	switch (bit == byte ? PCF_SCAN_UNIT(format) : scan) {
508	case 1:
509	    break;
510	case 2:
511	    TwoByteSwap((unsigned char *)bitmaps, sizebitmaps);
512	    break;
513	case 4:
514	    FourByteSwap((unsigned char *)bitmaps, sizebitmaps);
515	    break;
516	}
517    }
518    if (PCF_GLYPH_PAD(format) != glyph) {
519	char       *padbitmaps;
520	int         sizepadbitmaps;
521	int         old,
522	            new;
523	xCharInfo  *metric;
524
525	sizepadbitmaps = bitmapSizes[PCF_SIZE_TO_INDEX(glyph)];
526	padbitmaps = malloc(sizepadbitmaps);
527	if (!padbitmaps) {
528          pcfError("pcfReadFont(): Couldn't allocate padbitmaps (%d)\n", sizepadbitmaps);
529	    goto Bail;
530	}
531	new = 0;
532	for (i = 0; i < nbitmaps; i++) {
533	    old = offsets[i];
534	    metric = &metrics[i].metrics;
535	    offsets[i] = new;
536	    new += RepadBitmap(bitmaps + old, padbitmaps + new,
537			       PCF_GLYPH_PAD(format), glyph,
538			  metric->rightSideBearing - metric->leftSideBearing,
539			       metric->ascent + metric->descent);
540	}
541	free(bitmaps);
542	bitmaps = padbitmaps;
543    }
544    for (i = 0; i < nbitmaps; i++)
545	metrics[i].bits = bitmaps + offsets[i];
546
547    free(offsets);
548    offsets = NULL;
549
550    /* ink metrics ? */
551
552    ink_metrics = NULL;
553    if (pcfSeekToType(file, tables, ntables, PCF_INK_METRICS, &format, &size)) {
554	format = pcfGetLSB32(file);
555	if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) &&
556		!PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) {
557	    goto Bail;
558	}
559	if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
560	    nink_metrics = pcfGetINT32(file, format);
561	else
562	    nink_metrics = pcfGetINT16(file, format);
563	if (IS_EOF(file)) goto Bail;
564	if (nink_metrics != nmetrics)
565	    goto Bail;
566	/* nmetrics already checked */
567	ink_metrics = malloc(nink_metrics * sizeof(xCharInfo));
568	if (!ink_metrics) {
569            pcfError("pcfReadFont(): Couldn't allocate ink_metrics (%d*%d)\n",
570		     nink_metrics, (int) sizeof(xCharInfo));
571	    goto Bail;
572	}
573	for (i = 0; i < nink_metrics; i++)
574	    if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) {
575		if (!pcfGetMetric(file, format, ink_metrics + i))
576		    goto Bail;
577	    } else {
578		if (!pcfGetCompressedMetric(file, format, ink_metrics + i))
579		    goto Bail;
580	    }
581    }
582
583    /* encoding */
584
585    if (!pcfSeekToType(file, tables, ntables, PCF_BDF_ENCODINGS, &format, &size))
586	goto Bail;
587    format = pcfGetLSB32(file);
588    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
589	goto Bail;
590
591    pFont->info.firstCol = pcfGetINT16(file, format);
592    pFont->info.lastCol = pcfGetINT16(file, format);
593    pFont->info.firstRow = pcfGetINT16(file, format);
594    pFont->info.lastRow = pcfGetINT16(file, format);
595    pFont->info.defaultCh = pcfGetINT16(file, format);
596    if (IS_EOF(file)) goto Bail;
597    if (pFont->info.firstCol > pFont->info.lastCol ||
598       pFont->info.firstRow > pFont->info.lastRow ||
599       pFont->info.lastCol-pFont->info.firstCol > 255) goto Bail;
600
601    nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) *
602	(pFont->info.lastRow - pFont->info.firstRow + 1);
603
604    encoding = calloc(NUM_SEGMENTS(nencoding), sizeof(CharInfoPtr*));
605    if (!encoding) {
606	pcfError("pcfReadFont(): Couldn't allocate encoding (%d*%d)\n",
607		 nencoding, (int) sizeof(CharInfoPtr));
608	goto Bail;
609    }
610
611    pFont->info.allExist = TRUE;
612    for (i = 0; i < nencoding; i++) {
613	encodingOffset = pcfGetINT16(file, format);
614	if (IS_EOF(file)) goto Bail;
615	if (encodingOffset == 0xFFFF) {
616	    pFont->info.allExist = FALSE;
617	} else {
618            if(!encoding[SEGMENT_MAJOR(i)]) {
619                encoding[SEGMENT_MAJOR(i)]=
620                    calloc(BITMAP_FONT_SEGMENT_SIZE, sizeof(CharInfoPtr));
621                if(!encoding[SEGMENT_MAJOR(i)])
622                    goto Bail;
623            }
624	    ACCESSENCODINGL(encoding, i) = metrics + encodingOffset;
625        }
626    }
627
628    /* BDF style accelerators (i.e. bounds based on encoded glyphs) */
629
630    if (hasBDFAccelerators)
631	if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_BDF_ACCELERATORS))
632	    goto Bail;
633
634    bitmapFont = malloc(sizeof *bitmapFont);
635    if (!bitmapFont) {
636	pcfError("pcfReadFont(): Couldn't allocate bitmapFont (%d)\n",
637		 (int) sizeof *bitmapFont);
638	goto Bail;
639    }
640
641    bitmapFont->version_num = PCF_FILE_VERSION;
642    bitmapFont->num_chars = nmetrics;
643    bitmapFont->num_tables = ntables;
644    bitmapFont->metrics = metrics;
645    bitmapFont->ink_metrics = ink_metrics;
646    bitmapFont->bitmaps = bitmaps;
647    bitmapFont->encoding = encoding;
648    bitmapFont->pDefault = (CharInfoPtr) 0;
649    if (pFont->info.defaultCh != (unsigned short) NO_SUCH_CHAR) {
650	unsigned int r,
651	            c,
652	            cols;
653
654	r = pFont->info.defaultCh >> 8;
655	c = pFont->info.defaultCh & 0xFF;
656	if (pFont->info.firstRow <= r && r <= pFont->info.lastRow &&
657		pFont->info.firstCol <= c && c <= pFont->info.lastCol) {
658	    cols = pFont->info.lastCol - pFont->info.firstCol + 1;
659	    r = r - pFont->info.firstRow;
660	    c = c - pFont->info.firstCol;
661	    bitmapFont->pDefault = ACCESSENCODING(encoding, r * cols + c);
662	}
663    }
664    bitmapFont->bitmapExtra = (BitmapExtraPtr) 0;
665    pFont->fontPrivate = (pointer) bitmapFont;
666    pFont->get_glyphs = bitmapGetGlyphs;
667    pFont->get_metrics = bitmapGetMetrics;
668    pFont->unload_font = pcfUnloadFont;
669    pFont->unload_glyphs = NULL;
670    pFont->bit = bit;
671    pFont->byte = byte;
672    pFont->glyph = glyph;
673    pFont->scan = scan;
674    free(tables);
675    return Successful;
676Bail:
677    free(ink_metrics);
678    if(encoding) {
679        for(i=0; i<NUM_SEGMENTS(nencoding); i++)
680            free(encoding[i]);
681    }
682    free(encoding);
683    free(bitmaps);
684    free(metrics);
685    free(pFont->info.props);
686    pFont->info.nprops = 0;
687    pFont->info.props = 0;
688    free (pFont->info.isStringProp);
689    free(bitmapFont);
690    free(tables);
691    free(offsets);
692    return AllocError;
693}
694
695int
696pcfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file)
697{
698    PCFTablePtr tables;
699    int         ntables;
700    CARD32      format;
701    CARD32      size;
702    int         nencoding;
703    Bool	hasBDFAccelerators;
704
705    pFontInfo->isStringProp = NULL;
706    pFontInfo->props = NULL;
707    pFontInfo->nprops = 0;
708
709    if (!(tables = pcfReadTOC(file, &ntables)))
710	goto Bail;
711
712    /* properties */
713
714    if (!pcfGetProperties(pFontInfo, file, tables, ntables))
715	goto Bail;
716
717    /* Use the old accelerators if no BDF accelerators are in the file */
718
719    hasBDFAccelerators = pcfHasType (tables, ntables, PCF_BDF_ACCELERATORS);
720    if (!hasBDFAccelerators)
721	if (!pcfGetAccel (pFontInfo, file, tables, ntables, PCF_ACCELERATORS))
722	    goto Bail;
723
724    /* encoding */
725
726    if (!pcfSeekToType(file, tables, ntables, PCF_BDF_ENCODINGS, &format, &size))
727	goto Bail;
728    format = pcfGetLSB32(file);
729    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
730	goto Bail;
731
732    pFontInfo->firstCol = pcfGetINT16(file, format);
733    pFontInfo->lastCol = pcfGetINT16(file, format);
734    pFontInfo->firstRow = pcfGetINT16(file, format);
735    pFontInfo->lastRow = pcfGetINT16(file, format);
736    pFontInfo->defaultCh = pcfGetINT16(file, format);
737    if (IS_EOF(file)) goto Bail;
738    if (pFontInfo->firstCol > pFontInfo->lastCol ||
739       pFontInfo->firstRow > pFontInfo->lastRow ||
740       pFontInfo->lastCol-pFontInfo->firstCol > 255) goto Bail;
741
742    nencoding = (pFontInfo->lastCol - pFontInfo->firstCol + 1) *
743	(pFontInfo->lastRow - pFontInfo->firstRow + 1);
744
745    pFontInfo->allExist = TRUE;
746    while (nencoding--) {
747	if (pcfGetINT16(file, format) == 0xFFFF)
748	    pFontInfo->allExist = FALSE;
749	if (IS_EOF(file)) goto Bail;
750    }
751    if (IS_EOF(file)) goto Bail;
752
753    /* BDF style accelerators (i.e. bounds based on encoded glyphs) */
754
755    if (hasBDFAccelerators)
756	if (!pcfGetAccel (pFontInfo, file, tables, ntables, PCF_BDF_ACCELERATORS))
757	    goto Bail;
758
759    free(tables);
760    return Successful;
761Bail:
762    pFontInfo->nprops = 0;
763    free (pFontInfo->props);
764    free (pFontInfo->isStringProp);
765    free(tables);
766    return AllocError;
767}
768
769static void
770pcfUnloadFont(FontPtr pFont)
771{
772    BitmapFontPtr  bitmapFont;
773    int i,nencoding;
774
775    bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
776    free(bitmapFont->ink_metrics);
777    if(bitmapFont->encoding) {
778        nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) *
779	    (pFont->info.lastRow - pFont->info.firstRow + 1);
780        for(i=0; i<NUM_SEGMENTS(nencoding); i++)
781            free(bitmapFont->encoding[i]);
782    }
783    free(bitmapFont->encoding);
784    free(bitmapFont->bitmaps);
785    free(bitmapFont->metrics);
786    free(pFont->info.isStringProp);
787    free(pFont->info.props);
788    free(bitmapFont);
789    DestroyFontRec(pFont);
790}
791