Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  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.