source: trunk/poppler/freetype2/src/psaux/afmparse.c @ 262

Last change on this file since 262 was 262, checked in by Eugene Romanenko, 12 years ago

PDF plugin: freetype library updated to version 2.3.8

File size: 23.1 KB
Line 
1/***************************************************************************/
2/*                                                                         */
3/*  afmparse.c                                                             */
4/*                                                                         */
5/*    AFM parser (body).                                                   */
6/*                                                                         */
7/*  Copyright 2006, 2007, 2008 by                                          */
8/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9/*                                                                         */
10/*  This file is part of the FreeType project, and may only be used,       */
11/*  modified, and distributed under the terms of the FreeType project      */
12/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13/*  this file you indicate that you have read the license and              */
14/*  understand and accept it fully.                                        */
15/*                                                                         */
16/***************************************************************************/
17
18#include <ft2build.h>
19#include FT_FREETYPE_H
20#include FT_INTERNAL_POSTSCRIPT_AUX_H
21#include FT_INTERNAL_DEBUG_H
22
23#include "afmparse.h"
24#include "psconv.h"
25
26#include "psauxerr.h"
27
28
29/***************************************************************************/
30/*                                                                         */
31/*    AFM_Stream                                                           */
32/*                                                                         */
33/* The use of AFM_Stream is largely inspired by parseAFM.[ch] from t1lib.  */
34/*                                                                         */
35/*                                                                         */
36
37  enum
38  {
39    AFM_STREAM_STATUS_NORMAL,
40    AFM_STREAM_STATUS_EOC,
41    AFM_STREAM_STATUS_EOL,
42    AFM_STREAM_STATUS_EOF
43  };
44
45
46  typedef struct  AFM_StreamRec_
47  {
48    FT_Byte*  cursor;
49    FT_Byte*  base;
50    FT_Byte*  limit;
51
52    FT_Int    status;
53
54  } AFM_StreamRec;
55
56
57#ifndef EOF
58#define EOF -1
59#endif
60
61
62  /* this works because empty lines are ignored */
63#define AFM_IS_NEWLINE( ch )  ( (ch) == '\r' || (ch) == '\n' )
64
65#define AFM_IS_EOF( ch )      ( (ch) == EOF  || (ch) == '\x1a' )
66#define AFM_IS_SPACE( ch )    ( (ch) == ' '  || (ch) == '\t' )
67
68  /* column separator; there is no `column' in the spec actually */
69#define AFM_IS_SEP( ch )      ( (ch) == ';' )
70
71#define AFM_GETC()                                                       \
72          ( ( (stream)->cursor < (stream)->limit ) ? *(stream)->cursor++ \
73                                                   : EOF )
74
75#define AFM_STREAM_KEY_BEGIN( stream )    \
76          (char*)( (stream)->cursor - 1 )
77
78#define AFM_STREAM_KEY_LEN( stream, key )       \
79          ( (char*)(stream)->cursor - key - 1 )
80
81#define AFM_STATUS_EOC( stream ) \
82          ( (stream)->status >= AFM_STREAM_STATUS_EOC )
83
84#define AFM_STATUS_EOL( stream ) \
85          ( (stream)->status >= AFM_STREAM_STATUS_EOL )
86
87#define AFM_STATUS_EOF( stream ) \
88          ( (stream)->status >= AFM_STREAM_STATUS_EOF )
89
90
91  static int
92  afm_stream_skip_spaces( AFM_Stream  stream )
93  {
94    int  ch = 0;  /* make stupid compiler happy */
95
96
97    if ( AFM_STATUS_EOC( stream ) )
98      return ';';
99
100    while ( 1 )
101    {
102      ch = AFM_GETC();
103      if ( !AFM_IS_SPACE( ch ) )
104        break;
105    }
106
107    if ( AFM_IS_NEWLINE( ch ) )
108      stream->status = AFM_STREAM_STATUS_EOL;
109    else if ( AFM_IS_SEP( ch ) )
110      stream->status = AFM_STREAM_STATUS_EOC;
111    else if ( AFM_IS_EOF( ch ) )
112      stream->status = AFM_STREAM_STATUS_EOF;
113
114    return ch;
115  }
116
117
118  /* read a key or value in current column */
119  static char*
120  afm_stream_read_one( AFM_Stream  stream )
121  {
122    char*  str;
123    int    ch;
124
125
126    afm_stream_skip_spaces( stream );
127    if ( AFM_STATUS_EOC( stream ) )
128      return NULL;
129
130    str = AFM_STREAM_KEY_BEGIN( stream );
131
132    while ( 1 )
133    {
134      ch = AFM_GETC();
135      if ( AFM_IS_SPACE( ch ) )
136        break;
137      else if ( AFM_IS_NEWLINE( ch ) )
138      {
139        stream->status = AFM_STREAM_STATUS_EOL;
140        break;
141      }
142      else if ( AFM_IS_SEP( ch ) )
143      {
144        stream->status = AFM_STREAM_STATUS_EOC;
145        break;
146      }
147      else if ( AFM_IS_EOF( ch ) )
148      {
149        stream->status = AFM_STREAM_STATUS_EOF;
150        break;
151      }
152    }
153
154    return str;
155  }
156
157
158  /* read a string (i.e., read to EOL) */
159  static char*
160  afm_stream_read_string( AFM_Stream  stream )
161  {
162    char*  str;
163    int    ch;
164
165
166    afm_stream_skip_spaces( stream );
167    if ( AFM_STATUS_EOL( stream ) )
168      return NULL;
169
170    str = AFM_STREAM_KEY_BEGIN( stream );
171
172    /* scan to eol */
173    while ( 1 )
174    {
175      ch = AFM_GETC();
176      if ( AFM_IS_NEWLINE( ch ) )
177      {
178        stream->status = AFM_STREAM_STATUS_EOL;
179        break;
180      }
181      else if ( AFM_IS_EOF( ch ) )
182      {
183        stream->status = AFM_STREAM_STATUS_EOF;
184        break;
185      }
186    }
187
188    return str;
189  }
190
191
192  /*************************************************************************/
193  /*                                                                       */
194  /*    AFM_Parser                                                         */
195  /*                                                                       */
196  /*                                                                       */
197
198  /* all keys defined in Ch. 7-10 of 5004.AFM_Spec.pdf */
199  typedef enum  AFM_Token_
200  {
201    AFM_TOKEN_ASCENDER,
202    AFM_TOKEN_AXISLABEL,
203    AFM_TOKEN_AXISTYPE,
204    AFM_TOKEN_B,
205    AFM_TOKEN_BLENDAXISTYPES,
206    AFM_TOKEN_BLENDDESIGNMAP,
207    AFM_TOKEN_BLENDDESIGNPOSITIONS,
208    AFM_TOKEN_C,
209    AFM_TOKEN_CC,
210    AFM_TOKEN_CH,
211    AFM_TOKEN_CAPHEIGHT,
212    AFM_TOKEN_CHARWIDTH,
213    AFM_TOKEN_CHARACTERSET,
214    AFM_TOKEN_CHARACTERS,
215    AFM_TOKEN_DESCENDER,
216    AFM_TOKEN_ENCODINGSCHEME,
217    AFM_TOKEN_ENDAXIS,
218    AFM_TOKEN_ENDCHARMETRICS,
219    AFM_TOKEN_ENDCOMPOSITES,
220    AFM_TOKEN_ENDDIRECTION,
221    AFM_TOKEN_ENDFONTMETRICS,
222    AFM_TOKEN_ENDKERNDATA,
223    AFM_TOKEN_ENDKERNPAIRS,
224    AFM_TOKEN_ENDTRACKKERN,
225    AFM_TOKEN_ESCCHAR,
226    AFM_TOKEN_FAMILYNAME,
227    AFM_TOKEN_FONTBBOX,
228    AFM_TOKEN_FONTNAME,
229    AFM_TOKEN_FULLNAME,
230    AFM_TOKEN_ISBASEFONT,
231    AFM_TOKEN_ISCIDFONT,
232    AFM_TOKEN_ISFIXEDPITCH,
233    AFM_TOKEN_ISFIXEDV,
234    AFM_TOKEN_ITALICANGLE,
235    AFM_TOKEN_KP,
236    AFM_TOKEN_KPH,
237    AFM_TOKEN_KPX,
238    AFM_TOKEN_KPY,
239    AFM_TOKEN_L,
240    AFM_TOKEN_MAPPINGSCHEME,
241    AFM_TOKEN_METRICSSETS,
242    AFM_TOKEN_N,
243    AFM_TOKEN_NOTICE,
244    AFM_TOKEN_PCC,
245    AFM_TOKEN_STARTAXIS,
246    AFM_TOKEN_STARTCHARMETRICS,
247    AFM_TOKEN_STARTCOMPOSITES,
248    AFM_TOKEN_STARTDIRECTION,
249    AFM_TOKEN_STARTFONTMETRICS,
250    AFM_TOKEN_STARTKERNDATA,
251    AFM_TOKEN_STARTKERNPAIRS,
252    AFM_TOKEN_STARTKERNPAIRS0,
253    AFM_TOKEN_STARTKERNPAIRS1,
254    AFM_TOKEN_STARTTRACKKERN,
255    AFM_TOKEN_STDHW,
256    AFM_TOKEN_STDVW,
257    AFM_TOKEN_TRACKKERN,
258    AFM_TOKEN_UNDERLINEPOSITION,
259    AFM_TOKEN_UNDERLINETHICKNESS,
260    AFM_TOKEN_VV,
261    AFM_TOKEN_VVECTOR,
262    AFM_TOKEN_VERSION,
263    AFM_TOKEN_W,
264    AFM_TOKEN_W0,
265    AFM_TOKEN_W0X,
266    AFM_TOKEN_W0Y,
267    AFM_TOKEN_W1,
268    AFM_TOKEN_W1X,
269    AFM_TOKEN_W1Y,
270    AFM_TOKEN_WX,
271    AFM_TOKEN_WY,
272    AFM_TOKEN_WEIGHT,
273    AFM_TOKEN_WEIGHTVECTOR,
274    AFM_TOKEN_XHEIGHT,
275    N_AFM_TOKENS,
276    AFM_TOKEN_UNKNOWN
277
278  } AFM_Token;
279
280
281  static const char*  const afm_key_table[N_AFM_TOKENS] =
282  {
283    "Ascender",
284    "AxisLabel",
285    "AxisType",
286    "B",
287    "BlendAxisTypes",
288    "BlendDesignMap",
289    "BlendDesignPositions",
290    "C",
291    "CC",
292    "CH",
293    "CapHeight",
294    "CharWidth",
295    "CharacterSet",
296    "Characters",
297    "Descender",
298    "EncodingScheme",
299    "EndAxis",
300    "EndCharMetrics",
301    "EndComposites",
302    "EndDirection",
303    "EndFontMetrics",
304    "EndKernData",
305    "EndKernPairs",
306    "EndTrackKern",
307    "EscChar",
308    "FamilyName",
309    "FontBBox",
310    "FontName",
311    "FullName",
312    "IsBaseFont",
313    "IsCIDFont",
314    "IsFixedPitch",
315    "IsFixedV",
316    "ItalicAngle",
317    "KP",
318    "KPH",
319    "KPX",
320    "KPY",
321    "L",
322    "MappingScheme",
323    "MetricsSets",
324    "N",
325    "Notice",
326    "PCC",
327    "StartAxis",
328    "StartCharMetrics",
329    "StartComposites",
330    "StartDirection",
331    "StartFontMetrics",
332    "StartKernData",
333    "StartKernPairs",
334    "StartKernPairs0",
335    "StartKernPairs1",
336    "StartTrackKern",
337    "StdHW",
338    "StdVW",
339    "TrackKern",
340    "UnderlinePosition",
341    "UnderlineThickness",
342    "VV",
343    "VVector",
344    "Version",
345    "W",
346    "W0",
347    "W0X",
348    "W0Y",
349    "W1",
350    "W1X",
351    "W1Y",
352    "WX",
353    "WY",
354    "Weight",
355    "WeightVector",
356    "XHeight"
357  };
358
359
360  /*
361   * `afm_parser_read_vals' and `afm_parser_next_key' provide
362   * high-level operations to an AFM_Stream.  The rest of the
363   * parser functions should use them without accessing the
364   * AFM_Stream directly.
365   */
366
367  FT_LOCAL_DEF( FT_Int )
368  afm_parser_read_vals( AFM_Parser  parser,
369                        AFM_Value   vals,
370                        FT_Int      n )
371  {
372    AFM_Stream  stream = parser->stream;
373    char*       str;
374    FT_Int      i;
375
376
377    if ( n > AFM_MAX_ARGUMENTS )
378      return 0;
379
380    for ( i = 0; i < n; i++ )
381    {
382      FT_UInt    len;
383      AFM_Value  val = vals + i;
384
385
386      if ( val->type == AFM_VALUE_TYPE_STRING )
387        str = afm_stream_read_string( stream );
388      else
389        str = afm_stream_read_one( stream );
390
391      if ( !str )
392        break;
393
394      len = AFM_STREAM_KEY_LEN( stream, str );
395
396      switch ( val->type )
397      {
398      case AFM_VALUE_TYPE_STRING:
399      case AFM_VALUE_TYPE_NAME:
400        {
401          FT_Memory  memory = parser->memory;
402          FT_Error   error;
403
404
405          if ( !FT_QALLOC( val->u.s, len + 1 ) )
406          {
407            ft_memcpy( val->u.s, str, len );
408            val->u.s[len] = '\0';
409          }
410        }
411        break;
412
413      case AFM_VALUE_TYPE_FIXED:
414        val->u.f = PS_Conv_ToFixed( (FT_Byte**)(void*)&str,
415                                    (FT_Byte*)str + len, 0 );
416        break;
417
418      case AFM_VALUE_TYPE_INTEGER:
419        val->u.i = PS_Conv_ToInt( (FT_Byte**)(void*)&str,
420                                  (FT_Byte*)str + len );
421        break;
422
423      case AFM_VALUE_TYPE_BOOL:
424        val->u.b = FT_BOOL( len == 4                      &&
425                            !ft_strncmp( str, "true", 4 ) );
426        break;
427
428      case AFM_VALUE_TYPE_INDEX:
429        if ( parser->get_index )
430          val->u.i = parser->get_index( str, len, parser->user_data );
431        else
432          val->u.i = 0;
433        break;
434      }
435    }
436
437    return i;
438  }
439
440
441  FT_LOCAL_DEF( char* )
442  afm_parser_next_key( AFM_Parser  parser,
443                       FT_Bool     line,
444                       FT_UInt*    len )
445  {
446    AFM_Stream  stream = parser->stream;
447    char*       key    = 0;  /* make stupid compiler happy */
448
449
450    if ( line )
451    {
452      while ( 1 )
453      {
454        /* skip current line */
455        if ( !AFM_STATUS_EOL( stream ) )
456          afm_stream_read_string( stream );
457
458        stream->status = AFM_STREAM_STATUS_NORMAL;
459        key = afm_stream_read_one( stream );
460
461        /* skip empty line */
462        if ( !key                      &&
463             !AFM_STATUS_EOF( stream ) &&
464             AFM_STATUS_EOL( stream )  )
465          continue;
466
467        break;
468      }
469    }
470    else
471    {
472      while ( 1 )
473      {
474        /* skip current column */
475        while ( !AFM_STATUS_EOC( stream ) )
476          afm_stream_read_one( stream );
477
478        stream->status = AFM_STREAM_STATUS_NORMAL;
479        key = afm_stream_read_one( stream );
480
481        /* skip empty column */
482        if ( !key                      &&
483             !AFM_STATUS_EOF( stream ) &&
484             AFM_STATUS_EOC( stream )  )
485          continue;
486
487        break;
488      }
489    }
490
491    if ( len )
492      *len = ( key ) ? AFM_STREAM_KEY_LEN( stream, key )
493                     : 0;
494
495    return key;
496  }
497
498
499  static AFM_Token
500  afm_tokenize( const char*  key,
501                FT_UInt      len )
502  {
503    int  n;
504
505
506    for ( n = 0; n < N_AFM_TOKENS; n++ )
507    {
508      if ( *( afm_key_table[n] ) == *key )
509      {
510        for ( ; n < N_AFM_TOKENS; n++ )
511        {
512          if ( *( afm_key_table[n] ) != *key )
513            return AFM_TOKEN_UNKNOWN;
514
515          if ( ft_strncmp( afm_key_table[n], key, len ) == 0 )
516            return (AFM_Token) n;
517        }
518      }
519    }
520
521    return AFM_TOKEN_UNKNOWN;
522  }
523
524
525  FT_LOCAL_DEF( FT_Error )
526  afm_parser_init( AFM_Parser  parser,
527                   FT_Memory   memory,
528                   FT_Byte*    base,
529                   FT_Byte*    limit )
530  {
531    AFM_Stream  stream;
532    FT_Error    error;
533
534
535    if ( FT_NEW( stream ) )
536      return error;
537
538    stream->cursor = stream->base = base;
539    stream->limit  = limit;
540
541    /* don't skip the first line during the first call */
542    stream->status = AFM_STREAM_STATUS_EOL;
543
544    parser->memory    = memory;
545    parser->stream    = stream;
546    parser->FontInfo  = NULL;
547    parser->get_index = NULL;
548
549    return PSaux_Err_Ok;
550  }
551
552
553  FT_LOCAL( void )
554  afm_parser_done( AFM_Parser  parser )
555  {
556    FT_Memory  memory = parser->memory;
557
558
559    FT_FREE( parser->stream );
560  }
561
562
563  FT_LOCAL_DEF( FT_Error )
564  afm_parser_read_int( AFM_Parser  parser,
565                       FT_Int*     aint )
566  {
567    AFM_ValueRec  val;
568
569
570    val.type = AFM_VALUE_TYPE_INTEGER;
571
572    if ( afm_parser_read_vals( parser, &val, 1 ) == 1 )
573    {
574      *aint = val.u.i;
575
576      return PSaux_Err_Ok;
577    }
578    else
579      return PSaux_Err_Syntax_Error;
580  }
581
582
583  static FT_Error
584  afm_parse_track_kern( AFM_Parser  parser )
585  {
586    AFM_FontInfo   fi = parser->FontInfo;
587    AFM_TrackKern  tk;
588    char*          key;
589    FT_UInt        len;
590    int            n = -1;
591
592
593    if ( afm_parser_read_int( parser, &fi->NumTrackKern ) )
594        goto Fail;
595
596    if ( fi->NumTrackKern )
597    {
598      FT_Memory  memory = parser->memory;
599      FT_Error   error;
600
601
602      if ( FT_QNEW_ARRAY( fi->TrackKerns, fi->NumTrackKern ) )
603        return error;
604    }
605
606    while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
607    {
608      AFM_ValueRec  shared_vals[5];
609
610
611      switch ( afm_tokenize( key, len ) )
612      {
613      case AFM_TOKEN_TRACKKERN:
614        n++;
615
616        if ( n >= fi->NumTrackKern )
617          goto Fail;
618
619        tk = fi->TrackKerns + n;
620
621        shared_vals[0].type = AFM_VALUE_TYPE_INTEGER;
622        shared_vals[1].type = AFM_VALUE_TYPE_FIXED;
623        shared_vals[2].type = AFM_VALUE_TYPE_FIXED;
624        shared_vals[3].type = AFM_VALUE_TYPE_FIXED;
625        shared_vals[4].type = AFM_VALUE_TYPE_FIXED;
626        if ( afm_parser_read_vals( parser, shared_vals, 5 ) != 5 )
627          goto Fail;
628
629        tk->degree     = shared_vals[0].u.i;
630        tk->min_ptsize = shared_vals[1].u.f;
631        tk->min_kern   = shared_vals[2].u.f;
632        tk->max_ptsize = shared_vals[3].u.f;
633        tk->max_kern   = shared_vals[4].u.f;
634
635        /* is this correct? */
636        if ( tk->degree < 0 && tk->min_kern > 0 )
637          tk->min_kern = -tk->min_kern;
638        break;
639
640      case AFM_TOKEN_ENDTRACKKERN:
641      case AFM_TOKEN_ENDKERNDATA:
642      case AFM_TOKEN_ENDFONTMETRICS:
643        fi->NumTrackKern = n + 1;
644        return PSaux_Err_Ok;
645
646      case AFM_TOKEN_UNKNOWN:
647        break;
648
649      default:
650        goto Fail;
651      }
652    }
653
654  Fail:
655    return PSaux_Err_Syntax_Error;
656  }
657
658
659#undef  KERN_INDEX
660#define KERN_INDEX( g1, g2 )  ( ( (FT_ULong)g1 << 16 ) | g2 )
661
662
663  /* compare two kerning pairs */
664  FT_CALLBACK_DEF( int )
665  afm_compare_kern_pairs( const void*  a,
666                          const void*  b )
667  {
668    AFM_KernPair  kp1 = (AFM_KernPair)a;
669    AFM_KernPair  kp2 = (AFM_KernPair)b;
670
671    FT_ULong  index1 = KERN_INDEX( kp1->index1, kp1->index2 );
672    FT_ULong  index2 = KERN_INDEX( kp2->index1, kp2->index2 );
673
674
675    if ( index1 > index2 )
676      return 1;
677    else if ( index1 < index2 )
678      return -1;
679    else
680      return 0;
681  }
682
683
684  static FT_Error
685  afm_parse_kern_pairs( AFM_Parser  parser )
686  {
687    AFM_FontInfo  fi = parser->FontInfo;
688    AFM_KernPair  kp;
689    char*         key;
690    FT_UInt       len;
691    int           n = -1;
692
693
694    if ( afm_parser_read_int( parser, &fi->NumKernPair ) )
695      goto Fail;
696
697    if ( fi->NumKernPair )
698    {
699      FT_Memory  memory = parser->memory;
700      FT_Error   error;
701
702
703      if ( FT_QNEW_ARRAY( fi->KernPairs, fi->NumKernPair ) )
704        return error;
705    }
706
707    while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
708    {
709      AFM_Token  token = afm_tokenize( key, len );
710
711
712      switch ( token )
713      {
714      case AFM_TOKEN_KP:
715      case AFM_TOKEN_KPX:
716      case AFM_TOKEN_KPY:
717        {
718          FT_Int        r;
719          AFM_ValueRec  shared_vals[4];
720
721
722          n++;
723
724          if ( n >= fi->NumKernPair )
725            goto Fail;
726
727          kp = fi->KernPairs + n;
728
729          shared_vals[0].type = AFM_VALUE_TYPE_INDEX;
730          shared_vals[1].type = AFM_VALUE_TYPE_INDEX;
731          shared_vals[2].type = AFM_VALUE_TYPE_INTEGER;
732          shared_vals[3].type = AFM_VALUE_TYPE_INTEGER;
733          r = afm_parser_read_vals( parser, shared_vals, 4 );
734          if ( r < 3 )
735            goto Fail;
736
737          kp->index1 = shared_vals[0].u.i;
738          kp->index2 = shared_vals[1].u.i;
739          if ( token == AFM_TOKEN_KPY )
740          {
741            kp->x = 0;
742            kp->y = shared_vals[2].u.i;
743          }
744          else
745          {
746            kp->x = shared_vals[2].u.i;
747            kp->y = ( token == AFM_TOKEN_KP && r == 4 )
748                      ? shared_vals[3].u.i : 0;
749          }
750        }
751        break;
752
753      case AFM_TOKEN_ENDKERNPAIRS:
754      case AFM_TOKEN_ENDKERNDATA:
755      case AFM_TOKEN_ENDFONTMETRICS:
756        fi->NumKernPair = n + 1;
757        ft_qsort( fi->KernPairs, fi->NumKernPair,
758                  sizeof( AFM_KernPairRec ),
759                  afm_compare_kern_pairs );
760        return PSaux_Err_Ok;
761
762      case AFM_TOKEN_UNKNOWN:
763        break;
764
765      default:
766        goto Fail;
767      }
768    }
769
770  Fail:
771    return PSaux_Err_Syntax_Error;
772  }
773
774
775  static FT_Error
776  afm_parse_kern_data( AFM_Parser  parser )
777  {
778    FT_Error  error;
779    char*     key;
780    FT_UInt   len;
781
782
783    while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
784    {
785      switch ( afm_tokenize( key, len ) )
786      {
787      case AFM_TOKEN_STARTTRACKKERN:
788        error = afm_parse_track_kern( parser );
789        if ( error )
790          return error;
791        break;
792
793      case AFM_TOKEN_STARTKERNPAIRS:
794      case AFM_TOKEN_STARTKERNPAIRS0:
795        error = afm_parse_kern_pairs( parser );
796        if ( error )
797          return error;
798        break;
799
800      case AFM_TOKEN_ENDKERNDATA:
801      case AFM_TOKEN_ENDFONTMETRICS:
802        return PSaux_Err_Ok;
803
804      case AFM_TOKEN_UNKNOWN:
805        break;
806
807      default:
808        goto Fail;
809      }
810    }
811
812  Fail:
813    return PSaux_Err_Syntax_Error;
814  }
815
816
817  static FT_Error
818  afm_parser_skip_section( AFM_Parser  parser,
819                           FT_UInt     n,
820                           AFM_Token   end_section )
821  {
822    char*    key;
823    FT_UInt  len;
824
825
826    while ( n-- > 0 )
827    {
828      key = afm_parser_next_key( parser, 1, NULL );
829      if ( !key )
830        goto Fail;
831    }
832
833    while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
834    {
835      AFM_Token  token = afm_tokenize( key, len );
836
837
838      if ( token == end_section || token == AFM_TOKEN_ENDFONTMETRICS )
839        return PSaux_Err_Ok;
840    }
841
842  Fail:
843    return PSaux_Err_Syntax_Error;
844  }
845
846
847  FT_LOCAL_DEF( FT_Error )
848  afm_parser_parse( AFM_Parser  parser )
849  {
850    FT_Memory     memory = parser->memory;
851    AFM_FontInfo  fi     = parser->FontInfo;
852    FT_Error      error  = PSaux_Err_Syntax_Error;
853    char*         key;
854    FT_UInt       len;
855    FT_Int        metrics_sets = 0;
856
857
858    if ( !fi )
859      return PSaux_Err_Invalid_Argument;
860
861    key = afm_parser_next_key( parser, 1, &len );
862    if ( !key || len != 16                              ||
863         ft_strncmp( key, "StartFontMetrics", 16 ) != 0 )
864      return PSaux_Err_Unknown_File_Format;
865
866    while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
867    {
868      AFM_ValueRec  shared_vals[4];
869
870
871      switch ( afm_tokenize( key, len ) )
872      {
873      case AFM_TOKEN_METRICSSETS:
874        if ( afm_parser_read_int( parser, &metrics_sets ) )
875          goto Fail;
876
877        if ( metrics_sets != 0 && metrics_sets != 2 )
878        {
879          error = PSaux_Err_Unimplemented_Feature;
880
881          goto Fail;
882        }
883        break;
884
885      case AFM_TOKEN_ISCIDFONT:
886        shared_vals[0].type = AFM_VALUE_TYPE_BOOL;
887        if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 )
888          goto Fail;
889
890        fi->IsCIDFont = shared_vals[0].u.b;
891        break;
892
893      case AFM_TOKEN_FONTBBOX:
894        shared_vals[0].type = AFM_VALUE_TYPE_FIXED;
895        shared_vals[1].type = AFM_VALUE_TYPE_FIXED;
896        shared_vals[2].type = AFM_VALUE_TYPE_FIXED;
897        shared_vals[3].type = AFM_VALUE_TYPE_FIXED;
898        if ( afm_parser_read_vals( parser, shared_vals, 4 ) != 4 )
899          goto Fail;
900
901        fi->FontBBox.xMin = shared_vals[0].u.f;
902        fi->FontBBox.yMin = shared_vals[1].u.f;
903        fi->FontBBox.xMax = shared_vals[2].u.f;
904        fi->FontBBox.yMax = shared_vals[3].u.f;
905        break;
906
907      case AFM_TOKEN_ASCENDER:
908        shared_vals[0].type = AFM_VALUE_TYPE_FIXED;
909        if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 )
910          goto Fail;
911
912        fi->Ascender = shared_vals[0].u.f;
913        break;
914
915      case AFM_TOKEN_DESCENDER:
916        shared_vals[0].type = AFM_VALUE_TYPE_FIXED;
917        if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 )
918          goto Fail;
919
920        fi->Descender = shared_vals[0].u.f;
921        break;
922
923      case AFM_TOKEN_STARTCHARMETRICS:
924        {
925          FT_Int  n = 0;
926
927
928          if ( afm_parser_read_int( parser, &n ) )
929            goto Fail;
930
931          error = afm_parser_skip_section( parser, n,
932                                           AFM_TOKEN_ENDCHARMETRICS );
933          if ( error )
934            return error;
935        }
936        break;
937
938      case AFM_TOKEN_STARTKERNDATA:
939        error = afm_parse_kern_data( parser );
940        if ( error )
941          goto Fail;
942        /* fall through since we only support kern data */
943
944      case AFM_TOKEN_ENDFONTMETRICS:
945        return PSaux_Err_Ok;
946
947      default:
948        break;
949      }
950    }
951
952  Fail:
953    FT_FREE( fi->TrackKerns );
954    fi->NumTrackKern = 0;
955
956    FT_FREE( fi->KernPairs );
957    fi->NumKernPair = 0;
958
959    fi->IsCIDFont = 0;
960
961    return error;
962  }
963
964
965/* END */
Note: See TracBrowser for help on using the repository browser.