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