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