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