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