source: trunk/poppler/freetype-2.1.10/src/pcf/pcfread.c @ 2

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 16 years ago

First import

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