Home | History | Annotate | Download | only in type1
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  t1load.c                                                               */
      4 /*                                                                         */
      5 /*    Type 1 font loader (body).                                           */
      6 /*                                                                         */
      7 /*  Copyright 1996-2015 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 
     19   /*************************************************************************/
     20   /*                                                                       */
     21   /* This is the new and improved Type 1 data loader for FreeType 2.  The  */
     22   /* old loader has several problems: it is slow, complex, difficult to    */
     23   /* maintain, and contains incredible hacks to make it accept some        */
     24   /* ill-formed Type 1 fonts without hiccup-ing.  Moreover, about 5% of    */
     25   /* the Type 1 fonts on my machine still aren't loaded correctly by it.   */
     26   /*                                                                       */
     27   /* This version is much simpler, much faster and also easier to read and */
     28   /* maintain by a great order of magnitude.  The idea behind it is to     */
     29   /* _not_ try to read the Type 1 token stream with a state machine (i.e.  */
     30   /* a Postscript-like interpreter) but rather to perform simple pattern   */
     31   /* matching.                                                             */
     32   /*                                                                       */
     33   /* Indeed, nearly all data definitions follow a simple pattern like      */
     34   /*                                                                       */
     35   /*  ... /Field <data> ...                                                */
     36   /*                                                                       */
     37   /* where <data> can be a number, a boolean, a string, or an array of     */
     38   /* numbers.  There are a few exceptions, namely the encoding, font name, */
     39   /* charstrings, and subrs; they are handled with a special pattern       */
     40   /* matching routine.                                                     */
     41   /*                                                                       */
     42   /* All other common cases are handled very simply.  The matching rules   */
     43   /* are defined in the file `t1tokens.h' through the use of several       */
     44   /* macros calls PARSE_XXX.  This file is included twice here; the first  */
     45   /* time to generate parsing callback functions, the second time to       */
     46   /* generate a table of keywords (with pointers to the associated         */
     47   /* callback functions).                                                  */
     48   /*                                                                       */
     49   /* The function `parse_dict' simply scans *linearly* a given dictionary  */
     50   /* (either the top-level or private one) and calls the appropriate       */
     51   /* callback when it encounters an immediate keyword.                     */
     52   /*                                                                       */
     53   /* This is by far the fastest way one can find to parse and read all     */
     54   /* data.                                                                 */
     55   /*                                                                       */
     56   /* This led to tremendous code size reduction.  Note that later, the     */
     57   /* glyph loader will also be _greatly_ simplified, and the automatic     */
     58   /* hinter will replace the clumsy `t1hinter'.                            */
     59   /*                                                                       */
     60   /*************************************************************************/
     61 
     62 
     63 #include <ft2build.h>
     64 #include FT_INTERNAL_DEBUG_H
     65 #include FT_CONFIG_CONFIG_H
     66 #include FT_MULTIPLE_MASTERS_H
     67 #include FT_INTERNAL_TYPE1_TYPES_H
     68 #include FT_INTERNAL_CALC_H
     69 
     70 #include "t1load.h"
     71 #include "t1errors.h"
     72 
     73 
     74 #ifdef FT_CONFIG_OPTION_INCREMENTAL
     75 #define IS_INCREMENTAL  (FT_Bool)( face->root.internal->incremental_interface != 0 )
     76 #else
     77 #define IS_INCREMENTAL  0
     78 #endif
     79 
     80 
     81   /*************************************************************************/
     82   /*                                                                       */
     83   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
     84   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
     85   /* messages during execution.                                            */
     86   /*                                                                       */
     87 #undef  FT_COMPONENT
     88 #define FT_COMPONENT  trace_t1load
     89 
     90 
     91 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
     92 
     93 
     94   /*************************************************************************/
     95   /*************************************************************************/
     96   /*****                                                               *****/
     97   /*****                    MULTIPLE MASTERS SUPPORT                   *****/
     98   /*****                                                               *****/
     99   /*************************************************************************/
    100   /*************************************************************************/
    101 
    102   static FT_Error
    103   t1_allocate_blend( T1_Face  face,
    104                      FT_UInt  num_designs,
    105                      FT_UInt  num_axis )
    106   {
    107     PS_Blend   blend;
    108     FT_Memory  memory = face->root.memory;
    109     FT_Error   error  = FT_Err_Ok;
    110 
    111 
    112     blend = face->blend;
    113     if ( !blend )
    114     {
    115       if ( FT_NEW( blend ) )
    116         goto Exit;
    117 
    118       blend->num_default_design_vector = 0;
    119 
    120       face->blend = blend;
    121     }
    122 
    123     /* allocate design data if needed */
    124     if ( num_designs > 0 )
    125     {
    126       if ( blend->num_designs == 0 )
    127       {
    128         FT_UInt  nn;
    129 
    130 
    131         /* allocate the blend `private' and `font_info' dictionaries */
    132         if ( FT_NEW_ARRAY( blend->font_infos[1], num_designs     ) ||
    133              FT_NEW_ARRAY( blend->privates  [1], num_designs     ) ||
    134              FT_NEW_ARRAY( blend->bboxes    [1], num_designs     ) ||
    135              FT_NEW_ARRAY( blend->weight_vector, num_designs * 2 ) )
    136           goto Exit;
    137 
    138         blend->default_weight_vector = blend->weight_vector + num_designs;
    139 
    140         blend->font_infos[0] = &face->type1.font_info;
    141         blend->privates  [0] = &face->type1.private_dict;
    142         blend->bboxes    [0] = &face->type1.font_bbox;
    143 
    144         for ( nn = 2; nn <= num_designs; nn++ )
    145         {
    146           blend->font_infos[nn] = blend->font_infos[nn - 1] + 1;
    147           blend->privates  [nn] = blend->privates  [nn - 1] + 1;
    148           blend->bboxes    [nn] = blend->bboxes    [nn - 1] + 1;
    149         }
    150 
    151         blend->num_designs = num_designs;
    152       }
    153       else if ( blend->num_designs != num_designs )
    154         goto Fail;
    155     }
    156 
    157     /* allocate axis data if needed */
    158     if ( num_axis > 0 )
    159     {
    160       if ( blend->num_axis != 0 && blend->num_axis != num_axis )
    161         goto Fail;
    162 
    163       blend->num_axis = num_axis;
    164     }
    165 
    166     /* allocate the blend design pos table if needed */
    167     num_designs = blend->num_designs;
    168     num_axis    = blend->num_axis;
    169     if ( num_designs && num_axis && blend->design_pos[0] == 0 )
    170     {
    171       FT_UInt  n;
    172 
    173 
    174       if ( FT_NEW_ARRAY( blend->design_pos[0], num_designs * num_axis ) )
    175         goto Exit;
    176 
    177       for ( n = 1; n < num_designs; n++ )
    178         blend->design_pos[n] = blend->design_pos[0] + num_axis * n;
    179     }
    180 
    181   Exit:
    182     return error;
    183 
    184   Fail:
    185     error = FT_THROW( Invalid_File_Format );
    186     goto Exit;
    187   }
    188 
    189 
    190   FT_LOCAL_DEF( FT_Error )
    191   T1_Get_Multi_Master( T1_Face           face,
    192                        FT_Multi_Master*  master )
    193   {
    194     PS_Blend  blend = face->blend;
    195     FT_UInt   n;
    196     FT_Error  error;
    197 
    198 
    199     error = FT_THROW( Invalid_Argument );
    200 
    201     if ( blend )
    202     {
    203       master->num_axis    = blend->num_axis;
    204       master->num_designs = blend->num_designs;
    205 
    206       for ( n = 0; n < blend->num_axis; n++ )
    207       {
    208         FT_MM_Axis*   axis = master->axis + n;
    209         PS_DesignMap  map = blend->design_map + n;
    210 
    211 
    212         axis->name    = blend->axis_names[n];
    213         axis->minimum = map->design_points[0];
    214         axis->maximum = map->design_points[map->num_points - 1];
    215       }
    216 
    217       error = FT_Err_Ok;
    218     }
    219 
    220     return error;
    221   }
    222 
    223 
    224   /*************************************************************************/
    225   /*                                                                       */
    226   /* Given a normalized (blend) coordinate, figure out the design          */
    227   /* coordinate appropriate for that value.                                */
    228   /*                                                                       */
    229   static FT_Fixed
    230   mm_axis_unmap( PS_DesignMap  axismap,
    231                  FT_Fixed      ncv )
    232   {
    233     int  j;
    234 
    235 
    236     if ( ncv <= axismap->blend_points[0] )
    237       return INT_TO_FIXED( axismap->design_points[0] );
    238 
    239     for ( j = 1; j < axismap->num_points; ++j )
    240     {
    241       if ( ncv <= axismap->blend_points[j] )
    242         return INT_TO_FIXED( axismap->design_points[j - 1] ) +
    243                ( axismap->design_points[j] - axismap->design_points[j - 1] ) *
    244                FT_DivFix( ncv - axismap->blend_points[j - 1],
    245                           axismap->blend_points[j] -
    246                             axismap->blend_points[j - 1] );
    247     }
    248 
    249     return INT_TO_FIXED( axismap->design_points[axismap->num_points - 1] );
    250   }
    251 
    252 
    253   /*************************************************************************/
    254   /*                                                                       */
    255   /* Given a vector of weights, one for each design, figure out the        */
    256   /* normalized axis coordinates which gave rise to those weights.         */
    257   /*                                                                       */
    258   static void
    259   mm_weights_unmap( FT_Fixed*  weights,
    260                     FT_Fixed*  axiscoords,
    261                     FT_UInt    axis_count )
    262   {
    263     FT_ASSERT( axis_count <= T1_MAX_MM_AXIS );
    264 
    265     if ( axis_count == 1 )
    266       axiscoords[0] = weights[1];
    267 
    268     else if ( axis_count == 2 )
    269     {
    270       axiscoords[0] = weights[3] + weights[1];
    271       axiscoords[1] = weights[3] + weights[2];
    272     }
    273 
    274     else if ( axis_count == 3 )
    275     {
    276       axiscoords[0] = weights[7] + weights[5] + weights[3] + weights[1];
    277       axiscoords[1] = weights[7] + weights[6] + weights[3] + weights[2];
    278       axiscoords[2] = weights[7] + weights[6] + weights[5] + weights[4];
    279     }
    280 
    281     else
    282     {
    283       axiscoords[0] = weights[15] + weights[13] + weights[11] + weights[9] +
    284                         weights[7] + weights[5] + weights[3] + weights[1];
    285       axiscoords[1] = weights[15] + weights[14] + weights[11] + weights[10] +
    286                         weights[7] + weights[6] + weights[3] + weights[2];
    287       axiscoords[2] = weights[15] + weights[14] + weights[13] + weights[12] +
    288                         weights[7] + weights[6] + weights[5] + weights[4];
    289       axiscoords[3] = weights[15] + weights[14] + weights[13] + weights[12] +
    290                         weights[11] + weights[10] + weights[9] + weights[8];
    291     }
    292   }
    293 
    294 
    295   /*************************************************************************/
    296   /*                                                                       */
    297   /* Just a wrapper around T1_Get_Multi_Master to support the different    */
    298   /*  arguments needed by the GX var distortable fonts.                    */
    299   /*                                                                       */
    300   FT_LOCAL_DEF( FT_Error )
    301   T1_Get_MM_Var( T1_Face      face,
    302                  FT_MM_Var*  *master )
    303   {
    304     FT_Memory        memory = face->root.memory;
    305     FT_MM_Var       *mmvar = NULL;
    306     FT_Multi_Master  mmaster;
    307     FT_Error         error;
    308     FT_UInt          i;
    309     FT_Fixed         axiscoords[T1_MAX_MM_AXIS];
    310     PS_Blend         blend = face->blend;
    311 
    312 
    313     error = T1_Get_Multi_Master( face, &mmaster );
    314     if ( error )
    315       goto Exit;
    316     if ( FT_ALLOC( mmvar,
    317                    sizeof ( FT_MM_Var ) +
    318                      mmaster.num_axis * sizeof ( FT_Var_Axis ) ) )
    319       goto Exit;
    320 
    321     mmvar->num_axis        = mmaster.num_axis;
    322     mmvar->num_designs     = mmaster.num_designs;
    323     mmvar->num_namedstyles = ~0U;                        /* Does not apply */
    324     mmvar->axis            = (FT_Var_Axis*)&mmvar[1];
    325                                       /* Point to axes after MM_Var struct */
    326     mmvar->namedstyle      = NULL;
    327 
    328     for ( i = 0 ; i < mmaster.num_axis; ++i )
    329     {
    330       mmvar->axis[i].name    = mmaster.axis[i].name;
    331       mmvar->axis[i].minimum = INT_TO_FIXED( mmaster.axis[i].minimum);
    332       mmvar->axis[i].maximum = INT_TO_FIXED( mmaster.axis[i].maximum);
    333       mmvar->axis[i].def     = ( mmvar->axis[i].minimum +
    334                                    mmvar->axis[i].maximum ) / 2;
    335                             /* Does not apply.  But this value is in range */
    336       mmvar->axis[i].strid   = ~0U;                      /* Does not apply */
    337       mmvar->axis[i].tag     = ~0U;                      /* Does not apply */
    338 
    339       if ( ft_strcmp( mmvar->axis[i].name, "Weight" ) == 0 )
    340         mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'g', 'h', 't' );
    341       else if ( ft_strcmp( mmvar->axis[i].name, "Width" ) == 0 )
    342         mmvar->axis[i].tag = FT_MAKE_TAG( 'w', 'd', 't', 'h' );
    343       else if ( ft_strcmp( mmvar->axis[i].name, "OpticalSize" ) == 0 )
    344         mmvar->axis[i].tag = FT_MAKE_TAG( 'o', 'p', 's', 'z' );
    345     }
    346 
    347     if ( blend->num_designs == ( 1U << blend->num_axis ) )
    348     {
    349       mm_weights_unmap( blend->default_weight_vector,
    350                         axiscoords,
    351                         blend->num_axis );
    352 
    353       for ( i = 0; i < mmaster.num_axis; ++i )
    354         mmvar->axis[i].def = mm_axis_unmap( &blend->design_map[i],
    355                                             axiscoords[i] );
    356     }
    357 
    358     *master = mmvar;
    359 
    360   Exit:
    361     return error;
    362   }
    363 
    364 
    365   FT_LOCAL_DEF( FT_Error )
    366   T1_Set_MM_Blend( T1_Face    face,
    367                    FT_UInt    num_coords,
    368                    FT_Fixed*  coords )
    369   {
    370     PS_Blend  blend = face->blend;
    371     FT_UInt   n, m;
    372 
    373 
    374     if ( !blend )
    375       return FT_THROW( Invalid_Argument );
    376 
    377     if ( num_coords > blend->num_axis )
    378       num_coords = blend->num_axis;
    379 
    380     /* recompute the weight vector from the blend coordinates */
    381     for ( n = 0; n < blend->num_designs; n++ )
    382     {
    383       FT_Fixed  result = 0x10000L;  /* 1.0 fixed */
    384 
    385 
    386       for ( m = 0; m < blend->num_axis; m++ )
    387       {
    388         FT_Fixed  factor;
    389 
    390 
    391         /* get current blend axis position;                  */
    392         /* use a default value if we don't have a coordinate */
    393         factor = m < num_coords ? coords[m] : 0x8000;
    394         if ( factor < 0 )
    395           factor = 0;
    396         if ( factor > 0x10000L )
    397           factor = 0x10000L;
    398 
    399         if ( ( n & ( 1 << m ) ) == 0 )
    400           factor = 0x10000L - factor;
    401 
    402         result = FT_MulFix( result, factor );
    403       }
    404       blend->weight_vector[n] = result;
    405     }
    406 
    407     return FT_Err_Ok;
    408   }
    409 
    410 
    411   FT_LOCAL_DEF( FT_Error )
    412   T1_Set_MM_Design( T1_Face   face,
    413                     FT_UInt   num_coords,
    414                     FT_Long*  coords )
    415   {
    416     PS_Blend  blend = face->blend;
    417     FT_UInt   n, p;
    418     FT_Fixed  final_blends[T1_MAX_MM_DESIGNS];
    419 
    420 
    421     if ( !blend )
    422       return FT_THROW( Invalid_Argument );
    423 
    424     if ( num_coords > blend->num_axis )
    425       num_coords = blend->num_axis;
    426 
    427     /* compute the blend coordinates through the blend design map */
    428 
    429     for ( n = 0; n < blend->num_axis; n++ )
    430     {
    431       FT_Long       design;
    432       FT_Fixed      the_blend;
    433       PS_DesignMap  map     = blend->design_map + n;
    434       FT_Long*      designs = map->design_points;
    435       FT_Fixed*     blends  = map->blend_points;
    436       FT_Int        before  = -1, after = -1;
    437 
    438 
    439       /* use a default value if we don't have a coordinate */
    440       if ( n < num_coords )
    441         design = coords[n];
    442       else
    443         design = ( designs[map->num_points - 1] - designs[0] ) / 2;
    444 
    445       for ( p = 0; p < (FT_UInt)map->num_points; p++ )
    446       {
    447         FT_Long  p_design = designs[p];
    448 
    449 
    450         /* exact match? */
    451         if ( design == p_design )
    452         {
    453           the_blend = blends[p];
    454           goto Found;
    455         }
    456 
    457         if ( design < p_design )
    458         {
    459           after = (FT_Int)p;
    460           break;
    461         }
    462 
    463         before = (FT_Int)p;
    464       }
    465 
    466       /* now interpolate if necessary */
    467       if ( before < 0 )
    468         the_blend = blends[0];
    469 
    470       else if ( after < 0 )
    471         the_blend = blends[map->num_points - 1];
    472 
    473       else
    474         the_blend = FT_MulDiv( design         - designs[before],
    475                                blends [after] - blends [before],
    476                                designs[after] - designs[before] );
    477 
    478     Found:
    479       final_blends[n] = the_blend;
    480     }
    481 
    482     return T1_Set_MM_Blend( face, blend->num_axis, final_blends );
    483   }
    484 
    485 
    486   /*************************************************************************/
    487   /*                                                                       */
    488   /* Just a wrapper around T1_Set_MM_Design to support the different       */
    489   /* arguments needed by the GX var distortable fonts.                     */
    490   /*                                                                       */
    491   FT_LOCAL_DEF( FT_Error )
    492   T1_Set_Var_Design( T1_Face    face,
    493                      FT_UInt    num_coords,
    494                      FT_Fixed*  coords )
    495   {
    496      FT_Long  lcoords[T1_MAX_MM_AXIS];
    497      FT_UInt  i;
    498 
    499 
    500      if ( num_coords > T1_MAX_MM_AXIS )
    501        num_coords = T1_MAX_MM_AXIS;
    502 
    503      for ( i = 0; i < num_coords; ++i )
    504        lcoords[i] = FIXED_TO_INT( coords[i] );
    505 
    506      return T1_Set_MM_Design( face, num_coords, lcoords );
    507   }
    508 
    509 
    510   FT_LOCAL_DEF( void )
    511   T1_Done_Blend( T1_Face  face )
    512   {
    513     FT_Memory  memory = face->root.memory;
    514     PS_Blend   blend  = face->blend;
    515 
    516 
    517     if ( blend )
    518     {
    519       FT_UInt  num_designs = blend->num_designs;
    520       FT_UInt  num_axis    = blend->num_axis;
    521       FT_UInt  n;
    522 
    523 
    524       /* release design pos table */
    525       FT_FREE( blend->design_pos[0] );
    526       for ( n = 1; n < num_designs; n++ )
    527         blend->design_pos[n] = NULL;
    528 
    529       /* release blend `private' and `font info' dictionaries */
    530       FT_FREE( blend->privates[1] );
    531       FT_FREE( blend->font_infos[1] );
    532       FT_FREE( blend->bboxes[1] );
    533 
    534       for ( n = 0; n < num_designs; n++ )
    535       {
    536         blend->privates  [n] = NULL;
    537         blend->font_infos[n] = NULL;
    538         blend->bboxes    [n] = NULL;
    539       }
    540 
    541       /* release weight vectors */
    542       FT_FREE( blend->weight_vector );
    543       blend->default_weight_vector = NULL;
    544 
    545       /* release axis names */
    546       for ( n = 0; n < num_axis; n++ )
    547         FT_FREE( blend->axis_names[n] );
    548 
    549       /* release design map */
    550       for ( n = 0; n < num_axis; n++ )
    551       {
    552         PS_DesignMap  dmap = blend->design_map + n;
    553 
    554 
    555         FT_FREE( dmap->design_points );
    556         dmap->num_points = 0;
    557       }
    558 
    559       FT_FREE( face->blend );
    560     }
    561   }
    562 
    563 
    564   static void
    565   parse_blend_axis_types( T1_Face    face,
    566                           T1_Loader  loader )
    567   {
    568     T1_TokenRec  axis_tokens[T1_MAX_MM_AXIS];
    569     FT_Int       n, num_axis;
    570     FT_Error     error = FT_Err_Ok;
    571     PS_Blend     blend;
    572     FT_Memory    memory;
    573 
    574 
    575     /* take an array of objects */
    576     T1_ToTokenArray( &loader->parser, axis_tokens,
    577                      T1_MAX_MM_AXIS, &num_axis );
    578     if ( num_axis < 0 )
    579     {
    580       error = FT_ERR( Ignore );
    581       goto Exit;
    582     }
    583     if ( num_axis == 0 || num_axis > T1_MAX_MM_AXIS )
    584     {
    585       FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n",
    586                  num_axis ));
    587       error = FT_THROW( Invalid_File_Format );
    588       goto Exit;
    589     }
    590 
    591     /* allocate blend if necessary */
    592     error = t1_allocate_blend( face, 0, (FT_UInt)num_axis );
    593     if ( error )
    594       goto Exit;
    595 
    596     blend  = face->blend;
    597     memory = face->root.memory;
    598 
    599     /* each token is an immediate containing the name of the axis */
    600     for ( n = 0; n < num_axis; n++ )
    601     {
    602       T1_Token  token = axis_tokens + n;
    603       FT_Byte*  name;
    604       FT_UInt   len;
    605 
    606 
    607       /* skip first slash, if any */
    608       if ( token->start[0] == '/' )
    609         token->start++;
    610 
    611       len = (FT_UInt)( token->limit - token->start );
    612       if ( len == 0 )
    613       {
    614         error = FT_THROW( Invalid_File_Format );
    615         goto Exit;
    616       }
    617 
    618       name = (FT_Byte*)blend->axis_names[n];
    619       if ( name )
    620       {
    621         FT_TRACE0(( "parse_blend_axis_types:"
    622                     " overwriting axis name `%s' with `%*.s'\n",
    623                     name, len, token->start ));
    624         FT_FREE( name );
    625       }
    626 
    627       if ( FT_ALLOC( blend->axis_names[n], len + 1 ) )
    628         goto Exit;
    629 
    630       name = (FT_Byte*)blend->axis_names[n];
    631       FT_MEM_COPY( name, token->start, len );
    632       name[len] = '\0';
    633     }
    634 
    635   Exit:
    636     loader->parser.root.error = error;
    637   }
    638 
    639 
    640   static void
    641   parse_blend_design_positions( T1_Face    face,
    642                                 T1_Loader  loader )
    643   {
    644     T1_TokenRec  design_tokens[T1_MAX_MM_DESIGNS];
    645     FT_Int       num_designs;
    646     FT_Int       num_axis;
    647     T1_Parser    parser = &loader->parser;
    648 
    649     FT_Error     error = FT_Err_Ok;
    650     PS_Blend     blend;
    651 
    652 
    653     /* get the array of design tokens -- compute number of designs */
    654     T1_ToTokenArray( parser, design_tokens,
    655                      T1_MAX_MM_DESIGNS, &num_designs );
    656     if ( num_designs < 0 )
    657     {
    658       error = FT_ERR( Ignore );
    659       goto Exit;
    660     }
    661     if ( num_designs == 0 || num_designs > T1_MAX_MM_DESIGNS )
    662     {
    663       FT_ERROR(( "parse_blend_design_positions:"
    664                  " incorrect number of designs: %d\n",
    665                  num_designs ));
    666       error = FT_THROW( Invalid_File_Format );
    667       goto Exit;
    668     }
    669 
    670     {
    671       FT_Byte*  old_cursor = parser->root.cursor;
    672       FT_Byte*  old_limit  = parser->root.limit;
    673       FT_Int    n;
    674 
    675 
    676       blend    = face->blend;
    677       num_axis = 0;  /* make compiler happy */
    678 
    679       for ( n = 0; n < num_designs; n++ )
    680       {
    681         T1_TokenRec  axis_tokens[T1_MAX_MM_AXIS];
    682         T1_Token     token;
    683         FT_Int       axis, n_axis;
    684 
    685 
    686         /* read axis/coordinates tokens */
    687         token = design_tokens + n;
    688         parser->root.cursor = token->start;
    689         parser->root.limit  = token->limit;
    690         T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis );
    691 
    692         if ( n == 0 )
    693         {
    694           if ( n_axis <= 0 || n_axis > T1_MAX_MM_AXIS )
    695           {
    696             FT_ERROR(( "parse_blend_design_positions:"
    697                        " invalid number of axes: %d\n",
    698                        n_axis ));
    699             error = FT_THROW( Invalid_File_Format );
    700             goto Exit;
    701           }
    702 
    703           num_axis = n_axis;
    704           error = t1_allocate_blend( face,
    705                                      (FT_UInt)num_designs,
    706                                      (FT_UInt)num_axis );
    707           if ( error )
    708             goto Exit;
    709           blend = face->blend;
    710         }
    711         else if ( n_axis != num_axis )
    712         {
    713           FT_ERROR(( "parse_blend_design_positions: incorrect table\n" ));
    714           error = FT_THROW( Invalid_File_Format );
    715           goto Exit;
    716         }
    717 
    718         /* now read each axis token into the design position */
    719         for ( axis = 0; axis < n_axis; axis++ )
    720         {
    721           T1_Token  token2 = axis_tokens + axis;
    722 
    723 
    724           parser->root.cursor = token2->start;
    725           parser->root.limit  = token2->limit;
    726           blend->design_pos[n][axis] = T1_ToFixed( parser, 0 );
    727         }
    728       }
    729 
    730       loader->parser.root.cursor = old_cursor;
    731       loader->parser.root.limit  = old_limit;
    732     }
    733 
    734   Exit:
    735     loader->parser.root.error = error;
    736   }
    737 
    738 
    739   static void
    740   parse_blend_design_map( T1_Face    face,
    741                           T1_Loader  loader )
    742   {
    743     FT_Error     error  = FT_Err_Ok;
    744     T1_Parser    parser = &loader->parser;
    745     PS_Blend     blend;
    746     T1_TokenRec  axis_tokens[T1_MAX_MM_AXIS];
    747     FT_Int       n, num_axis;
    748     FT_Byte*     old_cursor;
    749     FT_Byte*     old_limit;
    750     FT_Memory    memory = face->root.memory;
    751 
    752 
    753     T1_ToTokenArray( parser, axis_tokens,
    754                      T1_MAX_MM_AXIS, &num_axis );
    755     if ( num_axis < 0 )
    756     {
    757       error = FT_ERR( Ignore );
    758       goto Exit;
    759     }
    760     if ( num_axis == 0 || num_axis > T1_MAX_MM_AXIS )
    761     {
    762       FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n",
    763                  num_axis ));
    764       error = FT_THROW( Invalid_File_Format );
    765       goto Exit;
    766     }
    767 
    768     old_cursor = parser->root.cursor;
    769     old_limit  = parser->root.limit;
    770 
    771     error = t1_allocate_blend( face, 0, (FT_UInt)num_axis );
    772     if ( error )
    773       goto Exit;
    774     blend = face->blend;
    775 
    776     /* now read each axis design map */
    777     for ( n = 0; n < num_axis; n++ )
    778     {
    779       PS_DesignMap  map = blend->design_map + n;
    780       T1_Token      axis_token;
    781       T1_TokenRec   point_tokens[T1_MAX_MM_MAP_POINTS];
    782       FT_Int        p, num_points;
    783 
    784 
    785       axis_token = axis_tokens + n;
    786 
    787       parser->root.cursor = axis_token->start;
    788       parser->root.limit  = axis_token->limit;
    789       T1_ToTokenArray( parser, point_tokens,
    790                        T1_MAX_MM_MAP_POINTS, &num_points );
    791 
    792       if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS )
    793       {
    794         FT_ERROR(( "parse_blend_design_map: incorrect table\n" ));
    795         error = FT_THROW( Invalid_File_Format );
    796         goto Exit;
    797       }
    798 
    799       if ( map->design_points )
    800       {
    801         FT_ERROR(( "parse_blend_design_map: duplicate table\n" ));
    802         error = FT_THROW( Invalid_File_Format );
    803         goto Exit;
    804       }
    805 
    806       /* allocate design map data */
    807       if ( FT_NEW_ARRAY( map->design_points, num_points * 2 ) )
    808         goto Exit;
    809       map->blend_points = map->design_points + num_points;
    810       map->num_points   = (FT_Byte)num_points;
    811 
    812       for ( p = 0; p < num_points; p++ )
    813       {
    814         T1_Token  point_token;
    815 
    816 
    817         point_token = point_tokens + p;
    818 
    819         /* don't include delimiting brackets */
    820         parser->root.cursor = point_token->start + 1;
    821         parser->root.limit  = point_token->limit - 1;
    822 
    823         map->design_points[p] = T1_ToInt( parser );
    824         map->blend_points [p] = T1_ToFixed( parser, 0 );
    825       }
    826     }
    827 
    828     parser->root.cursor = old_cursor;
    829     parser->root.limit  = old_limit;
    830 
    831   Exit:
    832     parser->root.error = error;
    833   }
    834 
    835 
    836   static void
    837   parse_weight_vector( T1_Face    face,
    838                        T1_Loader  loader )
    839   {
    840     T1_TokenRec  design_tokens[T1_MAX_MM_DESIGNS];
    841     FT_Int       num_designs;
    842     FT_Error     error  = FT_Err_Ok;
    843     T1_Parser    parser = &loader->parser;
    844     PS_Blend     blend  = face->blend;
    845     T1_Token     token;
    846     FT_Int       n;
    847     FT_Byte*     old_cursor;
    848     FT_Byte*     old_limit;
    849 
    850 
    851     T1_ToTokenArray( parser, design_tokens,
    852                      T1_MAX_MM_DESIGNS, &num_designs );
    853     if ( num_designs < 0 )
    854     {
    855       error = FT_ERR( Ignore );
    856       goto Exit;
    857     }
    858     if ( num_designs == 0 || num_designs > T1_MAX_MM_DESIGNS )
    859     {
    860       FT_ERROR(( "parse_weight_vector:"
    861                  " incorrect number of designs: %d\n",
    862                  num_designs ));
    863       error = FT_THROW( Invalid_File_Format );
    864       goto Exit;
    865     }
    866 
    867     if ( !blend || !blend->num_designs )
    868     {
    869       error = t1_allocate_blend( face, (FT_UInt)num_designs, 0 );
    870       if ( error )
    871         goto Exit;
    872       blend = face->blend;
    873     }
    874     else if ( blend->num_designs != (FT_UInt)num_designs )
    875     {
    876       FT_ERROR(( "parse_weight_vector:"
    877                  " /BlendDesignPosition and /WeightVector have\n"
    878                  "                    "
    879                  " different number of elements\n" ));
    880       error = FT_THROW( Invalid_File_Format );
    881       goto Exit;
    882     }
    883 
    884     old_cursor = parser->root.cursor;
    885     old_limit  = parser->root.limit;
    886 
    887     for ( n = 0; n < num_designs; n++ )
    888     {
    889       token = design_tokens + n;
    890       parser->root.cursor = token->start;
    891       parser->root.limit  = token->limit;
    892 
    893       blend->default_weight_vector[n] =
    894       blend->weight_vector[n]         = T1_ToFixed( parser, 0 );
    895     }
    896 
    897     parser->root.cursor = old_cursor;
    898     parser->root.limit  = old_limit;
    899 
    900   Exit:
    901     parser->root.error = error;
    902   }
    903 
    904 
    905   /* e.g., /BuildCharArray [0 0 0 0 0 0 0 0] def           */
    906   /* we're only interested in the number of array elements */
    907   static void
    908   parse_buildchar( T1_Face    face,
    909                    T1_Loader  loader )
    910   {
    911     face->len_buildchar = (FT_UInt)T1_ToFixedArray( &loader->parser,
    912                                                     0, NULL, 0 );
    913     return;
    914   }
    915 
    916 
    917 #endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */
    918 
    919 
    920 
    921 
    922   /*************************************************************************/
    923   /*************************************************************************/
    924   /*****                                                               *****/
    925   /*****                      TYPE 1 SYMBOL PARSING                    *****/
    926   /*****                                                               *****/
    927   /*************************************************************************/
    928   /*************************************************************************/
    929 
    930   static FT_Error
    931   t1_load_keyword( T1_Face         face,
    932                    T1_Loader       loader,
    933                    const T1_Field  field )
    934   {
    935     FT_Error  error;
    936     void*     dummy_object;
    937     void**    objects;
    938     FT_UInt   max_objects;
    939     PS_Blend  blend = face->blend;
    940 
    941 
    942     if ( blend && blend->num_designs == 0 )
    943       blend = NULL;
    944 
    945     /* if the keyword has a dedicated callback, call it */
    946     if ( field->type == T1_FIELD_TYPE_CALLBACK )
    947     {
    948       field->reader( (FT_Face)face, loader );
    949       error = loader->parser.root.error;
    950       goto Exit;
    951     }
    952 
    953     /* now, the keyword is either a simple field, or a table of fields; */
    954     /* we are now going to take care of it                              */
    955     switch ( field->location )
    956     {
    957     case T1_FIELD_LOCATION_FONT_INFO:
    958       dummy_object = &face->type1.font_info;
    959       objects      = &dummy_object;
    960       max_objects  = 0;
    961 
    962       if ( blend )
    963       {
    964         objects     = (void**)blend->font_infos;
    965         max_objects = blend->num_designs;
    966       }
    967       break;
    968 
    969     case T1_FIELD_LOCATION_FONT_EXTRA:
    970       dummy_object = &face->type1.font_extra;
    971       objects      = &dummy_object;
    972       max_objects  = 0;
    973       break;
    974 
    975     case T1_FIELD_LOCATION_PRIVATE:
    976       dummy_object = &face->type1.private_dict;
    977       objects      = &dummy_object;
    978       max_objects  = 0;
    979 
    980       if ( blend )
    981       {
    982         objects     = (void**)blend->privates;
    983         max_objects = blend->num_designs;
    984       }
    985       break;
    986 
    987     case T1_FIELD_LOCATION_BBOX:
    988       dummy_object = &face->type1.font_bbox;
    989       objects      = &dummy_object;
    990       max_objects  = 0;
    991 
    992       if ( blend )
    993       {
    994         objects     = (void**)blend->bboxes;
    995         max_objects = blend->num_designs;
    996       }
    997       break;
    998 
    999     case T1_FIELD_LOCATION_LOADER:
   1000       dummy_object = loader;
   1001       objects      = &dummy_object;
   1002       max_objects  = 0;
   1003       break;
   1004 
   1005     case T1_FIELD_LOCATION_FACE:
   1006       dummy_object = face;
   1007       objects      = &dummy_object;
   1008       max_objects  = 0;
   1009       break;
   1010 
   1011 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
   1012     case T1_FIELD_LOCATION_BLEND:
   1013       dummy_object = face->blend;
   1014       objects      = &dummy_object;
   1015       max_objects  = 0;
   1016       break;
   1017 #endif
   1018 
   1019     default:
   1020       dummy_object = &face->type1;
   1021       objects      = &dummy_object;
   1022       max_objects  = 0;
   1023     }
   1024 
   1025     if ( *objects )
   1026     {
   1027       if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
   1028            field->type == T1_FIELD_TYPE_FIXED_ARRAY   )
   1029         error = T1_Load_Field_Table( &loader->parser, field,
   1030                                      objects, max_objects, 0 );
   1031       else
   1032         error = T1_Load_Field( &loader->parser, field,
   1033                                objects, max_objects, 0 );
   1034     }
   1035     else
   1036     {
   1037       FT_TRACE1(( "t1_load_keyword: ignoring keyword `%s'"
   1038                   " which is not valid at this point\n"
   1039                   "                 (probably due to missing keywords)\n",
   1040                  field->ident ));
   1041       error = FT_Err_Ok;
   1042     }
   1043 
   1044   Exit:
   1045     return error;
   1046   }
   1047 
   1048 
   1049   static void
   1050   parse_private( T1_Face    face,
   1051                  T1_Loader  loader )
   1052   {
   1053     FT_UNUSED( face );
   1054 
   1055     loader->keywords_encountered |= T1_PRIVATE;
   1056   }
   1057 
   1058 
   1059   /* return 1 in case of success */
   1060 
   1061   static int
   1062   read_binary_data( T1_Parser  parser,
   1063                     FT_ULong*  size,
   1064                     FT_Byte**  base,
   1065                     FT_Bool    incremental )
   1066   {
   1067     FT_Byte*  cur;
   1068     FT_Byte*  limit = parser->root.limit;
   1069 
   1070 
   1071     /* the binary data has one of the following formats */
   1072     /*                                                  */
   1073     /*   `size' [white*] RD white ....... ND            */
   1074     /*   `size' [white*] -| white ....... |-            */
   1075     /*                                                  */
   1076 
   1077     T1_Skip_Spaces( parser );
   1078 
   1079     cur = parser->root.cursor;
   1080 
   1081     if ( cur < limit && ft_isdigit( *cur ) )
   1082     {
   1083       FT_Long  s = T1_ToInt( parser );
   1084 
   1085 
   1086       T1_Skip_PS_Token( parser );   /* `RD' or `-|' or something else */
   1087 
   1088       /* there is only one whitespace char after the */
   1089       /* `RD' or `-|' token                          */
   1090       *base = parser->root.cursor + 1;
   1091 
   1092       if ( s >= 0 && s < limit - *base )
   1093       {
   1094         parser->root.cursor += s + 1;
   1095         *size = (FT_ULong)s;
   1096         return !parser->root.error;
   1097       }
   1098     }
   1099 
   1100     if( !incremental )
   1101     {
   1102       FT_ERROR(( "read_binary_data: invalid size field\n" ));
   1103       parser->root.error = FT_THROW( Invalid_File_Format );
   1104     }
   1105 
   1106     return 0;
   1107   }
   1108 
   1109 
   1110   /* We now define the routines to handle the `/Encoding', `/Subrs', */
   1111   /* and `/CharStrings' dictionaries.                                */
   1112 
   1113   static void
   1114   t1_parse_font_matrix( T1_Face    face,
   1115                         T1_Loader  loader )
   1116   {
   1117     T1_Parser   parser = &loader->parser;
   1118     FT_Matrix*  matrix = &face->type1.font_matrix;
   1119     FT_Vector*  offset = &face->type1.font_offset;
   1120     FT_Face     root   = (FT_Face)&face->root;
   1121     FT_Fixed    temp[6];
   1122     FT_Fixed    temp_scale;
   1123     FT_Int      result;
   1124 
   1125 
   1126     /* input is scaled by 1000 to accommodate default FontMatrix */
   1127     result = T1_ToFixedArray( parser, 6, temp, 3 );
   1128 
   1129     if ( result < 6 )
   1130     {
   1131       parser->root.error = FT_THROW( Invalid_File_Format );
   1132       return;
   1133     }
   1134 
   1135     temp_scale = FT_ABS( temp[3] );
   1136 
   1137     if ( temp_scale == 0 )
   1138     {
   1139       FT_ERROR(( "t1_parse_font_matrix: invalid font matrix\n" ));
   1140       parser->root.error = FT_THROW( Invalid_File_Format );
   1141       return;
   1142     }
   1143 
   1144     /* atypical case */
   1145     if ( temp_scale != 0x10000L )
   1146     {
   1147       /* set units per EM based on FontMatrix values */
   1148       root->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale );
   1149 
   1150       temp[0] = FT_DivFix( temp[0], temp_scale );
   1151       temp[1] = FT_DivFix( temp[1], temp_scale );
   1152       temp[2] = FT_DivFix( temp[2], temp_scale );
   1153       temp[4] = FT_DivFix( temp[4], temp_scale );
   1154       temp[5] = FT_DivFix( temp[5], temp_scale );
   1155       temp[3] = temp[3] < 0 ? -0x10000L : 0x10000L;
   1156     }
   1157 
   1158     matrix->xx = temp[0];
   1159     matrix->yx = temp[1];
   1160     matrix->xy = temp[2];
   1161     matrix->yy = temp[3];
   1162 
   1163     /* note that the offsets must be expressed in integer font units */
   1164     offset->x = temp[4] >> 16;
   1165     offset->y = temp[5] >> 16;
   1166   }
   1167 
   1168 
   1169   static void
   1170   parse_encoding( T1_Face    face,
   1171                   T1_Loader  loader )
   1172   {
   1173     T1_Parser  parser = &loader->parser;
   1174     FT_Byte*   cur;
   1175     FT_Byte*   limit  = parser->root.limit;
   1176 
   1177     PSAux_Service  psaux = (PSAux_Service)face->psaux;
   1178 
   1179 
   1180     T1_Skip_Spaces( parser );
   1181     cur = parser->root.cursor;
   1182     if ( cur >= limit )
   1183     {
   1184       FT_ERROR(( "parse_encoding: out of bounds\n" ));
   1185       parser->root.error = FT_THROW( Invalid_File_Format );
   1186       return;
   1187     }
   1188 
   1189     /* if we have a number or `[', the encoding is an array, */
   1190     /* and we must load it now                               */
   1191     if ( ft_isdigit( *cur ) || *cur == '[' )
   1192     {
   1193       T1_Encoding  encode          = &face->type1.encoding;
   1194       FT_Int       count, n;
   1195       PS_Table     char_table      = &loader->encoding_table;
   1196       FT_Memory    memory          = parser->root.memory;
   1197       FT_Error     error;
   1198       FT_Bool      only_immediates = 0;
   1199 
   1200 
   1201       /* read the number of entries in the encoding; should be 256 */
   1202       if ( *cur == '[' )
   1203       {
   1204         count           = 256;
   1205         only_immediates = 1;
   1206         parser->root.cursor++;
   1207       }
   1208       else
   1209         count = (FT_Int)T1_ToInt( parser );
   1210 
   1211       /* only composite fonts (which we don't support) */
   1212       /* can have larger values                        */
   1213       if ( count > 256 )
   1214       {
   1215         FT_ERROR(( "parse_encoding: invalid encoding array size\n" ));
   1216         parser->root.error = FT_THROW( Invalid_File_Format );
   1217         return;
   1218       }
   1219 
   1220       T1_Skip_Spaces( parser );
   1221       if ( parser->root.cursor >= limit )
   1222         return;
   1223 
   1224       /* PostScript happily allows overwriting of encoding arrays */
   1225       if ( encode->char_index )
   1226       {
   1227         FT_FREE( encode->char_index );
   1228         FT_FREE( encode->char_name );
   1229         T1_Release_Table( char_table );
   1230       }
   1231 
   1232       /* we use a T1_Table to store our charnames */
   1233       loader->num_chars = encode->num_chars = count;
   1234       if ( FT_NEW_ARRAY( encode->char_index, count )     ||
   1235            FT_NEW_ARRAY( encode->char_name,  count )     ||
   1236            FT_SET_ERROR( psaux->ps_table_funcs->init(
   1237                            char_table, count, memory ) ) )
   1238       {
   1239         parser->root.error = error;
   1240         return;
   1241       }
   1242 
   1243       /* We need to `zero' out encoding_table.elements */
   1244       for ( n = 0; n < count; n++ )
   1245       {
   1246         char*  notdef = (char *)".notdef";
   1247 
   1248 
   1249         (void)T1_Add_Table( char_table, n, notdef, 8 );
   1250       }
   1251 
   1252       /* Now we need to read records of the form                */
   1253       /*                                                        */
   1254       /*   ... charcode /charname ...                           */
   1255       /*                                                        */
   1256       /* for each entry in our table.                           */
   1257       /*                                                        */
   1258       /* We simply look for a number followed by an immediate   */
   1259       /* name.  Note that this ignores correctly the sequence   */
   1260       /* that is often seen in type1 fonts:                     */
   1261       /*                                                        */
   1262       /*   0 1 255 { 1 index exch /.notdef put } for dup        */
   1263       /*                                                        */
   1264       /* used to clean the encoding array before anything else. */
   1265       /*                                                        */
   1266       /* Alternatively, if the array is directly given as       */
   1267       /*                                                        */
   1268       /*   /Encoding [ ... ]                                    */
   1269       /*                                                        */
   1270       /* we only read immediates.                               */
   1271 
   1272       n = 0;
   1273       T1_Skip_Spaces( parser );
   1274 
   1275       while ( parser->root.cursor < limit )
   1276       {
   1277         cur = parser->root.cursor;
   1278 
   1279         /* we stop when we encounter a `def' or `]' */
   1280         if ( *cur == 'd' && cur + 3 < limit )
   1281         {
   1282           if ( cur[1] == 'e'         &&
   1283                cur[2] == 'f'         &&
   1284                IS_PS_DELIM( cur[3] ) )
   1285           {
   1286             FT_TRACE6(( "encoding end\n" ));
   1287             cur += 3;
   1288             break;
   1289           }
   1290         }
   1291         if ( *cur == ']' )
   1292         {
   1293           FT_TRACE6(( "encoding end\n" ));
   1294           cur++;
   1295           break;
   1296         }
   1297 
   1298         /* check whether we've found an entry */
   1299         if ( ft_isdigit( *cur ) || only_immediates )
   1300         {
   1301           FT_Int  charcode;
   1302 
   1303 
   1304           if ( only_immediates )
   1305             charcode = n;
   1306           else
   1307           {
   1308             charcode = (FT_Int)T1_ToInt( parser );
   1309             T1_Skip_Spaces( parser );
   1310 
   1311             /* protect against invalid charcode */
   1312             if ( cur == parser->root.cursor )
   1313             {
   1314               parser->root.error = FT_THROW( Unknown_File_Format );
   1315               return;
   1316             }
   1317           }
   1318 
   1319           cur = parser->root.cursor;
   1320 
   1321           if ( cur + 2 < limit && *cur == '/' && n < count )
   1322           {
   1323             FT_UInt  len;
   1324 
   1325 
   1326             cur++;
   1327 
   1328             parser->root.cursor = cur;
   1329             T1_Skip_PS_Token( parser );
   1330             if ( parser->root.cursor >= limit )
   1331               return;
   1332             if ( parser->root.error )
   1333               return;
   1334 
   1335             len = (FT_UInt)( parser->root.cursor - cur );
   1336 
   1337             parser->root.error = T1_Add_Table( char_table, charcode,
   1338                                                cur, len + 1 );
   1339             if ( parser->root.error )
   1340               return;
   1341             char_table->elements[charcode][len] = '\0';
   1342 
   1343             n++;
   1344           }
   1345           else if ( only_immediates )
   1346           {
   1347             /* Since the current position is not updated for           */
   1348             /* immediates-only mode we would get an infinite loop if   */
   1349             /* we don't do anything here.                              */
   1350             /*                                                         */
   1351             /* This encoding array is not valid according to the type1 */
   1352             /* specification (it might be an encoding for a CID type1  */
   1353             /* font, however), so we conclude that this font is NOT a  */
   1354             /* type1 font.                                             */
   1355             parser->root.error = FT_THROW( Unknown_File_Format );
   1356             return;
   1357           }
   1358         }
   1359         else
   1360         {
   1361           T1_Skip_PS_Token( parser );
   1362           if ( parser->root.error )
   1363             return;
   1364         }
   1365 
   1366         T1_Skip_Spaces( parser );
   1367       }
   1368 
   1369       face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY;
   1370       parser->root.cursor       = cur;
   1371     }
   1372 
   1373     /* Otherwise, we should have either `StandardEncoding', */
   1374     /* `ExpertEncoding', or `ISOLatin1Encoding'             */
   1375     else
   1376     {
   1377       if ( cur + 17 < limit                                            &&
   1378            ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
   1379         face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD;
   1380 
   1381       else if ( cur + 15 < limit                                          &&
   1382                 ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
   1383         face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT;
   1384 
   1385       else if ( cur + 18 < limit                                             &&
   1386                 ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 )
   1387         face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1;
   1388 
   1389       else
   1390         parser->root.error = FT_ERR( Ignore );
   1391     }
   1392   }
   1393 
   1394 
   1395   static void
   1396   parse_subrs( T1_Face    face,
   1397                T1_Loader  loader )
   1398   {
   1399     T1_Parser  parser = &loader->parser;
   1400     PS_Table   table  = &loader->subrs;
   1401     FT_Memory  memory = parser->root.memory;
   1402     FT_Error   error;
   1403     FT_Int     num_subrs;
   1404 
   1405     PSAux_Service  psaux = (PSAux_Service)face->psaux;
   1406 
   1407 
   1408     T1_Skip_Spaces( parser );
   1409 
   1410     /* test for empty array */
   1411     if ( parser->root.cursor < parser->root.limit &&
   1412          *parser->root.cursor == '['              )
   1413     {
   1414       T1_Skip_PS_Token( parser );
   1415       T1_Skip_Spaces  ( parser );
   1416       if ( parser->root.cursor >= parser->root.limit ||
   1417            *parser->root.cursor != ']'               )
   1418         parser->root.error = FT_THROW( Invalid_File_Format );
   1419       return;
   1420     }
   1421 
   1422     num_subrs = (FT_Int)T1_ToInt( parser );
   1423 
   1424     /* position the parser right before the `dup' of the first subr */
   1425     T1_Skip_PS_Token( parser );         /* `array' */
   1426     if ( parser->root.error )
   1427       return;
   1428     T1_Skip_Spaces( parser );
   1429 
   1430     /* initialize subrs array -- with synthetic fonts it is possible */
   1431     /* we get here twice                                             */
   1432     if ( !loader->num_subrs )
   1433     {
   1434       error = psaux->ps_table_funcs->init( table, num_subrs, memory );
   1435       if ( error )
   1436         goto Fail;
   1437     }
   1438 
   1439     /* the format is simple:   */
   1440     /*                         */
   1441     /*   `index' + binary data */
   1442     /*                         */
   1443     for (;;)
   1444     {
   1445       FT_Long   idx;
   1446       FT_ULong  size;
   1447       FT_Byte*  base;
   1448 
   1449 
   1450       /* If we are out of data, or if the next token isn't `dup', */
   1451       /* we are done.                                             */
   1452       if ( parser->root.cursor + 4 >= parser->root.limit          ||
   1453           ft_strncmp( (char*)parser->root.cursor, "dup", 3 ) != 0 )
   1454         break;
   1455 
   1456       T1_Skip_PS_Token( parser );       /* `dup' */
   1457 
   1458       idx = T1_ToInt( parser );
   1459 
   1460       if ( !read_binary_data( parser, &size, &base, IS_INCREMENTAL ) )
   1461         return;
   1462 
   1463       /* The binary string is followed by one token, e.g. `NP' */
   1464       /* (bound to `noaccess put') or by two separate tokens:  */
   1465       /* `noaccess' & `put'.  We position the parser right     */
   1466       /* before the next `dup', if any.                        */
   1467       T1_Skip_PS_Token( parser );   /* `NP' or `|' or `noaccess' */
   1468       if ( parser->root.error )
   1469         return;
   1470       T1_Skip_Spaces  ( parser );
   1471 
   1472       if ( parser->root.cursor + 4 < parser->root.limit            &&
   1473            ft_strncmp( (char*)parser->root.cursor, "put", 3 ) == 0 )
   1474       {
   1475         T1_Skip_PS_Token( parser ); /* skip `put' */
   1476         T1_Skip_Spaces  ( parser );
   1477       }
   1478 
   1479       /* with synthetic fonts it is possible we get here twice */
   1480       if ( loader->num_subrs )
   1481         continue;
   1482 
   1483       /* some fonts use a value of -1 for lenIV to indicate that */
   1484       /* the charstrings are unencoded                           */
   1485       /*                                                         */
   1486       /* thanks to Tom Kacvinsky for pointing this out           */
   1487       /*                                                         */
   1488       if ( face->type1.private_dict.lenIV >= 0 )
   1489       {
   1490         FT_Byte*  temp;
   1491 
   1492 
   1493         /* some fonts define empty subr records -- this is not totally */
   1494         /* compliant to the specification (which says they should at   */
   1495         /* least contain a `return'), but we support them anyway       */
   1496         if ( size < (FT_ULong)face->type1.private_dict.lenIV )
   1497         {
   1498           error = FT_THROW( Invalid_File_Format );
   1499           goto Fail;
   1500         }
   1501 
   1502         /* t1_decrypt() shouldn't write to base -- make temporary copy */
   1503         if ( FT_ALLOC( temp, size ) )
   1504           goto Fail;
   1505         FT_MEM_COPY( temp, base, size );
   1506         psaux->t1_decrypt( temp, size, 4330 );
   1507         size -= (FT_ULong)face->type1.private_dict.lenIV;
   1508         error = T1_Add_Table( table, (FT_Int)idx,
   1509                               temp + face->type1.private_dict.lenIV, size );
   1510         FT_FREE( temp );
   1511       }
   1512       else
   1513         error = T1_Add_Table( table, (FT_Int)idx, base, size );
   1514       if ( error )
   1515         goto Fail;
   1516     }
   1517 
   1518     if ( !loader->num_subrs )
   1519       loader->num_subrs = num_subrs;
   1520 
   1521     return;
   1522 
   1523   Fail:
   1524     parser->root.error = error;
   1525   }
   1526 
   1527 
   1528 #define TABLE_EXTEND  5
   1529 
   1530 
   1531   static void
   1532   parse_charstrings( T1_Face    face,
   1533                      T1_Loader  loader )
   1534   {
   1535     T1_Parser      parser       = &loader->parser;
   1536     PS_Table       code_table   = &loader->charstrings;
   1537     PS_Table       name_table   = &loader->glyph_names;
   1538     PS_Table       swap_table   = &loader->swap_table;
   1539     FT_Memory      memory       = parser->root.memory;
   1540     FT_Error       error;
   1541 
   1542     PSAux_Service  psaux        = (PSAux_Service)face->psaux;
   1543 
   1544     FT_Byte*       cur          = parser->root.cursor;
   1545     FT_Byte*       limit        = parser->root.limit;
   1546     FT_Int         n, num_glyphs;
   1547     FT_Int         notdef_index = 0;
   1548     FT_Byte        notdef_found = 0;
   1549 
   1550 
   1551     num_glyphs = (FT_Int)T1_ToInt( parser );
   1552     if ( num_glyphs < 0 )
   1553     {
   1554       error = FT_THROW( Invalid_File_Format );
   1555       goto Fail;
   1556     }
   1557 
   1558     /* we certainly need more than 8 bytes per glyph */
   1559     if ( num_glyphs > ( limit - cur ) >> 3 )
   1560     {
   1561       FT_TRACE0(( "parse_charstrings: adjusting number of glyphs"
   1562                   " (from %d to %d)\n",
   1563                   num_glyphs, ( limit - cur ) >> 3 ));
   1564       num_glyphs = ( limit - cur ) >> 3;
   1565     }
   1566 
   1567     /* some fonts like Optima-Oblique not only define the /CharStrings */
   1568     /* array but access it also                                        */
   1569     if ( num_glyphs == 0 || parser->root.error )
   1570       return;
   1571 
   1572     /* initialize tables, leaving space for addition of .notdef, */
   1573     /* if necessary, and a few other glyphs to handle buggy      */
   1574     /* fonts which have more glyphs than specified.              */
   1575 
   1576     /* for some non-standard fonts like `Optima' which provides  */
   1577     /* different outlines depending on the resolution it is      */
   1578     /* possible to get here twice                                */
   1579     if ( !loader->num_glyphs )
   1580     {
   1581       error = psaux->ps_table_funcs->init(
   1582                 code_table, num_glyphs + 1 + TABLE_EXTEND, memory );
   1583       if ( error )
   1584         goto Fail;
   1585 
   1586       error = psaux->ps_table_funcs->init(
   1587                 name_table, num_glyphs + 1 + TABLE_EXTEND, memory );
   1588       if ( error )
   1589         goto Fail;
   1590 
   1591       /* Initialize table for swapping index notdef_index and */
   1592       /* index 0 names and codes (if necessary).              */
   1593 
   1594       error = psaux->ps_table_funcs->init( swap_table, 4, memory );
   1595       if ( error )
   1596         goto Fail;
   1597     }
   1598 
   1599     n = 0;
   1600 
   1601     for (;;)
   1602     {
   1603       FT_ULong  size;
   1604       FT_Byte*  base;
   1605 
   1606 
   1607       /* the format is simple:        */
   1608       /*   `/glyphname' + binary data */
   1609 
   1610       T1_Skip_Spaces( parser );
   1611 
   1612       cur = parser->root.cursor;
   1613       if ( cur >= limit )
   1614         break;
   1615 
   1616       /* we stop when we find a `def' or `end' keyword */
   1617       if ( cur + 3 < limit && IS_PS_DELIM( cur[3] ) )
   1618       {
   1619         if ( cur[0] == 'd' &&
   1620              cur[1] == 'e' &&
   1621              cur[2] == 'f' )
   1622         {
   1623           /* There are fonts which have this: */
   1624           /*                                  */
   1625           /*   /CharStrings 118 dict def      */
   1626           /*   Private begin                  */
   1627           /*   CharStrings begin              */
   1628           /*   ...                            */
   1629           /*                                  */
   1630           /* To catch this we ignore `def' if */
   1631           /* no charstring has actually been  */
   1632           /* seen.                            */
   1633           if ( n )
   1634             break;
   1635         }
   1636 
   1637         if ( cur[0] == 'e' &&
   1638              cur[1] == 'n' &&
   1639              cur[2] == 'd' )
   1640           break;
   1641       }
   1642 
   1643       T1_Skip_PS_Token( parser );
   1644       if ( parser->root.cursor >= limit )
   1645       {
   1646         error = FT_THROW( Invalid_File_Format );
   1647         goto Fail;
   1648       }
   1649       if ( parser->root.error )
   1650         return;
   1651 
   1652       if ( *cur == '/' )
   1653       {
   1654         FT_UInt  len;
   1655 
   1656 
   1657         if ( cur + 2 >= limit )
   1658         {
   1659           error = FT_THROW( Invalid_File_Format );
   1660           goto Fail;
   1661         }
   1662 
   1663         cur++;                              /* skip `/' */
   1664         len = (FT_UInt)( parser->root.cursor - cur );
   1665 
   1666         if ( !read_binary_data( parser, &size, &base, IS_INCREMENTAL ) )
   1667           return;
   1668 
   1669         /* for some non-standard fonts like `Optima' which provides */
   1670         /* different outlines depending on the resolution it is     */
   1671         /* possible to get here twice                               */
   1672         if ( loader->num_glyphs )
   1673           continue;
   1674 
   1675         error = T1_Add_Table( name_table, n, cur, len + 1 );
   1676         if ( error )
   1677           goto Fail;
   1678 
   1679         /* add a trailing zero to the name table */
   1680         name_table->elements[n][len] = '\0';
   1681 
   1682         /* record index of /.notdef */
   1683         if ( *cur == '.'                                              &&
   1684              ft_strcmp( ".notdef",
   1685                         (const char*)(name_table->elements[n]) ) == 0 )
   1686         {
   1687           notdef_index = n;
   1688           notdef_found = 1;
   1689         }
   1690 
   1691         if ( face->type1.private_dict.lenIV >= 0 &&
   1692              n < num_glyphs + TABLE_EXTEND       )
   1693         {
   1694           FT_Byte*  temp;
   1695 
   1696 
   1697           if ( size <= (FT_ULong)face->type1.private_dict.lenIV )
   1698           {
   1699             error = FT_THROW( Invalid_File_Format );
   1700             goto Fail;
   1701           }
   1702 
   1703           /* t1_decrypt() shouldn't write to base -- make temporary copy */
   1704           if ( FT_ALLOC( temp, size ) )
   1705             goto Fail;
   1706           FT_MEM_COPY( temp, base, size );
   1707           psaux->t1_decrypt( temp, size, 4330 );
   1708           size -= (FT_ULong)face->type1.private_dict.lenIV;
   1709           error = T1_Add_Table( code_table, n,
   1710                                 temp + face->type1.private_dict.lenIV, size );
   1711           FT_FREE( temp );
   1712         }
   1713         else
   1714           error = T1_Add_Table( code_table, n, base, size );
   1715         if ( error )
   1716           goto Fail;
   1717 
   1718         n++;
   1719       }
   1720     }
   1721 
   1722     loader->num_glyphs = n;
   1723 
   1724     /* if /.notdef is found but does not occupy index 0, do our magic. */
   1725     if ( notdef_found                                                 &&
   1726          ft_strcmp( ".notdef", (const char*)name_table->elements[0] ) )
   1727     {
   1728       /* Swap glyph in index 0 with /.notdef glyph.  First, add index 0  */
   1729       /* name and code entries to swap_table.  Then place notdef_index   */
   1730       /* name and code entries into swap_table.  Then swap name and code */
   1731       /* entries at indices notdef_index and 0 using values stored in    */
   1732       /* swap_table.                                                     */
   1733 
   1734       /* Index 0 name */
   1735       error = T1_Add_Table( swap_table, 0,
   1736                             name_table->elements[0],
   1737                             name_table->lengths [0] );
   1738       if ( error )
   1739         goto Fail;
   1740 
   1741       /* Index 0 code */
   1742       error = T1_Add_Table( swap_table, 1,
   1743                             code_table->elements[0],
   1744                             code_table->lengths [0] );
   1745       if ( error )
   1746         goto Fail;
   1747 
   1748       /* Index notdef_index name */
   1749       error = T1_Add_Table( swap_table, 2,
   1750                             name_table->elements[notdef_index],
   1751                             name_table->lengths [notdef_index] );
   1752       if ( error )
   1753         goto Fail;
   1754 
   1755       /* Index notdef_index code */
   1756       error = T1_Add_Table( swap_table, 3,
   1757                             code_table->elements[notdef_index],
   1758                             code_table->lengths [notdef_index] );
   1759       if ( error )
   1760         goto Fail;
   1761 
   1762       error = T1_Add_Table( name_table, notdef_index,
   1763                             swap_table->elements[0],
   1764                             swap_table->lengths [0] );
   1765       if ( error )
   1766         goto Fail;
   1767 
   1768       error = T1_Add_Table( code_table, notdef_index,
   1769                             swap_table->elements[1],
   1770                             swap_table->lengths [1] );
   1771       if ( error )
   1772         goto Fail;
   1773 
   1774       error = T1_Add_Table( name_table, 0,
   1775                             swap_table->elements[2],
   1776                             swap_table->lengths [2] );
   1777       if ( error )
   1778         goto Fail;
   1779 
   1780       error = T1_Add_Table( code_table, 0,
   1781                             swap_table->elements[3],
   1782                             swap_table->lengths [3] );
   1783       if ( error )
   1784         goto Fail;
   1785 
   1786     }
   1787     else if ( !notdef_found )
   1788     {
   1789       /* notdef_index is already 0, or /.notdef is undefined in   */
   1790       /* charstrings dictionary.  Worry about /.notdef undefined. */
   1791       /* We take index 0 and add it to the end of the table(s)    */
   1792       /* and add our own /.notdef glyph to index 0.               */
   1793 
   1794       /* 0 333 hsbw endchar */
   1795       FT_Byte  notdef_glyph[] = { 0x8B, 0xF7, 0xE1, 0x0D, 0x0E };
   1796       char*    notdef_name    = (char *)".notdef";
   1797 
   1798 
   1799       error = T1_Add_Table( swap_table, 0,
   1800                             name_table->elements[0],
   1801                             name_table->lengths [0] );
   1802       if ( error )
   1803         goto Fail;
   1804 
   1805       error = T1_Add_Table( swap_table, 1,
   1806                             code_table->elements[0],
   1807                             code_table->lengths [0] );
   1808       if ( error )
   1809         goto Fail;
   1810 
   1811       error = T1_Add_Table( name_table, 0, notdef_name, 8 );
   1812       if ( error )
   1813         goto Fail;
   1814 
   1815       error = T1_Add_Table( code_table, 0, notdef_glyph, 5 );
   1816 
   1817       if ( error )
   1818         goto Fail;
   1819 
   1820       error = T1_Add_Table( name_table, n,
   1821                             swap_table->elements[0],
   1822                             swap_table->lengths [0] );
   1823       if ( error )
   1824         goto Fail;
   1825 
   1826       error = T1_Add_Table( code_table, n,
   1827                             swap_table->elements[1],
   1828                             swap_table->lengths [1] );
   1829       if ( error )
   1830         goto Fail;
   1831 
   1832       /* we added a glyph. */
   1833       loader->num_glyphs += 1;
   1834     }
   1835 
   1836     return;
   1837 
   1838   Fail:
   1839     parser->root.error = error;
   1840   }
   1841 
   1842 
   1843   /*************************************************************************/
   1844   /*                                                                       */
   1845   /* Define the token field static variables.  This is a set of            */
   1846   /* T1_FieldRec variables.                                                */
   1847   /*                                                                       */
   1848   /*************************************************************************/
   1849 
   1850 
   1851   static
   1852   const T1_FieldRec  t1_keywords[] =
   1853   {
   1854 
   1855 #include "t1tokens.h"
   1856 
   1857     /* now add the special functions... */
   1858     T1_FIELD_CALLBACK( "FontMatrix",           t1_parse_font_matrix,
   1859                        T1_FIELD_DICT_FONTDICT )
   1860     T1_FIELD_CALLBACK( "Encoding",             parse_encoding,
   1861                        T1_FIELD_DICT_FONTDICT )
   1862     T1_FIELD_CALLBACK( "Subrs",                parse_subrs,
   1863                        T1_FIELD_DICT_PRIVATE )
   1864     T1_FIELD_CALLBACK( "CharStrings",          parse_charstrings,
   1865                        T1_FIELD_DICT_PRIVATE )
   1866     T1_FIELD_CALLBACK( "Private",              parse_private,
   1867                        T1_FIELD_DICT_FONTDICT )
   1868 
   1869 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
   1870     T1_FIELD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions,
   1871                        T1_FIELD_DICT_FONTDICT )
   1872     T1_FIELD_CALLBACK( "BlendDesignMap",       parse_blend_design_map,
   1873                        T1_FIELD_DICT_FONTDICT )
   1874     T1_FIELD_CALLBACK( "BlendAxisTypes",       parse_blend_axis_types,
   1875                        T1_FIELD_DICT_FONTDICT )
   1876     T1_FIELD_CALLBACK( "WeightVector",         parse_weight_vector,
   1877                        T1_FIELD_DICT_FONTDICT )
   1878     T1_FIELD_CALLBACK( "BuildCharArray",       parse_buildchar,
   1879                        T1_FIELD_DICT_PRIVATE )
   1880 #endif
   1881 
   1882     { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
   1883   };
   1884 
   1885 
   1886   static FT_Error
   1887   parse_dict( T1_Face    face,
   1888               T1_Loader  loader,
   1889               FT_Byte*   base,
   1890               FT_ULong   size )
   1891   {
   1892     T1_Parser  parser = &loader->parser;
   1893     FT_Byte   *limit, *start_binary = NULL;
   1894     FT_Bool    have_integer = 0;
   1895 
   1896 
   1897     parser->root.cursor = base;
   1898     parser->root.limit  = base + size;
   1899     parser->root.error  = FT_Err_Ok;
   1900 
   1901     limit = parser->root.limit;
   1902 
   1903     T1_Skip_Spaces( parser );
   1904 
   1905     while ( parser->root.cursor < limit )
   1906     {
   1907       FT_Byte*  cur;
   1908 
   1909 
   1910       cur = parser->root.cursor;
   1911 
   1912       /* look for `eexec' */
   1913       if ( IS_PS_TOKEN( cur, limit, "eexec" ) )
   1914         break;
   1915 
   1916       /* look for `closefile' which ends the eexec section */
   1917       else if ( IS_PS_TOKEN( cur, limit, "closefile" ) )
   1918         break;
   1919 
   1920       /* in a synthetic font the base font starts after a           */
   1921       /* `FontDictionary' token that is placed after a Private dict */
   1922       else if ( IS_PS_TOKEN( cur, limit, "FontDirectory" ) )
   1923       {
   1924         if ( loader->keywords_encountered & T1_PRIVATE )
   1925           loader->keywords_encountered |=
   1926             T1_FONTDIR_AFTER_PRIVATE;
   1927         parser->root.cursor += 13;
   1928       }
   1929 
   1930       /* check whether we have an integer */
   1931       else if ( ft_isdigit( *cur ) )
   1932       {
   1933         start_binary = cur;
   1934         T1_Skip_PS_Token( parser );
   1935         if ( parser->root.error )
   1936           goto Exit;
   1937         have_integer = 1;
   1938       }
   1939 
   1940       /* in valid Type 1 fonts we don't see `RD' or `-|' directly */
   1941       /* since those tokens are handled by parse_subrs and        */
   1942       /* parse_charstrings                                        */
   1943       else if ( *cur == 'R' && cur + 6 < limit && *(cur + 1) == 'D' &&
   1944                 have_integer )
   1945       {
   1946         FT_ULong  s;
   1947         FT_Byte*  b;
   1948 
   1949 
   1950         parser->root.cursor = start_binary;
   1951         if ( !read_binary_data( parser, &s, &b, IS_INCREMENTAL ) )
   1952           return FT_THROW( Invalid_File_Format );
   1953         have_integer = 0;
   1954       }
   1955 
   1956       else if ( *cur == '-' && cur + 6 < limit && *(cur + 1) == '|' &&
   1957                 have_integer )
   1958       {
   1959         FT_ULong  s;
   1960         FT_Byte*  b;
   1961 
   1962 
   1963         parser->root.cursor = start_binary;
   1964         if ( !read_binary_data( parser, &s, &b, IS_INCREMENTAL ) )
   1965           return FT_THROW( Invalid_File_Format );
   1966         have_integer = 0;
   1967       }
   1968 
   1969       /* look for immediates */
   1970       else if ( *cur == '/' && cur + 2 < limit )
   1971       {
   1972         FT_UInt  len;
   1973 
   1974 
   1975         cur++;
   1976 
   1977         parser->root.cursor = cur;
   1978         T1_Skip_PS_Token( parser );
   1979         if ( parser->root.error )
   1980           goto Exit;
   1981 
   1982         len = (FT_UInt)( parser->root.cursor - cur );
   1983 
   1984         if ( len > 0 && len < 22 && parser->root.cursor < limit )
   1985         {
   1986           /* now compare the immediate name to the keyword table */
   1987           T1_Field  keyword = (T1_Field)t1_keywords;
   1988 
   1989 
   1990           for (;;)
   1991           {
   1992             FT_Byte*  name;
   1993 
   1994 
   1995             name = (FT_Byte*)keyword->ident;
   1996             if ( !name )
   1997               break;
   1998 
   1999             if ( cur[0] == name[0]                      &&
   2000                  len == ft_strlen( (const char *)name ) &&
   2001                  ft_memcmp( cur, name, len ) == 0       )
   2002             {
   2003               /* We found it -- run the parsing callback!     */
   2004               /* We record every instance of every field      */
   2005               /* (until we reach the base font of a           */
   2006               /* synthetic font) to deal adequately with      */
   2007               /* multiple master fonts; this is also          */
   2008               /* necessary because later PostScript           */
   2009               /* definitions override earlier ones.           */
   2010 
   2011               /* Once we encounter `FontDirectory' after      */
   2012               /* `/Private', we know that this is a synthetic */
   2013               /* font; except for `/CharStrings' we are not   */
   2014               /* interested in anything that follows this     */
   2015               /* `FontDirectory'.                             */
   2016 
   2017               /* MM fonts have more than one /Private token at */
   2018               /* the top level; let's hope that all the junk   */
   2019               /* that follows the first /Private token is not  */
   2020               /* interesting to us.                            */
   2021 
   2022               /* According to Adobe Tech Note #5175 (CID-Keyed */
   2023               /* Font Installation for ATM Software) a `begin' */
   2024               /* must be followed by exactly one `end', and    */
   2025               /* `begin' -- `end' pairs must be accurately     */
   2026               /* paired.  We could use this to distinguish     */
   2027               /* between the global Private and the Private    */
   2028               /* dict that is a member of the Blend dict.      */
   2029 
   2030               const FT_UInt dict =
   2031                 ( loader->keywords_encountered & T1_PRIVATE )
   2032                     ? T1_FIELD_DICT_PRIVATE
   2033                     : T1_FIELD_DICT_FONTDICT;
   2034 
   2035               if ( !( dict & keyword->dict ) )
   2036               {
   2037                 FT_TRACE1(( "parse_dict: found `%s' but ignoring it"
   2038                             " since it is in the wrong dictionary\n",
   2039                             keyword->ident ));
   2040                 break;
   2041               }
   2042 
   2043               if ( !( loader->keywords_encountered &
   2044                       T1_FONTDIR_AFTER_PRIVATE     )                  ||
   2045                    ft_strcmp( (const char*)name, "CharStrings" ) == 0 )
   2046               {
   2047                 parser->root.error = t1_load_keyword( face,
   2048                                                       loader,
   2049                                                       keyword );
   2050                 if ( parser->root.error != FT_Err_Ok )
   2051                 {
   2052                   if ( FT_ERR_EQ( parser->root.error, Ignore ) )
   2053                     parser->root.error = FT_Err_Ok;
   2054                   else
   2055                     return parser->root.error;
   2056                 }
   2057               }
   2058               break;
   2059             }
   2060 
   2061             keyword++;
   2062           }
   2063         }
   2064 
   2065         have_integer = 0;
   2066       }
   2067       else
   2068       {
   2069         T1_Skip_PS_Token( parser );
   2070         if ( parser->root.error )
   2071           goto Exit;
   2072         have_integer = 0;
   2073       }
   2074 
   2075       T1_Skip_Spaces( parser );
   2076     }
   2077 
   2078   Exit:
   2079     return parser->root.error;
   2080   }
   2081 
   2082 
   2083   static void
   2084   t1_init_loader( T1_Loader  loader,
   2085                   T1_Face    face )
   2086   {
   2087     FT_UNUSED( face );
   2088 
   2089     FT_MEM_ZERO( loader, sizeof ( *loader ) );
   2090     loader->num_glyphs = 0;
   2091     loader->num_chars  = 0;
   2092 
   2093     /* initialize the tables -- simply set their `init' field to 0 */
   2094     loader->encoding_table.init  = 0;
   2095     loader->charstrings.init     = 0;
   2096     loader->glyph_names.init     = 0;
   2097     loader->subrs.init           = 0;
   2098     loader->swap_table.init      = 0;
   2099     loader->fontdata             = 0;
   2100     loader->keywords_encountered = 0;
   2101   }
   2102 
   2103 
   2104   static void
   2105   t1_done_loader( T1_Loader  loader )
   2106   {
   2107     T1_Parser  parser = &loader->parser;
   2108 
   2109 
   2110     /* finalize tables */
   2111     T1_Release_Table( &loader->encoding_table );
   2112     T1_Release_Table( &loader->charstrings );
   2113     T1_Release_Table( &loader->glyph_names );
   2114     T1_Release_Table( &loader->swap_table );
   2115     T1_Release_Table( &loader->subrs );
   2116 
   2117     /* finalize parser */
   2118     T1_Finalize_Parser( parser );
   2119   }
   2120 
   2121 
   2122   FT_LOCAL_DEF( FT_Error )
   2123   T1_Open_Face( T1_Face  face )
   2124   {
   2125     T1_LoaderRec   loader;
   2126     T1_Parser      parser;
   2127     T1_Font        type1 = &face->type1;
   2128     PS_Private     priv  = &type1->private_dict;
   2129     FT_Error       error;
   2130 
   2131     PSAux_Service  psaux = (PSAux_Service)face->psaux;
   2132 
   2133 
   2134     t1_init_loader( &loader, face );
   2135 
   2136     /* default values */
   2137     face->ndv_idx          = -1;
   2138     face->cdv_idx          = -1;
   2139     face->len_buildchar    = 0;
   2140 
   2141     priv->blue_shift       = 7;
   2142     priv->blue_fuzz        = 1;
   2143     priv->lenIV            = 4;
   2144     priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
   2145     priv->blue_scale       = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );
   2146 
   2147     parser = &loader.parser;
   2148     error  = T1_New_Parser( parser,
   2149                             face->root.stream,
   2150                             face->root.memory,
   2151                             psaux );
   2152     if ( error )
   2153       goto Exit;
   2154 
   2155     error = parse_dict( face, &loader,
   2156                         parser->base_dict, parser->base_len );
   2157     if ( error )
   2158       goto Exit;
   2159 
   2160     error = T1_Get_Private_Dict( parser, psaux );
   2161     if ( error )
   2162       goto Exit;
   2163 
   2164     error = parse_dict( face, &loader,
   2165                         parser->private_dict, parser->private_len );
   2166     if ( error )
   2167       goto Exit;
   2168 
   2169     /* ensure even-ness of `num_blue_values' */
   2170     priv->num_blue_values &= ~1;
   2171 
   2172 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
   2173 
   2174     if ( face->blend                                                     &&
   2175          face->blend->num_default_design_vector != 0                     &&
   2176          face->blend->num_default_design_vector != face->blend->num_axis )
   2177     {
   2178       /* we don't use it currently so just warn, reset, and ignore */
   2179       FT_ERROR(( "T1_Open_Face(): /DesignVector contains %u entries "
   2180                  "while there are %u axes.\n",
   2181                  face->blend->num_default_design_vector,
   2182                  face->blend->num_axis ));
   2183 
   2184       face->blend->num_default_design_vector = 0;
   2185     }
   2186 
   2187     /* the following can happen for MM instances; we then treat the */
   2188     /* font as a normal PS font                                     */
   2189     if ( face->blend                                             &&
   2190          ( !face->blend->num_designs || !face->blend->num_axis ) )
   2191       T1_Done_Blend( face );
   2192 
   2193     /* another safety check */
   2194     if ( face->blend )
   2195     {
   2196       FT_UInt  i;
   2197 
   2198 
   2199       for ( i = 0; i < face->blend->num_axis; i++ )
   2200         if ( !face->blend->design_map[i].num_points )
   2201         {
   2202           T1_Done_Blend( face );
   2203           break;
   2204         }
   2205     }
   2206 
   2207     if ( face->blend )
   2208     {
   2209       if ( face->len_buildchar > 0 )
   2210       {
   2211         FT_Memory  memory = face->root.memory;
   2212 
   2213 
   2214         if ( FT_NEW_ARRAY( face->buildchar, face->len_buildchar ) )
   2215         {
   2216           FT_ERROR(( "T1_Open_Face: cannot allocate BuildCharArray\n" ));
   2217           face->len_buildchar = 0;
   2218           goto Exit;
   2219         }
   2220       }
   2221     }
   2222     else
   2223       face->len_buildchar = 0;
   2224 
   2225 #endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */
   2226 
   2227     /* now, propagate the subrs, charstrings, and glyphnames tables */
   2228     /* to the Type1 data                                            */
   2229     type1->num_glyphs = loader.num_glyphs;
   2230 
   2231     if ( loader.subrs.init )
   2232     {
   2233       loader.subrs.init  = 0;
   2234       type1->num_subrs   = loader.num_subrs;
   2235       type1->subrs_block = loader.subrs.block;
   2236       type1->subrs       = loader.subrs.elements;
   2237       type1->subrs_len   = loader.subrs.lengths;
   2238     }
   2239 
   2240     if ( !IS_INCREMENTAL )
   2241       if ( !loader.charstrings.init )
   2242       {
   2243         FT_ERROR(( "T1_Open_Face: no `/CharStrings' array in face\n" ));
   2244         error = FT_THROW( Invalid_File_Format );
   2245       }
   2246 
   2247     loader.charstrings.init  = 0;
   2248     type1->charstrings_block = loader.charstrings.block;
   2249     type1->charstrings       = loader.charstrings.elements;
   2250     type1->charstrings_len   = loader.charstrings.lengths;
   2251 
   2252     /* we copy the glyph names `block' and `elements' fields; */
   2253     /* the `lengths' field must be released later             */
   2254     type1->glyph_names_block    = loader.glyph_names.block;
   2255     type1->glyph_names          = (FT_String**)loader.glyph_names.elements;
   2256     loader.glyph_names.block    = NULL;
   2257     loader.glyph_names.elements = NULL;
   2258 
   2259     /* we must now build type1.encoding when we have a custom array */
   2260     if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY )
   2261     {
   2262       FT_Int    charcode, idx, min_char, max_char;
   2263       FT_Byte*  glyph_name;
   2264 
   2265 
   2266       /* OK, we do the following: for each element in the encoding  */
   2267       /* table, look up the index of the glyph having the same name */
   2268       /* the index is then stored in type1.encoding.char_index, and */
   2269       /* the name to type1.encoding.char_name                       */
   2270 
   2271       min_char = 0;
   2272       max_char = 0;
   2273 
   2274       charcode = 0;
   2275       for ( ; charcode < loader.encoding_table.max_elems; charcode++ )
   2276       {
   2277         FT_Byte*  char_name;
   2278 
   2279 
   2280         type1->encoding.char_index[charcode] = 0;
   2281         type1->encoding.char_name [charcode] = (char *)".notdef";
   2282 
   2283         char_name = loader.encoding_table.elements[charcode];
   2284         if ( char_name )
   2285           for ( idx = 0; idx < type1->num_glyphs; idx++ )
   2286           {
   2287             glyph_name = (FT_Byte*)type1->glyph_names[idx];
   2288             if ( ft_strcmp( (const char*)char_name,
   2289                             (const char*)glyph_name ) == 0 )
   2290             {
   2291               type1->encoding.char_index[charcode] = (FT_UShort)idx;
   2292               type1->encoding.char_name [charcode] = (char*)glyph_name;
   2293 
   2294               /* Change min/max encoded char only if glyph name is */
   2295               /* not /.notdef                                      */
   2296               if ( ft_strcmp( (const char*)".notdef",
   2297                               (const char*)glyph_name ) != 0 )
   2298               {
   2299                 if ( charcode < min_char )
   2300                   min_char = charcode;
   2301                 if ( charcode >= max_char )
   2302                   max_char = charcode + 1;
   2303               }
   2304               break;
   2305             }
   2306           }
   2307       }
   2308 
   2309       type1->encoding.code_first = min_char;
   2310       type1->encoding.code_last  = max_char;
   2311       type1->encoding.num_chars  = loader.num_chars;
   2312     }
   2313 
   2314   Exit:
   2315     t1_done_loader( &loader );
   2316     return error;
   2317   }
   2318 
   2319 
   2320 /* END */
   2321