Home | History | Annotate | Download | only in psaux
      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 */
   2534