afmparse.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  afmparse.c                                                             */
00004 /*                                                                         */
00005 /*    AFM parser (body).                                                   */
00006 /*                                                                         */
00007 /*  Copyright 2006, 2007, 2008, 2009 by                                    */
00008 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00009 /*                                                                         */
00010 /*  This file is part of the FreeType project, and may only be used,       */
00011 /*  modified, and distributed under the terms of the FreeType project      */
00012 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00013 /*  this file you indicate that you have read the license and              */
00014 /*  understand and accept it fully.                                        */
00015 /*                                                                         */
00016 /***************************************************************************/
00017 
00018 #include <ft2build.h>
00019 #include FT_FREETYPE_H
00020 #include FT_INTERNAL_POSTSCRIPT_AUX_H
00021 
00022 #include "afmparse.h"
00023 #include "psconv.h"
00024 
00025 #include "psauxerr.h"
00026 
00027 
00028 /***************************************************************************/
00029 /*                                                                         */
00030 /*    AFM_Stream                                                           */
00031 /*                                                                         */
00032 /* The use of AFM_Stream is largely inspired by parseAFM.[ch] from t1lib.  */
00033 /*                                                                         */
00034 /*                                                                         */
00035 
00036   enum
00037   {
00038     AFM_STREAM_STATUS_NORMAL,
00039     AFM_STREAM_STATUS_EOC,
00040     AFM_STREAM_STATUS_EOL,
00041     AFM_STREAM_STATUS_EOF
00042   };
00043 
00044 
00045   typedef struct  AFM_StreamRec_
00046   {
00047     FT_Byte*  cursor;
00048     FT_Byte*  base;
00049     FT_Byte*  limit;
00050 
00051     FT_Int    status;
00052 
00053   } AFM_StreamRec;
00054 
00055 
00056 #ifndef EOF
00057 #define EOF -1
00058 #endif
00059 
00060 
00061   /* this works because empty lines are ignored */
00062 #define AFM_IS_NEWLINE( ch )  ( (ch) == '\r' || (ch) == '\n' )
00063 
00064 #define AFM_IS_EOF( ch )      ( (ch) == EOF  || (ch) == '\x1a' )
00065 #define AFM_IS_SPACE( ch )    ( (ch) == ' '  || (ch) == '\t' )
00066 
00067   /* column separator; there is no `column' in the spec actually */
00068 #define AFM_IS_SEP( ch )      ( (ch) == ';' )
00069 
00070 #define AFM_GETC()                                                       \
00071           ( ( (stream)->cursor < (stream)->limit ) ? *(stream)->cursor++ \
00072                                                    : EOF )
00073 
00074 #define AFM_STREAM_KEY_BEGIN( stream )    \
00075           (char*)( (stream)->cursor - 1 )
00076 
00077 #define AFM_STREAM_KEY_LEN( stream, key )       \
00078           ( (char*)(stream)->cursor - key - 1 )
00079 
00080 #define AFM_STATUS_EOC( stream ) \
00081           ( (stream)->status >= AFM_STREAM_STATUS_EOC )
00082 
00083 #define AFM_STATUS_EOL( stream ) \
00084           ( (stream)->status >= AFM_STREAM_STATUS_EOL )
00085 
00086 #define AFM_STATUS_EOF( stream ) \
00087           ( (stream)->status >= AFM_STREAM_STATUS_EOF )
00088 
00089 
00090   static int
00091   afm_stream_skip_spaces( AFM_Stream  stream )
00092   {
00093     int  ch = 0;  /* make stupid compiler happy */
00094 
00095 
00096     if ( AFM_STATUS_EOC( stream ) )
00097       return ';';
00098 
00099     while ( 1 )
00100     {
00101       ch = AFM_GETC();
00102       if ( !AFM_IS_SPACE( ch ) )
00103         break;
00104     }
00105 
00106     if ( AFM_IS_NEWLINE( ch ) )
00107       stream->status = AFM_STREAM_STATUS_EOL;
00108     else if ( AFM_IS_SEP( ch ) )
00109       stream->status = AFM_STREAM_STATUS_EOC;
00110     else if ( AFM_IS_EOF( ch ) )
00111       stream->status = AFM_STREAM_STATUS_EOF;
00112 
00113     return ch;
00114   }
00115 
00116 
00117   /* read a key or value in current column */
00118   static char*
00119   afm_stream_read_one( AFM_Stream  stream )
00120   {
00121     char*  str;
00122     int    ch;
00123 
00124 
00125     afm_stream_skip_spaces( stream );
00126     if ( AFM_STATUS_EOC( stream ) )
00127       return NULL;
00128 
00129     str = AFM_STREAM_KEY_BEGIN( stream );
00130 
00131     while ( 1 )
00132     {
00133       ch = AFM_GETC();
00134       if ( AFM_IS_SPACE( ch ) )
00135         break;
00136       else if ( AFM_IS_NEWLINE( ch ) )
00137       {
00138         stream->status = AFM_STREAM_STATUS_EOL;
00139         break;
00140       }
00141       else if ( AFM_IS_SEP( ch ) )
00142       {
00143         stream->status = AFM_STREAM_STATUS_EOC;
00144         break;
00145       }
00146       else if ( AFM_IS_EOF( ch ) )
00147       {
00148         stream->status = AFM_STREAM_STATUS_EOF;
00149         break;
00150       }
00151     }
00152 
00153     return str;
00154   }
00155 
00156 
00157   /* read a string (i.e., read to EOL) */
00158   static char*
00159   afm_stream_read_string( AFM_Stream  stream )
00160   {
00161     char*  str;
00162     int    ch;
00163 
00164 
00165     afm_stream_skip_spaces( stream );
00166     if ( AFM_STATUS_EOL( stream ) )
00167       return NULL;
00168 
00169     str = AFM_STREAM_KEY_BEGIN( stream );
00170 
00171     /* scan to eol */
00172     while ( 1 )
00173     {
00174       ch = AFM_GETC();
00175       if ( AFM_IS_NEWLINE( ch ) )
00176       {
00177         stream->status = AFM_STREAM_STATUS_EOL;
00178         break;
00179       }
00180       else if ( AFM_IS_EOF( ch ) )
00181       {
00182         stream->status = AFM_STREAM_STATUS_EOF;
00183         break;
00184       }
00185     }
00186 
00187     return str;
00188   }
00189 
00190 
00191   /*************************************************************************/
00192   /*                                                                       */
00193   /*    AFM_Parser                                                         */
00194   /*                                                                       */
00195   /*                                                                       */
00196 
00197   /* all keys defined in Ch. 7-10 of 5004.AFM_Spec.pdf */
00198   typedef enum  AFM_Token_
00199   {
00200     AFM_TOKEN_ASCENDER,
00201     AFM_TOKEN_AXISLABEL,
00202     AFM_TOKEN_AXISTYPE,
00203     AFM_TOKEN_B,
00204     AFM_TOKEN_BLENDAXISTYPES,
00205     AFM_TOKEN_BLENDDESIGNMAP,
00206     AFM_TOKEN_BLENDDESIGNPOSITIONS,
00207     AFM_TOKEN_C,
00208     AFM_TOKEN_CC,
00209     AFM_TOKEN_CH,
00210     AFM_TOKEN_CAPHEIGHT,
00211     AFM_TOKEN_CHARWIDTH,
00212     AFM_TOKEN_CHARACTERSET,
00213     AFM_TOKEN_CHARACTERS,
00214     AFM_TOKEN_DESCENDER,
00215     AFM_TOKEN_ENCODINGSCHEME,
00216     AFM_TOKEN_ENDAXIS,
00217     AFM_TOKEN_ENDCHARMETRICS,
00218     AFM_TOKEN_ENDCOMPOSITES,
00219     AFM_TOKEN_ENDDIRECTION,
00220     AFM_TOKEN_ENDFONTMETRICS,
00221     AFM_TOKEN_ENDKERNDATA,
00222     AFM_TOKEN_ENDKERNPAIRS,
00223     AFM_TOKEN_ENDTRACKKERN,
00224     AFM_TOKEN_ESCCHAR,
00225     AFM_TOKEN_FAMILYNAME,
00226     AFM_TOKEN_FONTBBOX,
00227     AFM_TOKEN_FONTNAME,
00228     AFM_TOKEN_FULLNAME,
00229     AFM_TOKEN_ISBASEFONT,
00230     AFM_TOKEN_ISCIDFONT,
00231     AFM_TOKEN_ISFIXEDPITCH,
00232     AFM_TOKEN_ISFIXEDV,
00233     AFM_TOKEN_ITALICANGLE,
00234     AFM_TOKEN_KP,
00235     AFM_TOKEN_KPH,
00236     AFM_TOKEN_KPX,
00237     AFM_TOKEN_KPY,
00238     AFM_TOKEN_L,
00239     AFM_TOKEN_MAPPINGSCHEME,
00240     AFM_TOKEN_METRICSSETS,
00241     AFM_TOKEN_N,
00242     AFM_TOKEN_NOTICE,
00243     AFM_TOKEN_PCC,
00244     AFM_TOKEN_STARTAXIS,
00245     AFM_TOKEN_STARTCHARMETRICS,
00246     AFM_TOKEN_STARTCOMPOSITES,
00247     AFM_TOKEN_STARTDIRECTION,
00248     AFM_TOKEN_STARTFONTMETRICS,
00249     AFM_TOKEN_STARTKERNDATA,
00250     AFM_TOKEN_STARTKERNPAIRS,
00251     AFM_TOKEN_STARTKERNPAIRS0,
00252     AFM_TOKEN_STARTKERNPAIRS1,
00253     AFM_TOKEN_STARTTRACKKERN,
00254     AFM_TOKEN_STDHW,
00255     AFM_TOKEN_STDVW,
00256     AFM_TOKEN_TRACKKERN,
00257     AFM_TOKEN_UNDERLINEPOSITION,
00258     AFM_TOKEN_UNDERLINETHICKNESS,
00259     AFM_TOKEN_VV,
00260     AFM_TOKEN_VVECTOR,
00261     AFM_TOKEN_VERSION,
00262     AFM_TOKEN_W,
00263     AFM_TOKEN_W0,
00264     AFM_TOKEN_W0X,
00265     AFM_TOKEN_W0Y,
00266     AFM_TOKEN_W1,
00267     AFM_TOKEN_W1X,
00268     AFM_TOKEN_W1Y,
00269     AFM_TOKEN_WX,
00270     AFM_TOKEN_WY,
00271     AFM_TOKEN_WEIGHT,
00272     AFM_TOKEN_WEIGHTVECTOR,
00273     AFM_TOKEN_XHEIGHT,
00274     N_AFM_TOKENS,
00275     AFM_TOKEN_UNKNOWN
00276 
00277   } AFM_Token;
00278 
00279 
00280   static const char*  const afm_key_table[N_AFM_TOKENS] =
00281   {
00282     "Ascender",
00283     "AxisLabel",
00284     "AxisType",
00285     "B",
00286     "BlendAxisTypes",
00287     "BlendDesignMap",
00288     "BlendDesignPositions",
00289     "C",
00290     "CC",
00291     "CH",
00292     "CapHeight",
00293     "CharWidth",
00294     "CharacterSet",
00295     "Characters",
00296     "Descender",
00297     "EncodingScheme",
00298     "EndAxis",
00299     "EndCharMetrics",
00300     "EndComposites",
00301     "EndDirection",
00302     "EndFontMetrics",
00303     "EndKernData",
00304     "EndKernPairs",
00305     "EndTrackKern",
00306     "EscChar",
00307     "FamilyName",
00308     "FontBBox",
00309     "FontName",
00310     "FullName",
00311     "IsBaseFont",
00312     "IsCIDFont",
00313     "IsFixedPitch",
00314     "IsFixedV",
00315     "ItalicAngle",
00316     "KP",
00317     "KPH",
00318     "KPX",
00319     "KPY",
00320     "L",
00321     "MappingScheme",
00322     "MetricsSets",
00323     "N",
00324     "Notice",
00325     "PCC",
00326     "StartAxis",
00327     "StartCharMetrics",
00328     "StartComposites",
00329     "StartDirection",
00330     "StartFontMetrics",
00331     "StartKernData",
00332     "StartKernPairs",
00333     "StartKernPairs0",
00334     "StartKernPairs1",
00335     "StartTrackKern",
00336     "StdHW",
00337     "StdVW",
00338     "TrackKern",
00339     "UnderlinePosition",
00340     "UnderlineThickness",
00341     "VV",
00342     "VVector",
00343     "Version",
00344     "W",
00345     "W0",
00346     "W0X",
00347     "W0Y",
00348     "W1",
00349     "W1X",
00350     "W1Y",
00351     "WX",
00352     "WY",
00353     "Weight",
00354     "WeightVector",
00355     "XHeight"
00356   };
00357 
00358 
00359   /*
00360    * `afm_parser_read_vals' and `afm_parser_next_key' provide
00361    * high-level operations to an AFM_Stream.  The rest of the
00362    * parser functions should use them without accessing the
00363    * AFM_Stream directly.
00364    */
00365 
00366   FT_LOCAL_DEF( FT_Int )
00367   afm_parser_read_vals( AFM_Parser  parser,
00368                         AFM_Value   vals,
00369                         FT_UInt     n )
00370   {
00371     AFM_Stream  stream = parser->stream;
00372     char*       str;
00373     FT_UInt     i;
00374 
00375 
00376     if ( n > AFM_MAX_ARGUMENTS )
00377       return 0;
00378 
00379     for ( i = 0; i < n; i++ )
00380     {
00381       FT_Offset  len;
00382       AFM_Value  val = vals + i;
00383 
00384 
00385       if ( val->type == AFM_VALUE_TYPE_STRING )
00386         str = afm_stream_read_string( stream );
00387       else
00388         str = afm_stream_read_one( stream );
00389 
00390       if ( !str )
00391         break;
00392 
00393       len = AFM_STREAM_KEY_LEN( stream, str );
00394 
00395       switch ( val->type )
00396       {
00397       case AFM_VALUE_TYPE_STRING:
00398       case AFM_VALUE_TYPE_NAME:
00399         {
00400           FT_Memory  memory = parser->memory;
00401           FT_Error   error;
00402 
00403 
00404           if ( !FT_QALLOC( val->u.s, len + 1 ) )
00405           {
00406             ft_memcpy( val->u.s, str, len );
00407             val->u.s[len] = '\0';
00408           }
00409         }
00410         break;
00411 
00412       case AFM_VALUE_TYPE_FIXED:
00413         val->u.f = PS_Conv_ToFixed( (FT_Byte**)(void*)&str,
00414                                     (FT_Byte*)str + len, 0 );
00415         break;
00416 
00417       case AFM_VALUE_TYPE_INTEGER:
00418         val->u.i = PS_Conv_ToInt( (FT_Byte**)(void*)&str,
00419                                   (FT_Byte*)str + len );
00420         break;
00421 
00422       case AFM_VALUE_TYPE_BOOL:
00423         val->u.b = FT_BOOL( len == 4                      &&
00424                             !ft_strncmp( str, "true", 4 ) );
00425         break;
00426 
00427       case AFM_VALUE_TYPE_INDEX:
00428         if ( parser->get_index )
00429           val->u.i = parser->get_index( str, len, parser->user_data );
00430         else
00431           val->u.i = 0;
00432         break;
00433       }
00434     }
00435 
00436     return i;
00437   }
00438 
00439 
00440   FT_LOCAL_DEF( char* )
00441   afm_parser_next_key( AFM_Parser  parser,
00442                        FT_Bool     line,
00443                        FT_Offset*  len )
00444   {
00445     AFM_Stream  stream = parser->stream;
00446     char*       key    = 0;  /* make stupid compiler happy */
00447 
00448 
00449     if ( line )
00450     {
00451       while ( 1 )
00452       {
00453         /* skip current line */
00454         if ( !AFM_STATUS_EOL( stream ) )
00455           afm_stream_read_string( stream );
00456 
00457         stream->status = AFM_STREAM_STATUS_NORMAL;
00458         key = afm_stream_read_one( stream );
00459 
00460         /* skip empty line */
00461         if ( !key                      &&
00462              !AFM_STATUS_EOF( stream ) &&
00463              AFM_STATUS_EOL( stream )  )
00464           continue;
00465 
00466         break;
00467       }
00468     }
00469     else
00470     {
00471       while ( 1 )
00472       {
00473         /* skip current column */
00474         while ( !AFM_STATUS_EOC( stream ) )
00475           afm_stream_read_one( stream );
00476 
00477         stream->status = AFM_STREAM_STATUS_NORMAL;
00478         key = afm_stream_read_one( stream );
00479 
00480         /* skip empty column */
00481         if ( !key                      &&
00482              !AFM_STATUS_EOF( stream ) &&
00483              AFM_STATUS_EOC( stream )  )
00484           continue;
00485 
00486         break;
00487       }
00488     }
00489 
00490     if ( len )
00491       *len = ( key ) ? (FT_Offset)AFM_STREAM_KEY_LEN( stream, key )
00492                      : 0;
00493 
00494     return key;
00495   }
00496 
00497 
00498   static AFM_Token
00499   afm_tokenize( const char*  key,
00500                 FT_Offset    len )
00501   {
00502     int  n;
00503 
00504 
00505     for ( n = 0; n < N_AFM_TOKENS; n++ )
00506     {
00507       if ( *( afm_key_table[n] ) == *key )
00508       {
00509         for ( ; n < N_AFM_TOKENS; n++ )
00510         {
00511           if ( *( afm_key_table[n] ) != *key )
00512             return AFM_TOKEN_UNKNOWN;
00513 
00514           if ( ft_strncmp( afm_key_table[n], key, len ) == 0 )
00515             return (AFM_Token) n;
00516         }
00517       }
00518     }
00519 
00520     return AFM_TOKEN_UNKNOWN;
00521   }
00522 
00523 
00524   FT_LOCAL_DEF( FT_Error )
00525   afm_parser_init( AFM_Parser  parser,
00526                    FT_Memory   memory,
00527                    FT_Byte*    base,
00528                    FT_Byte*    limit )
00529   {
00530     AFM_Stream  stream;
00531     FT_Error    error;
00532 
00533 
00534     if ( FT_NEW( stream ) )
00535       return error;
00536 
00537     stream->cursor = stream->base = base;
00538     stream->limit  = limit;
00539 
00540     /* don't skip the first line during the first call */
00541     stream->status = AFM_STREAM_STATUS_EOL;
00542 
00543     parser->memory    = memory;
00544     parser->stream    = stream;
00545     parser->FontInfo  = NULL;
00546     parser->get_index = NULL;
00547 
00548     return PSaux_Err_Ok;
00549   }
00550 
00551 
00552   FT_LOCAL( void )
00553   afm_parser_done( AFM_Parser  parser )
00554   {
00555     FT_Memory  memory = parser->memory;
00556 
00557 
00558     FT_FREE( parser->stream );
00559   }
00560 
00561 
00562   FT_LOCAL_DEF( FT_Error )
00563   afm_parser_read_int( AFM_Parser  parser,
00564                        FT_Int*     aint )
00565   {
00566     AFM_ValueRec  val;
00567 
00568 
00569     val.type = AFM_VALUE_TYPE_INTEGER;
00570 
00571     if ( afm_parser_read_vals( parser, &val, 1 ) == 1 )
00572     {
00573       *aint = val.u.i;
00574 
00575       return PSaux_Err_Ok;
00576     }
00577     else
00578       return PSaux_Err_Syntax_Error;
00579   }
00580 
00581 
00582   static FT_Error
00583   afm_parse_track_kern( AFM_Parser  parser )
00584   {
00585     AFM_FontInfo   fi = parser->FontInfo;
00586     AFM_TrackKern  tk;
00587     char*          key;
00588     FT_Offset      len;
00589     int            n = -1;
00590 
00591 
00592     if ( afm_parser_read_int( parser, &fi->NumTrackKern ) )
00593         goto Fail;
00594 
00595     if ( fi->NumTrackKern )
00596     {
00597       FT_Memory  memory = parser->memory;
00598       FT_Error   error;
00599 
00600 
00601       if ( FT_QNEW_ARRAY( fi->TrackKerns, fi->NumTrackKern ) )
00602         return error;
00603     }
00604 
00605     while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
00606     {
00607       AFM_ValueRec  shared_vals[5];
00608 
00609 
00610       switch ( afm_tokenize( key, len ) )
00611       {
00612       case AFM_TOKEN_TRACKKERN:
00613         n++;
00614 
00615         if ( n >= fi->NumTrackKern )
00616           goto Fail;
00617 
00618         tk = fi->TrackKerns + n;
00619 
00620         shared_vals[0].type = AFM_VALUE_TYPE_INTEGER;
00621         shared_vals[1].type = AFM_VALUE_TYPE_FIXED;
00622         shared_vals[2].type = AFM_VALUE_TYPE_FIXED;
00623         shared_vals[3].type = AFM_VALUE_TYPE_FIXED;
00624         shared_vals[4].type = AFM_VALUE_TYPE_FIXED;
00625         if ( afm_parser_read_vals( parser, shared_vals, 5 ) != 5 )
00626           goto Fail;
00627 
00628         tk->degree     = shared_vals[0].u.i;
00629         tk->min_ptsize = shared_vals[1].u.f;
00630         tk->min_kern   = shared_vals[2].u.f;
00631         tk->max_ptsize = shared_vals[3].u.f;
00632         tk->max_kern   = shared_vals[4].u.f;
00633 
00634         /* is this correct? */
00635         if ( tk->degree < 0 && tk->min_kern > 0 )
00636           tk->min_kern = -tk->min_kern;
00637         break;
00638 
00639       case AFM_TOKEN_ENDTRACKKERN:
00640       case AFM_TOKEN_ENDKERNDATA:
00641       case AFM_TOKEN_ENDFONTMETRICS:
00642         fi->NumTrackKern = n + 1;
00643         return PSaux_Err_Ok;
00644 
00645       case AFM_TOKEN_UNKNOWN:
00646         break;
00647 
00648       default:
00649         goto Fail;
00650       }
00651     }
00652 
00653   Fail:
00654     return PSaux_Err_Syntax_Error;
00655   }
00656 
00657 
00658 #undef  KERN_INDEX
00659 #define KERN_INDEX( g1, g2 )  ( ( (FT_ULong)g1 << 16 ) | g2 )
00660 
00661 
00662   /* compare two kerning pairs */
00663   FT_CALLBACK_DEF( int )
00664   afm_compare_kern_pairs( const void*  a,
00665                           const void*  b )
00666   {
00667     AFM_KernPair  kp1 = (AFM_KernPair)a;
00668     AFM_KernPair  kp2 = (AFM_KernPair)b;
00669 
00670     FT_ULong  index1 = KERN_INDEX( kp1->index1, kp1->index2 );
00671     FT_ULong  index2 = KERN_INDEX( kp2->index1, kp2->index2 );
00672 
00673 
00674     if ( index1 > index2 )
00675       return 1;
00676     else if ( index1 < index2 )
00677       return -1;
00678     else
00679       return 0;
00680   }
00681 
00682 
00683   static FT_Error
00684   afm_parse_kern_pairs( AFM_Parser  parser )
00685   {
00686     AFM_FontInfo  fi = parser->FontInfo;
00687     AFM_KernPair  kp;
00688     char*         key;
00689     FT_Offset     len;
00690     int           n = -1;
00691 
00692 
00693     if ( afm_parser_read_int( parser, &fi->NumKernPair ) )
00694       goto Fail;
00695 
00696     if ( fi->NumKernPair )
00697     {
00698       FT_Memory  memory = parser->memory;
00699       FT_Error   error;
00700 
00701 
00702       if ( FT_QNEW_ARRAY( fi->KernPairs, fi->NumKernPair ) )
00703         return error;
00704     }
00705 
00706     while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
00707     {
00708       AFM_Token  token = afm_tokenize( key, len );
00709 
00710 
00711       switch ( token )
00712       {
00713       case AFM_TOKEN_KP:
00714       case AFM_TOKEN_KPX:
00715       case AFM_TOKEN_KPY:
00716         {
00717           FT_Int        r;
00718           AFM_ValueRec  shared_vals[4];
00719 
00720 
00721           n++;
00722 
00723           if ( n >= fi->NumKernPair )
00724             goto Fail;
00725 
00726           kp = fi->KernPairs + n;
00727 
00728           shared_vals[0].type = AFM_VALUE_TYPE_INDEX;
00729           shared_vals[1].type = AFM_VALUE_TYPE_INDEX;
00730           shared_vals[2].type = AFM_VALUE_TYPE_INTEGER;
00731           shared_vals[3].type = AFM_VALUE_TYPE_INTEGER;
00732           r = afm_parser_read_vals( parser, shared_vals, 4 );
00733           if ( r < 3 )
00734             goto Fail;
00735 
00736           kp->index1 = shared_vals[0].u.i;
00737           kp->index2 = shared_vals[1].u.i;
00738           if ( token == AFM_TOKEN_KPY )
00739           {
00740             kp->x = 0;
00741             kp->y = shared_vals[2].u.i;
00742           }
00743           else
00744           {
00745             kp->x = shared_vals[2].u.i;
00746             kp->y = ( token == AFM_TOKEN_KP && r == 4 )
00747                       ? shared_vals[3].u.i : 0;
00748           }
00749         }
00750         break;
00751 
00752       case AFM_TOKEN_ENDKERNPAIRS:
00753       case AFM_TOKEN_ENDKERNDATA:
00754       case AFM_TOKEN_ENDFONTMETRICS:
00755         fi->NumKernPair = n + 1;
00756         ft_qsort( fi->KernPairs, fi->NumKernPair,
00757                   sizeof( AFM_KernPairRec ),
00758                   afm_compare_kern_pairs );
00759         return PSaux_Err_Ok;
00760 
00761       case AFM_TOKEN_UNKNOWN:
00762         break;
00763 
00764       default:
00765         goto Fail;
00766       }
00767     }
00768 
00769   Fail:
00770     return PSaux_Err_Syntax_Error;
00771   }
00772 
00773 
00774   static FT_Error
00775   afm_parse_kern_data( AFM_Parser  parser )
00776   {
00777     FT_Error   error;
00778     char*      key;
00779     FT_Offset  len;
00780 
00781 
00782     while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
00783     {
00784       switch ( afm_tokenize( key, len ) )
00785       {
00786       case AFM_TOKEN_STARTTRACKKERN:
00787         error = afm_parse_track_kern( parser );
00788         if ( error )
00789           return error;
00790         break;
00791 
00792       case AFM_TOKEN_STARTKERNPAIRS:
00793       case AFM_TOKEN_STARTKERNPAIRS0:
00794         error = afm_parse_kern_pairs( parser );
00795         if ( error )
00796           return error;
00797         break;
00798 
00799       case AFM_TOKEN_ENDKERNDATA:
00800       case AFM_TOKEN_ENDFONTMETRICS:
00801         return PSaux_Err_Ok;
00802 
00803       case AFM_TOKEN_UNKNOWN:
00804         break;
00805 
00806       default:
00807         goto Fail;
00808       }
00809     }
00810 
00811   Fail:
00812     return PSaux_Err_Syntax_Error;
00813   }
00814 
00815 
00816   static FT_Error
00817   afm_parser_skip_section( AFM_Parser  parser,
00818                            FT_UInt     n,
00819                            AFM_Token   end_section )
00820   {
00821     char*      key;
00822     FT_Offset  len;
00823 
00824 
00825     while ( n-- > 0 )
00826     {
00827       key = afm_parser_next_key( parser, 1, NULL );
00828       if ( !key )
00829         goto Fail;
00830     }
00831 
00832     while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
00833     {
00834       AFM_Token  token = afm_tokenize( key, len );
00835 
00836 
00837       if ( token == end_section || token == AFM_TOKEN_ENDFONTMETRICS )
00838         return PSaux_Err_Ok;
00839     }
00840 
00841   Fail:
00842     return PSaux_Err_Syntax_Error;
00843   }
00844 
00845 
00846   FT_LOCAL_DEF( FT_Error )
00847   afm_parser_parse( AFM_Parser  parser )
00848   {
00849     FT_Memory     memory = parser->memory;
00850     AFM_FontInfo  fi     = parser->FontInfo;
00851     FT_Error      error  = PSaux_Err_Syntax_Error;
00852     char*         key;
00853     FT_Offset     len;
00854     FT_Int        metrics_sets = 0;
00855 
00856 
00857     if ( !fi )
00858       return PSaux_Err_Invalid_Argument;
00859 
00860     key = afm_parser_next_key( parser, 1, &len );
00861     if ( !key || len != 16                              ||
00862          ft_strncmp( key, "StartFontMetrics", 16 ) != 0 )
00863       return PSaux_Err_Unknown_File_Format;
00864 
00865     while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
00866     {
00867       AFM_ValueRec  shared_vals[4];
00868 
00869 
00870       switch ( afm_tokenize( key, len ) )
00871       {
00872       case AFM_TOKEN_METRICSSETS:
00873         if ( afm_parser_read_int( parser, &metrics_sets ) )
00874           goto Fail;
00875 
00876         if ( metrics_sets != 0 && metrics_sets != 2 )
00877         {
00878           error = PSaux_Err_Unimplemented_Feature;
00879 
00880           goto Fail;
00881         }
00882         break;
00883 
00884       case AFM_TOKEN_ISCIDFONT:
00885         shared_vals[0].type = AFM_VALUE_TYPE_BOOL;
00886         if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 )
00887           goto Fail;
00888 
00889         fi->IsCIDFont = shared_vals[0].u.b;
00890         break;
00891 
00892       case AFM_TOKEN_FONTBBOX:
00893         shared_vals[0].type = AFM_VALUE_TYPE_FIXED;
00894         shared_vals[1].type = AFM_VALUE_TYPE_FIXED;
00895         shared_vals[2].type = AFM_VALUE_TYPE_FIXED;
00896         shared_vals[3].type = AFM_VALUE_TYPE_FIXED;
00897         if ( afm_parser_read_vals( parser, shared_vals, 4 ) != 4 )
00898           goto Fail;
00899 
00900         fi->FontBBox.xMin = shared_vals[0].u.f;
00901         fi->FontBBox.yMin = shared_vals[1].u.f;
00902         fi->FontBBox.xMax = shared_vals[2].u.f;
00903         fi->FontBBox.yMax = shared_vals[3].u.f;
00904         break;
00905 
00906       case AFM_TOKEN_ASCENDER:
00907         shared_vals[0].type = AFM_VALUE_TYPE_FIXED;
00908         if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 )
00909           goto Fail;
00910 
00911         fi->Ascender = shared_vals[0].u.f;
00912         break;
00913 
00914       case AFM_TOKEN_DESCENDER:
00915         shared_vals[0].type = AFM_VALUE_TYPE_FIXED;
00916         if ( afm_parser_read_vals( parser, shared_vals, 1 ) != 1 )
00917           goto Fail;
00918 
00919         fi->Descender = shared_vals[0].u.f;
00920         break;
00921 
00922       case AFM_TOKEN_STARTCHARMETRICS:
00923         {
00924           FT_Int  n = 0;
00925 
00926 
00927           if ( afm_parser_read_int( parser, &n ) )
00928             goto Fail;
00929 
00930           error = afm_parser_skip_section( parser, n,
00931                                            AFM_TOKEN_ENDCHARMETRICS );
00932           if ( error )
00933             return error;
00934         }
00935         break;
00936 
00937       case AFM_TOKEN_STARTKERNDATA:
00938         error = afm_parse_kern_data( parser );
00939         if ( error )
00940           goto Fail;
00941         /* fall through since we only support kern data */
00942 
00943       case AFM_TOKEN_ENDFONTMETRICS:
00944         return PSaux_Err_Ok;
00945 
00946       default:
00947         break;
00948       }
00949     }
00950 
00951   Fail:
00952     FT_FREE( fi->TrackKerns );
00953     fi->NumTrackKern = 0;
00954 
00955     FT_FREE( fi->KernPairs );
00956     fi->NumKernPair = 0;
00957 
00958     fi->IsCIDFont = 0;
00959 
00960     return error;
00961   }
00962 
00963 
00964 /* END */

Generated on Tue Jul 5 14:13:50 2011 for ROOT_528-00b_version by  doxygen 1.5.1