upload tizen2.0 source
[framework/uifw/xorg/lib/libxfont.git] / src / bitmap / pcfread.c
1 /*
2
3 Copyright 1990, 1998  The Open Group
4
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
21
22 Except as contained in this notice, the name of The Open Group shall
23 not be used in advertising or otherwise to promote the sale, use or
24 other dealings in this Software without prior written authorization
25 from 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
48 void
49 pcfError(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
62 static void pcfUnloadFont ( FontPtr pFont );
63 static 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
70 static int
71 pcfGetLSB32(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
83 static int
84 pcfGetINT32(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
103 static int
104 pcfGetINT16(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
121 static      PCFTablePtr
122 pcfReadTOC(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
168 static Bool
169 pcfGetMetric(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
182 static Bool
183 pcfGetCompressedMetric(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  */
200 static Bool
201 pcfSeekToType(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
220 static Bool
221 pcfHasType (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
238 static Bool
239 pcfGetProperties(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;
325 Bail:
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
339 static Bool
340 pcfGetAccel(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;
383 Bail:
384     return FALSE;
385 }
386
387 int
388 pcfReadFont(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;
676 Bail:
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
695 int
696 pcfReadFontInfo(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;
761 Bail:
762     pFontInfo->nprops = 0;
763     free (pFontInfo->props);
764     free (pFontInfo->isStringProp);
765     free(tables);
766     return AllocError;
767 }
768
769 static void
770 pcfUnloadFont(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 }