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         (void)T1_Add_Table( char_table, n, ".notdef", 8 );
1511 
1512       /* Now we need to read records of the form                */
1513       /*                                                        */
1514       /*   ... charcode /charname ...                           */
1515       /*                                                        */
1516       /* for each entry in our table.                           */
1517       /*                                                        */
1518       /* We simply look for a number followed by an immediate   */
1519       /* name.  Note that this ignores correctly the sequence   */
1520       /* that is often seen in type1 fonts:                     */
1521       /*                                                        */
1522       /*   0 1 255 { 1 index exch /.notdef put } for dup        */
1523       /*                                                        */
1524       /* used to clean the encoding array before anything else. */
1525       /*                                                        */
1526       /* Alternatively, if the array is directly given as       */
1527       /*                                                        */
1528       /*   /Encoding [ ... ]                                    */
1529       /*                                                        */
1530       /* we only read immediates.                               */
1531 
1532       n = 0;
1533       T1_Skip_Spaces( parser );
1534 
1535       while ( parser->root.cursor < limit )
1536       {
1537         cur = parser->root.cursor;
1538 
1539         /* we stop when we encounter a `def' or `]' */
1540         if ( *cur == 'd' && cur + 3 < limit )
1541         {
1542           if ( cur[1] == 'e'         &&
1543                cur[2] == 'f'         &&
1544                IS_PS_DELIM( cur[3] ) )
1545           {
1546             FT_TRACE6(( "encoding end\n" ));
1547             cur += 3;
1548             break;
1549           }
1550         }
1551         if ( *cur == ']' )
1552         {
1553           FT_TRACE6(( "encoding end\n" ));
1554           cur++;
1555           break;
1556         }
1557 
1558         /* check whether we've found an entry */
1559         if ( ft_isdigit( *cur ) || only_immediates )
1560         {
1561           FT_Int  charcode;
1562 
1563 
1564           if ( only_immediates )
1565             charcode = n;
1566           else
1567           {
1568             charcode = (FT_Int)T1_ToInt( parser );
1569             T1_Skip_Spaces( parser );
1570 
1571             /* protect against invalid charcode */
1572             if ( cur == parser->root.cursor )
1573             {
1574               parser->root.error = FT_THROW( Unknown_File_Format );
1575               return;
1576             }
1577           }
1578 
1579           cur = parser->root.cursor;
1580 
1581           if ( cur + 2 < limit && *cur == '/' && n < count )
1582           {
1583             FT_UInt  len;
1584 
1585 
1586             cur++;
1587 
1588             parser->root.cursor = cur;
1589             T1_Skip_PS_Token( parser );
1590             if ( parser->root.cursor >= limit )
1591               return;
1592             if ( parser->root.error )
1593               return;
1594 
1595             len = (FT_UInt)( parser->root.cursor - cur );
1596 
1597             if ( n < array_size )
1598             {
1599               parser->root.error = T1_Add_Table( char_table, charcode,
1600                                                  cur, len + 1 );
1601               if ( parser->root.error )
1602                 return;
1603               char_table->elements[charcode][len] = '\0';
1604             }
1605 
1606             n++;
1607           }
1608           else if ( only_immediates )
1609           {
1610             /* Since the current position is not updated for           */
1611             /* immediates-only mode we would get an infinite loop if   */
1612             /* we don't do anything here.                              */
1613             /*                                                         */
1614             /* This encoding array is not valid according to the type1 */
1615             /* specification (it might be an encoding for a CID type1  */
1616             /* font, however), so we conclude that this font is NOT a  */
1617             /* type1 font.                                             */
1618             parser->root.error = FT_THROW( Unknown_File_Format );
1619             return;
1620           }
1621         }
1622         else
1623         {
1624           T1_Skip_PS_Token( parser );
1625           if ( parser->root.error )
1626             return;
1627         }
1628 
1629         T1_Skip_Spaces( parser );
1630       }
1631 
1632 #ifdef FT_DEBUG_LEVEL_TRACE
1633       FT_TRACE4(( " [" ));
1634 
1635       /* XXX show encoding vector */
1636       FT_TRACE4(( "..." ));
1637 
1638       FT_TRACE4(( "]\n" ));
1639 #endif
1640 
1641       face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY;
1642       parser->root.cursor       = cur;
1643     }
1644 
1645     /* Otherwise, we should have either `StandardEncoding', */
1646     /* `ExpertEncoding', or `ISOLatin1Encoding'             */
1647     else
1648     {
1649       if ( cur + 17 < limit                                            &&
1650            ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
1651       {
1652         face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD;
1653         FT_TRACE4(( " StandardEncoding\n" ));
1654       }
1655 
1656       else if ( cur + 15 < limit                                          &&
1657                 ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
1658       {
1659         face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT;
1660         FT_TRACE4(( " ExpertEncoding\n" ));
1661       }
1662 
1663       else if ( cur + 18 < limit                                             &&
1664                 ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 )
1665       {
1666         face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1;
1667         FT_TRACE4(( " ISOLatin1Encoding\n" ));
1668       }
1669 
1670       else
1671       {
1672         parser->root.error = FT_ERR( Ignore );
1673         FT_TRACE4(( "<unknown>\n" ));
1674       }
1675     }
1676   }
1677 
1678 
1679   static void
1680   parse_subrs( T1_Face    face,
1681                T1_Loader  loader )
1682   {
1683     T1_Parser  parser = &loader->parser;
1684     PS_Table   table  = &loader->subrs;
1685     FT_Memory  memory = parser->root.memory;
1686     FT_Error   error;
1687     FT_Int     num_subrs;
1688     FT_UInt    count;
1689 
1690     PSAux_Service  psaux = (PSAux_Service)face->psaux;
1691 
1692 
1693     T1_Skip_Spaces( parser );
1694 
1695     /* test for empty array */
1696     if ( parser->root.cursor < parser->root.limit &&
1697          *parser->root.cursor == '['              )
1698     {
1699       T1_Skip_PS_Token( parser );
1700       T1_Skip_Spaces  ( parser );
1701       if ( parser->root.cursor >= parser->root.limit ||
1702            *parser->root.cursor != ']'               )
1703         parser->root.error = FT_THROW( Invalid_File_Format );
1704       return;
1705     }
1706 
1707     num_subrs = (FT_Int)T1_ToInt( parser );
1708     if ( num_subrs < 0 )
1709     {
1710       parser->root.error = FT_THROW( Invalid_File_Format );
1711       return;
1712     }
1713 
1714     /* we certainly need more than 8 bytes per subroutine */
1715     if ( parser->root.limit >= parser->root.cursor                     &&
1716          num_subrs > ( parser->root.limit - parser->root.cursor ) >> 3 )
1717     {
1718       /*
1719        * There are two possibilities.  Either the font contains an invalid
1720        * value for `num_subrs', or we have a subsetted font where the
1721        * subroutine indices are not adjusted, e.g.
1722        *
1723        *   /Subrs 812 array
1724        *     dup 0 { ... } NP
1725        *     dup 51 { ... } NP
1726        *     dup 681 { ... } NP
1727        *   ND
1728        *
1729        * In both cases, we use a number hash that maps from subr indices to
1730        * actual array elements.
1731        */
1732 
1733       FT_TRACE0(( "parse_subrs: adjusting number of subroutines"
1734                   " (from %d to %d)\n",
1735                   num_subrs,
1736                   ( parser->root.limit - parser->root.cursor ) >> 3 ));
1737       num_subrs = ( parser->root.limit - parser->root.cursor ) >> 3;
1738 
1739       if ( !loader->subrs_hash )
1740       {
1741         if ( FT_NEW( loader->subrs_hash ) )
1742           goto Fail;
1743 
1744         error = ft_hash_num_init( loader->subrs_hash, memory );
1745         if ( error )
1746           goto Fail;
1747       }
1748     }
1749 
1750     /* position the parser right before the `dup' of the first subr */
1751     T1_Skip_PS_Token( parser );         /* `array' */
1752     if ( parser->root.error )
1753       return;
1754     T1_Skip_Spaces( parser );
1755 
1756     /* initialize subrs array -- with synthetic fonts it is possible */
1757     /* we get here twice                                             */
1758     if ( !loader->num_subrs )
1759     {
1760       error = psaux->ps_table_funcs->init( table, num_subrs, memory );
1761       if ( error )
1762         goto Fail;
1763     }
1764 
1765     /* the format is simple:   */
1766     /*                         */
1767     /*   `index' + binary data */
1768     /*                         */
1769     for ( count = 0; ; count++ )
1770     {
1771       FT_Long   idx;
1772       FT_ULong  size;
1773       FT_Byte*  base;
1774 
1775 
1776       /* If we are out of data, or if the next token isn't `dup', */
1777       /* we are done.                                             */
1778       if ( parser->root.cursor + 4 >= parser->root.limit          ||
1779           ft_strncmp( (char*)parser->root.cursor, "dup", 3 ) != 0 )
1780         break;
1781 
1782       T1_Skip_PS_Token( parser );       /* `dup' */
1783 
1784       idx = T1_ToInt( parser );
1785 
1786       if ( !read_binary_data( parser, &size, &base, IS_INCREMENTAL ) )
1787         return;
1788 
1789       /* The binary string is followed by one token, e.g. `NP' */
1790       /* (bound to `noaccess put') or by two separate tokens:  */
1791       /* `noaccess' & `put'.  We position the parser right     */
1792       /* before the next `dup', if any.                        */
1793       T1_Skip_PS_Token( parser );   /* `NP' or `|' or `noaccess' */
1794       if ( parser->root.error )
1795         return;
1796       T1_Skip_Spaces  ( parser );
1797 
1798       if ( parser->root.cursor + 4 < parser->root.limit            &&
1799            ft_strncmp( (char*)parser->root.cursor, "put", 3 ) == 0 )
1800       {
1801         T1_Skip_PS_Token( parser ); /* skip `put' */
1802         T1_Skip_Spaces  ( parser );
1803       }
1804 
1805       /* if we use a hash, the subrs index is the key, and a running */
1806       /* counter specified for `T1_Add_Table' acts as the value      */
1807       if ( loader->subrs_hash )
1808       {
1809         ft_hash_num_insert( idx, count, loader->subrs_hash, memory );
1810         idx = count;
1811       }
1812 
1813       /* with synthetic fonts it is possible we get here twice */
1814       if ( loader->num_subrs )
1815         continue;
1816 
1817       /* some fonts use a value of -1 for lenIV to indicate that */
1818       /* the charstrings are unencoded                           */
1819       /*                                                         */
1820       /* thanks to Tom Kacvinsky for pointing this out           */
1821       /*                                                         */
1822       if ( face->type1.private_dict.lenIV >= 0 )
1823       {
1824         FT_Byte*  temp = NULL;
1825 
1826 
1827         /* some fonts define empty subr records -- this is not totally */
1828         /* compliant to the specification (which says they should at   */
1829         /* least contain a `return'), but we support them anyway       */
1830         if ( size < (FT_ULong)face->type1.private_dict.lenIV )
1831         {
1832           error = FT_THROW( Invalid_File_Format );
1833           goto Fail;
1834         }
1835 
1836         /* t1_decrypt() shouldn't write to base -- make temporary copy */
1837         if ( FT_ALLOC( temp, size ) )
1838           goto Fail;
1839         FT_MEM_COPY( temp, base, size );
1840         psaux->t1_decrypt( temp, size, 4330 );
1841         size -= (FT_ULong)face->type1.private_dict.lenIV;
1842         error = T1_Add_Table( table, (FT_Int)idx,
1843                               temp + face->type1.private_dict.lenIV, size );
1844         FT_FREE( temp );
1845       }
1846       else
1847         error = T1_Add_Table( table, (FT_Int)idx, base, size );
1848       if ( error )
1849         goto Fail;
1850     }
1851 
1852     if ( !loader->num_subrs )
1853       loader->num_subrs = num_subrs;
1854 
1855 #ifdef FT_DEBUG_LEVEL_TRACE
1856       FT_TRACE4(( " <" ));
1857 
1858       /* XXX show subrs? */
1859       FT_TRACE4(( "%d elements", num_subrs ));
1860 
1861       FT_TRACE4(( ">\n" ));
1862 #endif
1863 
1864     return;
1865 
1866   Fail:
1867     parser->root.error = error;
1868   }
1869 
1870 
1871 #define TABLE_EXTEND  5
1872 
1873 
1874   static void
1875   parse_charstrings( T1_Face    face,
1876                      T1_Loader  loader )
1877   {
1878     T1_Parser      parser       = &loader->parser;
1879     PS_Table       code_table   = &loader->charstrings;
1880     PS_Table       name_table   = &loader->glyph_names;
1881     PS_Table       swap_table   = &loader->swap_table;
1882     FT_Memory      memory       = parser->root.memory;
1883     FT_Error       error;
1884 
1885     PSAux_Service  psaux        = (PSAux_Service)face->psaux;
1886 
1887     FT_Byte*       cur          = parser->root.cursor;
1888     FT_Byte*       limit        = parser->root.limit;
1889     FT_Int         n, num_glyphs;
1890     FT_Int         notdef_index = 0;
1891     FT_Byte        notdef_found = 0;
1892 
1893 
1894     num_glyphs = (FT_Int)T1_ToInt( parser );
1895     if ( num_glyphs < 0 )
1896     {
1897       error = FT_THROW( Invalid_File_Format );
1898       goto Fail;
1899     }
1900 
1901     /* we certainly need more than 8 bytes per glyph */
1902     if ( num_glyphs > ( limit - cur ) >> 3 )
1903     {
1904       FT_TRACE0(( "parse_charstrings: adjusting number of glyphs"
1905                   " (from %d to %d)\n",
1906                   num_glyphs, ( limit - cur ) >> 3 ));
1907       num_glyphs = ( limit - cur ) >> 3;
1908     }
1909 
1910     /* some fonts like Optima-Oblique not only define the /CharStrings */
1911     /* array but access it also                                        */
1912     if ( num_glyphs == 0 || parser->root.error )
1913       return;
1914 
1915     /* initialize tables, leaving space for addition of .notdef, */
1916     /* if necessary, and a few other glyphs to handle buggy      */
1917     /* fonts which have more glyphs than specified.              */
1918 
1919     /* for some non-standard fonts like `Optima' which provides  */
1920     /* different outlines depending on the resolution it is      */
1921     /* possible to get here twice                                */
1922     if ( !loader->num_glyphs )
1923     {
1924       error = psaux->ps_table_funcs->init(
1925                 code_table, num_glyphs + 1 + TABLE_EXTEND, memory );
1926       if ( error )
1927         goto Fail;
1928 
1929       error = psaux->ps_table_funcs->init(
1930                 name_table, num_glyphs + 1 + TABLE_EXTEND, memory );
1931       if ( error )
1932         goto Fail;
1933 
1934       /* Initialize table for swapping index notdef_index and */
1935       /* index 0 names and codes (if necessary).              */
1936 
1937       error = psaux->ps_table_funcs->init( swap_table, 4, memory );
1938       if ( error )
1939         goto Fail;
1940     }
1941 
1942     n = 0;
1943 
1944     for (;;)
1945     {
1946       FT_ULong  size;
1947       FT_Byte*  base;
1948 
1949 
1950       /* the format is simple:        */
1951       /*   `/glyphname' + binary data */
1952 
1953       T1_Skip_Spaces( parser );
1954 
1955       cur = parser->root.cursor;
1956       if ( cur >= limit )
1957         break;
1958 
1959       /* we stop when we find a `def' or `end' keyword */
1960       if ( cur + 3 < limit && IS_PS_DELIM( cur[3] ) )
1961       {
1962         if ( cur[0] == 'd' &&
1963              cur[1] == 'e' &&
1964              cur[2] == 'f' )
1965         {
1966           /* There are fonts which have this: */
1967           /*                                  */
1968           /*   /CharStrings 118 dict def      */
1969           /*   Private begin                  */
1970           /*   CharStrings begin              */
1971           /*   ...                            */
1972           /*                                  */
1973           /* To catch this we ignore `def' if */
1974           /* no charstring has actually been  */
1975           /* seen.                            */
1976           if ( n )
1977             break;
1978         }
1979 
1980         if ( cur[0] == 'e' &&
1981              cur[1] == 'n' &&
1982              cur[2] == 'd' )
1983           break;
1984       }
1985 
1986       T1_Skip_PS_Token( parser );
1987       if ( parser->root.cursor >= limit )
1988       {
1989         error = FT_THROW( Invalid_File_Format );
1990         goto Fail;
1991       }
1992       if ( parser->root.error )
1993         return;
1994 
1995       if ( *cur == '/' )
1996       {
1997         FT_UInt  len;
1998 
1999 
2000         if ( cur + 2 >= limit )
2001         {
2002           error = FT_THROW( Invalid_File_Format );
2003           goto Fail;
2004         }
2005 
2006         cur++;                              /* skip `/' */
2007         len = (FT_UInt)( parser->root.cursor - cur );
2008 
2009         if ( !read_binary_data( parser, &size, &base, IS_INCREMENTAL ) )
2010           return;
2011 
2012         /* for some non-standard fonts like `Optima' which provides */
2013         /* different outlines depending on the resolution it is     */
2014         /* possible to get here twice                               */
2015         if ( loader->num_glyphs )
2016           continue;
2017 
2018         error = T1_Add_Table( name_table, n, cur, len + 1 );
2019         if ( error )
2020           goto Fail;
2021 
2022         /* add a trailing zero to the name table */
2023         name_table->elements[n][len] = '\0';
2024 
2025         /* record index of /.notdef */
2026         if ( *cur == '.'                                              &&
2027              ft_strcmp( ".notdef",
2028                         (const char*)(name_table->elements[n]) ) == 0 )
2029         {
2030           notdef_index = n;
2031           notdef_found = 1;
2032         }
2033 
2034         if ( face->type1.private_dict.lenIV >= 0 &&
2035              n < num_glyphs + TABLE_EXTEND       )
2036         {
2037           FT_Byte*  temp = NULL;
2038 
2039 
2040           if ( size <= (FT_ULong)face->type1.private_dict.lenIV )
2041           {
2042             error = FT_THROW( Invalid_File_Format );
2043             goto Fail;
2044           }
2045 
2046           /* t1_decrypt() shouldn't write to base -- make temporary copy */
2047           if ( FT_ALLOC( temp, size ) )
2048             goto Fail;
2049           FT_MEM_COPY( temp, base, size );
2050           psaux->t1_decrypt( temp, size, 4330 );
2051           size -= (FT_ULong)face->type1.private_dict.lenIV;
2052           error = T1_Add_Table( code_table, n,
2053                                 temp + face->type1.private_dict.lenIV, size );
2054           FT_FREE( temp );
2055         }
2056         else
2057           error = T1_Add_Table( code_table, n, base, size );
2058         if ( error )
2059           goto Fail;
2060 
2061         n++;
2062       }
2063     }
2064 
2065     if ( !n )
2066     {
2067       error = FT_THROW( Invalid_File_Format );
2068       goto Fail;
2069     }
2070 
2071     loader->num_glyphs = n;
2072 
2073     /* if /.notdef is found but does not occupy index 0, do our magic. */
2074     if ( notdef_found                                                 &&
2075          ft_strcmp( ".notdef", (const char*)name_table->elements[0] ) )
2076     {
2077       /* Swap glyph in index 0 with /.notdef glyph.  First, add index 0  */
2078       /* name and code entries to swap_table.  Then place notdef_index   */
2079       /* name and code entries into swap_table.  Then swap name and code */
2080       /* entries at indices notdef_index and 0 using values stored in    */
2081       /* swap_table.                                                     */
2082 
2083       /* Index 0 name */
2084       error = T1_Add_Table( swap_table, 0,
2085                             name_table->elements[0],
2086                             name_table->lengths [0] );
2087       if ( error )
2088         goto Fail;
2089 
2090       /* Index 0 code */
2091       error = T1_Add_Table( swap_table, 1,
2092                             code_table->elements[0],
2093                             code_table->lengths [0] );
2094       if ( error )
2095         goto Fail;
2096 
2097       /* Index notdef_index name */
2098       error = T1_Add_Table( swap_table, 2,
2099                             name_table->elements[notdef_index],
2100                             name_table->lengths [notdef_index] );
2101       if ( error )
2102         goto Fail;
2103 
2104       /* Index notdef_index code */
2105       error = T1_Add_Table( swap_table, 3,
2106                             code_table->elements[notdef_index],
2107                             code_table->lengths [notdef_index] );
2108       if ( error )
2109         goto Fail;
2110 
2111       error = T1_Add_Table( name_table, notdef_index,
2112                             swap_table->elements[0],
2113                             swap_table->lengths [0] );
2114       if ( error )
2115         goto Fail;
2116 
2117       error = T1_Add_Table( code_table, notdef_index,
2118                             swap_table->elements[1],
2119                             swap_table->lengths [1] );
2120       if ( error )
2121         goto Fail;
2122 
2123       error = T1_Add_Table( name_table, 0,
2124                             swap_table->elements[2],
2125                             swap_table->lengths [2] );
2126       if ( error )
2127         goto Fail;
2128 
2129       error = T1_Add_Table( code_table, 0,
2130                             swap_table->elements[3],
2131                             swap_table->lengths [3] );
2132       if ( error )
2133         goto Fail;
2134 
2135     }
2136     else if ( !notdef_found )
2137     {
2138       /* notdef_index is already 0, or /.notdef is undefined in   */
2139       /* charstrings dictionary.  Worry about /.notdef undefined. */
2140       /* We take index 0 and add it to the end of the table(s)    */
2141       /* and add our own /.notdef glyph to index 0.               */
2142 
2143       /* 0 333 hsbw endchar */
2144       FT_Byte  notdef_glyph[] = { 0x8B, 0xF7, 0xE1, 0x0D, 0x0E };
2145 
2146 
2147       error = T1_Add_Table( swap_table, 0,
2148                             name_table->elements[0],
2149                             name_table->lengths [0] );
2150       if ( error )
2151         goto Fail;
2152 
2153       error = T1_Add_Table( swap_table, 1,
2154                             code_table->elements[0],
2155                             code_table->lengths [0] );
2156       if ( error )
2157         goto Fail;
2158 
2159       error = T1_Add_Table( name_table, 0, ".notdef", 8 );
2160       if ( error )
2161         goto Fail;
2162 
2163       error = T1_Add_Table( code_table, 0, notdef_glyph, 5 );
2164 
2165       if ( error )
2166         goto Fail;
2167 
2168       error = T1_Add_Table( name_table, n,
2169                             swap_table->elements[0],
2170                             swap_table->lengths [0] );
2171       if ( error )
2172         goto Fail;
2173 
2174       error = T1_Add_Table( code_table, n,
2175                             swap_table->elements[1],
2176                             swap_table->lengths [1] );
2177       if ( error )
2178         goto Fail;
2179 
2180       /* we added a glyph. */
2181       loader->num_glyphs += 1;
2182     }
2183 
2184 #ifdef FT_DEBUG_LEVEL_TRACE
2185       FT_TRACE4(( " <" ));
2186 
2187       /* XXX show charstrings? */
2188       FT_TRACE4(( "%d elements", loader->num_glyphs ));
2189 
2190       FT_TRACE4(( ">\n" ));
2191 #endif
2192 
2193     return;
2194 
2195   Fail:
2196     parser->root.error = error;
2197   }
2198 
2199 
2200   /**************************************************************************
2201    *
2202    * Define the token field static variables.  This is a set of
2203    * T1_FieldRec variables.
2204    *
2205    */
2206 
2207 
2208   static
2209   const T1_FieldRec  t1_keywords[] =
2210   {
2211 
2212 #include "t1tokens.h"
2213 
2214     /* now add the special functions... */
2215     T1_FIELD_CALLBACK( "FontMatrix",           t1_parse_font_matrix,
2216                        T1_FIELD_DICT_FONTDICT )
2217     T1_FIELD_CALLBACK( "Encoding",             parse_encoding,
2218                        T1_FIELD_DICT_FONTDICT )
2219     T1_FIELD_CALLBACK( "Subrs",                parse_subrs,
2220                        T1_FIELD_DICT_PRIVATE )
2221     T1_FIELD_CALLBACK( "CharStrings",          parse_charstrings,
2222                        T1_FIELD_DICT_PRIVATE )
2223     T1_FIELD_CALLBACK( "Private",              parse_private,
2224                        T1_FIELD_DICT_FONTDICT )
2225 
2226 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
2227     T1_FIELD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions,
2228                        T1_FIELD_DICT_FONTDICT )
2229     T1_FIELD_CALLBACK( "BlendDesignMap",       parse_blend_design_map,
2230                        T1_FIELD_DICT_FONTDICT )
2231     T1_FIELD_CALLBACK( "BlendAxisTypes",       parse_blend_axis_types,
2232                        T1_FIELD_DICT_FONTDICT )
2233     T1_FIELD_CALLBACK( "WeightVector",         parse_weight_vector,
2234                        T1_FIELD_DICT_FONTDICT )
2235     T1_FIELD_CALLBACK( "BuildCharArray",       parse_buildchar,
2236                        T1_FIELD_DICT_PRIVATE )
2237 #endif
2238 
2239     { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
2240   };
2241 
2242 
2243   static FT_Error
2244   parse_dict( T1_Face    face,
2245               T1_Loader  loader,
2246               FT_Byte*   base,
2247               FT_ULong   size )
2248   {
2249     T1_Parser  parser = &loader->parser;
2250     FT_Byte   *limit, *start_binary = NULL;
2251     FT_Bool    have_integer = 0;
2252 
2253 
2254     parser->root.cursor = base;
2255     parser->root.limit  = base + size;
2256     parser->root.error  = FT_Err_Ok;
2257 
2258     limit = parser->root.limit;
2259 
2260     T1_Skip_Spaces( parser );
2261 
2262     while ( parser->root.cursor < limit )
2263     {
2264       FT_Byte*  cur;
2265 
2266 
2267       cur = parser->root.cursor;
2268 
2269       /* look for `eexec' */
2270       if ( IS_PS_TOKEN( cur, limit, "eexec" ) )
2271         break;
2272 
2273       /* look for `closefile' which ends the eexec section */
2274       else if ( IS_PS_TOKEN( cur, limit, "closefile" ) )
2275         break;
2276 
2277       /* in a synthetic font the base font starts after a           */
2278       /* `FontDictionary' token that is placed after a Private dict */
2279       else if ( IS_PS_TOKEN( cur, limit, "FontDirectory" ) )
2280       {
2281         if ( loader->keywords_encountered & T1_PRIVATE )
2282           loader->keywords_encountered |=
2283             T1_FONTDIR_AFTER_PRIVATE;
2284         parser->root.cursor += 13;
2285       }
2286 
2287       /* check whether we have an integer */
2288       else if ( ft_isdigit( *cur ) )
2289       {
2290         start_binary = cur;
2291         T1_Skip_PS_Token( parser );
2292         if ( parser->root.error )
2293           goto Exit;
2294         have_integer = 1;
2295       }
2296 
2297       /* in valid Type 1 fonts we don't see `RD' or `-|' directly */
2298       /* since those tokens are handled by parse_subrs and        */
2299       /* parse_charstrings                                        */
2300       else if ( *cur == 'R' && cur + 6 < limit && *(cur + 1) == 'D' &&
2301                 have_integer )
2302       {
2303         FT_ULong  s;
2304         FT_Byte*  b;
2305 
2306 
2307         parser->root.cursor = start_binary;
2308         if ( !read_binary_data( parser, &s, &b, IS_INCREMENTAL ) )
2309           return FT_THROW( Invalid_File_Format );
2310         have_integer = 0;
2311       }
2312 
2313       else if ( *cur == '-' && cur + 6 < limit && *(cur + 1) == '|' &&
2314                 have_integer )
2315       {
2316         FT_ULong  s;
2317         FT_Byte*  b;
2318 
2319 
2320         parser->root.cursor = start_binary;
2321         if ( !read_binary_data( parser, &s, &b, IS_INCREMENTAL ) )
2322           return FT_THROW( Invalid_File_Format );
2323         have_integer = 0;
2324       }
2325 
2326       /* look for immediates */
2327       else if ( *cur == '/' && cur + 2 < limit )
2328       {
2329         FT_UInt  len;
2330 
2331 
2332         cur++;
2333 
2334         parser->root.cursor = cur;
2335         T1_Skip_PS_Token( parser );
2336         if ( parser->root.error )
2337           goto Exit;
2338 
2339         len = (FT_UInt)( parser->root.cursor - cur );
2340 
2341         if ( len > 0 && len < 22 && parser->root.cursor < limit )
2342         {
2343           /* now compare the immediate name to the keyword table */
2344           T1_Field  keyword = (T1_Field)t1_keywords;
2345 
2346 
2347           for (;;)
2348           {
2349             FT_Byte*  name;
2350 
2351 
2352             name = (FT_Byte*)keyword->ident;
2353             if ( !name )
2354               break;
2355 
2356             if ( cur[0] == name[0]                      &&
2357                  len == ft_strlen( (const char *)name ) &&
2358                  ft_memcmp( cur, name, len ) == 0       )
2359             {
2360               /* We found it -- run the parsing callback!     */
2361               /* We record every instance of every field      */
2362               /* (until we reach the base font of a           */
2363               /* synthetic font) to deal adequately with      */
2364               /* multiple master fonts; this is also          */
2365               /* necessary because later PostScript           */
2366               /* definitions override earlier ones.           */
2367 
2368               /* Once we encounter `FontDirectory' after      */
2369               /* `/Private', we know that this is a synthetic */
2370               /* font; except for `/CharStrings' we are not   */
2371               /* interested in anything that follows this     */
2372               /* `FontDirectory'.                             */
2373 
2374               /* MM fonts have more than one /Private token at */
2375               /* the top level; let's hope that all the junk   */
2376               /* that follows the first /Private token is not  */
2377               /* interesting to us.                            */
2378 
2379               /* According to Adobe Tech Note #5175 (CID-Keyed */
2380               /* Font Installation for ATM Software) a `begin' */
2381               /* must be followed by exactly one `end', and    */
2382               /* `begin' -- `end' pairs must be accurately     */
2383               /* paired.  We could use this to distinguish     */
2384               /* between the global Private and the Private    */
2385               /* dict that is a member of the Blend dict.      */
2386 
2387               const FT_UInt dict =
2388                 ( loader->keywords_encountered & T1_PRIVATE )
2389                     ? T1_FIELD_DICT_PRIVATE
2390                     : T1_FIELD_DICT_FONTDICT;
2391 
2392 
2393               if ( !( dict & keyword->dict ) )
2394               {
2395                 FT_TRACE1(( "parse_dict: found `%s' but ignoring it"
2396                             " since it is in the wrong dictionary\n",
2397                             keyword->ident ));
2398                 break;
2399               }
2400 
2401               if ( !( loader->keywords_encountered &
2402                       T1_FONTDIR_AFTER_PRIVATE     )                  ||
2403                    ft_strcmp( (const char*)name, "CharStrings" ) == 0 )
2404               {
2405                 parser->root.error = t1_load_keyword( face,
2406                                                       loader,
2407                                                       keyword );
2408                 if ( parser->root.error )
2409                 {
2410                   if ( FT_ERR_EQ( parser->root.error, Ignore ) )
2411                     parser->root.error = FT_Err_Ok;
2412                   else
2413                     return parser->root.error;
2414                 }
2415               }
2416               break;
2417             }
2418 
2419             keyword++;
2420           }
2421         }
2422 
2423         have_integer = 0;
2424       }
2425       else
2426       {
2427         T1_Skip_PS_Token( parser );
2428         if ( parser->root.error )
2429           goto Exit;
2430         have_integer = 0;
2431       }
2432 
2433       T1_Skip_Spaces( parser );
2434     }
2435 
2436   Exit:
2437     return parser->root.error;
2438   }
2439 
2440 
2441   static void
2442   t1_init_loader( T1_Loader  loader,
2443                   T1_Face    face )
2444   {
2445     FT_UNUSED( face );
2446 
2447     FT_ZERO( loader );
2448   }
2449 
2450 
2451   static void
2452   t1_done_loader( T1_Loader  loader )
2453   {
2454     T1_Parser  parser = &loader->parser;
2455     FT_Memory  memory = parser->root.memory;
2456 
2457 
2458     /* finalize tables */
2459     T1_Release_Table( &loader->encoding_table );
2460     T1_Release_Table( &loader->charstrings );
2461     T1_Release_Table( &loader->glyph_names );
2462     T1_Release_Table( &loader->swap_table );
2463     T1_Release_Table( &loader->subrs );
2464 
2465     /* finalize hash */
2466     ft_hash_num_free( loader->subrs_hash, memory );
2467     FT_FREE( loader->subrs_hash );
2468 
2469     /* finalize parser */
2470     T1_Finalize_Parser( parser );
2471   }
2472 
2473 
2474   FT_LOCAL_DEF( FT_Error )
2475   T1_Open_Face( T1_Face  face )
2476   {
2477     T1_LoaderRec   loader;
2478     T1_Parser      parser;
2479     T1_Font        type1 = &face->type1;
2480     PS_Private     priv  = &type1->private_dict;
2481     FT_Error       error;
2482 
2483     PSAux_Service  psaux = (PSAux_Service)face->psaux;
2484 
2485 
2486     t1_init_loader( &loader, face );
2487 
2488     /* default values */
2489     face->ndv_idx          = -1;
2490     face->cdv_idx          = -1;
2491     face->len_buildchar    = 0;
2492 
2493     priv->blue_shift       = 7;
2494     priv->blue_fuzz        = 1;
2495     priv->lenIV            = 4;
2496     priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
2497     priv->blue_scale       = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );
2498 
2499     parser = &loader.parser;
2500     error  = T1_New_Parser( parser,
2501                             face->root.stream,
2502                             face->root.memory,
2503                             psaux );
2504     if ( error )
2505       goto Exit;
2506 
2507     FT_TRACE4(( " top dictionary:\n" ));
2508     error = parse_dict( face, &loader,
2509                         parser->base_dict, parser->base_len );
2510     if ( error )
2511       goto Exit;
2512 
2513     error = T1_Get_Private_Dict( parser, psaux );
2514     if ( error )
2515       goto Exit;
2516 
2517     FT_TRACE4(( " private dictionary:\n" ));
2518     error = parse_dict( face, &loader,
2519                         parser->private_dict, parser->private_len );
2520     if ( error )
2521       goto Exit;
2522 
2523     /* ensure even-ness of `num_blue_values' */
2524     priv->num_blue_values &= ~1;
2525 
2526 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
2527 
2528     /* we don't support Multiple Master fonts with intermediate designs; */
2529     /* this implies that `num_designs' must be equal to `2^^num_axis'    */
2530     if ( face->blend                                                 &&
2531          face->blend->num_designs != ( 1U << face->blend->num_axis ) )
2532     {
2533       FT_ERROR(( "T1_Open_Face:"
2534                  " number-of-designs != 2 ^^ number-of-axes\n" ));
2535       T1_Done_Blend( face );
2536     }
2537 
2538     if ( face->blend                                                     &&
2539          face->blend->num_default_design_vector != 0                     &&
2540          face->blend->num_default_design_vector != face->blend->num_axis )
2541     {
2542       /* we don't use it currently so just warn, reset, and ignore */
2543       FT_ERROR(( "T1_Open_Face(): /DesignVector contains %u entries "
2544                  "while there are %u axes.\n",
2545                  face->blend->num_default_design_vector,
2546                  face->blend->num_axis ));
2547 
2548       face->blend->num_default_design_vector = 0;
2549     }
2550 
2551     /* the following can happen for MM instances; we then treat the */
2552     /* font as a normal PS font                                     */
2553     if ( face->blend                                             &&
2554          ( !face->blend->num_designs || !face->blend->num_axis ) )
2555       T1_Done_Blend( face );
2556 
2557     /* another safety check */
2558     if ( face->blend )
2559     {
2560       FT_UInt  i;
2561 
2562 
2563       for ( i = 0; i < face->blend->num_axis; i++ )
2564         if ( !face->blend->design_map[i].num_points )
2565         {
2566           T1_Done_Blend( face );
2567           break;
2568         }
2569     }
2570 
2571     if ( face->blend )
2572     {
2573       if ( face->len_buildchar > 0 )
2574       {
2575         FT_Memory  memory = face->root.memory;
2576 
2577 
2578         if ( FT_NEW_ARRAY( face->buildchar, face->len_buildchar ) )
2579         {
2580           FT_ERROR(( "T1_Open_Face: cannot allocate BuildCharArray\n" ));
2581           face->len_buildchar = 0;
2582           goto Exit;
2583         }
2584       }
2585     }
2586     else
2587       face->len_buildchar = 0;
2588 
2589 #endif /* !T1_CONFIG_OPTION_NO_MM_SUPPORT */
2590 
2591     /* now, propagate the subrs, charstrings, and glyphnames tables */
2592     /* to the Type1 data                                            */
2593     type1->num_glyphs = loader.num_glyphs;
2594 
2595     if ( loader.subrs.init )
2596     {
2597       type1->num_subrs   = loader.num_subrs;
2598       type1->subrs_block = loader.subrs.block;
2599       type1->subrs       = loader.subrs.elements;
2600       type1->subrs_len   = loader.subrs.lengths;
2601       type1->subrs_hash  = loader.subrs_hash;
2602 
2603       /* prevent `t1_done_loader' from freeing the propagated data */
2604       loader.subrs.init = 0;
2605       loader.subrs_hash = NULL;
2606     }
2607 
2608     if ( !IS_INCREMENTAL )
2609       if ( !loader.charstrings.init )
2610       {
2611         FT_ERROR(( "T1_Open_Face: no `/CharStrings' array in face\n" ));
2612         error = FT_THROW( Invalid_File_Format );
2613       }
2614 
2615     loader.charstrings.init  = 0;
2616     type1->charstrings_block = loader.charstrings.block;
2617     type1->charstrings       = loader.charstrings.elements;
2618     type1->charstrings_len   = loader.charstrings.lengths;
2619 
2620     /* we copy the glyph names `block' and `elements' fields; */
2621     /* the `lengths' field must be released later             */
2622     type1->glyph_names_block    = loader.glyph_names.block;
2623     type1->glyph_names          = (FT_String**)loader.glyph_names.elements;
2624     loader.glyph_names.block    = NULL;
2625     loader.glyph_names.elements = NULL;
2626 
2627     /* we must now build type1.encoding when we have a custom array */
2628     if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY )
2629     {
2630       FT_Int  charcode, idx, min_char, max_char;
2631 
2632 
2633       /* OK, we do the following: for each element in the encoding  */
2634       /* table, look up the index of the glyph having the same name */
2635       /* the index is then stored in type1.encoding.char_index, and */
2636       /* the name to type1.encoding.char_name                       */
2637 
2638       min_char = 0;
2639       max_char = 0;
2640 
2641       charcode = 0;
2642       for ( ; charcode < loader.encoding_table.max_elems; charcode++ )
2643       {
2644         const FT_String*  char_name =
2645               (const FT_String*)loader.encoding_table.elements[charcode];
2646 
2647 
2648         type1->encoding.char_index[charcode] = 0;
2649         type1->encoding.char_name [charcode] = ".notdef";
2650 
2651         if ( char_name )
2652           for ( idx = 0; idx < type1->num_glyphs; idx++ )
2653           {
2654             const FT_String*  glyph_name = type1->glyph_names[idx];
2655 
2656 
2657             if ( ft_strcmp( char_name, glyph_name ) == 0 )
2658             {
2659               type1->encoding.char_index[charcode] = (FT_UShort)idx;
2660               type1->encoding.char_name [charcode] = glyph_name;
2661 
2662               /* Change min/max encoded char only if glyph name is */
2663               /* not /.notdef                                      */
2664               if ( ft_strcmp( ".notdef", glyph_name ) != 0 )
2665               {
2666                 if ( charcode < min_char )
2667                   min_char = charcode;
2668                 if ( charcode >= max_char )
2669                   max_char = charcode + 1;
2670               }
2671               break;
2672             }
2673           }
2674       }
2675 
2676       type1->encoding.code_first = min_char;
2677       type1->encoding.code_last  = max_char;
2678       type1->encoding.num_chars  = loader.num_chars;
2679     }
2680 
2681     /* some sanitizing to avoid overflows later on; */
2682     /* the upper limits are ad-hoc values           */
2683     if ( priv->blue_shift > 1000 || priv->blue_shift < 0 )
2684     {
2685       FT_TRACE2(( "T1_Open_Face:"
2686                   " setting unlikely BlueShift value %d to default (7)\n",
2687                   priv->blue_shift ));
2688       priv->blue_shift = 7;
2689     }
2690 
2691     if ( priv->blue_fuzz > 1000 || priv->blue_fuzz < 0 )
2692     {
2693       FT_TRACE2(( "T1_Open_Face:"
2694                   " setting unlikely BlueFuzz value %d to default (1)\n",
2695                   priv->blue_fuzz ));
2696       priv->blue_fuzz = 1;
2697     }
2698 
2699   Exit:
2700     t1_done_loader( &loader );
2701     return error;
2702   }
2703 
2704 
2705 /* END */