misc/libfreetype/src/psaux/afmparse.c
changeset 9431 0f5961910e27
parent 9357 a501f5ec7b34
parent 9429 7a97a554ac80
child 9433 f0a8ac191839
equal deleted inserted replaced
9357:a501f5ec7b34 9431:0f5961910e27
     1 /***************************************************************************/
       
     2 /*                                                                         */
       
     3 /*  afmparse.c                                                             */
       
     4 /*                                                                         */
       
     5 /*    AFM parser (body).                                                   */
       
     6 /*                                                                         */
       
     7 /*  Copyright 2006, 2007, 2008, 2009, 2010 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 
       
    22 #include "afmparse.h"
       
    23 #include "psconv.h"
       
    24 
       
    25 #include "psauxerr.h"
       
    26 
       
    27 
       
    28 /***************************************************************************/
       
    29 /*                                                                         */
       
    30 /*    AFM_Stream                                                           */
       
    31 /*                                                                         */
       
    32 /* The use of AFM_Stream is largely inspired by parseAFM.[ch] from t1lib.  */
       
    33 /*                                                                         */
       
    34 /*                                                                         */
       
    35 
       
    36   enum
       
    37   {
       
    38     AFM_STREAM_STATUS_NORMAL,
       
    39     AFM_STREAM_STATUS_EOC,
       
    40     AFM_STREAM_STATUS_EOL,
       
    41     AFM_STREAM_STATUS_EOF
       
    42   };
       
    43 
       
    44 
       
    45   typedef struct  AFM_StreamRec_
       
    46   {
       
    47     FT_Byte*  cursor;
       
    48     FT_Byte*  base;
       
    49     FT_Byte*  limit;
       
    50 
       
    51     FT_Int    status;
       
    52 
       
    53   } AFM_StreamRec;
       
    54 
       
    55 
       
    56 #ifndef EOF
       
    57 #define EOF -1
       
    58 #endif
       
    59 
       
    60 
       
    61   /* this works because empty lines are ignored */
       
    62 #define AFM_IS_NEWLINE( ch )  ( (ch) == '\r' || (ch) == '\n' )
       
    63 
       
    64 #define AFM_IS_EOF( ch )      ( (ch) == EOF  || (ch) == '\x1a' )
       
    65 #define AFM_IS_SPACE( ch )    ( (ch) == ' '  || (ch) == '\t' )
       
    66 
       
    67   /* column separator; there is no `column' in the spec actually */
       
    68 #define AFM_IS_SEP( ch )      ( (ch) == ';' )
       
    69 
       
    70 #define AFM_GETC()                                                       \
       
    71           ( ( (stream)->cursor < (stream)->limit ) ? *(stream)->cursor++ \
       
    72                                                    : EOF )
       
    73 
       
    74 #define AFM_STREAM_KEY_BEGIN( stream )    \
       
    75           (char*)( (stream)->cursor - 1 )
       
    76 
       
    77 #define AFM_STREAM_KEY_LEN( stream, key )       \
       
    78           ( (char*)(stream)->cursor - key - 1 )
       
    79 
       
    80 #define AFM_STATUS_EOC( stream ) \
       
    81           ( (stream)->status >= AFM_STREAM_STATUS_EOC )
       
    82 
       
    83 #define AFM_STATUS_EOL( stream ) \
       
    84           ( (stream)->status >= AFM_STREAM_STATUS_EOL )
       
    85 
       
    86 #define AFM_STATUS_EOF( stream ) \
       
    87           ( (stream)->status >= AFM_STREAM_STATUS_EOF )
       
    88 
       
    89 
       
    90   static int
       
    91   afm_stream_skip_spaces( AFM_Stream  stream )
       
    92   {
       
    93     int  ch = 0;  /* make stupid compiler happy */
       
    94 
       
    95 
       
    96     if ( AFM_STATUS_EOC( stream ) )
       
    97       return ';';
       
    98 
       
    99     while ( 1 )
       
   100     {
       
   101       ch = AFM_GETC();
       
   102       if ( !AFM_IS_SPACE( ch ) )
       
   103         break;
       
   104     }
       
   105 
       
   106     if ( AFM_IS_NEWLINE( ch ) )
       
   107       stream->status = AFM_STREAM_STATUS_EOL;
       
   108     else if ( AFM_IS_SEP( ch ) )
       
   109       stream->status = AFM_STREAM_STATUS_EOC;
       
   110     else if ( AFM_IS_EOF( ch ) )
       
   111       stream->status = AFM_STREAM_STATUS_EOF;
       
   112 
       
   113     return ch;
       
   114   }
       
   115 
       
   116 
       
   117   /* read a key or value in current column */
       
   118   static char*
       
   119   afm_stream_read_one( AFM_Stream  stream )
       
   120   {
       
   121     char*  str;
       
   122     int    ch;
       
   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       ch = AFM_GETC();
       
   134       if ( AFM_IS_SPACE( ch ) )
       
   135         break;
       
   136       else if ( AFM_IS_NEWLINE( ch ) )
       
   137       {
       
   138         stream->status = AFM_STREAM_STATUS_EOL;
       
   139         break;
       
   140       }
       
   141       else if ( AFM_IS_SEP( ch ) )
       
   142       {
       
   143         stream->status = AFM_STREAM_STATUS_EOC;
       
   144         break;
       
   145       }
       
   146       else if ( AFM_IS_EOF( ch ) )
       
   147       {
       
   148         stream->status = AFM_STREAM_STATUS_EOF;
       
   149         break;
       
   150       }
       
   151     }
       
   152 
       
   153     return str;
       
   154   }
       
   155 
       
   156 
       
   157   /* read a string (i.e., read to EOL) */
       
   158   static char*
       
   159   afm_stream_read_string( AFM_Stream  stream )
       
   160   {
       
   161     char*  str;
       
   162     int    ch;
       
   163 
       
   164 
       
   165     afm_stream_skip_spaces( stream );
       
   166     if ( AFM_STATUS_EOL( stream ) )
       
   167       return NULL;
       
   168 
       
   169     str = AFM_STREAM_KEY_BEGIN( stream );
       
   170 
       
   171     /* scan to eol */
       
   172     while ( 1 )
       
   173     {
       
   174       ch = AFM_GETC();
       
   175       if ( AFM_IS_NEWLINE( ch ) )
       
   176       {
       
   177         stream->status = AFM_STREAM_STATUS_EOL;
       
   178         break;
       
   179       }
       
   180       else if ( AFM_IS_EOF( ch ) )
       
   181       {
       
   182         stream->status = AFM_STREAM_STATUS_EOF;
       
   183         break;
       
   184       }
       
   185     }
       
   186 
       
   187     return str;
       
   188   }
       
   189 
       
   190 
       
   191   /*************************************************************************/
       
   192   /*                                                                       */
       
   193   /*    AFM_Parser                                                         */
       
   194   /*                                                                       */
       
   195   /*                                                                       */
       
   196 
       
   197   /* all keys defined in Ch. 7-10 of 5004.AFM_Spec.pdf */
       
   198   typedef enum  AFM_Token_
       
   199   {
       
   200     AFM_TOKEN_ASCENDER,
       
   201     AFM_TOKEN_AXISLABEL,
       
   202     AFM_TOKEN_AXISTYPE,
       
   203     AFM_TOKEN_B,
       
   204     AFM_TOKEN_BLENDAXISTYPES,
       
   205     AFM_TOKEN_BLENDDESIGNMAP,
       
   206     AFM_TOKEN_BLENDDESIGNPOSITIONS,
       
   207     AFM_TOKEN_C,
       
   208     AFM_TOKEN_CC,
       
   209     AFM_TOKEN_CH,
       
   210     AFM_TOKEN_CAPHEIGHT,
       
   211     AFM_TOKEN_CHARWIDTH,
       
   212     AFM_TOKEN_CHARACTERSET,
       
   213     AFM_TOKEN_CHARACTERS,
       
   214     AFM_TOKEN_DESCENDER,
       
   215     AFM_TOKEN_ENCODINGSCHEME,
       
   216     AFM_TOKEN_ENDAXIS,
       
   217     AFM_TOKEN_ENDCHARMETRICS,
       
   218     AFM_TOKEN_ENDCOMPOSITES,
       
   219     AFM_TOKEN_ENDDIRECTION,
       
   220     AFM_TOKEN_ENDFONTMETRICS,
       
   221     AFM_TOKEN_ENDKERNDATA,
       
   222     AFM_TOKEN_ENDKERNPAIRS,
       
   223     AFM_TOKEN_ENDTRACKKERN,
       
   224     AFM_TOKEN_ESCCHAR,
       
   225     AFM_TOKEN_FAMILYNAME,
       
   226     AFM_TOKEN_FONTBBOX,
       
   227     AFM_TOKEN_FONTNAME,
       
   228     AFM_TOKEN_FULLNAME,
       
   229     AFM_TOKEN_ISBASEFONT,
       
   230     AFM_TOKEN_ISCIDFONT,
       
   231     AFM_TOKEN_ISFIXEDPITCH,
       
   232     AFM_TOKEN_ISFIXEDV,
       
   233     AFM_TOKEN_ITALICANGLE,
       
   234     AFM_TOKEN_KP,
       
   235     AFM_TOKEN_KPH,
       
   236     AFM_TOKEN_KPX,
       
   237     AFM_TOKEN_KPY,
       
   238     AFM_TOKEN_L,
       
   239     AFM_TOKEN_MAPPINGSCHEME,
       
   240     AFM_TOKEN_METRICSSETS,
       
   241     AFM_TOKEN_N,
       
   242     AFM_TOKEN_NOTICE,
       
   243     AFM_TOKEN_PCC,
       
   244     AFM_TOKEN_STARTAXIS,
       
   245     AFM_TOKEN_STARTCHARMETRICS,
       
   246     AFM_TOKEN_STARTCOMPOSITES,
       
   247     AFM_TOKEN_STARTDIRECTION,
       
   248     AFM_TOKEN_STARTFONTMETRICS,
       
   249     AFM_TOKEN_STARTKERNDATA,
       
   250     AFM_TOKEN_STARTKERNPAIRS,
       
   251     AFM_TOKEN_STARTKERNPAIRS0,
       
   252     AFM_TOKEN_STARTKERNPAIRS1,
       
   253     AFM_TOKEN_STARTTRACKKERN,
       
   254     AFM_TOKEN_STDHW,
       
   255     AFM_TOKEN_STDVW,
       
   256     AFM_TOKEN_TRACKKERN,
       
   257     AFM_TOKEN_UNDERLINEPOSITION,
       
   258     AFM_TOKEN_UNDERLINETHICKNESS,
       
   259     AFM_TOKEN_VV,
       
   260     AFM_TOKEN_VVECTOR,
       
   261     AFM_TOKEN_VERSION,
       
   262     AFM_TOKEN_W,
       
   263     AFM_TOKEN_W0,
       
   264     AFM_TOKEN_W0X,
       
   265     AFM_TOKEN_W0Y,
       
   266     AFM_TOKEN_W1,
       
   267     AFM_TOKEN_W1X,
       
   268     AFM_TOKEN_W1Y,
       
   269     AFM_TOKEN_WX,
       
   270     AFM_TOKEN_WY,
       
   271     AFM_TOKEN_WEIGHT,
       
   272     AFM_TOKEN_WEIGHTVECTOR,
       
   273     AFM_TOKEN_XHEIGHT,
       
   274     N_AFM_TOKENS,
       
   275     AFM_TOKEN_UNKNOWN
       
   276 
       
   277   } AFM_Token;
       
   278 
       
   279 
       
   280   static const char*  const afm_key_table[N_AFM_TOKENS] =
       
   281   {
       
   282     "Ascender",
       
   283     "AxisLabel",
       
   284     "AxisType",
       
   285     "B",
       
   286     "BlendAxisTypes",
       
   287     "BlendDesignMap",
       
   288     "BlendDesignPositions",
       
   289     "C",
       
   290     "CC",
       
   291     "CH",
       
   292     "CapHeight",
       
   293     "CharWidth",
       
   294     "CharacterSet",
       
   295     "Characters",
       
   296     "Descender",
       
   297     "EncodingScheme",
       
   298     "EndAxis",
       
   299     "EndCharMetrics",
       
   300     "EndComposites",
       
   301     "EndDirection",
       
   302     "EndFontMetrics",
       
   303     "EndKernData",
       
   304     "EndKernPairs",
       
   305     "EndTrackKern",
       
   306     "EscChar",
       
   307     "FamilyName",
       
   308     "FontBBox",
       
   309     "FontName",
       
   310     "FullName",
       
   311     "IsBaseFont",
       
   312     "IsCIDFont",
       
   313     "IsFixedPitch",
       
   314     "IsFixedV",
       
   315     "ItalicAngle",
       
   316     "KP",
       
   317     "KPH",
       
   318     "KPX",
       
   319     "KPY",
       
   320     "L",
       
   321     "MappingScheme",
       
   322     "MetricsSets",
       
   323     "N",
       
   324     "Notice",
       
   325     "PCC",
       
   326     "StartAxis",
       
   327     "StartCharMetrics",
       
   328     "StartComposites",
       
   329     "StartDirection",
       
   330     "StartFontMetrics",
       
   331     "StartKernData",
       
   332     "StartKernPairs",
       
   333     "StartKernPairs0",
       
   334     "StartKernPairs1",
       
   335     "StartTrackKern",
       
   336     "StdHW",
       
   337     "StdVW",
       
   338     "TrackKern",
       
   339     "UnderlinePosition",
       
   340     "UnderlineThickness",
       
   341     "VV",
       
   342     "VVector",
       
   343     "Version",
       
   344     "W",
       
   345     "W0",
       
   346     "W0X",
       
   347     "W0Y",
       
   348     "W1",
       
   349     "W1X",
       
   350     "W1Y",
       
   351     "WX",
       
   352     "WY",
       
   353     "Weight",
       
   354     "WeightVector",
       
   355     "XHeight"
       
   356   };
       
   357 
       
   358 
       
   359   /*
       
   360    * `afm_parser_read_vals' and `afm_parser_next_key' provide
       
   361    * high-level operations to an AFM_Stream.  The rest of the
       
   362    * parser functions should use them without accessing the
       
   363    * AFM_Stream directly.
       
   364    */
       
   365 
       
   366   FT_LOCAL_DEF( FT_Int )
       
   367   afm_parser_read_vals( AFM_Parser  parser,
       
   368                         AFM_Value   vals,
       
   369                         FT_UInt     n )
       
   370   {
       
   371     AFM_Stream  stream = parser->stream;
       
   372     char*       str;
       
   373     FT_UInt     i;
       
   374 
       
   375 
       
   376     if ( n > AFM_MAX_ARGUMENTS )
       
   377       return 0;
       
   378 
       
   379     for ( i = 0; i < n; i++ )
       
   380     {
       
   381       FT_Offset  len;
       
   382       AFM_Value  val = vals + i;
       
   383 
       
   384 
       
   385       if ( val->type == AFM_VALUE_TYPE_STRING )
       
   386         str = afm_stream_read_string( stream );
       
   387       else
       
   388         str = afm_stream_read_one( stream );
       
   389 
       
   390       if ( !str )
       
   391         break;
       
   392 
       
   393       len = AFM_STREAM_KEY_LEN( stream, str );
       
   394 
       
   395       switch ( val->type )
       
   396       {
       
   397       case AFM_VALUE_TYPE_STRING:
       
   398       case AFM_VALUE_TYPE_NAME:
       
   399         {
       
   400           FT_Memory  memory = parser->memory;
       
   401           FT_Error   error;
       
   402 
       
   403 
       
   404           if ( !FT_QALLOC( val->u.s, len + 1 ) )
       
   405           {
       
   406             ft_memcpy( val->u.s, str, len );
       
   407             val->u.s[len] = '\0';
       
   408           }
       
   409         }
       
   410         break;
       
   411 
       
   412       case AFM_VALUE_TYPE_FIXED:
       
   413         val->u.f = PS_Conv_ToFixed( (FT_Byte**)(void*)&str,
       
   414                                     (FT_Byte*)str + len, 0 );
       
   415         break;
       
   416 
       
   417       case AFM_VALUE_TYPE_INTEGER:
       
   418         val->u.i = PS_Conv_ToInt( (FT_Byte**)(void*)&str,
       
   419                                   (FT_Byte*)str + len );
       
   420         break;
       
   421 
       
   422       case AFM_VALUE_TYPE_BOOL:
       
   423         val->u.b = FT_BOOL( len == 4                      &&
       
   424                             !ft_strncmp( str, "true", 4 ) );
       
   425         break;
       
   426 
       
   427       case AFM_VALUE_TYPE_INDEX:
       
   428         if ( parser->get_index )
       
   429           val->u.i = parser->get_index( str, len, parser->user_data );
       
   430         else
       
   431           val->u.i = 0;
       
   432         break;
       
   433       }
       
   434     }
       
   435 
       
   436     return i;
       
   437   }
       
   438 
       
   439 
       
   440   FT_LOCAL_DEF( char* )
       
   441   afm_parser_next_key( AFM_Parser  parser,
       
   442                        FT_Bool     line,
       
   443                        FT_Offset*  len )
       
   444   {
       
   445     AFM_Stream  stream = parser->stream;
       
   446     char*       key    = 0;  /* make stupid compiler happy */
       
   447 
       
   448 
       
   449     if ( line )
       
   450     {
       
   451       while ( 1 )
       
   452       {
       
   453         /* skip current line */
       
   454         if ( !AFM_STATUS_EOL( stream ) )
       
   455           afm_stream_read_string( stream );
       
   456 
       
   457         stream->status = AFM_STREAM_STATUS_NORMAL;
       
   458         key = afm_stream_read_one( stream );
       
   459 
       
   460         /* skip empty line */
       
   461         if ( !key                      &&
       
   462              !AFM_STATUS_EOF( stream ) &&
       
   463              AFM_STATUS_EOL( stream )  )
       
   464           continue;
       
   465 
       
   466         break;
       
   467       }
       
   468     }
       
   469     else
       
   470     {
       
   471       while ( 1 )
       
   472       {
       
   473         /* skip current column */
       
   474         while ( !AFM_STATUS_EOC( stream ) )
       
   475           afm_stream_read_one( stream );
       
   476 
       
   477         stream->status = AFM_STREAM_STATUS_NORMAL;
       
   478         key = afm_stream_read_one( stream );
       
   479 
       
   480         /* skip empty column */
       
   481         if ( !key                      &&
       
   482              !AFM_STATUS_EOF( stream ) &&
       
   483              AFM_STATUS_EOC( stream )  )
       
   484           continue;
       
   485 
       
   486         break;
       
   487       }
       
   488     }
       
   489 
       
   490     if ( len )
       
   491       *len = ( key ) ? (FT_Offset)AFM_STREAM_KEY_LEN( stream, key )
       
   492                      : 0;
       
   493 
       
   494     return key;
       
   495   }
       
   496 
       
   497 
       
   498   static AFM_Token
       
   499   afm_tokenize( const char*  key,
       
   500                 FT_Offset    len )
       
   501   {
       
   502     int  n;
       
   503 
       
   504 
       
   505     for ( n = 0; n < N_AFM_TOKENS; n++ )
       
   506     {
       
   507       if ( *( afm_key_table[n] ) == *key )
       
   508       {
       
   509         for ( ; n < N_AFM_TOKENS; n++ )
       
   510         {
       
   511           if ( *( afm_key_table[n] ) != *key )
       
   512             return AFM_TOKEN_UNKNOWN;
       
   513 
       
   514           if ( ft_strncmp( afm_key_table[n], key, len ) == 0 )
       
   515             return (AFM_Token) n;
       
   516         }
       
   517       }
       
   518     }
       
   519 
       
   520     return AFM_TOKEN_UNKNOWN;
       
   521   }
       
   522 
       
   523 
       
   524   FT_LOCAL_DEF( FT_Error )
       
   525   afm_parser_init( AFM_Parser  parser,
       
   526                    FT_Memory   memory,
       
   527                    FT_Byte*    base,
       
   528                    FT_Byte*    limit )
       
   529   {
       
   530     AFM_Stream  stream = NULL;
       
   531     FT_Error    error;
       
   532 
       
   533 
       
   534     if ( FT_NEW( stream ) )
       
   535       return error;
       
   536 
       
   537     stream->cursor = stream->base = base;
       
   538     stream->limit  = limit;
       
   539 
       
   540     /* don't skip the first line during the first call */
       
   541     stream->status = AFM_STREAM_STATUS_EOL;
       
   542 
       
   543     parser->memory    = memory;
       
   544     parser->stream    = stream;
       
   545     parser->FontInfo  = NULL;
       
   546     parser->get_index = NULL;
       
   547 
       
   548     return PSaux_Err_Ok;
       
   549   }
       
   550 
       
   551 
       
   552   FT_LOCAL( void )
       
   553   afm_parser_done( AFM_Parser  parser )
       
   554   {
       
   555     FT_Memory  memory = parser->memory;
       
   556 
       
   557 
       
   558     FT_FREE( parser->stream );
       
   559   }
       
   560 
       
   561 
       
   562   FT_LOCAL_DEF( FT_Error )
       
   563   afm_parser_read_int( AFM_Parser  parser,
       
   564                        FT_Int*     aint )
       
   565   {
       
   566     AFM_ValueRec  val;
       
   567 
       
   568 
       
   569     val.type = AFM_VALUE_TYPE_INTEGER;
       
   570 
       
   571     if ( afm_parser_read_vals( parser, &val, 1 ) == 1 )
       
   572     {
       
   573       *aint = val.u.i;
       
   574 
       
   575       return PSaux_Err_Ok;
       
   576     }
       
   577     else
       
   578       return PSaux_Err_Syntax_Error;
       
   579   }
       
   580 
       
   581 
       
   582   static FT_Error
       
   583   afm_parse_track_kern( AFM_Parser  parser )
       
   584   {
       
   585     AFM_FontInfo   fi = parser->FontInfo;
       
   586     AFM_TrackKern  tk;
       
   587     char*          key;
       
   588     FT_Offset      len;
       
   589     int            n = -1;
       
   590 
       
   591 
       
   592     if ( afm_parser_read_int( parser, &fi->NumTrackKern ) )
       
   593         goto Fail;
       
   594 
       
   595     if ( fi->NumTrackKern )
       
   596     {
       
   597       FT_Memory  memory = parser->memory;
       
   598       FT_Error   error;
       
   599 
       
   600 
       
   601       if ( FT_QNEW_ARRAY( fi->TrackKerns, fi->NumTrackKern ) )
       
   602         return error;
       
   603     }
       
   604 
       
   605     while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
       
   606     {
       
   607       AFM_ValueRec  shared_vals[5];
       
   608 
       
   609 
       
   610       switch ( afm_tokenize( key, len ) )
       
   611       {
       
   612       case AFM_TOKEN_TRACKKERN:
       
   613         n++;
       
   614 
       
   615         if ( n >= fi->NumTrackKern )
       
   616           goto Fail;
       
   617 
       
   618         tk = fi->TrackKerns + n;
       
   619 
       
   620         shared_vals[0].type = AFM_VALUE_TYPE_INTEGER;
       
   621         shared_vals[1].type = AFM_VALUE_TYPE_FIXED;
       
   622         shared_vals[2].type = AFM_VALUE_TYPE_FIXED;
       
   623         shared_vals[3].type = AFM_VALUE_TYPE_FIXED;
       
   624         shared_vals[4].type = AFM_VALUE_TYPE_FIXED;
       
   625         if ( afm_parser_read_vals( parser, shared_vals, 5 ) != 5 )
       
   626           goto Fail;
       
   627 
       
   628         tk->degree     = shared_vals[0].u.i;
       
   629         tk->min_ptsize = shared_vals[1].u.f;
       
   630         tk->min_kern   = shared_vals[2].u.f;
       
   631         tk->max_ptsize = shared_vals[3].u.f;
       
   632         tk->max_kern   = shared_vals[4].u.f;
       
   633 
       
   634         /* is this correct? */
       
   635         if ( tk->degree < 0 && tk->min_kern > 0 )
       
   636           tk->min_kern = -tk->min_kern;
       
   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 PSaux_Err_Ok;
       
   644 
       
   645       case AFM_TOKEN_UNKNOWN:
       
   646         break;
       
   647 
       
   648       default:
       
   649         goto Fail;
       
   650       }
       
   651     }
       
   652 
       
   653   Fail:
       
   654     return PSaux_Err_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 PSaux_Err_Ok;
       
   760 
       
   761       case AFM_TOKEN_UNKNOWN:
       
   762         break;
       
   763 
       
   764       default:
       
   765         goto Fail;
       
   766       }
       
   767     }
       
   768 
       
   769   Fail:
       
   770     return PSaux_Err_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 PSaux_Err_Ok;
       
   802 
       
   803       case AFM_TOKEN_UNKNOWN:
       
   804         break;
       
   805 
       
   806       default:
       
   807         goto Fail;
       
   808       }
       
   809     }
       
   810 
       
   811   Fail:
       
   812     return PSaux_Err_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 PSaux_Err_Ok;
       
   839     }
       
   840 
       
   841   Fail:
       
   842     return PSaux_Err_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  = PSaux_Err_Syntax_Error;
       
   852     char*         key;
       
   853     FT_Offset     len;
       
   854     FT_Int        metrics_sets = 0;
       
   855 
       
   856 
       
   857     if ( !fi )
       
   858       return PSaux_Err_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 PSaux_Err_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 = PSaux_Err_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 PSaux_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 */