1 /****************************************************************************
   2  *
   3  * psobjs.c
   4  *
   5  *   Auxiliary functions for PostScript fonts (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 #include <ft2build.h>
  20 #include FT_INTERNAL_POSTSCRIPT_AUX_H
  21 #include FT_INTERNAL_DEBUG_H
  22 #include FT_INTERNAL_CALC_H
  23 #include FT_DRIVER_H
  24 
  25 #include "psobjs.h"
  26 #include "psconv.h"
  27 
  28 #include "psauxerr.h"
  29 #include "psauxmod.h"
  30 
  31 
  32   /**************************************************************************
  33    *
  34    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
  35    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
  36    * messages during execution.
  37    */
  38 #undef  FT_COMPONENT
  39 #define FT_COMPONENT  psobjs
  40 
  41 
  42   /*************************************************************************/
  43   /*************************************************************************/
  44   /*****                                                               *****/
  45   /*****                             PS_TABLE                          *****/
  46   /*****                                                               *****/
  47   /*************************************************************************/
  48   /*************************************************************************/
  49 
  50   /**************************************************************************
  51    *
  52    * @Function:
  53    *   ps_table_new
  54    *
  55    * @Description:
  56    *   Initializes a PS_Table.
  57    *
  58    * @InOut:
  59    *   table ::
  60    *     The address of the target table.
  61    *
  62    * @Input:
  63    *   count ::
  64    *     The table size = the maximum number of elements.
  65    *
  66    *   memory ::
  67    *     The memory object to use for all subsequent
  68    *     reallocations.
  69    *
  70    * @Return:
  71    *   FreeType error code.  0 means success.
  72    */
  73   FT_LOCAL_DEF( FT_Error )
  74   ps_table_new( PS_Table   table,
  75                 FT_Int     count,
  76                 FT_Memory  memory )
  77   {
  78     FT_Error  error;
  79 
  80 
  81     table->memory = memory;
  82     if ( FT_NEW_ARRAY( table->elements, count ) ||
  83          FT_NEW_ARRAY( table->lengths,  count ) )
  84       goto Exit;
  85 
  86     table->max_elems = count;
  87     table->init      = 0xDEADBEEFUL;
  88     table->num_elems = 0;
  89     table->block     = NULL;
  90     table->capacity  = 0;
  91     table->cursor    = 0;
  92 
  93     *(PS_Table_FuncsRec*)&table->funcs = ps_table_funcs;
  94 
  95   Exit:
  96     if ( error )
  97       FT_FREE( table->elements );
  98 
  99     return error;
 100   }
 101 
 102 
 103   static void
 104   shift_elements( PS_Table  table,
 105                   FT_Byte*  old_base )
 106   {
 107     FT_PtrDist  delta  = table->block - old_base;
 108     FT_Byte**   offset = table->elements;
 109     FT_Byte**   limit  = offset + table->max_elems;
 110 
 111 
 112     for ( ; offset < limit; offset++ )
 113     {
 114       if ( offset[0] )
 115         offset[0] += delta;
 116     }
 117   }
 118 
 119 
 120   static FT_Error
 121   reallocate_t1_table( PS_Table   table,
 122                        FT_Offset  new_size )
 123   {
 124     FT_Memory  memory   = table->memory;
 125     FT_Byte*   old_base = table->block;
 126     FT_Error   error;
 127 
 128 
 129     /* allocate new base block */
 130     if ( FT_ALLOC( table->block, new_size ) )
 131     {
 132       table->block = old_base;
 133       return error;
 134     }
 135 
 136     /* copy elements and shift offsets */
 137     if ( old_base )
 138     {
 139       FT_MEM_COPY( table->block, old_base, table->capacity );
 140       shift_elements( table, old_base );
 141       FT_FREE( old_base );
 142     }
 143 
 144     table->capacity = new_size;
 145 
 146     return FT_Err_Ok;
 147   }
 148 
 149 
 150   /**************************************************************************
 151    *
 152    * @Function:
 153    *   ps_table_add
 154    *
 155    * @Description:
 156    *   Adds an object to a PS_Table, possibly growing its memory block.
 157    *
 158    * @InOut:
 159    *   table ::
 160    *     The target table.
 161    *
 162    * @Input:
 163    *   idx ::
 164    *     The index of the object in the table.
 165    *
 166    *   object ::
 167    *     The address of the object to copy in memory.
 168    *
 169    *   length ::
 170    *     The length in bytes of the source object.
 171    *
 172    * @Return:
 173    *   FreeType error code.  0 means success.  An error is returned if a
 174    *   reallocation fails.
 175    */
 176   FT_LOCAL_DEF( FT_Error )
 177   ps_table_add( PS_Table     table,
 178                 FT_Int       idx,
 179                 const void*  object,
 180                 FT_UInt      length )
 181   {
 182     if ( idx < 0 || idx >= table->max_elems )
 183     {
 184       FT_ERROR(( "ps_table_add: invalid index\n" ));
 185       return FT_THROW( Invalid_Argument );
 186     }
 187 
 188     /* grow the base block if needed */
 189     if ( table->cursor + length > table->capacity )
 190     {
 191       FT_Error    error;
 192       FT_Offset   new_size = table->capacity;
 193       FT_PtrDist  in_offset;
 194 
 195 
 196       in_offset = (FT_Byte*)object - table->block;
 197       if ( in_offset < 0 || (FT_Offset)in_offset >= table->capacity )
 198         in_offset = -1;
 199 
 200       while ( new_size < table->cursor + length )
 201       {
 202         /* increase size by 25% and round up to the nearest multiple
 203            of 1024 */
 204         new_size += ( new_size >> 2 ) + 1;
 205         new_size  = FT_PAD_CEIL( new_size, 1024 );
 206       }
 207 
 208       error = reallocate_t1_table( table, new_size );
 209       if ( error )
 210         return error;
 211 
 212       if ( in_offset >= 0 )
 213         object = table->block + in_offset;
 214     }
 215 
 216     /* add the object to the base block and adjust offset */
 217     table->elements[idx] = table->block + table->cursor;
 218     table->lengths [idx] = length;
 219     FT_MEM_COPY( table->block + table->cursor, object, length );
 220 
 221     table->cursor += length;
 222     return FT_Err_Ok;
 223   }
 224 
 225 
 226   /**************************************************************************
 227    *
 228    * @Function:
 229    *   ps_table_done
 230    *
 231    * @Description:
 232    *   Finalizes a PS_TableRec (i.e., reallocate it to its current
 233    *   cursor).
 234    *
 235    * @InOut:
 236    *   table ::
 237    *     The target table.
 238    *
 239    * @Note:
 240    *   This function does NOT release the heap's memory block.  It is up
 241    *   to the caller to clean it, or reference it in its own structures.
 242    */
 243   FT_LOCAL_DEF( void )
 244   ps_table_done( PS_Table  table )
 245   {
 246     FT_Memory  memory = table->memory;
 247     FT_Error   error;
 248     FT_Byte*   old_base = table->block;
 249 
 250 
 251     /* should never fail, because rec.cursor <= rec.size */
 252     if ( !old_base )
 253       return;
 254 
 255     if ( FT_ALLOC( table->block, table->cursor ) )
 256       return;
 257     FT_MEM_COPY( table->block, old_base, table->cursor );
 258     shift_elements( table, old_base );
 259 
 260     table->capacity = table->cursor;
 261     FT_FREE( old_base );
 262 
 263     FT_UNUSED( error );
 264   }
 265 
 266 
 267   FT_LOCAL_DEF( void )
 268   ps_table_release( PS_Table  table )
 269   {
 270     FT_Memory  memory = table->memory;
 271 
 272 
 273     if ( (FT_ULong)table->init == 0xDEADBEEFUL )
 274     {
 275       FT_FREE( table->block );
 276       FT_FREE( table->elements );
 277       FT_FREE( table->lengths );
 278       table->init = 0;
 279     }
 280   }
 281 
 282 
 283   /*************************************************************************/
 284   /*************************************************************************/
 285   /*****                                                               *****/
 286   /*****                            T1 PARSER                          *****/
 287   /*****                                                               *****/
 288   /*************************************************************************/
 289   /*************************************************************************/
 290 
 291 
 292   /* first character must be already part of the comment */
 293 
 294   static void
 295   skip_comment( FT_Byte*  *acur,
 296                 FT_Byte*   limit )
 297   {
 298     FT_Byte*  cur = *acur;
 299 
 300 
 301     while ( cur < limit )
 302     {
 303       if ( IS_PS_NEWLINE( *cur ) )
 304         break;
 305       cur++;
 306     }
 307 
 308     *acur = cur;
 309   }
 310 
 311 
 312   static void
 313   skip_spaces( FT_Byte*  *acur,
 314                FT_Byte*   limit )
 315   {
 316     FT_Byte*  cur = *acur;
 317 
 318 
 319     while ( cur < limit )
 320     {
 321       if ( !IS_PS_SPACE( *cur ) )
 322       {
 323         if ( *cur == '%' )
 324           /* According to the PLRM, a comment is equal to a space. */
 325           skip_comment( &cur, limit );
 326         else
 327           break;
 328       }
 329       cur++;
 330     }
 331 
 332     *acur = cur;
 333   }
 334 
 335 
 336 #define IS_OCTAL_DIGIT( c ) ( '0' <= (c) && (c) <= '7' )
 337 
 338 
 339   /* first character must be `(';                               */
 340   /* *acur is positioned at the character after the closing `)' */
 341 
 342   static FT_Error
 343   skip_literal_string( FT_Byte*  *acur,
 344                        FT_Byte*   limit )
 345   {
 346     FT_Byte*      cur   = *acur;
 347     FT_Int        embed = 0;
 348     FT_Error      error = FT_ERR( Invalid_File_Format );
 349     unsigned int  i;
 350 
 351 
 352     while ( cur < limit )
 353     {
 354       FT_Byte  c = *cur;
 355 
 356 
 357       cur++;
 358 
 359       if ( c == '\\' )
 360       {
 361         /* Red Book 3rd ed., section `Literal Text Strings', p. 29:     */
 362         /* A backslash can introduce three different types              */
 363         /* of escape sequences:                                         */
 364         /*   - a special escaped char like \r, \n, etc.                 */
 365         /*   - a one-, two-, or three-digit octal number                */
 366         /*   - none of the above in which case the backslash is ignored */
 367 
 368         if ( cur == limit )
 369           /* error (or to be ignored?) */
 370           break;
 371 
 372         switch ( *cur )
 373         {
 374           /* skip `special' escape */
 375         case 'n':
 376         case 'r':
 377         case 't':
 378         case 'b':
 379         case 'f':
 380         case '\\':
 381         case '(':
 382         case ')':
 383           cur++;
 384           break;
 385 
 386         default:
 387           /* skip octal escape or ignore backslash */
 388           for ( i = 0; i < 3 && cur < limit; i++ )
 389           {
 390             if ( !IS_OCTAL_DIGIT( *cur ) )
 391               break;
 392 
 393             cur++;
 394           }
 395         }
 396       }
 397       else if ( c == '(' )
 398         embed++;
 399       else if ( c == ')' )
 400       {
 401         embed--;
 402         if ( embed == 0 )
 403         {
 404           error = FT_Err_Ok;
 405           break;
 406         }
 407       }
 408     }
 409 
 410     *acur = cur;
 411 
 412     return error;
 413   }
 414 
 415 
 416   /* first character must be `<' */
 417 
 418   static FT_Error
 419   skip_string( FT_Byte*  *acur,
 420                FT_Byte*   limit )
 421   {
 422     FT_Byte*  cur = *acur;
 423     FT_Error  err =  FT_Err_Ok;
 424 
 425 
 426     while ( ++cur < limit )
 427     {
 428       /* All whitespace characters are ignored. */
 429       skip_spaces( &cur, limit );
 430       if ( cur >= limit )
 431         break;
 432 
 433       if ( !IS_PS_XDIGIT( *cur ) )
 434         break;
 435     }
 436 
 437     if ( cur < limit && *cur != '>' )
 438     {
 439       FT_ERROR(( "skip_string: missing closing delimiter `>'\n" ));
 440       err = FT_THROW( Invalid_File_Format );
 441     }
 442     else
 443       cur++;
 444 
 445     *acur = cur;
 446     return err;
 447   }
 448 
 449 
 450   /* first character must be the opening brace that */
 451   /* starts the procedure                           */
 452 
 453   /* NB: [ and ] need not match:                    */
 454   /* `/foo {[} def' is a valid PostScript fragment, */
 455   /* even within a Type1 font                       */
 456 
 457   static FT_Error
 458   skip_procedure( FT_Byte*  *acur,
 459                   FT_Byte*   limit )
 460   {
 461     FT_Byte*  cur;
 462     FT_Int    embed = 0;
 463     FT_Error  error = FT_Err_Ok;
 464 
 465 
 466     FT_ASSERT( **acur == '{' );
 467 
 468     for ( cur = *acur; cur < limit && error == FT_Err_Ok; cur++ )
 469     {
 470       switch ( *cur )
 471       {
 472       case '{':
 473         embed++;
 474         break;
 475 
 476       case '}':
 477         embed--;
 478         if ( embed == 0 )
 479         {
 480           cur++;
 481           goto end;
 482         }
 483         break;
 484 
 485       case '(':
 486         error = skip_literal_string( &cur, limit );
 487         break;
 488 
 489       case '<':
 490         error = skip_string( &cur, limit );
 491         break;
 492 
 493       case '%':
 494         skip_comment( &cur, limit );
 495         break;
 496       }
 497     }
 498 
 499   end:
 500     if ( embed != 0 )
 501       error = FT_THROW( Invalid_File_Format );
 502 
 503     *acur = cur;
 504 
 505     return error;
 506   }
 507 
 508 
 509   /************************************************************************
 510    *
 511    * All exported parsing routines handle leading whitespace and stop at
 512    * the first character which isn't part of the just handled token.
 513    *
 514    */
 515 
 516 
 517   FT_LOCAL_DEF( void )
 518   ps_parser_skip_PS_token( PS_Parser  parser )
 519   {
 520     /* Note: PostScript allows any non-delimiting, non-whitespace        */
 521     /*       character in a name (PS Ref Manual, 3rd ed, p31).           */
 522     /*       PostScript delimiters are (, ), <, >, [, ], {, }, /, and %. */
 523 
 524     FT_Byte*  cur   = parser->cursor;
 525     FT_Byte*  limit = parser->limit;
 526     FT_Error  error = FT_Err_Ok;
 527 
 528 
 529     skip_spaces( &cur, limit );             /* this also skips comments */
 530     if ( cur >= limit )
 531       goto Exit;
 532 
 533     /* self-delimiting, single-character tokens */
 534     if ( *cur == '[' || *cur == ']' )
 535     {
 536       cur++;
 537       goto Exit;
 538     }
 539 
 540     /* skip balanced expressions (procedures and strings) */
 541 
 542     if ( *cur == '{' )                              /* {...} */
 543     {
 544       error = skip_procedure( &cur, limit );
 545       goto Exit;
 546     }
 547 
 548     if ( *cur == '(' )                              /* (...) */
 549     {
 550       error = skip_literal_string( &cur, limit );
 551       goto Exit;
 552     }
 553 
 554     if ( *cur == '<' )                              /* <...> */
 555     {
 556       if ( cur + 1 < limit && *(cur + 1) == '<' )   /* << */
 557       {
 558         cur++;
 559         cur++;
 560       }
 561       else
 562         error = skip_string( &cur, limit );
 563 
 564       goto Exit;
 565     }
 566 
 567     if ( *cur == '>' )
 568     {
 569       cur++;
 570       if ( cur >= limit || *cur != '>' )             /* >> */
 571       {
 572         FT_ERROR(( "ps_parser_skip_PS_token:"
 573                    " unexpected closing delimiter `>'\n" ));
 574         error = FT_THROW( Invalid_File_Format );
 575         goto Exit;
 576       }
 577       cur++;
 578       goto Exit;
 579     }
 580 
 581     if ( *cur == '/' )
 582       cur++;
 583 
 584     /* anything else */
 585     while ( cur < limit )
 586     {
 587       /* *cur might be invalid (e.g., ')' or '}'), but this   */
 588       /* is handled by the test `cur == parser->cursor' below */
 589       if ( IS_PS_DELIM( *cur ) )
 590         break;
 591 
 592       cur++;
 593     }
 594 
 595   Exit:
 596     if ( cur < limit && cur == parser->cursor )
 597     {
 598       FT_ERROR(( "ps_parser_skip_PS_token:"
 599                  " current token is `%c' which is self-delimiting\n"
 600                  "                        "
 601                  " but invalid at this point\n",
 602                  *cur ));
 603 
 604       error = FT_THROW( Invalid_File_Format );
 605     }
 606 
 607     if ( cur > limit )
 608       cur = limit;
 609 
 610     parser->error  = error;
 611     parser->cursor = cur;
 612   }
 613 
 614 
 615   FT_LOCAL_DEF( void )
 616   ps_parser_skip_spaces( PS_Parser  parser )
 617   {
 618     skip_spaces( &parser->cursor, parser->limit );
 619   }
 620 
 621 
 622   /* `token' here means either something between balanced delimiters */
 623   /* or the next token; the delimiters are not removed.              */
 624 
 625   FT_LOCAL_DEF( void )
 626   ps_parser_to_token( PS_Parser  parser,
 627                       T1_Token   token )
 628   {
 629     FT_Byte*  cur;
 630     FT_Byte*  limit;
 631     FT_Int    embed;
 632 
 633 
 634     token->type  = T1_TOKEN_TYPE_NONE;
 635     token->start = NULL;
 636     token->limit = NULL;
 637 
 638     /* first of all, skip leading whitespace */
 639     ps_parser_skip_spaces( parser );
 640 
 641     cur   = parser->cursor;
 642     limit = parser->limit;
 643 
 644     if ( cur >= limit )
 645       return;
 646 
 647     switch ( *cur )
 648     {
 649       /************* check for literal string *****************/
 650     case '(':
 651       token->type  = T1_TOKEN_TYPE_STRING;
 652       token->start = cur;
 653 
 654       if ( skip_literal_string( &cur, limit ) == FT_Err_Ok )
 655         token->limit = cur;
 656       break;
 657 
 658       /************* check for programs/array *****************/
 659     case '{':
 660       token->type  = T1_TOKEN_TYPE_ARRAY;
 661       token->start = cur;
 662 
 663       if ( skip_procedure( &cur, limit ) == FT_Err_Ok )
 664         token->limit = cur;
 665       break;
 666 
 667       /************* check for table/array ********************/
 668       /* XXX: in theory we should also look for "<<"          */
 669       /*      since this is semantically equivalent to "[";   */
 670       /*      in practice it doesn't matter (?)               */
 671     case '[':
 672       token->type  = T1_TOKEN_TYPE_ARRAY;
 673       embed        = 1;
 674       token->start = cur++;
 675 
 676       /* we need this to catch `[ ]' */
 677       parser->cursor = cur;
 678       ps_parser_skip_spaces( parser );
 679       cur = parser->cursor;
 680 
 681       while ( cur < limit && !parser->error )
 682       {
 683         /* XXX: this is wrong because it does not      */
 684         /*      skip comments, procedures, and strings */
 685         if ( *cur == '[' )
 686           embed++;
 687         else if ( *cur == ']' )
 688         {
 689           embed--;
 690           if ( embed <= 0 )
 691           {
 692             token->limit = ++cur;
 693             break;
 694           }
 695         }
 696 
 697         parser->cursor = cur;
 698         ps_parser_skip_PS_token( parser );
 699         /* we need this to catch `[XXX ]' */
 700         ps_parser_skip_spaces  ( parser );
 701         cur = parser->cursor;
 702       }
 703       break;
 704 
 705       /* ************ otherwise, it is any token **************/
 706     default:
 707       token->start = cur;
 708       token->type  = ( *cur == '/' ) ? T1_TOKEN_TYPE_KEY : T1_TOKEN_TYPE_ANY;
 709       ps_parser_skip_PS_token( parser );
 710       cur = parser->cursor;
 711       if ( !parser->error )
 712         token->limit = cur;
 713     }
 714 
 715     if ( !token->limit )
 716     {
 717       token->start = NULL;
 718       token->type  = T1_TOKEN_TYPE_NONE;
 719     }
 720 
 721     parser->cursor = cur;
 722   }
 723 
 724 
 725   /* NB: `tokens' can be NULL if we only want to count */
 726   /* the number of array elements                      */
 727 
 728   FT_LOCAL_DEF( void )
 729   ps_parser_to_token_array( PS_Parser  parser,
 730                             T1_Token   tokens,
 731                             FT_UInt    max_tokens,
 732                             FT_Int*    pnum_tokens )
 733   {
 734     T1_TokenRec  master;
 735 
 736 
 737     *pnum_tokens = -1;
 738 
 739     /* this also handles leading whitespace */
 740     ps_parser_to_token( parser, &master );
 741 
 742     if ( master.type == T1_TOKEN_TYPE_ARRAY )
 743     {
 744       FT_Byte*  old_cursor = parser->cursor;
 745       FT_Byte*  old_limit  = parser->limit;
 746       T1_Token  cur        = tokens;
 747       T1_Token  limit      = cur + max_tokens;
 748 
 749 
 750       /* don't include outermost delimiters */
 751       parser->cursor = master.start + 1;
 752       parser->limit  = master.limit - 1;
 753 
 754       while ( parser->cursor < parser->limit )
 755       {
 756         T1_TokenRec  token;
 757 
 758 
 759         ps_parser_to_token( parser, &token );
 760         if ( !token.type )
 761           break;
 762 
 763         if ( tokens && cur < limit )
 764           *cur = token;
 765 
 766         cur++;
 767       }
 768 
 769       *pnum_tokens = (FT_Int)( cur - tokens );
 770 
 771       parser->cursor = old_cursor;
 772       parser->limit  = old_limit;
 773     }
 774   }
 775 
 776 
 777   /* first character must be a delimiter or a part of a number */
 778   /* NB: `coords' can be NULL if we just want to skip the      */
 779   /*     array; in this case we ignore `max_coords'            */
 780 
 781   static FT_Int
 782   ps_tocoordarray( FT_Byte*  *acur,
 783                    FT_Byte*   limit,
 784                    FT_Int     max_coords,
 785                    FT_Short*  coords )
 786   {
 787     FT_Byte*  cur   = *acur;
 788     FT_Int    count = 0;
 789     FT_Byte   c, ender;
 790 
 791 
 792     if ( cur >= limit )
 793       goto Exit;
 794 
 795     /* check for the beginning of an array; otherwise, only one number */
 796     /* will be read                                                    */
 797     c     = *cur;
 798     ender = 0;
 799 
 800     if ( c == '[' )
 801       ender = ']';
 802     else if ( c == '{' )
 803       ender = '}';
 804 
 805     if ( ender )
 806       cur++;
 807 
 808     /* now, read the coordinates */
 809     while ( cur < limit )
 810     {
 811       FT_Short  dummy;
 812       FT_Byte*  old_cur;
 813 
 814 
 815       /* skip whitespace in front of data */
 816       skip_spaces( &cur, limit );
 817       if ( cur >= limit )
 818         goto Exit;
 819 
 820       if ( *cur == ender )
 821       {
 822         cur++;
 823         break;
 824       }
 825 
 826       old_cur = cur;
 827 
 828       if ( coords && count >= max_coords )
 829         break;
 830 
 831       /* call PS_Conv_ToFixed() even if coords == NULL */
 832       /* to properly parse number at `cur'             */
 833       *( coords ? &coords[count] : &dummy ) =
 834         (FT_Short)( PS_Conv_ToFixed( &cur, limit, 0 ) >> 16 );
 835 
 836       if ( old_cur == cur )
 837       {
 838         count = -1;
 839         goto Exit;
 840       }
 841       else
 842         count++;
 843 
 844       if ( !ender )
 845         break;
 846     }
 847 
 848   Exit:
 849     *acur = cur;
 850     return count;
 851   }
 852 
 853 
 854   /* first character must be a delimiter or a part of a number */
 855   /* NB: `values' can be NULL if we just want to skip the      */
 856   /*     array; in this case we ignore `max_values'            */
 857   /*                                                           */
 858   /* return number of successfully parsed values               */
 859 
 860   static FT_Int
 861   ps_tofixedarray( FT_Byte*  *acur,
 862                    FT_Byte*   limit,
 863                    FT_Int     max_values,
 864                    FT_Fixed*  values,
 865                    FT_Int     power_ten )
 866   {
 867     FT_Byte*  cur   = *acur;
 868     FT_Int    count = 0;
 869     FT_Byte   c, ender;
 870 
 871 
 872     if ( cur >= limit )
 873       goto Exit;
 874 
 875     /* Check for the beginning of an array.  Otherwise, only one number */
 876     /* will be read.                                                    */
 877     c     = *cur;
 878     ender = 0;
 879 
 880     if ( c == '[' )
 881       ender = ']';
 882     else if ( c == '{' )
 883       ender = '}';
 884 
 885     if ( ender )
 886       cur++;
 887 
 888     /* now, read the values */
 889     while ( cur < limit )
 890     {
 891       FT_Fixed  dummy;
 892       FT_Byte*  old_cur;
 893 
 894 
 895       /* skip whitespace in front of data */
 896       skip_spaces( &cur, limit );
 897       if ( cur >= limit )
 898         goto Exit;
 899 
 900       if ( *cur == ender )
 901       {
 902         cur++;
 903         break;
 904       }
 905 
 906       old_cur = cur;
 907 
 908       if ( values && count >= max_values )
 909         break;
 910 
 911       /* call PS_Conv_ToFixed() even if coords == NULL */
 912       /* to properly parse number at `cur'             */
 913       *( values ? &values[count] : &dummy ) =
 914         PS_Conv_ToFixed( &cur, limit, power_ten );
 915 
 916       if ( old_cur == cur )
 917       {
 918         count = -1;
 919         goto Exit;
 920       }
 921       else
 922         count++;
 923 
 924       if ( !ender )
 925         break;
 926     }
 927 
 928   Exit:
 929     *acur = cur;
 930     return count;
 931   }
 932 
 933 
 934 #if 0
 935 
 936   static FT_String*
 937   ps_tostring( FT_Byte**  cursor,
 938                FT_Byte*   limit,
 939                FT_Memory  memory )
 940   {
 941     FT_Byte*    cur = *cursor;
 942     FT_UInt     len = 0;
 943     FT_Int      count;
 944     FT_String*  result;
 945     FT_Error    error;
 946 
 947 
 948     /* XXX: some stupid fonts have a `Notice' or `Copyright' string     */
 949     /*      that simply doesn't begin with an opening parenthesis, even */
 950     /*      though they have a closing one!  E.g. "amuncial.pfb"        */
 951     /*                                                                  */
 952     /*      We must deal with these ill-fated cases there.  Note that   */
 953     /*      these fonts didn't work with the old Type 1 driver as the   */
 954     /*      notice/copyright was not recognized as a valid string token */
 955     /*      and made the old token parser commit errors.                */
 956 
 957     while ( cur < limit && ( *cur == ' ' || *cur == '\t' ) )
 958       cur++;
 959     if ( cur + 1 >= limit )
 960       return 0;
 961 
 962     if ( *cur == '(' )
 963       cur++;  /* skip the opening parenthesis, if there is one */
 964 
 965     *cursor = cur;
 966     count   = 0;
 967 
 968     /* then, count its length */
 969     for ( ; cur < limit; cur++ )
 970     {
 971       if ( *cur == '(' )
 972         count++;
 973 
 974       else if ( *cur == ')' )
 975       {
 976         count--;
 977         if ( count < 0 )
 978           break;
 979       }
 980     }
 981 
 982     len = (FT_UInt)( cur - *cursor );
 983     if ( cur >= limit || FT_ALLOC( result, len + 1 ) )
 984       return 0;
 985 
 986     /* now copy the string */
 987     FT_MEM_COPY( result, *cursor, len );
 988     result[len] = '\0';
 989     *cursor = cur;
 990     return result;
 991   }
 992 
 993 #endif /* 0 */
 994 
 995 
 996   static int
 997   ps_tobool( FT_Byte*  *acur,
 998              FT_Byte*   limit )
 999   {
1000     FT_Byte*  cur    = *acur;
1001     FT_Bool   result = 0;
1002 
1003 
1004     /* return 1 if we find `true', 0 otherwise */
1005     if ( cur + 3 < limit &&
1006          cur[0] == 't'   &&
1007          cur[1] == 'r'   &&
1008          cur[2] == 'u'   &&
1009          cur[3] == 'e'   )
1010     {
1011       result = 1;
1012       cur   += 5;
1013     }
1014     else if ( cur + 4 < limit &&
1015               cur[0] == 'f'   &&
1016               cur[1] == 'a'   &&
1017               cur[2] == 'l'   &&
1018               cur[3] == 's'   &&
1019               cur[4] == 'e'   )
1020     {
1021       result = 0;
1022       cur   += 6;
1023     }
1024 
1025     *acur = cur;
1026     return result;
1027   }
1028 
1029 
1030   /* load a simple field (i.e. non-table) into the current list of objects */
1031 
1032   FT_LOCAL_DEF( FT_Error )
1033   ps_parser_load_field( PS_Parser       parser,
1034                         const T1_Field  field,
1035                         void**          objects,
1036                         FT_UInt         max_objects,
1037                         FT_ULong*       pflags )
1038   {
1039     T1_TokenRec   token;
1040     FT_Byte*      cur;
1041     FT_Byte*      limit;
1042     FT_UInt       count;
1043     FT_UInt       idx;
1044     FT_Error      error;
1045     T1_FieldType  type;
1046 
1047 
1048     /* this also skips leading whitespace */
1049     ps_parser_to_token( parser, &token );
1050     if ( !token.type )
1051       goto Fail;
1052 
1053     count = 1;
1054     idx   = 0;
1055     cur   = token.start;
1056     limit = token.limit;
1057 
1058     type = field->type;
1059 
1060     /* we must detect arrays in /FontBBox */
1061     if ( type == T1_FIELD_TYPE_BBOX )
1062     {
1063       T1_TokenRec  token2;
1064       FT_Byte*     old_cur   = parser->cursor;
1065       FT_Byte*     old_limit = parser->limit;
1066 
1067 
1068       /* don't include delimiters */
1069       parser->cursor = token.start + 1;
1070       parser->limit  = token.limit - 1;
1071 
1072       ps_parser_to_token( parser, &token2 );
1073       parser->cursor = old_cur;
1074       parser->limit  = old_limit;
1075 
1076       if ( token2.type == T1_TOKEN_TYPE_ARRAY )
1077       {
1078         type = T1_FIELD_TYPE_MM_BBOX;
1079         goto FieldArray;
1080       }
1081     }
1082     else if ( token.type == T1_TOKEN_TYPE_ARRAY )
1083     {
1084       count = max_objects;
1085 
1086     FieldArray:
1087       /* if this is an array and we have no blend, an error occurs */
1088       if ( max_objects == 0 )
1089         goto Fail;
1090 
1091       idx = 1;
1092 
1093       /* don't include delimiters */
1094       cur++;
1095       limit--;
1096     }
1097 
1098     for ( ; count > 0; count--, idx++ )
1099     {
1100       FT_Byte*    q      = (FT_Byte*)objects[idx] + field->offset;
1101       FT_Long     val;
1102       FT_String*  string = NULL;
1103 
1104 
1105       skip_spaces( &cur, limit );
1106 
1107       switch ( type )
1108       {
1109       case T1_FIELD_TYPE_BOOL:
1110         val = ps_tobool( &cur, limit );
1111         FT_TRACE4(( " %s", val ? "true" : "false" ));
1112         goto Store_Integer;
1113 
1114       case T1_FIELD_TYPE_FIXED:
1115         val = PS_Conv_ToFixed( &cur, limit, 0 );
1116         FT_TRACE4(( " %f", (double)val / 65536 ));
1117         goto Store_Integer;
1118 
1119       case T1_FIELD_TYPE_FIXED_1000:
1120         val = PS_Conv_ToFixed( &cur, limit, 3 );
1121         FT_TRACE4(( " %f", (double)val / 65536 / 1000 ));
1122         goto Store_Integer;
1123 
1124       case T1_FIELD_TYPE_INTEGER:
1125         val = PS_Conv_ToInt( &cur, limit );
1126         FT_TRACE4(( " %ld", val ));
1127         /* fall through */
1128 
1129       Store_Integer:
1130         switch ( field->size )
1131         {
1132         case (8 / FT_CHAR_BIT):
1133           *(FT_Byte*)q = (FT_Byte)val;
1134           break;
1135 
1136         case (16 / FT_CHAR_BIT):
1137           *(FT_UShort*)q = (FT_UShort)val;
1138           break;
1139 
1140         case (32 / FT_CHAR_BIT):
1141           *(FT_UInt32*)q = (FT_UInt32)val;
1142           break;
1143 
1144         default:                /* for 64-bit systems */
1145           *(FT_Long*)q = val;
1146         }
1147         break;
1148 
1149       case T1_FIELD_TYPE_STRING:
1150       case T1_FIELD_TYPE_KEY:
1151         {
1152           FT_Memory  memory = parser->memory;
1153           FT_UInt    len    = (FT_UInt)( limit - cur );
1154 
1155 
1156           if ( cur >= limit )
1157             break;
1158 
1159           /* we allow both a string or a name   */
1160           /* for cases like /FontName (foo) def */
1161           if ( token.type == T1_TOKEN_TYPE_KEY )
1162           {
1163             /* don't include leading `/' */
1164             len--;
1165             cur++;
1166           }
1167           else if ( token.type == T1_TOKEN_TYPE_STRING )
1168           {
1169             /* don't include delimiting parentheses    */
1170             /* XXX we don't handle <<...>> here        */
1171             /* XXX should we convert octal escapes?    */
1172             /*     if so, what encoding should we use? */
1173             cur++;
1174             len -= 2;
1175           }
1176           else
1177           {
1178             FT_ERROR(( "ps_parser_load_field:"
1179                        " expected a name or string\n"
1180                        "                     "
1181                        " but found token of type %d instead\n",
1182                        token.type ));
1183             error = FT_THROW( Invalid_File_Format );
1184             goto Exit;
1185           }
1186 
1187           /* for this to work (FT_String**)q must have been */
1188           /* initialized to NULL                            */
1189           if ( *(FT_String**)q )
1190           {
1191             FT_TRACE0(( "ps_parser_load_field: overwriting field %s\n",
1192                         field->ident ));
1193             FT_FREE( *(FT_String**)q );
1194             *(FT_String**)q = NULL;
1195           }
1196 
1197           if ( FT_ALLOC( string, len + 1 ) )
1198             goto Exit;
1199 
1200           FT_MEM_COPY( string, cur, len );
1201           string[len] = 0;
1202 
1203 #ifdef FT_DEBUG_LEVEL_TRACE
1204           if ( token.type == T1_TOKEN_TYPE_STRING )
1205             FT_TRACE4(( " (%s)", string ));
1206           else
1207             FT_TRACE4(( " /%s", string ));
1208 #endif
1209 
1210           *(FT_String**)q = string;
1211         }
1212         break;
1213 
1214       case T1_FIELD_TYPE_BBOX:
1215         {
1216           FT_Fixed  temp[4];
1217           FT_BBox*  bbox = (FT_BBox*)q;
1218           FT_Int    result;
1219 
1220 
1221           result = ps_tofixedarray( &cur, limit, 4, temp, 0 );
1222 
1223           if ( result < 4 )
1224           {
1225             FT_ERROR(( "ps_parser_load_field:"
1226                        " expected four integers in bounding box\n" ));
1227             error = FT_THROW( Invalid_File_Format );
1228             goto Exit;
1229           }
1230 
1231           bbox->xMin = FT_RoundFix( temp[0] );
1232           bbox->yMin = FT_RoundFix( temp[1] );
1233           bbox->xMax = FT_RoundFix( temp[2] );
1234           bbox->yMax = FT_RoundFix( temp[3] );
1235 
1236           FT_TRACE4(( " [%d %d %d %d]",
1237                       bbox->xMin / 65536,
1238                       bbox->yMin / 65536,
1239                       bbox->xMax / 65536,
1240                       bbox->yMax / 65536 ));
1241         }
1242         break;
1243 
1244       case T1_FIELD_TYPE_MM_BBOX:
1245         {
1246           FT_Memory  memory = parser->memory;
1247           FT_Fixed*  temp   = NULL;
1248           FT_Int     result;
1249           FT_UInt    i;
1250 
1251 
1252           if ( FT_NEW_ARRAY( temp, max_objects * 4 ) )
1253             goto Exit;
1254 
1255           for ( i = 0; i < 4; i++ )
1256           {
1257             result = ps_tofixedarray( &cur, limit, (FT_Int)max_objects,
1258                                       temp + i * max_objects, 0 );
1259             if ( result < 0 || (FT_UInt)result < max_objects )
1260             {
1261               FT_ERROR(( "ps_parser_load_field:"
1262                          " expected %d integer%s in the %s subarray\n"
1263                          "                     "
1264                          " of /FontBBox in the /Blend dictionary\n",
1265                          max_objects, max_objects > 1 ? "s" : "",
1266                          i == 0 ? "first"
1267                                 : ( i == 1 ? "second"
1268                                            : ( i == 2 ? "third"
1269                                                       : "fourth" ) ) ));
1270               error = FT_THROW( Invalid_File_Format );
1271 
1272               FT_FREE( temp );
1273               goto Exit;
1274             }
1275 
1276             skip_spaces( &cur, limit );
1277           }
1278 
1279           FT_TRACE4(( " [" ));
1280           for ( i = 0; i < max_objects; i++ )
1281           {
1282             FT_BBox*  bbox = (FT_BBox*)objects[i];
1283 
1284 
1285             bbox->xMin = FT_RoundFix( temp[i                  ] );
1286             bbox->yMin = FT_RoundFix( temp[i +     max_objects] );
1287             bbox->xMax = FT_RoundFix( temp[i + 2 * max_objects] );
1288             bbox->yMax = FT_RoundFix( temp[i + 3 * max_objects] );
1289 
1290             FT_TRACE4(( " [%d %d %d %d]",
1291                         bbox->xMin / 65536,
1292                         bbox->yMin / 65536,
1293                         bbox->xMax / 65536,
1294                         bbox->yMax / 65536 ));
1295           }
1296           FT_TRACE4(( "]" ));
1297 
1298           FT_FREE( temp );
1299         }
1300         break;
1301 
1302       default:
1303         /* an error occurred */
1304         goto Fail;
1305       }
1306     }
1307 
1308 #if 0  /* obsolete -- keep for reference */
1309     if ( pflags )
1310       *pflags |= 1L << field->flag_bit;
1311 #else
1312     FT_UNUSED( pflags );
1313 #endif
1314 
1315     error = FT_Err_Ok;
1316 
1317   Exit:
1318     return error;
1319 
1320   Fail:
1321     error = FT_THROW( Invalid_File_Format );
1322     goto Exit;
1323   }
1324 
1325 
1326 #define T1_MAX_TABLE_ELEMENTS  32
1327 
1328 
1329   FT_LOCAL_DEF( FT_Error )
1330   ps_parser_load_field_table( PS_Parser       parser,
1331                               const T1_Field  field,
1332                               void**          objects,
1333                               FT_UInt         max_objects,
1334                               FT_ULong*       pflags )
1335   {
1336     T1_TokenRec  elements[T1_MAX_TABLE_ELEMENTS];
1337     T1_Token     token;
1338     FT_Int       num_elements;
1339     FT_Error     error = FT_Err_Ok;
1340     FT_Byte*     old_cursor;
1341     FT_Byte*     old_limit;
1342     T1_FieldRec  fieldrec = *(T1_Field)field;
1343 
1344 
1345     fieldrec.type = T1_FIELD_TYPE_INTEGER;
1346     if ( field->type == T1_FIELD_TYPE_FIXED_ARRAY ||
1347          field->type == T1_FIELD_TYPE_BBOX        )
1348       fieldrec.type = T1_FIELD_TYPE_FIXED;
1349 
1350     ps_parser_to_token_array( parser, elements,
1351                               T1_MAX_TABLE_ELEMENTS, &num_elements );
1352     if ( num_elements < 0 )
1353     {
1354       error = FT_ERR( Ignore );
1355       goto Exit;
1356     }
1357     if ( (FT_UInt)num_elements > field->array_max )
1358       num_elements = (FT_Int)field->array_max;
1359 
1360     old_cursor = parser->cursor;
1361     old_limit  = parser->limit;
1362 
1363     /* we store the elements count if necessary;           */
1364     /* we further assume that `count_offset' can't be zero */
1365     if ( field->type != T1_FIELD_TYPE_BBOX && field->count_offset != 0 )
1366       *(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) =
1367         (FT_Byte)num_elements;
1368 
1369     FT_TRACE4(( " [" ));
1370 
1371     /* we now load each element, adjusting the field.offset on each one */
1372     token = elements;
1373     for ( ; num_elements > 0; num_elements--, token++ )
1374     {
1375       parser->cursor = token->start;
1376       parser->limit  = token->limit;
1377 
1378       error = ps_parser_load_field( parser,
1379                                     &fieldrec,
1380                                     objects,
1381                                     max_objects,
1382                                     0 );
1383       if ( error )
1384         break;
1385 
1386       fieldrec.offset += fieldrec.size;
1387     }
1388 
1389     FT_TRACE4(( "]" ));
1390 
1391 #if 0  /* obsolete -- keep for reference */
1392     if ( pflags )
1393       *pflags |= 1L << field->flag_bit;
1394 #else
1395     FT_UNUSED( pflags );
1396 #endif
1397 
1398     parser->cursor = old_cursor;
1399     parser->limit  = old_limit;
1400 
1401   Exit:
1402     return error;
1403   }
1404 
1405 
1406   FT_LOCAL_DEF( FT_Long )
1407   ps_parser_to_int( PS_Parser  parser )
1408   {
1409     ps_parser_skip_spaces( parser );
1410     return PS_Conv_ToInt( &parser->cursor, parser->limit );
1411   }
1412 
1413 
1414   /* first character must be `<' if `delimiters' is non-zero */
1415 
1416   FT_LOCAL_DEF( FT_Error )
1417   ps_parser_to_bytes( PS_Parser  parser,
1418                       FT_Byte*   bytes,
1419                       FT_Offset  max_bytes,
1420                       FT_ULong*  pnum_bytes,
1421                       FT_Bool    delimiters )
1422   {
1423     FT_Error  error = FT_Err_Ok;
1424     FT_Byte*  cur;
1425 
1426 
1427     ps_parser_skip_spaces( parser );
1428     cur = parser->cursor;
1429 
1430     if ( cur >= parser->limit )
1431       goto Exit;
1432 
1433     if ( delimiters )
1434     {
1435       if ( *cur != '<' )
1436       {
1437         FT_ERROR(( "ps_parser_to_bytes: Missing starting delimiter `<'\n" ));
1438         error = FT_THROW( Invalid_File_Format );
1439         goto Exit;
1440       }
1441 
1442       cur++;
1443     }
1444 
1445     *pnum_bytes = PS_Conv_ASCIIHexDecode( &cur,
1446                                           parser->limit,
1447                                           bytes,
1448                                           max_bytes );
1449 
1450     parser->cursor = cur;
1451 
1452     if ( delimiters )
1453     {
1454       if ( cur < parser->limit && *cur != '>' )
1455       {
1456         FT_ERROR(( "ps_parser_to_bytes: Missing closing delimiter `>'\n" ));
1457         error = FT_THROW( Invalid_File_Format );
1458         goto Exit;
1459       }
1460 
1461       parser->cursor++;
1462     }
1463 
1464   Exit:
1465     return error;
1466   }
1467 
1468 
1469   FT_LOCAL_DEF( FT_Fixed )
1470   ps_parser_to_fixed( PS_Parser  parser,
1471                       FT_Int     power_ten )
1472   {
1473     ps_parser_skip_spaces( parser );
1474     return PS_Conv_ToFixed( &parser->cursor, parser->limit, power_ten );
1475   }
1476 
1477 
1478   FT_LOCAL_DEF( FT_Int )
1479   ps_parser_to_coord_array( PS_Parser  parser,
1480                             FT_Int     max_coords,
1481                             FT_Short*  coords )
1482   {
1483     ps_parser_skip_spaces( parser );
1484     return ps_tocoordarray( &parser->cursor, parser->limit,
1485                             max_coords, coords );
1486   }
1487 
1488 
1489   FT_LOCAL_DEF( FT_Int )
1490   ps_parser_to_fixed_array( PS_Parser  parser,
1491                             FT_Int     max_values,
1492                             FT_Fixed*  values,
1493                             FT_Int     power_ten )
1494   {
1495     ps_parser_skip_spaces( parser );
1496     return ps_tofixedarray( &parser->cursor, parser->limit,
1497                             max_values, values, power_ten );
1498   }
1499 
1500 
1501 #if 0
1502 
1503   FT_LOCAL_DEF( FT_String* )
1504   T1_ToString( PS_Parser  parser )
1505   {
1506     return ps_tostring( &parser->cursor, parser->limit, parser->memory );
1507   }
1508 
1509 
1510   FT_LOCAL_DEF( FT_Bool )
1511   T1_ToBool( PS_Parser  parser )
1512   {
1513     return ps_tobool( &parser->cursor, parser->limit );
1514   }
1515 
1516 #endif /* 0 */
1517 
1518 
1519   FT_LOCAL_DEF( void )
1520   ps_parser_init( PS_Parser  parser,
1521                   FT_Byte*   base,
1522                   FT_Byte*   limit,
1523                   FT_Memory  memory )
1524   {
1525     parser->error  = FT_Err_Ok;
1526     parser->base   = base;
1527     parser->limit  = limit;
1528     parser->cursor = base;
1529     parser->memory = memory;
1530     parser->funcs  = ps_parser_funcs;
1531   }
1532 
1533 
1534   FT_LOCAL_DEF( void )
1535   ps_parser_done( PS_Parser  parser )
1536   {
1537     FT_UNUSED( parser );
1538   }
1539 
1540 
1541   /*************************************************************************/
1542   /*************************************************************************/
1543   /*****                                                               *****/
1544   /*****                            T1 BUILDER                         *****/
1545   /*****                                                               *****/
1546   /*************************************************************************/
1547   /*************************************************************************/
1548 
1549   /**************************************************************************
1550    *
1551    * @Function:
1552    *   t1_builder_init
1553    *
1554    * @Description:
1555    *   Initializes a given glyph builder.
1556    *
1557    * @InOut:
1558    *   builder ::
1559    *     A pointer to the glyph builder to initialize.
1560    *
1561    * @Input:
1562    *   face ::
1563    *     The current face object.
1564    *
1565    *   size ::
1566    *     The current size object.
1567    *
1568    *   glyph ::
1569    *     The current glyph object.
1570    *
1571    *   hinting ::
1572    *     Whether hinting should be applied.
1573    */
1574   FT_LOCAL_DEF( void )
1575   t1_builder_init( T1_Builder    builder,
1576                    FT_Face       face,
1577                    FT_Size       size,
1578                    FT_GlyphSlot  glyph,
1579                    FT_Bool       hinting )
1580   {
1581     builder->parse_state = T1_Parse_Start;
1582     builder->load_points = 1;
1583 
1584     builder->face   = face;
1585     builder->glyph  = glyph;
1586     builder->memory = face->memory;
1587 
1588     if ( glyph )
1589     {
1590       FT_GlyphLoader  loader = glyph->internal->loader;
1591 
1592 
1593       builder->loader  = loader;
1594       builder->base    = &loader->base.outline;
1595       builder->current = &loader->current.outline;
1596       FT_GlyphLoader_Rewind( loader );
1597 
1598       builder->hints_globals = size->internal->module_data;
1599       builder->hints_funcs   = NULL;
1600 
1601       if ( hinting )
1602         builder->hints_funcs = glyph->internal->glyph_hints;
1603     }
1604 
1605     builder->pos_x = 0;
1606     builder->pos_y = 0;
1607 
1608     builder->left_bearing.x = 0;
1609     builder->left_bearing.y = 0;
1610     builder->advance.x      = 0;
1611     builder->advance.y      = 0;
1612 
1613     builder->funcs = t1_builder_funcs;
1614   }
1615 
1616 
1617   /**************************************************************************
1618    *
1619    * @Function:
1620    *   t1_builder_done
1621    *
1622    * @Description:
1623    *   Finalizes a given glyph builder.  Its contents can still be used
1624    *   after the call, but the function saves important information
1625    *   within the corresponding glyph slot.
1626    *
1627    * @Input:
1628    *   builder ::
1629    *     A pointer to the glyph builder to finalize.
1630    */
1631   FT_LOCAL_DEF( void )
1632   t1_builder_done( T1_Builder  builder )
1633   {
1634     FT_GlyphSlot  glyph = builder->glyph;
1635 
1636 
1637     if ( glyph )
1638       glyph->outline = *builder->base;
1639   }
1640 
1641 
1642   /* check that there is enough space for `count' more points */
1643   FT_LOCAL_DEF( FT_Error )
1644   t1_builder_check_points( T1_Builder  builder,
1645                            FT_Int      count )
1646   {
1647     return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
1648   }
1649 
1650 
1651   /* add a new point, do not check space */
1652   FT_LOCAL_DEF( void )
1653   t1_builder_add_point( T1_Builder  builder,
1654                         FT_Pos      x,
1655                         FT_Pos      y,
1656                         FT_Byte     flag )
1657   {
1658     FT_Outline*  outline = builder->current;
1659 
1660 
1661     if ( builder->load_points )
1662     {
1663       FT_Vector*  point   = outline->points + outline->n_points;
1664       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
1665 
1666 
1667       point->x = FIXED_TO_INT( x );
1668       point->y = FIXED_TO_INT( y );
1669       *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
1670     }
1671     outline->n_points++;
1672   }
1673 
1674 
1675   /* check space for a new on-curve point, then add it */
1676   FT_LOCAL_DEF( FT_Error )
1677   t1_builder_add_point1( T1_Builder  builder,
1678                          FT_Pos      x,
1679                          FT_Pos      y )
1680   {
1681     FT_Error  error;
1682 
1683 
1684     error = t1_builder_check_points( builder, 1 );
1685     if ( !error )
1686       t1_builder_add_point( builder, x, y, 1 );
1687 
1688     return error;
1689   }
1690 
1691 
1692   /* check space for a new contour, then add it */
1693   FT_LOCAL_DEF( FT_Error )
1694   t1_builder_add_contour( T1_Builder  builder )
1695   {
1696     FT_Outline*  outline = builder->current;
1697     FT_Error     error;
1698 
1699 
1700     /* this might happen in invalid fonts */
1701     if ( !outline )
1702     {
1703       FT_ERROR(( "t1_builder_add_contour: no outline to add points to\n" ));
1704       return FT_THROW( Invalid_File_Format );
1705     }
1706 
1707     if ( !builder->load_points )
1708     {
1709       outline->n_contours++;
1710       return FT_Err_Ok;
1711     }
1712 
1713     error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
1714     if ( !error )
1715     {
1716       if ( outline->n_contours > 0 )
1717         outline->contours[outline->n_contours - 1] =
1718           (short)( outline->n_points - 1 );
1719 
1720       outline->n_contours++;
1721     }
1722 
1723     return error;
1724   }
1725 
1726 
1727   /* if a path was begun, add its first on-curve point */
1728   FT_LOCAL_DEF( FT_Error )
1729   t1_builder_start_point( T1_Builder  builder,
1730                           FT_Pos      x,
1731                           FT_Pos      y )
1732   {
1733     FT_Error  error = FT_ERR( Invalid_File_Format );
1734 
1735 
1736     /* test whether we are building a new contour */
1737 
1738     if ( builder->parse_state == T1_Parse_Have_Path )
1739       error = FT_Err_Ok;
1740     else
1741     {
1742       builder->parse_state = T1_Parse_Have_Path;
1743       error = t1_builder_add_contour( builder );
1744       if ( !error )
1745         error = t1_builder_add_point1( builder, x, y );
1746     }
1747 
1748     return error;
1749   }
1750 
1751 
1752   /* close the current contour */
1753   FT_LOCAL_DEF( void )
1754   t1_builder_close_contour( T1_Builder  builder )
1755   {
1756     FT_Outline*  outline = builder->current;
1757     FT_Int       first;
1758 
1759 
1760     if ( !outline )
1761       return;
1762 
1763     first = outline->n_contours <= 1
1764             ? 0 : outline->contours[outline->n_contours - 2] + 1;
1765 
1766     /* in malformed fonts it can happen that a contour was started */
1767     /* but no points were added                                    */
1768     if ( outline->n_contours && first == outline->n_points )
1769     {
1770       outline->n_contours--;
1771       return;
1772     }
1773 
1774     /* We must not include the last point in the path if it */
1775     /* is located on the first point.                       */
1776     if ( outline->n_points > 1 )
1777     {
1778       FT_Vector*  p1      = outline->points + first;
1779       FT_Vector*  p2      = outline->points + outline->n_points - 1;
1780       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
1781 
1782 
1783       /* `delete' last point only if it coincides with the first */
1784       /* point and it is not a control point (which can happen). */
1785       if ( p1->x == p2->x && p1->y == p2->y )
1786         if ( *control == FT_CURVE_TAG_ON )
1787           outline->n_points--;
1788     }
1789 
1790     if ( outline->n_contours > 0 )
1791     {
1792       /* Don't add contours only consisting of one point, i.e.,  */
1793       /* check whether the first and the last point is the same. */
1794       if ( first == outline->n_points - 1 )
1795       {
1796         outline->n_contours--;
1797         outline->n_points--;
1798       }
1799       else
1800         outline->contours[outline->n_contours - 1] =
1801           (short)( outline->n_points - 1 );
1802     }
1803   }
1804 
1805 
1806   /*************************************************************************/
1807   /*************************************************************************/
1808   /*****                                                               *****/
1809   /*****                           CFF BUILDER                         *****/
1810   /*****                                                               *****/
1811   /*************************************************************************/
1812   /*************************************************************************/
1813 
1814 
1815   /**************************************************************************
1816    *
1817    * @Function:
1818    *   cff_builder_init
1819    *
1820    * @Description:
1821    *   Initializes a given glyph builder.
1822    *
1823    * @InOut:
1824    *   builder ::
1825    *     A pointer to the glyph builder to initialize.
1826    *
1827    * @Input:
1828    *   face ::
1829    *     The current face object.
1830    *
1831    *   size ::
1832    *     The current size object.
1833    *
1834    *   glyph ::
1835    *     The current glyph object.
1836    *
1837    *   hinting ::
1838    *     Whether hinting is active.
1839    */
1840   FT_LOCAL_DEF( void )
1841   cff_builder_init( CFF_Builder*   builder,
1842                     TT_Face        face,
1843                     CFF_Size       size,
1844                     CFF_GlyphSlot  glyph,
1845                     FT_Bool        hinting )
1846   {
1847     builder->path_begun  = 0;
1848     builder->load_points = 1;
1849 
1850     builder->face   = face;
1851     builder->glyph  = glyph;
1852     builder->memory = face->root.memory;
1853 
1854     if ( glyph )
1855     {
1856       FT_GlyphLoader  loader = glyph->root.internal->loader;
1857 
1858 
1859       builder->loader  = loader;
1860       builder->base    = &loader->base.outline;
1861       builder->current = &loader->current.outline;
1862       FT_GlyphLoader_Rewind( loader );
1863 
1864       builder->hints_globals = NULL;
1865       builder->hints_funcs   = NULL;
1866 
1867       if ( hinting && size )
1868       {
1869         FT_Size       ftsize   = FT_SIZE( size );
1870         CFF_Internal  internal = (CFF_Internal)ftsize->internal->module_data;
1871 
1872         if ( internal )
1873         {
1874           builder->hints_globals = (void *)internal->topfont;
1875           builder->hints_funcs   = glyph->root.internal->glyph_hints;
1876         }
1877       }
1878     }
1879 
1880     builder->pos_x = 0;
1881     builder->pos_y = 0;
1882 
1883     builder->left_bearing.x = 0;
1884     builder->left_bearing.y = 0;
1885     builder->advance.x      = 0;
1886     builder->advance.y      = 0;
1887 
1888     builder->funcs = cff_builder_funcs;
1889   }
1890 
1891 
1892   /**************************************************************************
1893    *
1894    * @Function:
1895    *   cff_builder_done
1896    *
1897    * @Description:
1898    *   Finalizes a given glyph builder.  Its contents can still be used
1899    *   after the call, but the function saves important information
1900    *   within the corresponding glyph slot.
1901    *
1902    * @Input:
1903    *   builder ::
1904    *     A pointer to the glyph builder to finalize.
1905    */
1906   FT_LOCAL_DEF( void )
1907   cff_builder_done( CFF_Builder*  builder )
1908   {
1909     CFF_GlyphSlot  glyph = builder->glyph;
1910 
1911 
1912     if ( glyph )
1913       glyph->root.outline = *builder->base;
1914   }
1915 
1916 
1917   /* check that there is enough space for `count' more points */
1918   FT_LOCAL_DEF( FT_Error )
1919   cff_check_points( CFF_Builder*  builder,
1920                     FT_Int        count )
1921   {
1922     return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
1923   }
1924 
1925 
1926   /* add a new point, do not check space */
1927   FT_LOCAL_DEF( void )
1928   cff_builder_add_point( CFF_Builder*  builder,
1929                          FT_Pos        x,
1930                          FT_Pos        y,
1931                          FT_Byte       flag )
1932   {
1933     FT_Outline*  outline = builder->current;
1934 
1935 
1936     if ( builder->load_points )
1937     {
1938       FT_Vector*  point   = outline->points + outline->n_points;
1939       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
1940 
1941 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
1942       PS_Driver  driver   = (PS_Driver)FT_FACE_DRIVER( builder->face );
1943 
1944 
1945       if ( driver->hinting_engine == FT_HINTING_FREETYPE )
1946       {
1947         point->x = x >> 16;
1948         point->y = y >> 16;
1949       }
1950       else
1951 #endif
1952       {
1953         /* cf2_decoder_parse_charstrings uses 16.16 coordinates */
1954         point->x = x >> 10;
1955         point->y = y >> 10;
1956       }
1957       *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
1958     }
1959 
1960     outline->n_points++;
1961   }
1962 
1963 
1964   /* check space for a new on-curve point, then add it */
1965   FT_LOCAL_DEF( FT_Error )
1966   cff_builder_add_point1( CFF_Builder*  builder,
1967                           FT_Pos        x,
1968                           FT_Pos        y )
1969   {
1970     FT_Error  error;
1971 
1972 
1973     error = cff_check_points( builder, 1 );
1974     if ( !error )
1975       cff_builder_add_point( builder, x, y, 1 );
1976 
1977     return error;
1978   }
1979 
1980 
1981   /* check space for a new contour, then add it */
1982   FT_LOCAL_DEF( FT_Error )
1983   cff_builder_add_contour( CFF_Builder*  builder )
1984   {
1985     FT_Outline*  outline = builder->current;
1986     FT_Error     error;
1987 
1988 
1989     if ( !builder->load_points )
1990     {
1991       outline->n_contours++;
1992       return FT_Err_Ok;
1993     }
1994 
1995     error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
1996     if ( !error )
1997     {
1998       if ( outline->n_contours > 0 )
1999         outline->contours[outline->n_contours - 1] =
2000           (short)( outline->n_points - 1 );
2001 
2002       outline->n_contours++;
2003     }
2004 
2005     return error;
2006   }
2007 
2008 
2009   /* if a path was begun, add its first on-curve point */
2010   FT_LOCAL_DEF( FT_Error )
2011   cff_builder_start_point( CFF_Builder*  builder,
2012                            FT_Pos        x,
2013                            FT_Pos        y )
2014   {
2015     FT_Error  error = FT_Err_Ok;
2016 
2017 
2018     /* test whether we are building a new contour */
2019     if ( !builder->path_begun )
2020     {
2021       builder->path_begun = 1;
2022       error = cff_builder_add_contour( builder );
2023       if ( !error )
2024         error = cff_builder_add_point1( builder, x, y );
2025     }
2026 
2027     return error;
2028   }
2029 
2030 
2031   /* close the current contour */
2032   FT_LOCAL_DEF( void )
2033   cff_builder_close_contour( CFF_Builder*  builder )
2034   {
2035     FT_Outline*  outline = builder->current;
2036     FT_Int       first;
2037 
2038 
2039     if ( !outline )
2040       return;
2041 
2042     first = outline->n_contours <= 1
2043             ? 0 : outline->contours[outline->n_contours - 2] + 1;
2044 
2045     /* in malformed fonts it can happen that a contour was started */
2046     /* but no points were added                                    */
2047     if ( outline->n_contours && first == outline->n_points )
2048     {
2049       outline->n_contours--;
2050       return;
2051     }
2052 
2053     /* We must not include the last point in the path if it */
2054     /* is located on the first point.                       */
2055     if ( outline->n_points > 1 )
2056     {
2057       FT_Vector*  p1      = outline->points + first;
2058       FT_Vector*  p2      = outline->points + outline->n_points - 1;
2059       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
2060 
2061 
2062       /* `delete' last point only if it coincides with the first    */
2063       /* point and if it is not a control point (which can happen). */
2064       if ( p1->x == p2->x && p1->y == p2->y )
2065         if ( *control == FT_CURVE_TAG_ON )
2066           outline->n_points--;
2067     }
2068 
2069     if ( outline->n_contours > 0 )
2070     {
2071       /* Don't add contours only consisting of one point, i.e., */
2072       /* check whether begin point and last point are the same. */
2073       if ( first == outline->n_points - 1 )
2074       {
2075         outline->n_contours--;
2076         outline->n_points--;
2077       }
2078       else
2079         outline->contours[outline->n_contours - 1] =
2080           (short)( outline->n_points - 1 );
2081     }
2082   }
2083 
2084 
2085   /*************************************************************************/
2086   /*************************************************************************/
2087   /*****                                                               *****/
2088   /*****                            PS BUILDER                         *****/
2089   /*****                                                               *****/
2090   /*************************************************************************/
2091   /*************************************************************************/
2092 
2093   /**************************************************************************
2094    *
2095    * @Function:
2096    *   ps_builder_init
2097    *
2098    * @Description:
2099    *   Initializes a given glyph builder.
2100    *
2101    * @InOut:
2102    *   builder ::
2103    *     A pointer to the glyph builder to initialize.
2104    *
2105    * @Input:
2106    *   face ::
2107    *     The current face object.
2108    *
2109    *   size ::
2110    *     The current size object.
2111    *
2112    *   glyph ::
2113    *     The current glyph object.
2114    *
2115    *   hinting ::
2116    *     Whether hinting should be applied.
2117    */
2118   FT_LOCAL_DEF( void )
2119   ps_builder_init( PS_Builder*  ps_builder,
2120                    void*        builder,
2121                    FT_Bool      is_t1 )
2122   {
2123     FT_ZERO( ps_builder );
2124 
2125     if ( is_t1 )
2126     {
2127       T1_Builder  t1builder = (T1_Builder)builder;
2128 
2129 
2130       ps_builder->memory  = t1builder->memory;
2131       ps_builder->face    = (FT_Face)t1builder->face;
2132       ps_builder->glyph   = (CFF_GlyphSlot)t1builder->glyph;
2133       ps_builder->loader  = t1builder->loader;
2134       ps_builder->base    = t1builder->base;
2135       ps_builder->current = t1builder->current;
2136 
2137       ps_builder->pos_x = &t1builder->pos_x;
2138       ps_builder->pos_y = &t1builder->pos_y;
2139 
2140       ps_builder->left_bearing = &t1builder->left_bearing;
2141       ps_builder->advance      = &t1builder->advance;
2142 
2143       ps_builder->bbox        = &t1builder->bbox;
2144       ps_builder->path_begun  = 0;
2145       ps_builder->load_points = t1builder->load_points;
2146       ps_builder->no_recurse  = t1builder->no_recurse;
2147 
2148       ps_builder->metrics_only = t1builder->metrics_only;
2149     }
2150     else
2151     {
2152       CFF_Builder*  cffbuilder = (CFF_Builder*)builder;
2153 
2154 
2155       ps_builder->memory  = cffbuilder->memory;
2156       ps_builder->face    = (FT_Face)cffbuilder->face;
2157       ps_builder->glyph   = cffbuilder->glyph;
2158       ps_builder->loader  = cffbuilder->loader;
2159       ps_builder->base    = cffbuilder->base;
2160       ps_builder->current = cffbuilder->current;
2161 
2162       ps_builder->pos_x = &cffbuilder->pos_x;
2163       ps_builder->pos_y = &cffbuilder->pos_y;
2164 
2165       ps_builder->left_bearing = &cffbuilder->left_bearing;
2166       ps_builder->advance      = &cffbuilder->advance;
2167 
2168       ps_builder->bbox        = &cffbuilder->bbox;
2169       ps_builder->path_begun  = cffbuilder->path_begun;
2170       ps_builder->load_points = cffbuilder->load_points;
2171       ps_builder->no_recurse  = cffbuilder->no_recurse;
2172 
2173       ps_builder->metrics_only = cffbuilder->metrics_only;
2174     }
2175 
2176     ps_builder->is_t1 = is_t1;
2177     ps_builder->funcs = ps_builder_funcs;
2178   }
2179 
2180 
2181   /**************************************************************************
2182    *
2183    * @Function:
2184    *   ps_builder_done
2185    *
2186    * @Description:
2187    *   Finalizes a given glyph builder.  Its contents can still be used
2188    *   after the call, but the function saves important information
2189    *   within the corresponding glyph slot.
2190    *
2191    * @Input:
2192    *   builder ::
2193    *     A pointer to the glyph builder to finalize.
2194    */
2195   FT_LOCAL_DEF( void )
2196   ps_builder_done( PS_Builder*  builder )
2197   {
2198     CFF_GlyphSlot  glyph = builder->glyph;
2199 
2200 
2201     if ( glyph )
2202       glyph->root.outline = *builder->base;
2203   }
2204 
2205 
2206   /* check that there is enough space for `count' more points */
2207   FT_LOCAL_DEF( FT_Error )
2208   ps_builder_check_points( PS_Builder*  builder,
2209                            FT_Int       count )
2210   {
2211     return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
2212   }
2213 
2214 
2215   /* add a new point, do not check space */
2216   FT_LOCAL_DEF( void )
2217   ps_builder_add_point( PS_Builder*  builder,
2218                         FT_Pos       x,
2219                         FT_Pos       y,
2220                         FT_Byte      flag )
2221   {
2222     FT_Outline*  outline = builder->current;
2223 
2224 
2225     if ( builder->load_points )
2226     {
2227       FT_Vector*  point   = outline->points + outline->n_points;
2228       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
2229 
2230 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
2231       PS_Driver  driver   = (PS_Driver)FT_FACE_DRIVER( builder->face );
2232 
2233 
2234       if ( !builder->is_t1 &&
2235            driver->hinting_engine == FT_HINTING_FREETYPE )
2236       {
2237         point->x = x >> 16;
2238         point->y = y >> 16;
2239       }
2240       else
2241 #endif
2242 #ifdef T1_CONFIG_OPTION_OLD_ENGINE
2243 #ifndef CFF_CONFIG_OPTION_OLD_ENGINE
2244       PS_Driver  driver   = (PS_Driver)FT_FACE_DRIVER( builder->face );
2245 #endif
2246       if ( builder->is_t1 &&
2247            driver->hinting_engine == FT_HINTING_FREETYPE )
2248       {
2249         point->x = FIXED_TO_INT( x );
2250         point->y = FIXED_TO_INT( y );
2251       }
2252       else
2253 #endif
2254       {
2255         /* cf2_decoder_parse_charstrings uses 16.16 coordinates */
2256         point->x = x >> 10;
2257         point->y = y >> 10;
2258       }
2259       *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
2260     }
2261     outline->n_points++;
2262   }
2263 
2264 
2265   /* check space for a new on-curve point, then add it */
2266   FT_LOCAL_DEF( FT_Error )
2267   ps_builder_add_point1( PS_Builder*  builder,
2268                          FT_Pos       x,
2269                          FT_Pos       y )
2270   {
2271     FT_Error  error;
2272 
2273 
2274     error = ps_builder_check_points( builder, 1 );
2275     if ( !error )
2276       ps_builder_add_point( builder, x, y, 1 );
2277 
2278     return error;
2279   }
2280 
2281 
2282   /* check space for a new contour, then add it */
2283   FT_LOCAL_DEF( FT_Error )
2284   ps_builder_add_contour( PS_Builder*  builder )
2285   {
2286     FT_Outline*  outline = builder->current;
2287     FT_Error     error;
2288 
2289 
2290     /* this might happen in invalid fonts */
2291     if ( !outline )
2292     {
2293       FT_ERROR(( "ps_builder_add_contour: no outline to add points to\n" ));
2294       return FT_THROW( Invalid_File_Format );
2295     }
2296 
2297     if ( !builder->load_points )
2298     {
2299       outline->n_contours++;
2300       return FT_Err_Ok;
2301     }
2302 
2303     error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
2304     if ( !error )
2305     {
2306       if ( outline->n_contours > 0 )
2307         outline->contours[outline->n_contours - 1] =
2308           (short)( outline->n_points - 1 );
2309 
2310       outline->n_contours++;
2311     }
2312 
2313     return error;
2314   }
2315 
2316 
2317   /* if a path was begun, add its first on-curve point */
2318   FT_LOCAL_DEF( FT_Error )
2319   ps_builder_start_point( PS_Builder*  builder,
2320                           FT_Pos       x,
2321                           FT_Pos       y )
2322   {
2323     FT_Error  error = FT_Err_Ok;
2324 
2325 
2326     /* test whether we are building a new contour */
2327     if ( !builder->path_begun )
2328     {
2329       builder->path_begun = 1;
2330       error = ps_builder_add_contour( builder );
2331       if ( !error )
2332         error = ps_builder_add_point1( builder, x, y );
2333     }
2334 
2335     return error;
2336   }
2337 
2338 
2339   /* close the current contour */
2340   FT_LOCAL_DEF( void )
2341   ps_builder_close_contour( PS_Builder*  builder )
2342   {
2343     FT_Outline*  outline = builder->current;
2344     FT_Int       first;
2345 
2346 
2347     if ( !outline )
2348       return;
2349 
2350     first = outline->n_contours <= 1
2351             ? 0 : outline->contours[outline->n_contours - 2] + 1;
2352 
2353     /* in malformed fonts it can happen that a contour was started */
2354     /* but no points were added                                    */
2355     if ( outline->n_contours && first == outline->n_points )
2356     {
2357       outline->n_contours--;
2358       return;
2359     }
2360 
2361     /* We must not include the last point in the path if it */
2362     /* is located on the first point.                       */
2363     if ( outline->n_points > 1 )
2364     {
2365       FT_Vector*  p1      = outline->points + first;
2366       FT_Vector*  p2      = outline->points + outline->n_points - 1;
2367       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
2368 
2369 
2370       /* `delete' last point only if it coincides with the first */
2371       /* point and it is not a control point (which can happen). */
2372       if ( p1->x == p2->x && p1->y == p2->y )
2373         if ( *control == FT_CURVE_TAG_ON )
2374           outline->n_points--;
2375     }
2376 
2377     if ( outline->n_contours > 0 )
2378     {
2379       /* Don't add contours only consisting of one point, i.e.,  */
2380       /* check whether the first and the last point is the same. */
2381       if ( first == outline->n_points - 1 )
2382       {
2383         outline->n_contours--;
2384         outline->n_points--;
2385       }
2386       else
2387         outline->contours[outline->n_contours - 1] =
2388           (short)( outline->n_points - 1 );
2389     }
2390   }
2391 
2392 
2393   /*************************************************************************/
2394   /*************************************************************************/
2395   /*****                                                               *****/
2396   /*****                            OTHER                              *****/
2397   /*****                                                               *****/
2398   /*************************************************************************/
2399   /*************************************************************************/
2400 
2401 
2402   /**************************************************************************
2403    *
2404    * @Function:
2405    *   ps_decoder_init
2406    *
2407    * @Description:
2408    *   Creates a wrapper decoder for use in the combined
2409    *   Type 1 / CFF interpreter.
2410    *
2411    * @InOut:
2412    *   ps_decoder ::
2413    *     A pointer to the decoder to initialize.
2414    *
2415    * @Input:
2416    *   decoder ::
2417    *     A pointer to the original decoder.
2418    *
2419    *   is_t1 ::
2420    *     Flag indicating Type 1 or CFF
2421    */
2422   FT_LOCAL_DEF( void )
2423   ps_decoder_init( PS_Decoder*  ps_decoder,
2424                    void*        decoder,
2425                    FT_Bool      is_t1 )
2426   {
2427     FT_ZERO( ps_decoder );
2428 
2429     if ( is_t1 )
2430     {
2431       T1_Decoder  t1_decoder = (T1_Decoder)decoder;
2432 
2433 
2434       ps_builder_init( &ps_decoder->builder,
2435                        &t1_decoder->builder,
2436                        is_t1 );
2437 
2438       ps_decoder->cf2_instance = &t1_decoder->cf2_instance;
2439       ps_decoder->psnames      = t1_decoder->psnames;
2440 
2441       ps_decoder->num_glyphs  = t1_decoder->num_glyphs;
2442       ps_decoder->glyph_names = t1_decoder->glyph_names;
2443       ps_decoder->hint_mode   = t1_decoder->hint_mode;
2444       ps_decoder->blend       = t1_decoder->blend;
2445 
2446       ps_decoder->num_locals  = (FT_UInt)t1_decoder->num_subrs;
2447       ps_decoder->locals      = t1_decoder->subrs;
2448       ps_decoder->locals_len  = t1_decoder->subrs_len;
2449       ps_decoder->locals_hash = t1_decoder->subrs_hash;
2450 
2451       ps_decoder->buildchar     = t1_decoder->buildchar;
2452       ps_decoder->len_buildchar = t1_decoder->len_buildchar;
2453 
2454       ps_decoder->lenIV = t1_decoder->lenIV;
2455     }
2456     else
2457     {
2458       CFF_Decoder*  cff_decoder = (CFF_Decoder*)decoder;
2459 
2460 
2461       ps_builder_init( &ps_decoder->builder,
2462                        &cff_decoder->builder,
2463                        is_t1 );
2464 
2465       ps_decoder->cff             = cff_decoder->cff;
2466       ps_decoder->cf2_instance    = &cff_decoder->cff->cf2_instance;
2467       ps_decoder->current_subfont = cff_decoder->current_subfont;
2468 
2469       ps_decoder->num_globals  = cff_decoder->num_globals;
2470       ps_decoder->globals      = cff_decoder->globals;
2471       ps_decoder->globals_bias = cff_decoder->globals_bias;
2472       ps_decoder->num_locals   = cff_decoder->num_locals;
2473       ps_decoder->locals       = cff_decoder->locals;
2474       ps_decoder->locals_bias  = cff_decoder->locals_bias;
2475 
2476       ps_decoder->glyph_width   = &cff_decoder->glyph_width;
2477       ps_decoder->width_only    = cff_decoder->width_only;
2478 
2479       ps_decoder->hint_mode = cff_decoder->hint_mode;
2480 
2481       ps_decoder->get_glyph_callback  = cff_decoder->get_glyph_callback;
2482       ps_decoder->free_glyph_callback = cff_decoder->free_glyph_callback;
2483     }
2484   }
2485 
2486 
2487   /* Synthesize a SubFont object for Type 1 fonts, for use in the  */
2488   /* new interpreter to access Private dict data.                  */
2489   FT_LOCAL_DEF( void )
2490   t1_make_subfont( FT_Face      face,
2491                    PS_Private   priv,
2492                    CFF_SubFont  subfont )
2493   {
2494     CFF_Private  cpriv = &subfont->private_dict;
2495     FT_UInt      n, count;
2496 
2497 
2498     FT_ZERO( subfont );
2499     FT_ZERO( cpriv );
2500 
2501     count = cpriv->num_blue_values = priv->num_blue_values;
2502     for ( n = 0; n < count; n++ )
2503       cpriv->blue_values[n] = (FT_Pos)priv->blue_values[n];
2504 
2505     count = cpriv->num_other_blues = priv->num_other_blues;
2506     for ( n = 0; n < count; n++ )
2507       cpriv->other_blues[n] = (FT_Pos)priv->other_blues[n];
2508 
2509     count = cpriv->num_family_blues = priv->num_family_blues;
2510     for ( n = 0; n < count; n++ )
2511       cpriv->family_blues[n] = (FT_Pos)priv->family_blues[n];
2512 
2513     count = cpriv->num_family_other_blues = priv->num_family_other_blues;
2514     for ( n = 0; n < count; n++ )
2515       cpriv->family_other_blues[n] = (FT_Pos)priv->family_other_blues[n];
2516 
2517     cpriv->blue_scale = priv->blue_scale;
2518     cpriv->blue_shift = (FT_Pos)priv->blue_shift;
2519     cpriv->blue_fuzz  = (FT_Pos)priv->blue_fuzz;
2520 
2521     cpriv->standard_width  = (FT_Pos)priv->standard_width[0];
2522     cpriv->standard_height = (FT_Pos)priv->standard_height[0];
2523 
2524     count = cpriv->num_snap_widths = priv->num_snap_widths;
2525     for ( n = 0; n < count; n++ )
2526       cpriv->snap_widths[n] = (FT_Pos)priv->snap_widths[n];
2527 
2528     count = cpriv->num_snap_heights = priv->num_snap_heights;
2529     for ( n = 0; n < count; n++ )
2530       cpriv->snap_heights[n] = (FT_Pos)priv->snap_heights[n];
2531 
2532     cpriv->force_bold       = priv->force_bold;
2533     cpriv->lenIV            = priv->lenIV;
2534     cpriv->language_group   = priv->language_group;
2535     cpriv->expansion_factor = priv->expansion_factor;
2536 
2537     cpriv->subfont = subfont;
2538 
2539 
2540     /* Initialize the random number generator. */
2541     if ( face->internal->random_seed != -1 )
2542     {
2543       /* If we have a face-specific seed, use it.    */
2544       /* If non-zero, update it to a positive value. */
2545       subfont->random = (FT_UInt32)face->internal->random_seed;
2546       if ( face->internal->random_seed )
2547       {
2548         do
2549         {
2550           face->internal->random_seed = (FT_Int32)cff_random(
2551             (FT_UInt32)face->internal->random_seed );
2552 
2553         } while ( face->internal->random_seed < 0 );
2554       }
2555     }
2556     if ( !subfont->random )
2557     {
2558       FT_UInt32  seed;
2559 
2560 
2561       /* compute random seed from some memory addresses */
2562       seed = (FT_UInt32)( (FT_Offset)(char*)&seed    ^
2563                           (FT_Offset)(char*)&face    ^
2564                           (FT_Offset)(char*)&subfont );
2565       seed = seed ^ ( seed >> 10 ) ^ ( seed >> 20 );
2566       if ( seed == 0 )
2567         seed = 0x7384;
2568 
2569       subfont->random = seed;
2570     }
2571   }
2572 
2573 
2574   FT_LOCAL_DEF( void )
2575   t1_decrypt( FT_Byte*   buffer,
2576               FT_Offset  length,
2577               FT_UShort  seed )
2578   {
2579     PS_Conv_EexecDecode( &buffer,
2580                          buffer + length,
2581                          buffer,
2582                          length,
2583                          &seed );
2584   }
2585 
2586 
2587   FT_LOCAL_DEF( FT_UInt32 )
2588   cff_random( FT_UInt32  r )
2589   {
2590     /* a 32bit version of the `xorshift' algorithm */
2591     r ^= r << 13;
2592     r ^= r >> 17;
2593     r ^= r << 5;
2594 
2595     return r;
2596   }
2597 
2598 
2599 /* END */