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