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