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