pcfread.c revision b0d196e1
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    }
491
492    sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX(format)];
493    /* guard against completely empty font */
494    bitmaps = malloc(sizebitmaps ? sizebitmaps : 1);
495    if (!bitmaps) {
496      pcfError("pcfReadFont(): Couldn't allocate bitmaps (%d)\n", sizebitmaps ? sizebitmaps : 1);
497	goto Bail;
498    }
499    FontFileRead(file, bitmaps, sizebitmaps);
500    if (IS_EOF(file)) goto Bail;
501    position += sizebitmaps;
502
503    if (PCF_BIT_ORDER(format) != bit)
504	BitOrderInvert((unsigned char *)bitmaps, sizebitmaps);
505    if ((PCF_BYTE_ORDER(format) == PCF_BIT_ORDER(format)) != (bit == byte)) {
506	switch (bit == byte ? PCF_SCAN_UNIT(format) : scan) {
507	case 1:
508	    break;
509	case 2:
510	    TwoByteSwap((unsigned char *)bitmaps, sizebitmaps);
511	    break;
512	case 4:
513	    FourByteSwap((unsigned char *)bitmaps, sizebitmaps);
514	    break;
515	}
516    }
517    if (PCF_GLYPH_PAD(format) != glyph) {
518	char       *padbitmaps;
519	int         sizepadbitmaps;
520	int         old,
521	            new;
522	xCharInfo  *metric;
523
524	sizepadbitmaps = bitmapSizes[PCF_SIZE_TO_INDEX(glyph)];
525	padbitmaps = malloc(sizepadbitmaps);
526	if (!padbitmaps) {
527          pcfError("pcfReadFont(): Couldn't allocate padbitmaps (%d)\n", sizepadbitmaps);
528	    goto Bail;
529	}
530	new = 0;
531	for (i = 0; i < nbitmaps; i++) {
532	    old = offsets[i];
533	    metric = &metrics[i].metrics;
534	    offsets[i] = new;
535	    new += RepadBitmap(bitmaps + old, padbitmaps + new,
536			       PCF_GLYPH_PAD(format), glyph,
537			  metric->rightSideBearing - metric->leftSideBearing,
538			       metric->ascent + metric->descent);
539	}
540	free(bitmaps);
541	bitmaps = padbitmaps;
542    }
543    for (i = 0; i < nbitmaps; i++)
544	metrics[i].bits = bitmaps + offsets[i];
545
546    free(offsets);
547    offsets = NULL;
548
549    /* ink metrics ? */
550
551    ink_metrics = NULL;
552    if (pcfSeekToType(file, tables, ntables, PCF_INK_METRICS, &format, &size)) {
553	format = pcfGetLSB32(file);
554	if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT) &&
555		!PCF_FORMAT_MATCH(format, PCF_COMPRESSED_METRICS)) {
556	    goto Bail;
557	}
558	if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
559	    nink_metrics = pcfGetINT32(file, format);
560	else
561	    nink_metrics = pcfGetINT16(file, format);
562	if (IS_EOF(file)) goto Bail;
563	if (nink_metrics != nmetrics)
564	    goto Bail;
565	/* nmetrics already checked */
566	ink_metrics = malloc(nink_metrics * sizeof(xCharInfo));
567	if (!ink_metrics) {
568            pcfError("pcfReadFont(): Couldn't allocate ink_metrics (%d*%d)\n",
569		     nink_metrics, (int) sizeof(xCharInfo));
570	    goto Bail;
571	}
572	for (i = 0; i < nink_metrics; i++)
573	    if (PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT)) {
574		if (!pcfGetMetric(file, format, ink_metrics + i))
575		    goto Bail;
576	    } else {
577		if (!pcfGetCompressedMetric(file, format, ink_metrics + i))
578		    goto Bail;
579	    }
580    }
581
582    /* encoding */
583
584    if (!pcfSeekToType(file, tables, ntables, PCF_BDF_ENCODINGS, &format, &size))
585	goto Bail;
586    format = pcfGetLSB32(file);
587    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
588	goto Bail;
589
590    pFont->info.firstCol = pcfGetINT16(file, format);
591    pFont->info.lastCol = pcfGetINT16(file, format);
592    pFont->info.firstRow = pcfGetINT16(file, format);
593    pFont->info.lastRow = pcfGetINT16(file, format);
594    pFont->info.defaultCh = pcfGetINT16(file, format);
595    if (IS_EOF(file)) goto Bail;
596    if (pFont->info.firstCol > pFont->info.lastCol ||
597       pFont->info.firstRow > pFont->info.lastRow ||
598       pFont->info.lastCol-pFont->info.firstCol > 255) goto Bail;
599
600    nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) *
601	(pFont->info.lastRow - pFont->info.firstRow + 1);
602
603    encoding = calloc(NUM_SEGMENTS(nencoding), sizeof(CharInfoPtr*));
604    if (!encoding) {
605	pcfError("pcfReadFont(): Couldn't allocate encoding (%d*%d)\n",
606		 nencoding, (int) sizeof(CharInfoPtr));
607	goto Bail;
608    }
609
610    pFont->info.allExist = TRUE;
611    for (i = 0; i < nencoding; i++) {
612	encodingOffset = pcfGetINT16(file, format);
613	if (IS_EOF(file)) goto Bail;
614	if (encodingOffset == 0xFFFF) {
615	    pFont->info.allExist = FALSE;
616	} else {
617            if(!encoding[SEGMENT_MAJOR(i)]) {
618                encoding[SEGMENT_MAJOR(i)]=
619                    calloc(BITMAP_FONT_SEGMENT_SIZE, sizeof(CharInfoPtr));
620                if(!encoding[SEGMENT_MAJOR(i)])
621                    goto Bail;
622            }
623	    ACCESSENCODINGL(encoding, i) = metrics + encodingOffset;
624        }
625    }
626
627    /* BDF style accelerators (i.e. bounds based on encoded glyphs) */
628
629    if (hasBDFAccelerators)
630	if (!pcfGetAccel (&pFont->info, file, tables, ntables, PCF_BDF_ACCELERATORS))
631	    goto Bail;
632
633    bitmapFont = malloc(sizeof *bitmapFont);
634    if (!bitmapFont) {
635	pcfError("pcfReadFont(): Couldn't allocate bitmapFont (%d)\n",
636		 (int) sizeof *bitmapFont);
637	goto Bail;
638    }
639
640    bitmapFont->version_num = PCF_FILE_VERSION;
641    bitmapFont->num_chars = nmetrics;
642    bitmapFont->num_tables = ntables;
643    bitmapFont->metrics = metrics;
644    bitmapFont->ink_metrics = ink_metrics;
645    bitmapFont->bitmaps = bitmaps;
646    bitmapFont->encoding = encoding;
647    bitmapFont->pDefault = (CharInfoPtr) 0;
648    if (pFont->info.defaultCh != (unsigned short) NO_SUCH_CHAR) {
649	unsigned int r,
650	            c,
651	            cols;
652
653	r = pFont->info.defaultCh >> 8;
654	c = pFont->info.defaultCh & 0xFF;
655	if (pFont->info.firstRow <= r && r <= pFont->info.lastRow &&
656		pFont->info.firstCol <= c && c <= pFont->info.lastCol) {
657	    cols = pFont->info.lastCol - pFont->info.firstCol + 1;
658	    r = r - pFont->info.firstRow;
659	    c = c - pFont->info.firstCol;
660	    bitmapFont->pDefault = ACCESSENCODING(encoding, r * cols + c);
661	}
662    }
663    bitmapFont->bitmapExtra = (BitmapExtraPtr) 0;
664    pFont->fontPrivate = (pointer) bitmapFont;
665    pFont->get_glyphs = bitmapGetGlyphs;
666    pFont->get_metrics = bitmapGetMetrics;
667    pFont->unload_font = pcfUnloadFont;
668    pFont->unload_glyphs = NULL;
669    pFont->bit = bit;
670    pFont->byte = byte;
671    pFont->glyph = glyph;
672    pFont->scan = scan;
673    free(tables);
674    return Successful;
675Bail:
676    free(ink_metrics);
677    if(encoding) {
678        for(i=0; i<NUM_SEGMENTS(nencoding); i++)
679            free(encoding[i]);
680    }
681    free(encoding);
682    free(bitmaps);
683    free(metrics);
684    free(pFont->info.props);
685    pFont->info.nprops = 0;
686    pFont->info.props = 0;
687    free (pFont->info.isStringProp);
688    free(bitmapFont);
689    free(tables);
690    free(offsets);
691    return AllocError;
692}
693
694int
695pcfReadFontInfo(FontInfoPtr pFontInfo, FontFilePtr file)
696{
697    PCFTablePtr tables;
698    int         ntables;
699    CARD32      format;
700    CARD32      size;
701    int         nencoding;
702    Bool	hasBDFAccelerators;
703
704    pFontInfo->isStringProp = NULL;
705    pFontInfo->props = NULL;
706    pFontInfo->nprops = 0;
707
708    if (!(tables = pcfReadTOC(file, &ntables)))
709	goto Bail;
710
711    /* properties */
712
713    if (!pcfGetProperties(pFontInfo, file, tables, ntables))
714	goto Bail;
715
716    /* Use the old accelerators if no BDF accelerators are in the file */
717
718    hasBDFAccelerators = pcfHasType (tables, ntables, PCF_BDF_ACCELERATORS);
719    if (!hasBDFAccelerators)
720	if (!pcfGetAccel (pFontInfo, file, tables, ntables, PCF_ACCELERATORS))
721	    goto Bail;
722
723    /* encoding */
724
725    if (!pcfSeekToType(file, tables, ntables, PCF_BDF_ENCODINGS, &format, &size))
726	goto Bail;
727    format = pcfGetLSB32(file);
728    if (!PCF_FORMAT_MATCH(format, PCF_DEFAULT_FORMAT))
729	goto Bail;
730
731    pFontInfo->firstCol = pcfGetINT16(file, format);
732    pFontInfo->lastCol = pcfGetINT16(file, format);
733    pFontInfo->firstRow = pcfGetINT16(file, format);
734    pFontInfo->lastRow = pcfGetINT16(file, format);
735    pFontInfo->defaultCh = pcfGetINT16(file, format);
736    if (IS_EOF(file)) goto Bail;
737    if (pFontInfo->firstCol > pFontInfo->lastCol ||
738       pFontInfo->firstRow > pFontInfo->lastRow ||
739       pFontInfo->lastCol-pFontInfo->firstCol > 255) goto Bail;
740
741    nencoding = (pFontInfo->lastCol - pFontInfo->firstCol + 1) *
742	(pFontInfo->lastRow - pFontInfo->firstRow + 1);
743
744    pFontInfo->allExist = TRUE;
745    while (nencoding--) {
746	if (pcfGetINT16(file, format) == 0xFFFF)
747	    pFontInfo->allExist = FALSE;
748	if (IS_EOF(file)) goto Bail;
749    }
750    if (IS_EOF(file)) goto Bail;
751
752    /* BDF style accelerators (i.e. bounds based on encoded glyphs) */
753
754    if (hasBDFAccelerators)
755	if (!pcfGetAccel (pFontInfo, file, tables, ntables, PCF_BDF_ACCELERATORS))
756	    goto Bail;
757
758    free(tables);
759    return Successful;
760Bail:
761    pFontInfo->nprops = 0;
762    free (pFontInfo->props);
763    free (pFontInfo->isStringProp);
764    free(tables);
765    return AllocError;
766}
767
768static void
769pcfUnloadFont(FontPtr pFont)
770{
771    BitmapFontPtr  bitmapFont;
772    int i,nencoding;
773
774    bitmapFont = (BitmapFontPtr) pFont->fontPrivate;
775    free(bitmapFont->ink_metrics);
776    if(bitmapFont->encoding) {
777        nencoding = (pFont->info.lastCol - pFont->info.firstCol + 1) *
778	    (pFont->info.lastRow - pFont->info.firstRow + 1);
779        for(i=0; i<NUM_SEGMENTS(nencoding); i++)
780            free(bitmapFont->encoding[i]);
781    }
782    free(bitmapFont->encoding);
783    free(bitmapFont->bitmaps);
784    free(bitmapFont->metrics);
785    free(pFont->info.isStringProp);
786    free(pFont->info.props);
787    free(bitmapFont);
788    DestroyFontRec(pFont);
789}
790