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