misc fixes to get rrdtool working without included libraries.
[rrdtool.git] / libraries / freetype-2.0.5 / pcfread.c
1 /*  pcfread.c
2
3     FreeType font driver for pcf fonts
4
5   Copyright 2000-2001 by
6   Francesco Zappa Nardelli
7
8 Permission is hereby granted, free of charge, to any person obtaining a copy
9 of this software and associated documentation files (the "Software"), to deal
10 in the Software without restriction, including without limitation the rights
11 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the Software is
13 furnished to do so, subject to the following conditions:
14
15 The above copyright notice and this permission notice shall be included in
16 all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
21 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 THE SOFTWARE.
25 */
26
27
28 #include <ft2build.h>
29
30 #include FT_INTERNAL_DEBUG_H
31 #include FT_INTERNAL_STREAM_H
32 #include FT_INTERNAL_OBJECTS_H
33
34 #include "pcf.h"
35 #include "pcfdriver.h"
36
37 #include "pcferror.h"
38
39 #include <string.h>     /* strlen(), strcpy() */
40
41
42   /*************************************************************************/
43   /*                                                                       */
44   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
45   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
46   /* messages during execution.                                            */
47   /*                                                                       */
48 #undef  FT_COMPONENT
49 #define FT_COMPONENT  trace_pcfread
50
51
52 #if defined( FT_DEBUG_LEVEL_TRACE )
53   static char*  tableNames[] =
54   {
55     "prop", "accl", "mtrcs", "bmps", "imtrcs",
56     "enc", "swidth", "names", "accel"
57   };
58 #endif
59
60
61   static
62   const FT_Frame_Field  pcf_toc_header[] =
63   {
64 #undef  FT_STRUCTURE
65 #define FT_STRUCTURE  PCF_TocRec
66
67     FT_FRAME_START( 8 ),
68       FT_FRAME_ULONG_LE( version ),
69       FT_FRAME_ULONG_LE( count ),
70     FT_FRAME_END
71   };
72
73
74   static
75   const FT_Frame_Field  pcf_table_header[] =
76   {
77 #undef  FT_STRUCTURE
78 #define FT_STRUCTURE  PCF_TableRec
79
80     FT_FRAME_START( 16  ),
81       FT_FRAME_ULONG_LE( type ),
82       FT_FRAME_ULONG_LE( format ),
83       FT_FRAME_ULONG_LE( size ),
84       FT_FRAME_ULONG_LE( offset ),
85     FT_FRAME_END
86   };
87
88
89   static FT_Error
90   pcf_read_TOC( FT_Stream  stream,
91                 PCF_Face   face )
92   {
93     FT_Error   error;
94     PCF_Toc    toc = &face->toc;
95     PCF_Table  tables;
96
97     FT_Memory     memory = FT_FACE(face)->memory;
98     unsigned int  i;
99
100
101     if ( FILE_Seek ( 0 )                   ||
102          READ_Fields ( pcf_toc_header, toc ) )
103       return PCF_Err_Cannot_Open_Resource;
104
105     if ( toc->version != PCF_FILE_VERSION )
106       return PCF_Err_Invalid_File_Format;
107
108     if ( ALLOC( face->toc.tables, toc->count * sizeof ( PCF_TableRec ) ) )
109       return PCF_Err_Out_Of_Memory;
110
111     tables = face->toc.tables;
112     for ( i = 0; i < toc->count; i++ )
113     {
114       if ( READ_Fields( pcf_table_header, tables ) )
115         goto Exit;
116       tables++;
117     }
118
119 #if defined( FT_DEBUG_LEVEL_TRACE )
120
121     {
122       unsigned int  i,j;
123       char*         name = "?";
124
125
126       FT_TRACE4(( "Tables count: %ld\n", face->toc.count ));
127       tables = face->toc.tables;
128       for ( i = 0; i < toc->count; i++ )
129       {
130         for( j = 0; j < sizeof ( tableNames ) / sizeof ( tableNames[0] ); j++ )
131           if ( tables[i].type == (unsigned int)( 1 << j ) )
132             name=tableNames[j];
133         FT_TRACE4(( "Table %d: type=%-6s format=0x%04lX "
134                     "size=0x%06lX (%8ld) offset=0x%04lX\n",
135                     i, name,
136                     tables[i].format,
137                     tables[i].size, tables[i].size,
138                     tables[i].offset ));
139       }
140     }
141
142 #endif
143
144     return PCF_Err_Ok;
145
146   Exit:
147     FREE( face->toc.tables );
148     return error;
149   }
150
151
152   static
153   const FT_Frame_Field  pcf_metric_header[] =
154   {
155 #undef  FT_STRUCTURE
156 #define FT_STRUCTURE  PCF_MetricRec
157
158     FT_FRAME_START( 12 ),
159       FT_FRAME_SHORT_LE( leftSideBearing ),
160       FT_FRAME_SHORT_LE( rightSideBearing ),
161       FT_FRAME_SHORT_LE( characterWidth ),
162       FT_FRAME_SHORT_LE( ascent ),
163       FT_FRAME_SHORT_LE( descent ),
164       FT_FRAME_SHORT_LE( attributes ),
165     FT_FRAME_END
166   };
167
168
169   static
170   const FT_Frame_Field  pcf_metric_msb_header[] =
171   {
172 #undef  FT_STRUCTURE
173 #define FT_STRUCTURE  PCF_MetricRec
174
175     FT_FRAME_START( 12 ),
176       FT_FRAME_SHORT( leftSideBearing ),
177       FT_FRAME_SHORT( rightSideBearing ),
178       FT_FRAME_SHORT( characterWidth ),
179       FT_FRAME_SHORT( ascent ),
180       FT_FRAME_SHORT( descent ),
181       FT_FRAME_SHORT( attributes ),
182     FT_FRAME_END
183   };
184
185
186   static
187   const FT_Frame_Field  pcf_compressed_metric_header[] =
188   {
189 #undef  FT_STRUCTURE
190 #define FT_STRUCTURE  PCF_Compressed_MetricRec
191
192     FT_FRAME_START( 5 ),
193       FT_FRAME_BYTE( leftSideBearing ),
194       FT_FRAME_BYTE( rightSideBearing ),
195       FT_FRAME_BYTE( characterWidth ),
196       FT_FRAME_BYTE( ascent ),
197       FT_FRAME_BYTE( descent ),
198     FT_FRAME_END
199   };
200
201
202   static FT_Error
203   pcf_parse_metric( FT_Stream              stream,
204                     const FT_Frame_Field*  header,
205                     PCF_Metric             metric )
206   {
207     FT_Error  error = PCF_Err_Ok;
208
209
210     if ( READ_Fields( header, metric ) )
211       return error;
212
213     return PCF_Err_Ok;
214   }
215
216
217   static FT_Error
218   pcf_parse_compressed_metric( FT_Stream   stream,
219                                PCF_Metric  metric )
220   {
221     PCF_Compressed_MetricRec  compr_metric;
222     FT_Error                  error = PCF_Err_Ok;
223
224
225     if ( READ_Fields( pcf_compressed_metric_header, &compr_metric ) )
226       return error;
227
228     metric->leftSideBearing =
229       (FT_Short)( compr_metric.leftSideBearing - 0x80 );
230     metric->rightSideBearing =
231       (FT_Short)( compr_metric.rightSideBearing - 0x80 );
232     metric->characterWidth =
233       (FT_Short)( compr_metric.characterWidth - 0x80 );
234     metric->ascent =
235       (FT_Short)( compr_metric.ascent - 0x80 );
236     metric->descent =
237       (FT_Short)( compr_metric.descent - 0x80 );
238     metric->attributes = 0;
239
240     return PCF_Err_Ok;
241   }
242
243
244   static FT_Error
245   pcf_get_metric( FT_Stream   stream,
246                   FT_ULong    format,
247                   PCF_Metric  metric )
248   {
249     FT_Error error = PCF_Err_Ok;
250
251
252     if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
253     {
254       if ( PCF_BYTE_ORDER( format ) == MSBFirst )
255         error = pcf_parse_metric( stream, pcf_metric_msb_header, metric );
256       else
257         error = pcf_parse_metric( stream, pcf_metric_header, metric );
258     }
259     else
260       error = pcf_parse_compressed_metric( stream, metric );
261
262     return error;
263   }
264
265
266   static FT_Error
267   pcfSeekToType( FT_Stream  stream,
268                  PCF_Table  tables,
269                  int        ntables,
270                  FT_ULong   type,
271                  FT_ULong*  formatp,
272                  FT_ULong*  sizep )
273   {
274     FT_Error error;
275     int      i;
276
277
278     for ( i = 0; i < ntables; i++ )
279       if ( tables[i].type == type )
280       {
281         if ( stream->pos > tables[i].offset )
282           return PCF_Err_Invalid_Stream_Skip;
283         if ( FILE_Skip( tables[i].offset - stream->pos ) )
284           return PCF_Err_Invalid_Stream_Skip;
285         *sizep   = tables[i].size;  /* unused - to be removed */
286         *formatp = tables[i].format;
287         return PCF_Err_Ok;
288       }
289
290     return PCF_Err_Invalid_File_Format;
291   }
292
293
294   static FT_Bool
295   pcfHasType( PCF_Table  tables,
296               int        ntables,
297               FT_ULong   type )
298   {
299     int i;
300
301
302     for ( i = 0; i < ntables; i++ )
303       if ( tables[i].type == type )
304         return TRUE;
305
306     return FALSE;
307   }
308
309
310   static
311   const FT_Frame_Field  pcf_property_header[] =
312   {
313 #undef  FT_STRUCTURE
314 #define FT_STRUCTURE  PCF_ParsePropertyRec
315
316     FT_FRAME_START( 9 ),
317       FT_FRAME_LONG_LE( name ),
318       FT_FRAME_BYTE   ( isString ),
319       FT_FRAME_LONG_LE( value ),
320     FT_FRAME_END
321   };
322
323
324   static
325   const FT_Frame_Field  pcf_property_msb_header[] =
326   {
327 #undef  FT_STRUCTURE
328 #define FT_STRUCTURE  PCF_ParsePropertyRec
329
330     FT_FRAME_START( 9 ),
331       FT_FRAME_LONG( name ),
332       FT_FRAME_BYTE( isString ),
333       FT_FRAME_LONG( value ),
334     FT_FRAME_END
335   };
336
337
338   static PCF_Property
339   find_property( PCF_Face          face,
340                  const FT_String*  prop )
341   {
342     PCF_Property  properties = face->properties;
343     FT_Bool       found      = 0;
344     int           i;
345
346
347     for ( i = 0 ; i < face->nprops && !found; i++ )
348     {
349       if ( !strcmp( properties[i].name, prop ) )
350         found = 1;
351     }
352
353     if ( found )
354       return properties + i - 1;
355     else
356       return NULL;
357   }
358
359
360   static FT_Error
361   pcf_get_properties( FT_Stream  stream,
362                       PCF_Face   face )
363   {
364     PCF_ParseProperty  props      = 0;
365     PCF_Property       properties = 0;
366     int                nprops, i;
367     FT_ULong           format, size;
368     FT_Error           error;
369     FT_Memory          memory     = FT_FACE(face)->memory;
370     FT_ULong           string_size;
371     FT_String*         strings    = 0;
372
373
374     error = pcfSeekToType( stream,
375                            face->toc.tables,
376                            face->toc.count,
377                            PCF_PROPERTIES,
378                            &format,
379                            &size );
380     if ( error )
381       goto Bail;
382
383     if ( READ_ULongLE( format ) )
384       goto Bail;
385
386     FT_TRACE4(( "get_prop: format = %ld\n", format ));
387
388     if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
389       goto Bail;
390
391     if ( PCF_BYTE_ORDER( format ) == MSBFirst )
392       (void)READ_ULong( nprops );
393     else
394       (void)READ_ULongLE( nprops );
395     if ( error )
396       goto Bail;
397
398     FT_TRACE4(( "get_prop: nprop = %d\n", nprops ));
399
400     if ( ALLOC( props, nprops * sizeof ( PCF_ParsePropertyRec ) ) )
401       goto Bail;
402
403     for ( i = 0; i < nprops; i++ )
404     {
405       if ( PCF_BYTE_ORDER( format ) == MSBFirst )
406       {
407         if ( READ_Fields( pcf_property_msb_header, props + i ) )
408           goto Bail;
409       }
410       else
411       {
412         if ( READ_Fields( pcf_property_header, props + i ) )
413           goto Bail;
414       }
415     }
416
417     /* pad the property array                                            */
418     /*                                                                   */
419     /* clever here - nprops is the same as the number of odd-units read, */
420     /* as only isStringProp are odd length   (Keith Packard)             */
421     /*                                                                   */
422     if ( nprops & 3 )
423     {
424       i = 4 - ( nprops & 3 );
425       FT_Skip_Stream( stream, i );
426     }
427
428     if ( PCF_BYTE_ORDER( format ) == MSBFirst )
429       (void)READ_ULong( string_size );
430     else
431       (void)READ_ULongLE( string_size );
432     if ( error )
433       goto Bail;
434
435     FT_TRACE4(( "get_prop: string_size = %ld\n", string_size ));
436
437     if ( ALLOC( strings, string_size * sizeof ( char ) ) )
438       goto Bail;
439
440     error = FT_Read_Stream( stream, (FT_Byte*)strings, string_size );
441     if ( error )
442       goto Bail;
443
444     if ( ALLOC( properties, nprops * sizeof ( PCF_PropertyRec ) ) )
445       goto Bail;
446
447     for ( i = 0; i < nprops; i++ )
448     {
449       /* XXX: make atom */
450       if ( ALLOC( properties[i].name,
451                      ( strlen( strings + props[i].name ) + 1 ) *
452                        sizeof ( char ) ) )
453         goto Bail;
454       strcpy( properties[i].name,strings + props[i].name );
455
456       properties[i].isString = props[i].isString;
457
458       if ( props[i].isString )
459       {
460         if ( ALLOC( properties[i].value.atom,
461                        ( strlen( strings + props[i].value ) + 1 ) *
462                          sizeof ( char ) ) )
463           goto Bail;
464         strcpy( properties[i].value.atom, strings + props[i].value );
465       }
466       else
467         properties[i].value.integer = props[i].value;
468     }
469
470     face->properties = properties;
471     face->nprops = nprops;
472
473     FREE( props );
474     FREE( strings );
475
476     return PCF_Err_Ok;
477
478   Bail:
479     FREE( props );
480     FREE( strings );
481
482     return error;
483   }
484
485
486   static FT_Error
487   pcf_get_metrics( FT_Stream  stream,
488                    PCF_Face   face )
489   {
490     FT_Error    error    = PCF_Err_Ok;
491     FT_Memory   memory   = FT_FACE(face)->memory;
492     FT_ULong    format   = 0;
493     FT_ULong    size     = 0;
494     PCF_Metric  metrics  = 0;
495     int         i;
496     int         nmetrics = -1;
497
498
499     error = pcfSeekToType( stream,
500                            face->toc.tables,
501                            face->toc.count,
502                            PCF_METRICS,
503                            &format,
504                            &size );
505     if ( error )
506       return error;
507
508     error = READ_ULongLE( format );
509
510     if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT )   &&
511          !PCF_FORMAT_MATCH( format, PCF_COMPRESSED_METRICS ) )
512       return PCF_Err_Invalid_File_Format;
513
514     if ( PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
515     {
516       if ( PCF_BYTE_ORDER( format ) == MSBFirst )
517         (void)READ_ULong( nmetrics );
518       else
519         (void)READ_ULongLE( nmetrics );
520     }
521     else
522     {
523       if ( PCF_BYTE_ORDER( format ) == MSBFirst )
524         (void)READ_UShort( nmetrics );
525       else
526         (void)READ_UShortLE( nmetrics );
527     }
528     if ( error || nmetrics == -1 )
529       return PCF_Err_Invalid_File_Format;
530
531     face->nmetrics = nmetrics;
532
533     if ( ALLOC( face->metrics, nmetrics * sizeof ( PCF_MetricRec ) ) )
534       return PCF_Err_Out_Of_Memory;
535
536     metrics = face->metrics;
537     for ( i = 0; i < nmetrics; i++ )
538     {
539       pcf_get_metric( stream, format, metrics + i );
540
541       metrics[i].bits = 0;
542
543       FT_TRACE4(( "%d : width=%d, "
544                   "lsb=%d, rsb=%d, ascent=%d, descent=%d, swidth=%d\n",
545                   i,
546                   ( metrics + i )->characterWidth,
547                   ( metrics + i )->leftSideBearing,
548                   ( metrics + i )->rightSideBearing,
549                   ( metrics + i )->ascent,
550                   ( metrics + i )->descent,
551                   ( metrics + i )->attributes ));
552
553       if ( error )
554         break;
555     }
556
557     if ( error )
558       FREE( face->metrics );
559     return error;
560   }
561
562
563   static FT_Error
564   pcf_get_bitmaps( FT_Stream  stream,
565                    PCF_Face   face )
566   {
567     FT_Error   error  = PCF_Err_Ok;
568     FT_Memory  memory = FT_FACE(face)->memory;
569     FT_Long*   offsets;
570     FT_Long    bitmapSizes[GLYPHPADOPTIONS];
571     FT_ULong   format, size;
572     int        nbitmaps, i, sizebitmaps = 0;
573     char*      bitmaps;
574
575
576     error = pcfSeekToType( stream,
577                            face->toc.tables,
578                            face->toc.count,
579                            PCF_BITMAPS,
580                            &format,
581                            &size );
582     if ( error )
583       return error;
584
585     error = FT_Access_Frame( stream, 8 );
586     if ( error )
587       return error;
588     format = GET_ULongLE();
589     if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
590       return PCF_Err_Invalid_File_Format;
591
592     if ( PCF_BYTE_ORDER( format ) == MSBFirst )
593       nbitmaps  = GET_ULong();
594     else
595       nbitmaps  = GET_ULongLE();
596     FT_Forget_Frame( stream );
597     if ( nbitmaps != face->nmetrics )
598       return PCF_Err_Invalid_File_Format;
599
600     if ( ALLOC( offsets, nbitmaps * sizeof ( FT_ULong ) ) )
601       return error;
602
603     if ( error )
604       goto Bail;
605     for ( i = 0; i < nbitmaps; i++ )
606     {
607       if ( PCF_BYTE_ORDER( format ) == MSBFirst )
608         (void)READ_Long( offsets[i] );
609       else
610         (void)READ_LongLE( offsets[i] );
611
612       FT_TRACE4(( "bitmap %d is at offset %ld\n", i, offsets[i] ));
613     }
614     if ( error )
615       goto Bail;
616
617     if ( error )
618       goto Bail;
619     for ( i = 0; i < GLYPHPADOPTIONS; i++ )
620     {
621       if ( PCF_BYTE_ORDER( format ) == MSBFirst )
622         (void)READ_Long( bitmapSizes[i] );
623       else
624         (void)READ_LongLE( bitmapSizes[i] );
625       if ( error )
626         goto Bail;
627
628       sizebitmaps = bitmapSizes[PCF_GLYPH_PAD_INDEX( format )];
629
630       FT_TRACE4(( "padding %d implies a size of %ld\n", i, bitmapSizes[i] ));
631     }
632
633     FT_TRACE4(( "  %d bitmaps, padding index %ld\n",
634                 nbitmaps,
635                 PCF_GLYPH_PAD_INDEX( format ) ));
636     FT_TRACE4(( "bitmap size = %d\n", sizebitmaps ));
637
638     for ( i = 0; i < nbitmaps; i++ )
639       face->metrics[i].bits = stream->pos + offsets[i];
640
641     face->bitmapsFormat = format;
642
643     FREE ( offsets );
644     return error;
645
646   Bail:
647     FREE ( offsets );
648     FREE ( bitmaps );
649     return error;
650   }
651
652
653   static FT_Error
654   pcf_get_encodings( FT_Stream  stream,
655                      PCF_Face   face )
656   {
657     FT_Error      error   = PCF_Err_Ok;
658     FT_Memory     memory  = FT_FACE(face)->memory;
659     FT_ULong      format, size;
660     int           firstCol, lastCol;
661     int           firstRow, lastRow;
662     int           nencoding, encodingOffset;
663     int           i, j;
664     PCF_Encoding  tmpEncoding, encoding = 0;
665
666
667     error = pcfSeekToType( stream,
668                            face->toc.tables,
669                            face->toc.count,
670                            PCF_BDF_ENCODINGS,
671                            &format,
672                            &size );
673     if ( error )
674       return error;
675
676     error = FT_Access_Frame( stream, 14 );
677     if ( error )
678       return error;
679     format = GET_ULongLE();
680     if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT ) )
681       return PCF_Err_Invalid_File_Format;
682
683     if ( PCF_BYTE_ORDER( format ) == MSBFirst )
684     {
685       firstCol          = GET_Short();
686       lastCol           = GET_Short();
687       firstRow          = GET_Short();
688       lastRow           = GET_Short();
689       face->defaultChar = GET_Short();
690     }
691     else
692     {
693       firstCol          = GET_ShortLE();
694       lastCol           = GET_ShortLE();
695       firstRow          = GET_ShortLE();
696       lastRow           = GET_ShortLE();
697       face->defaultChar = GET_ShortLE();
698     }
699
700     FT_Forget_Frame( stream );
701
702     FT_TRACE4(( "enc: firstCol %d, lastCol %d, firstRow %d, lastRow %d\n",
703                 firstCol, lastCol, firstRow, lastRow ));
704
705     nencoding = ( lastCol - firstCol + 1 ) * ( lastRow - firstRow + 1 );
706
707     if ( ALLOC( tmpEncoding, nencoding * sizeof ( PCF_EncodingRec ) ) )
708       return PCF_Err_Out_Of_Memory;
709
710     error = FT_Access_Frame( stream, 2 * nencoding );
711     if ( error )
712       goto Bail;
713
714     for ( i = 0, j = 0 ; i < nencoding; i++ )
715     {
716       if ( PCF_BYTE_ORDER( format ) == MSBFirst )
717         encodingOffset = GET_Short();
718       else
719         encodingOffset = GET_ShortLE();
720
721       if ( encodingOffset != -1 )
722       {
723         tmpEncoding[j].enc = ( ( ( i / ( lastCol - firstCol + 1 ) ) +
724                                  firstRow ) * 256 ) +
725                                ( ( i % ( lastCol - firstCol + 1 ) ) +
726                                  firstCol );
727
728         tmpEncoding[j].glyph = (FT_Short)encodingOffset;
729         j++;
730       }
731
732       FT_TRACE4(( "enc n. %d ; Uni %ld ; Glyph %d\n",
733                   i, tmpEncoding[j - 1].enc, encodingOffset ));
734     }
735     FT_Forget_Frame( stream );
736
737     if ( ALLOC( encoding, (--j) * sizeof ( PCF_EncodingRec ) ) )
738       goto Bail;
739
740     for ( i = 0; i < j; i++ )
741     {
742       encoding[i].enc   = tmpEncoding[i].enc;
743       encoding[i].glyph = tmpEncoding[i].glyph;
744     }
745
746     face->nencodings = j;
747     face->encodings  = encoding;
748     FREE( tmpEncoding );
749
750     return error;
751
752   Bail:
753     FREE( encoding );
754     FREE( tmpEncoding );
755     return error;
756   }
757
758
759   static
760   const FT_Frame_Field  pcf_accel_header[] =
761   {
762 #undef  FT_STRUCTURE
763 #define FT_STRUCTURE  PCF_AccelRec
764
765     FT_FRAME_START( 20 ),
766       FT_FRAME_BYTE      ( noOverlap ),
767       FT_FRAME_BYTE      ( constantMetrics ),
768       FT_FRAME_BYTE      ( terminalFont ),
769       FT_FRAME_BYTE      ( constantWidth ),
770       FT_FRAME_BYTE      ( inkInside ),
771       FT_FRAME_BYTE      ( inkMetrics ),
772       FT_FRAME_BYTE      ( drawDirection ),
773       FT_FRAME_SKIP_BYTES( 1 ),
774       FT_FRAME_LONG_LE   ( fontAscent ),
775       FT_FRAME_LONG_LE   ( fontDescent ),
776       FT_FRAME_LONG_LE   ( maxOverlap ),
777     FT_FRAME_END
778   };
779
780
781   static
782   const FT_Frame_Field  pcf_accel_msb_header[] =
783   {
784 #undef  FT_STRUCTURE
785 #define FT_STRUCTURE  PCF_AccelRec
786
787     FT_FRAME_START( 20 ),
788       FT_FRAME_BYTE      ( noOverlap ),
789       FT_FRAME_BYTE      ( constantMetrics ),
790       FT_FRAME_BYTE      ( terminalFont ),
791       FT_FRAME_BYTE      ( constantWidth ),
792       FT_FRAME_BYTE      ( inkInside ),
793       FT_FRAME_BYTE      ( inkMetrics ),
794       FT_FRAME_BYTE      ( drawDirection ),
795       FT_FRAME_SKIP_BYTES( 1 ),
796       FT_FRAME_LONG      ( fontAscent ),
797       FT_FRAME_LONG      ( fontDescent ),
798       FT_FRAME_LONG      ( maxOverlap ),
799     FT_FRAME_END
800   };
801
802
803   static FT_Error
804   pcf_get_accel( FT_Stream  stream,
805                  PCF_Face   face,
806                  FT_ULong   type )
807   {
808     FT_ULong   format, size;
809     FT_Error   error = PCF_Err_Ok;
810     PCF_Accel  accel = &face->accel;
811
812
813     error = pcfSeekToType( stream,
814                            face->toc.tables,
815                            face->toc.count,
816                            type,
817                            &format,
818                            &size );
819     if ( error )
820       goto Bail;
821
822     error = READ_ULongLE( format );
823     if ( !PCF_FORMAT_MATCH( format, PCF_DEFAULT_FORMAT )  &&
824          !PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
825       goto Bail;
826
827     if ( PCF_BYTE_ORDER( format ) == MSBFirst )
828     {
829       if ( READ_Fields( pcf_accel_msb_header, accel ) )
830         goto Bail;
831     }
832     else
833     {
834       if ( READ_Fields( pcf_accel_header, accel ) )
835         goto Bail;
836     }
837
838     error = pcf_get_metric( stream, format, &(accel->minbounds) );
839     if ( error )
840       goto Bail;
841     error = pcf_get_metric( stream, format, &(accel->maxbounds) );
842     if ( error )
843       goto Bail;
844
845     if ( PCF_FORMAT_MATCH( format, PCF_ACCEL_W_INKBOUNDS ) )
846     {
847       error = pcf_get_metric( stream, format, &(accel->ink_minbounds) );
848       if ( error )
849         goto Bail;
850       error = pcf_get_metric( stream, format, &(accel->ink_maxbounds) );
851       if ( error )
852         goto Bail;
853     }
854     else
855     {
856       accel->ink_minbounds = accel->minbounds; /* I'm not sure about this */
857       accel->ink_maxbounds = accel->maxbounds;
858     }
859     return error;
860
861   Bail:
862     return error;
863   }
864
865
866   FT_LOCAL_DEF FT_Error
867   pcf_load_font( FT_Stream  stream,
868                  PCF_Face   face )
869   {
870     FT_Error   error  = PCF_Err_Ok;
871     FT_Memory  memory = FT_FACE(face)->memory;
872     FT_Bool    hasBDFAccelerators;
873
874
875     error = pcf_read_TOC( stream, face );
876     if ( error )
877       return error;
878
879     error = pcf_get_properties( stream, face );
880     if ( error )
881       return error;;
882
883     /* Use the old accelerators if no BDF accelerators are in the file. */
884     hasBDFAccelerators = pcfHasType( face->toc.tables,
885                                      face->toc.count,
886                                      PCF_BDF_ACCELERATORS );
887     if ( !hasBDFAccelerators )
888     {
889       error = pcf_get_accel( stream, face, PCF_ACCELERATORS );
890       if ( error )
891         goto Bail;
892     }
893
894     /* metrics */
895     error = pcf_get_metrics( stream, face );
896     if ( error )
897       goto Bail;
898
899     /* bitmaps */
900     error = pcf_get_bitmaps( stream, face );
901     if ( error )
902       goto Bail;
903
904     /* encodings */
905     error = pcf_get_encodings( stream, face );
906     if ( error )
907       goto Bail;
908
909     /* BDF style accelerators (i.e. bounds based on encoded glyphs) */
910     if ( hasBDFAccelerators )
911     {
912       error = pcf_get_accel( stream, face, PCF_BDF_ACCELERATORS );
913       if ( error )
914         goto Bail;
915     }
916
917     /* XXX: TO DO: inkmetrics and glyph_names are missing */
918
919     /* now construct the face object */
920     {
921       FT_Face       root = FT_FACE( face );
922       PCF_Property  prop;
923
924
925       root->num_faces = 1;
926       root->face_index = 0;
927       root->face_flags = FT_FACE_FLAG_FIXED_SIZES |
928                          FT_FACE_FLAG_HORIZONTAL  |
929                          FT_FACE_FLAG_FAST_GLYPHS;
930
931       if ( face->accel.constantWidth )
932         root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
933
934       root->style_flags = 0;
935       prop = find_property( face, "SLANT" );
936       if ( prop != NULL )
937         if ( prop->isString )
938           if ( ( *(prop->value.atom) == 'O' ) ||
939                ( *(prop->value.atom) == 'I' ) )
940             root->style_flags |= FT_STYLE_FLAG_ITALIC;
941
942       prop = find_property( face, "WEIGHT_NAME" );
943       if ( prop != NULL )
944         if ( prop->isString )
945           if ( *(prop->value.atom) == 'B' )
946             root->style_flags |= FT_STYLE_FLAG_BOLD;
947
948       root->style_name = (char *)"Regular";
949
950       if ( root->style_flags & FT_STYLE_FLAG_BOLD ) {
951         if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
952           root->style_name = (char *)"Bold Italic";
953         else
954           root->style_name = (char *)"Bold";
955       }
956       else if ( root->style_flags & FT_STYLE_FLAG_ITALIC )
957         root->style_name = (char *)"Italic";
958
959       prop = find_property( face, "FAMILY_NAME" );
960       if ( prop != NULL )
961       {
962         if ( prop->isString )
963         {
964           int  l = strlen( prop->value.atom ) + 1;
965
966
967           if ( ALLOC( root->family_name, l * sizeof ( char ) ) )
968             goto Bail;
969           strcpy( root->family_name, prop->value.atom );
970         }
971       }
972       else
973         root->family_name = 0;
974
975       root->num_glyphs = face->nmetrics;
976
977       root->num_fixed_sizes = 1;
978       if ( ALLOC_ARRAY( root->available_sizes, 1, FT_Bitmap_Size ) )
979         goto Bail;
980
981       prop = find_property( face, "PIXEL_SIZE" );
982       if ( prop != NULL )
983       {
984         PCF_Property  xres = 0, yres = 0;
985
986
987         xres = find_property( face, "RESOLUTION_X" );
988         yres = find_property( face, "RESOLUTION_Y" );
989         if ( ( xres != NULL ) && ( yres != NULL ) )
990         {
991           root->available_sizes->width =
992             (FT_Short)( prop->value.integer * 75 / xres->value.integer );
993           root->available_sizes->height =
994             (FT_Short)( prop->value.integer * 75 / yres->value.integer );
995         }
996       }
997       else
998       { /* XXX */
999 #if 0
1000         printf( "PCF Warning: Pixel Size undefined, assuming 12\n");
1001 #endif
1002         root->available_sizes->width = 12;
1003         root->available_sizes->height = 12;
1004       }
1005
1006       /* XXX: charmaps */
1007       root->charmaps     = &face->charmap_handle;
1008       root->num_charmaps = 1;
1009
1010       {
1011         PCF_Property  charset_registry = 0, charset_encoding = 0;
1012
1013
1014         charset_registry = find_property( face, "CHARSET_REGISTRY" );
1015         charset_encoding = find_property( face, "CHARSET_ENCODING" );
1016
1017         if ( ( charset_registry != NULL ) &&
1018              ( charset_encoding != NULL ) )
1019         {
1020           if ( ( charset_registry->isString ) &&
1021                ( charset_encoding->isString ) )
1022           {
1023             if ( ALLOC( face->charset_encoding,
1024                         ( strlen( charset_encoding->value.atom ) + 1 ) *
1025                           sizeof ( char ) ) )
1026               goto Bail;
1027             if ( ALLOC( face->charset_registry,
1028                         ( strlen( charset_registry->value.atom ) + 1 ) *
1029                           sizeof ( char ) ) )
1030               goto Bail;
1031             strcpy( face->charset_registry, charset_registry->value.atom );
1032             strcpy( face->charset_encoding, charset_encoding->value.atom );
1033
1034 #if 0
1035             if ( !strcmp( charset_registry, "ISO10646" ) )
1036             {
1037               face->charmap.encoding    = ft_encoding_unicode;
1038               face->charmap.platform_id = 3;
1039               face->charmap.encoding_id = 1;
1040               face->charmap.face        = root;
1041               face->charmap_handle
1042
1043               return PCF_Err_Ok;
1044             }
1045 #endif
1046           }
1047         }
1048       }
1049
1050       face->charmap.encoding    = ft_encoding_none;
1051       face->charmap.platform_id = 0;
1052       face->charmap.encoding_id = 0;
1053       face->charmap.face        = root;
1054       face->charmap_handle      = &face->charmap;
1055       root->charmap             = face->charmap_handle;
1056     }
1057     return PCF_Err_Ok;
1058
1059   Bail:
1060     PCF_Done_Face( face );
1061     return PCF_Err_Invalid_File_Format;
1062   }
1063
1064
1065 /* END */