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