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