pcfread.c revision 1a17810d
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
48void
49pcfError(const char* message, ...)
50{
51    va_list args;
52
53    va_start(args, message);
54
55    fprintf(stderr, "PCF Error: ");
56    vfprintf(stderr, message, args);
57    va_end(args);
58}
59
60/* Read PCF font files */
61
62static void pcfUnloadFont ( FontPtr pFont );
63static int  position;
64
65
66#define IS_EOF(file) ((file)->eof == BUFFILEEOF)
67
68#define FONT_FILE_GETC_ERR(f)  (tmp = FontFileGetc(f), BAIL_ON_EOF)
69
70static int
71pcfGetLSB32(FontFilePtr file)
72{
73    int         c;
74
75    c = FontFileGetc(file);
76    c |= FontFileGetc(file) << 8;
77    c |= FontFileGetc(file) << 16;
78    c |= FontFileGetc(file) << 24;
79    position += 4;
80    return c;
81}
82
83static int
84pcfGetINT32(FontFilePtr file, CARD32 format)
85{
86    int         c;
87
88    if (PCF_BYTE_ORDER(format) == MSBFirst) {
89	c = FontFileGetc(file) << 24;
90	c |= FontFileGetc(file) << 16;
91	c |= FontFileGetc(file) << 8;
92	c |= FontFileGetc(file);
93    } else {
94	c = FontFileGetc(file);
95	c |= FontFileGetc(file) << 8;
96	c |= FontFileGetc(file) << 16;
97	c |= FontFileGetc(file) << 24;
98    }
99    position += 4;
100    return c;
101}
102
103static int
104pcfGetINT16(FontFilePtr file, CARD32 format)
105{
106    int         c;
107
108    if (PCF_BYTE_ORDER(format) == MSBFirst) {
109	c = FontFileGetc(file) << 8;
110	c |= FontFileGetc(file);
111    } else {
112	c = FontFileGetc(file);
113	c |= FontFileGetc(file) << 8;
114    }
115    position += 2;
116    return c;
117}
118
119#define pcfGetINT8(file, format) (position++, FontFileGetc(file))
120
121static      PCFTablePtr
122pcfReadTOC(FontFilePtr file, int *countp)
123{
124    CARD32      version;
125    PCFTablePtr tables;
126    int         count;
127    int         i;
128
129    position = 0;
130    version = pcfGetLSB32(file);
131    if (version != PCF_FILE_VERSION)
132	return (PCFTablePtr) NULL;
133    count = pcfGetLSB32(file);
134    if (IS_EOF(file)) return (PCFTablePtr) NULL;
135    if (count < 0 || count > INT32_MAX / sizeof(PCFTableRec)) {
136	pcfError("pcfReadTOC(): invalid file format\n");
137	return NULL;
138    }
139    tables = malloc(count * sizeof(PCFTableRec));
140    if (!tables) {
141	pcfError("pcfReadTOC(): Couldn't allocate tables (%d*%d)\n",
142		 count, (int) sizeof(PCFTableRec));
143	return (PCFTablePtr) NULL;
144    }
145    for (i = 0; i < count; i++) {
146	tables[i].type = pcfGetLSB32(file);
147	tables[i].format = pcfGetLSB32(file);
148	tables[i].size = pcfGetLSB32(file);
149	tables[i].offset = pcfGetLSB32(file);
150	if (IS_EOF(file)) goto Bail;
151    }
152
153    *countp = count;
154    return tables;
155
156 Bail:
157    free(tables);
158    return (PCFTablePtr) NULL;
159}
160
161/*
162 * PCF supports two formats for metrics, both the regular
163 * jumbo size, and 'lite' metrics, which are useful
164 * for most fonts which have even vaguely reasonable
165 * metrics
166 */
167
168static Bool
169pcfGetMetric(FontFilePtr file, CARD32 format, xCharInfo *metric)
170{
171    metric->leftSideBearing = pcfGetINT16(file, format);
172    metric->rightSideBearing = pcfGetINT16(file, format);
173    metric->characterWidth = pcfGetINT16(file, format);
174    metric->ascent = pcfGetINT16(file, format);
175    metric->descent = pcfGetINT16(file, format);
176    metric->attributes = pcfGetINT16(file, format);
177    if (IS_EOF(file)) return FALSE;
178
179    return TRUE;
180}
181
182static Bool
183pcfGetCompressedMetric(FontFilePtr file, CARD32 format, xCharInfo *metric)
184{
185    metric->leftSideBearing = pcfGetINT8(file, format) - 0x80;
186    metric->rightSideBearing = pcfGetINT8(file, format) - 0x80;
187    metric->characterWidth = pcfGetINT8(file, format) - 0x80;
188    metric->ascent = pcfGetINT8(file, format) - 0x80;
189    metric->descent = pcfGetINT8(file, format) - 0x80;
190    metric->attributes = 0;
191    if (IS_EOF(file)) return FALSE;
192
193    return TRUE;
194}
195
196/*
197 * Position the file to the begining of the specified table
198 * in the font file
199 */
200static Bool
201pcfSeekToType(FontFilePtr file, PCFTablePtr tables, int ntables,
202	      CARD32 type, CARD32 *formatp, CARD32 *sizep)
203{
204    int         i;
205
206    for (i = 0; i < ntables; i++)
207	if (tables[i].type == type) {
208	    if (position > tables[i].offset)
209		return FALSE;
210	    if (!FontFileSkip(file, tables[i].offset - position))
211		return FALSE;
212	    position = tables[i].offset;
213	    *sizep = tables[i].size;
214	    *formatp = tables[i].format;
215	    return TRUE;
216	}
217    return FALSE;
218}
219
220static Bool
221pcfHasType (PCFTablePtr tables, int ntables, CARD32 type)
222{
223    int         i;
224
225    for (i = 0; i < ntables; i++)
226	if (tables[i].type == type)
227	    return TRUE;
228    return FALSE;
229}
230
231/*
232 * pcfGetProperties
233 *
234 * Reads the font properties from the font file, filling in the FontInfo rec
235 * supplied.  Used by by both ReadFont and ReadFontInfo routines.
236 */
237
238static Bool
239pcfGetProperties(FontInfoPtr pFontInfo, FontFilePtr file,
240		 PCFTablePtr tables, int ntables)
241{
242    FontPropPtr props = 0;
243    int         nprops;
244    char       *isStringProp = 0;
245    CARD32      format;
246    int         i;
247    CARD32      size;
248    int         string_size;
249    char       *strings;
250
251    /* font properties */
252
253    if (!pcfSeekToType(file, tables, ntables, PCF_PROPERTIES, &format, &size))
254	goto Bail;
255    format = pcfGetLSB32(file);
256    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
257	goto Bail;
258    nprops = pcfGetINT32(file, format);
259    if (nprops <= 0 || nprops > INT32_MAX / sizeof(FontPropRec)) {
260	pcfError("pcfGetProperties(): invalid nprops value (%d)\n", nprops);
261	goto Bail;
262    }
263    if (IS_EOF(file)) goto Bail;
264    props = malloc(nprops * sizeof(FontPropRec));
265    if (!props) {
266	pcfError("pcfGetProperties(): Couldn't allocate props (%d*%d)\n",
267	       nprops, (int) sizeof(FontPropRec));
268	goto Bail;
269    }
270    isStringProp = malloc(nprops * sizeof(char));
271    if (!isStringProp) {
272	pcfError("pcfGetProperties(): Couldn't allocate isStringProp (%d*%d)\n",
273	       nprops, (int) sizeof(char));
274	goto Bail;
275    }
276    for (i = 0; i < nprops; i++) {
277	props[i].name = pcfGetINT32(file, format);
278	isStringProp[i] = pcfGetINT8(file, format);
279	props[i].value = pcfGetINT32(file, format);
280	if (props[i].name < 0
281	    || (isStringProp[i] != 0 && isStringProp[i] != 1)
282	    || (isStringProp[i] && props[i].value < 0)) {
283	    pcfError("pcfGetProperties(): invalid file format %ld %d %ld\n",
284		     props[i].name, isStringProp[i], props[i].value);
285	    goto Bail;
286	}
287	if (IS_EOF(file)) goto Bail;
288    }
289    /* pad the property array */
290    /*
291     * clever here - nprops is the same as the number of odd-units read, as
292     * only isStringProp are odd length
293     */
294    if (nprops & 3)
295    {
296	i = 4 - (nprops & 3);
297	(void)FontFileSkip(file, i);
298	position += i;
299    }
300    if (IS_EOF(file)) goto Bail;
301    string_size = pcfGetINT32(file, format);
302    if (string_size < 0) goto Bail;
303    if (IS_EOF(file)) goto Bail;
304    strings = malloc(string_size);
305    if (!strings) {
306      pcfError("pcfGetProperties(): Couldn't allocate strings (%d)\n", string_size);
307	goto Bail;
308    }
309    FontFileRead(file, strings, string_size);
310    if (IS_EOF(file)) goto Bail;
311    position += string_size;
312    for (i = 0; i < nprops; i++) {
313	props[i].name = MakeAtom(strings + props[i].name,
314				 strlen(strings + props[i].name), TRUE);
315	if (isStringProp[i]) {
316	    props[i].value = MakeAtom(strings + props[i].value,
317				      strlen(strings + props[i].value), TRUE);
318	}
319    }
320    free(strings);
321    pFontInfo->isStringProp = isStringProp;
322    pFontInfo->props = props;
323    pFontInfo->nprops = nprops;
324    return TRUE;
325Bail:
326    free(isStringProp);
327    free(props);
328    return FALSE;
329}
330
331
332/*
333 * pcfReadAccel
334 *
335 * Fill in the accelerator information from the font file; used
336 * to read both BDF_ACCELERATORS and old style ACCELERATORS
337 */
338
339static Bool
340pcfGetAccel(FontInfoPtr pFontInfo, FontFilePtr file,
341	    PCFTablePtr tables, int ntables, CARD32 type)
342{
343    CARD32      format;
344    CARD32	size;
345
346    if (!pcfSeekToType(file, tables, ntables, type, &format, &size) ||
347	IS_EOF(file))
348	goto Bail;
349    format = pcfGetLSB32(file);
350    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) &&
351	!PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS))
352    {
353	goto Bail;
354    }
355    pFontInfo->noOverlap = pcfGetINT8(file, format);
356    pFontInfo->constantMetrics = pcfGetINT8(file, format);
357    pFontInfo->terminalFont = pcfGetINT8(file, format);
358    pFontInfo->constantWidth = pcfGetINT8(file, format);
359    pFontInfo->inkInside = pcfGetINT8(file, format);
360    pFontInfo->inkMetrics = pcfGetINT8(file, format);
361    pFontInfo->drawDirection = pcfGetINT8(file, format);
362    pFontInfo->anamorphic = FALSE;
363    pFontInfo->cachable = TRUE;
364     /* natural alignment */ pcfGetINT8(file, format);
365    pFontInfo->fontAscent = pcfGetINT32(file, format);
366    pFontInfo->fontDescent = pcfGetINT32(file, format);
367    pFontInfo->maxOverlap = pcfGetINT32(file, format);
368    if (IS_EOF(file)) goto Bail;
369    if (!pcfGetMetric(file, format, &pFontInfo->minbounds))
370	goto Bail;
371    if (!pcfGetMetric(file, format, &pFontInfo->maxbounds))
372	goto Bail;
373    if (PCF_FORMAT_MATCH(format, PCF_ACCEL_W_INKBOUNDS)) {
374	if (!pcfGetMetric(file, format, &pFontInfo->ink_minbounds))
375	    goto Bail;
376	if (!pcfGetMetric(file, format, &pFontInfo->ink_maxbounds))
377	    goto Bail;
378    } else {
379	pFontInfo->ink_minbounds = pFontInfo->minbounds;
380	pFontInfo->ink_maxbounds = pFontInfo->maxbounds;
381    }
382    return TRUE;
383Bail:
384    return FALSE;
385}
386
387int
388pcfReadFont(FontPtr pFont, FontFilePtr file,
389	    int bit, int byte, int glyph, int scan)
390{
391    CARD32      format;
392    CARD32      size;
393    BitmapFontPtr  bitmapFont = 0;
394    int         i;
395    PCFTablePtr tables = 0;
396    int         ntables;
397    int         nmetrics;
398    int         nbitmaps;
399    int         sizebitmaps;
400    int         nink_metrics;
401    CharInfoPtr metrics = 0;
402    xCharInfo  *ink_metrics = 0;
403    char       *bitmaps = 0;
404    CharInfoPtr **encoding = 0;
405    int         nencoding = 0;
406    int         encodingOffset;
407    CARD32      bitmapSizes[GLYPHPADOPTIONS];
408    CARD32     *offsets = 0;
409    Bool	hasBDFAccelerators;
410
411    pFont->info.nprops = 0;
412    pFont->info.props = 0;
413    pFont->info.isStringProp=0;
414
415    if (!(tables = pcfReadTOC(file, &ntables)))
416	goto Bail;
417
418    /* properties */
419
420    if (!pcfGetProperties(&pFont->info, file, tables, ntables))
421	goto Bail;
422
423    /* Use the old accelerators if no BDF accelerators are in the file */
424
425    hasBDFAccelerators = pcfHasType (tables, ntables, PCF_BDF_ACCELERATORS);
426    if (!hasBDFAccelerators)
427	if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_ACCELERATORS))
428	    goto Bail;
429
430    /* metrics */
431
432    if (!pcfSeekToType(file, tables, ntables, PCF_METRICS, &format, &size)) {
433	goto Bail;
434    }
435    format = pcfGetLSB32(file);
436    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) &&
437	    !PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) {
438	goto Bail;
439    }
440    if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
441	nmetrics = pcfGetINT32(file, format);
442    else
443	nmetrics = pcfGetINT16(file, format);
444    if (IS_EOF(file)) goto Bail;
445    if (nmetrics < 0 || nmetrics > INT32_MAX / sizeof(CharInfoRec)) {
446	pcfError("pcfReadFont(): invalid file format\n");
447	goto Bail;
448    }
449    metrics = malloc(nmetrics * sizeof(CharInfoRec));
450    if (!metrics) {
451	pcfError("pcfReadFont(): Couldn't allocate metrics (%d*%d)\n",
452		 nmetrics, (int) sizeof(CharInfoRec));
453	goto Bail;
454    }
455    for (i = 0; i < nmetrics; i++)
456	if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) {
457	    if (!pcfGetMetric(file, format, &(metrics + i)->metrics))
458		goto Bail;
459	} else {
460	    if (!pcfGetCompressedMetric(file, format, &(metrics + i)->metrics))
461		goto Bail;
462	}
463
464    /* bitmaps */
465
466    if (!pcfSeekToType(file, tables, ntables, PCF_BITMAPS, &format, &size))
467	goto Bail;
468    format = pcfGetLSB32(file);
469    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
470	goto Bail;
471
472    nbitmaps = pcfGetINT32(file, format);
473    if (nbitmaps != nmetrics || IS_EOF(file))
474	goto Bail;
475    /* nmetrics is already ok, so nbitmap also is */
476    offsets = malloc(nbitmaps * sizeof(CARD32));
477    if (!offsets) {
478	pcfError("pcfReadFont(): Couldn't allocate offsets (%d*%d)\n",
479		 nbitmaps, (int) sizeof(CARD32));
480	goto Bail;
481    }
482    for (i = 0; i < nbitmaps; i++) {
483	offsets[i] = pcfGetINT32(file, format);
484	if (IS_EOF(file)) goto Bail;
485    }
486
487    for (i = 0; i < GLYPHPADOPTIONS; i++) {
488	bitmapSizes[i] = pcfGetINT32(file, format);
489	if (IS_EOF(file)) goto Bail;
490	if (bitmapSizes[i] < 0) 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