Home | History | Annotate | Download | only in psaux
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  psobjs.c                                                               */
      4 /*                                                                         */
      5 /*    Auxiliary functions for PostScript fonts (body).                     */
      6 /*                                                                         */
      7 /*  Copyright 1996-2013 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 
     24 #include "psobjs.h"
     25 #include "psconv.h"
     26 
     27 #include "psauxerr.h"
     28 
     29 
     30   /*************************************************************************/
     31   /*                                                                       */
     32   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
     33   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
     34   /* messages during execution.                                            */
     35   /*                                                                       */
     36 #undef  FT_COMPONENT
     37 #define FT_COMPONENT  trace_psobjs
     38 
     39 
     40   /*************************************************************************/
     41   /*************************************************************************/
     42   /*****                                                               *****/
     43   /*****                             PS_TABLE                          *****/
     44   /*****                                                               *****/
     45   /*************************************************************************/
     46   /*************************************************************************/
     47 
     48   /*************************************************************************/
     49   /*                                                                       */
     50   /* <Function>                                                            */
     51   /*    ps_table_new                                                       */
     52   /*                                                                       */
     53   /* <Description>                                                         */
     54   /*    Initializes a PS_Table.                                            */
     55   /*                                                                       */
     56   /* <InOut>                                                               */
     57   /*    table  :: The address of the target table.                         */
     58   /*                                                                       */
     59   /* <Input>                                                               */
     60   /*    count  :: The table size = the maximum number of elements.         */
     61   /*                                                                       */
     62   /*    memory :: The memory object to use for all subsequent              */
     63   /*              reallocations.                                           */
     64   /*                                                                       */
     65   /* <Return>                                                              */
     66   /*    FreeType error code.  0 means success.                             */
     67   /*                                                                       */
     68   FT_LOCAL_DEF( FT_Error )
     69   ps_table_new( PS_Table   table,
     70                 FT_Int     count,
     71                 FT_Memory  memory )
     72   {
     73     FT_Error  error;
     74 
     75 
     76     table->memory = memory;
     77     if ( FT_NEW_ARRAY( table->elements, count ) ||
     78          FT_NEW_ARRAY( table->lengths,  count ) )
     79       goto Exit;
     80 
     81     table->max_elems = count;
     82     table->init      = 0xDEADBEEFUL;
     83     table->num_elems = 0;
     84     table->block     = 0;
     85     table->capacity  = 0;
     86     table->cursor    = 0;
     87 
     88     *(PS_Table_FuncsRec*)&table->funcs = ps_table_funcs;
     89 
     90   Exit:
     91     if ( error )
     92       FT_FREE( table->elements );
     93 
     94     return error;
     95   }
     96 
     97 
     98   static void
     99   shift_elements( PS_Table  table,
    100                   FT_Byte*  old_base )
    101   {
    102     FT_PtrDist  delta  = table->block - old_base;
    103     FT_Byte**   offset = table->elements;
    104     FT_Byte**   limit  = offset + table->max_elems;
    105 
    106 
    107     for ( ; offset < limit; offset++ )
    108     {
    109       if ( offset[0] )
    110         offset[0] += delta;
    111     }
    112   }
    113 
    114 
    115   static FT_Error
    116   reallocate_t1_table( PS_Table   table,
    117                        FT_Offset  new_size )
    118   {
    119     FT_Memory  memory   = table->memory;
    120     FT_Byte*   old_base = table->block;
    121     FT_Error   error;
    122 
    123 
    124     /* allocate new base block */
    125     if ( FT_ALLOC( table->block, new_size ) )
    126     {
    127       table->block = old_base;
    128       return error;
    129     }
    130 
    131     /* copy elements and shift offsets */
    132     if ( old_base )
    133     {
    134       FT_MEM_COPY( table->block, old_base, table->capacity );
    135       shift_elements( table, old_base );
    136       FT_FREE( old_base );
    137     }
    138 
    139     table->capacity = new_size;
    140 
    141     return FT_Err_Ok;
    142   }
    143 
    144 
    145   /*************************************************************************/
    146   /*                                                                       */
    147   /* <Function>                                                            */
    148   /*    ps_table_add                                                       */
    149   /*                                                                       */
    150   /* <Description>                                                         */
    151   /*    Adds an object to a PS_Table, possibly growing its memory block.   */
    152   /*                                                                       */
    153   /* <InOut>                                                               */
    154   /*    table  :: The target table.                                        */
    155   /*                                                                       */
    156   /* <Input>                                                               */
    157   /*    idx    :: The index of the object in the table.                    */
    158   /*                                                                       */
    159   /*    object :: The address of the object to copy in memory.             */
    160   /*                                                                       */
    161   /*    length :: The length in bytes of the source object.                */
    162   /*                                                                       */
    163   /* <Return>                                                              */
    164   /*    FreeType error code.  0 means success.  An error is returned if a  */
    165   /*    reallocation fails.                                                */
    166   /*                                                                       */
    167   FT_LOCAL_DEF( FT_Error )
    168   ps_table_add( PS_Table    table,
    169                 FT_Int      idx,
    170                 void*       object,
    171                 FT_PtrDist  length )
    172   {
    173     if ( idx < 0 || idx >= table->max_elems )
    174     {
    175       FT_ERROR(( "ps_table_add: invalid index\n" ));
    176       return FT_THROW( Invalid_Argument );
    177     }
    178 
    179     if ( length < 0 )
    180     {
    181       FT_ERROR(( "ps_table_add: invalid length\n" ));
    182       return FT_THROW( Invalid_Argument );
    183     }
    184 
    185     /* grow the base block if needed */
    186     if ( table->cursor + length > table->capacity )
    187     {
    188       FT_Error    error;
    189       FT_Offset   new_size = table->capacity;
    190       FT_PtrDist  in_offset;
    191 
    192 
    193       in_offset = (FT_Byte*)object - table->block;
    194       if ( in_offset < 0 || (FT_Offset)in_offset >= table->capacity )
    195         in_offset = -1;
    196 
    197       while ( new_size < table->cursor + length )
    198       {
    199         /* increase size by 25% and round up to the nearest multiple
    200            of 1024 */
    201         new_size += ( new_size >> 2 ) + 1;
    202         new_size  = FT_PAD_CEIL( new_size, 1024 );
    203       }
    204 
    205       error = reallocate_t1_table( table, new_size );
    206       if ( error )
    207         return error;
    208 
    209       if ( in_offset >= 0 )
    210         object = table->block + in_offset;
    211     }
    212 
    213     /* add the object to the base block and adjust offset */
    214     table->elements[idx] = table->block + table->cursor;
    215     table->lengths [idx] = length;
    216     FT_MEM_COPY( table->block + table->cursor, object, length );
    217 
    218     table->cursor += length;
    219     return FT_Err_Ok;
    220   }
    221 
    222 
    223   /*************************************************************************/
    224   /*                                                                       */
    225   /* <Function>                                                            */
    226   /*    ps_table_done                                                      */
    227   /*                                                                       */
    228   /* <Description>                                                         */
    229   /*    Finalizes a PS_TableRec (i.e., reallocate it to its current        */
    230   /*    cursor).                                                           */
    231   /*                                                                       */
    232   /* <InOut>                                                               */
    233   /*    table :: The target table.                                         */
    234   /*                                                                       */
    235   /* <Note>                                                                */
    236   /*    This function does NOT release the heap's memory block.  It is up  */
    237   /*    to the caller to clean it, or reference it in its own structures.  */
    238   /*                                                                       */
    239   FT_LOCAL_DEF( void )
    240   ps_table_done( PS_Table  table )
    241   {
    242     FT_Memory  memory = table->memory;
    243     FT_Error   error;
    244     FT_Byte*   old_base = table->block;
    245 
    246 
    247     /* should never fail, because rec.cursor <= rec.size */
    248     if ( !old_base )
    249       return;
    250 
    251     if ( FT_ALLOC( table->block, table->cursor ) )
    252       return;
    253     FT_MEM_COPY( table->block, old_base, table->cursor );
    254     shift_elements( table, old_base );
    255 
    256     table->capacity = table->cursor;
    257     FT_FREE( old_base );
    258 
    259     FT_UNUSED( error );
    260   }
    261 
    262 
    263   FT_LOCAL_DEF( void )
    264   ps_table_release( PS_Table  table )
    265   {
    266     FT_Memory  memory = table->memory;
    267 
    268 
    269     if ( (FT_ULong)table->init == 0xDEADBEEFUL )
    270     {
    271       FT_FREE( table->block );
    272       FT_FREE( table->elements );
    273       FT_FREE( table->lengths );
    274       table->init = 0;
    275     }
    276   }
    277 
    278 
    279   /*************************************************************************/
    280   /*************************************************************************/
    281   /*****                                                               *****/
    282   /*****                            T1 PARSER                          *****/
    283   /*****                                                               *****/
    284   /*************************************************************************/
    285   /*************************************************************************/
    286 
    287 
    288   /* first character must be already part of the comment */
    289 
    290   static void
    291   skip_comment( FT_Byte*  *acur,
    292                 FT_Byte*   limit )
    293   {
    294     FT_Byte*  cur = *acur;
    295 
    296 
    297     while ( cur < limit )
    298     {
    299       if ( IS_PS_NEWLINE( *cur ) )
    300         break;
    301       cur++;
    302     }
    303 
    304     *acur = cur;
    305   }
    306 
    307 
    308   static void
    309   skip_spaces( FT_Byte*  *acur,
    310                FT_Byte*   limit )
    311   {
    312     FT_Byte*  cur = *acur;
    313 
    314 
    315     while ( cur < limit )
    316     {
    317       if ( !IS_PS_SPACE( *cur ) )
    318       {
    319         if ( *cur == '%' )
    320           /* According to the PLRM, a comment is equal to a space. */
    321           skip_comment( &cur, limit );
    322         else
    323           break;
    324       }
    325       cur++;
    326     }
    327 
    328     *acur = cur;
    329   }
    330 
    331 
    332 #define IS_OCTAL_DIGIT( c ) ( '0' <= (c) && (c) <= '7' )
    333 
    334 
    335   /* first character must be `(';                               */
    336   /* *acur is positioned at the character after the closing `)' */
    337 
    338   static FT_Error
    339   skip_literal_string( FT_Byte*  *acur,
    340                        FT_Byte*   limit )
    341   {
    342     FT_Byte*      cur   = *acur;
    343     FT_Int        embed = 0;
    344     FT_Error      error = FT_ERR( Invalid_File_Format );
    345     unsigned int  i;
    346 
    347 
    348     while ( cur < limit )
    349     {
    350       FT_Byte  c = *cur;
    351 
    352 
    353       ++cur;
    354 
    355       if ( c == '\\' )
    356       {
    357         /* Red Book 3rd ed., section `Literal Text Strings', p. 29:     */
    358         /* A backslash can introduce three different types              */
    359         /* of escape sequences:                                         */
    360         /*   - a special escaped char like \r, \n, etc.                 */
    361         /*   - a one-, two-, or three-digit octal number                */
    362         /*   - none of the above in which case the backslash is ignored */
    363 
    364         if ( cur == limit )
    365           /* error (or to be ignored?) */
    366           break;
    367 
    368         switch ( *cur )
    369         {
    370           /* skip `special' escape */
    371         case 'n':
    372         case 'r':
    373         case 't':
    374         case 'b':
    375         case 'f':
    376         case '\\':
    377         case '(':
    378         case ')':
    379           ++cur;
    380           break;
    381 
    382         default:
    383           /* skip octal escape or ignore backslash */
    384           for ( i = 0; i < 3 && cur < limit; ++i )
    385           {
    386             if ( !IS_OCTAL_DIGIT( *cur ) )
    387               break;
    388 
    389             ++cur;
    390           }
    391         }
    392       }
    393       else if ( c == '(' )
    394         embed++;
    395       else if ( c == ')' )
    396       {
    397         embed--;
    398         if ( embed == 0 )
    399         {
    400           error = FT_Err_Ok;
    401           break;
    402         }
    403       }
    404     }
    405 
    406     *acur = cur;
    407 
    408     return error;
    409   }
    410 
    411 
    412   /* first character must be `<' */
    413 
    414   static FT_Error
    415   skip_string( FT_Byte*  *acur,
    416                FT_Byte*   limit )
    417   {
    418     FT_Byte*  cur = *acur;
    419     FT_Error  err =  FT_Err_Ok;
    420 
    421 
    422     while ( ++cur < limit )
    423     {
    424       /* All whitespace characters are ignored. */
    425       skip_spaces( &cur, limit );
    426       if ( cur >= limit )
    427         break;
    428 
    429       if ( !IS_PS_XDIGIT( *cur ) )
    430         break;
    431     }
    432 
    433     if ( cur < limit && *cur != '>' )
    434     {
    435       FT_ERROR(( "skip_string: missing closing delimiter `>'\n" ));
    436       err = FT_THROW( Invalid_File_Format );
    437     }
    438     else
    439       cur++;
    440 
    441     *acur = cur;
    442     return err;
    443   }
    444 
    445 
    446   /* first character must be the opening brace that */
    447   /* starts the procedure                           */
    448 
    449   /* NB: [ and ] need not match:                    */
    450   /* `/foo {[} def' is a valid PostScript fragment, */
    451   /* even within a Type1 font                       */
    452 
    453   static FT_Error
    454   skip_procedure( FT_Byte*  *acur,
    455                   FT_Byte*   limit )
    456   {
    457     FT_Byte*  cur;
    458     FT_Int    embed = 0;
    459     FT_Error  error = FT_Err_Ok;
    460 
    461 
    462     FT_ASSERT( **acur == '{' );
    463 
    464     for ( cur = *acur; cur < limit && error == FT_Err_Ok; ++cur )
    465     {
    466       switch ( *cur )
    467       {
    468       case '{':
    469         ++embed;
    470         break;
    471 
    472       case '}':
    473         --embed;
    474         if ( embed == 0 )
    475         {
    476           ++cur;
    477           goto end;
    478         }
    479         break;
    480 
    481       case '(':
    482         error = skip_literal_string( &cur, limit );
    483         break;
    484 
    485       case '<':
    486         error = skip_string( &cur, limit );
    487         break;
    488 
    489       case '%':
    490         skip_comment( &cur, limit );
    491         break;
    492       }
    493     }
    494 
    495   end:
    496     if ( embed != 0 )
    497       error = FT_THROW( Invalid_File_Format );
    498 
    499     *acur = cur;
    500 
    501     return error;
    502   }
    503 
    504 
    505   /***********************************************************************/
    506   /*                                                                     */
    507   /* All exported parsing routines handle leading whitespace and stop at */
    508   /* the first character which isn't part of the just handled token.     */
    509   /*                                                                     */
    510   /***********************************************************************/
    511 
    512 
    513   FT_LOCAL_DEF( void )
    514   ps_parser_skip_PS_token( PS_Parser  parser )
    515   {
    516     /* Note: PostScript allows any non-delimiting, non-whitespace        */
    517     /*       character in a name (PS Ref Manual, 3rd ed, p31).           */
    518     /*       PostScript delimiters are (, ), <, >, [, ], {, }, /, and %. */
    519 
    520     FT_Byte*  cur   = parser->cursor;
    521     FT_Byte*  limit = parser->limit;
    522     FT_Error  error = FT_Err_Ok;
    523 
    524 
    525     skip_spaces( &cur, limit );             /* this also skips comments */
    526     if ( cur >= limit )
    527       goto Exit;
    528 
    529     /* self-delimiting, single-character tokens */
    530     if ( *cur == '[' || *cur == ']' )
    531     {
    532       cur++;
    533       goto Exit;
    534     }
    535 
    536     /* skip balanced expressions (procedures and strings) */
    537 
    538     if ( *cur == '{' )                              /* {...} */
    539     {
    540       error = skip_procedure( &cur, limit );
    541       goto Exit;
    542     }
    543 
    544     if ( *cur == '(' )                              /* (...) */
    545     {
    546       error = skip_literal_string( &cur, limit );
    547       goto Exit;
    548     }
    549 
    550     if ( *cur == '<' )                              /* <...> */
    551     {
    552       if ( cur + 1 < limit && *(cur + 1) == '<' )   /* << */
    553       {
    554         cur++;
    555         cur++;
    556       }
    557       else
    558         error = skip_string( &cur, limit );
    559 
    560       goto Exit;
    561     }
    562 
    563     if ( *cur == '>' )
    564     {
    565       cur++;
    566       if ( cur >= limit || *cur != '>' )             /* >> */
    567       {
    568         FT_ERROR(( "ps_parser_skip_PS_token:"
    569                    " unexpected closing delimiter `>'\n" ));
    570         error = FT_THROW( Invalid_File_Format );
    571         goto Exit;
    572       }
    573       cur++;
    574       goto Exit;
    575     }
    576 
    577     if ( *cur == '/' )
    578       cur++;
    579 
    580     /* anything else */
    581     while ( cur < limit )
    582     {
    583       /* *cur might be invalid (e.g., ')' or '}'), but this   */
    584       /* is handled by the test `cur == parser->cursor' below */
    585       if ( IS_PS_DELIM( *cur ) )
    586         break;
    587 
    588       cur++;
    589     }
    590 
    591   Exit:
    592     if ( cur < limit && cur == parser->cursor )
    593     {
    594       FT_ERROR(( "ps_parser_skip_PS_token:"
    595                  " current token is `%c' which is self-delimiting\n"
    596                  "                        "
    597                  " but invalid at this point\n",
    598                  *cur ));
    599 
    600       error = FT_THROW( Invalid_File_Format );
    601     }
    602 
    603     parser->error  = error;
    604     parser->cursor = cur;
    605   }
    606 
    607 
    608   FT_LOCAL_DEF( void )
    609   ps_parser_skip_spaces( PS_Parser  parser )
    610   {
    611     skip_spaces( &parser->cursor, parser->limit );
    612   }
    613 
    614 
    615   /* `token' here means either something between balanced delimiters */
    616   /* or the next token; the delimiters are not removed.              */
    617 
    618   FT_LOCAL_DEF( void )
    619   ps_parser_to_token( PS_Parser  parser,
    620                       T1_Token   token )
    621   {
    622     FT_Byte*  cur;
    623     FT_Byte*  limit;
    624     FT_Int    embed;
    625 
    626 
    627     token->type  = T1_TOKEN_TYPE_NONE;
    628     token->start = 0;
    629     token->limit = 0;
    630 
    631     /* first of all, skip leading whitespace */
    632     ps_parser_skip_spaces( parser );
    633 
    634     cur   = parser->cursor;
    635     limit = parser->limit;
    636 
    637     if ( cur >= limit )
    638       return;
    639 
    640     switch ( *cur )
    641     {
    642       /************* check for literal string *****************/
    643     case '(':
    644       token->type  = T1_TOKEN_TYPE_STRING;
    645       token->start = cur;
    646 
    647       if ( skip_literal_string( &cur, limit ) == FT_Err_Ok )
    648         token->limit = cur;
    649       break;
    650 
    651       /************* check for programs/array *****************/
    652     case '{':
    653       token->type  = T1_TOKEN_TYPE_ARRAY;
    654       token->start = cur;
    655 
    656       if ( skip_procedure( &cur, limit ) == FT_Err_Ok )
    657         token->limit = cur;
    658       break;
    659 
    660       /************* check for table/array ********************/
    661       /* XXX: in theory we should also look for "<<"          */
    662       /*      since this is semantically equivalent to "[";   */
    663       /*      in practice it doesn't matter (?)               */
    664     case '[':
    665       token->type  = T1_TOKEN_TYPE_ARRAY;
    666       embed        = 1;
    667       token->start = cur++;
    668 
    669       /* we need this to catch `[ ]' */
    670       parser->cursor = cur;
    671       ps_parser_skip_spaces( parser );
    672       cur = parser->cursor;
    673 
    674       while ( cur < limit && !parser->error )
    675       {
    676         /* XXX: this is wrong because it does not      */
    677         /*      skip comments, procedures, and strings */
    678         if ( *cur == '[' )
    679           embed++;
    680         else if ( *cur == ']' )
    681         {
    682           embed--;
    683           if ( embed <= 0 )
    684           {
    685             token->limit = ++cur;
    686             break;
    687           }
    688         }
    689 
    690         parser->cursor = cur;
    691         ps_parser_skip_PS_token( parser );
    692         /* we need this to catch `[XXX ]' */
    693         ps_parser_skip_spaces  ( parser );
    694         cur = parser->cursor;
    695       }
    696       break;
    697 
    698       /* ************ otherwise, it is any token **************/
    699     default:
    700       token->start = cur;
    701       token->type  = ( *cur == '/' ? T1_TOKEN_TYPE_KEY : T1_TOKEN_TYPE_ANY );
    702       ps_parser_skip_PS_token( parser );
    703       cur = parser->cursor;
    704       if ( !parser->error )
    705         token->limit = cur;
    706     }
    707 
    708     if ( !token->limit )
    709     {
    710       token->start = 0;
    711       token->type  = T1_TOKEN_TYPE_NONE;
    712     }
    713 
    714     parser->cursor = cur;
    715   }
    716 
    717 
    718   /* NB: `tokens' can be NULL if we only want to count */
    719   /* the number of array elements                      */
    720 
    721   FT_LOCAL_DEF( void )
    722   ps_parser_to_token_array( PS_Parser  parser,
    723                             T1_Token   tokens,
    724                             FT_UInt    max_tokens,
    725                             FT_Int*    pnum_tokens )
    726   {
    727     T1_TokenRec  master;
    728 
    729 
    730     *pnum_tokens = -1;
    731 
    732     /* this also handles leading whitespace */
    733     ps_parser_to_token( parser, &master );
    734 
    735     if ( master.type == T1_TOKEN_TYPE_ARRAY )
    736     {
    737       FT_Byte*  old_cursor = parser->cursor;
    738       FT_Byte*  old_limit  = parser->limit;
    739       T1_Token  cur        = tokens;
    740       T1_Token  limit      = cur + max_tokens;
    741 
    742 
    743       /* don't include outermost delimiters */
    744       parser->cursor = master.start + 1;
    745       parser->limit  = master.limit - 1;
    746 
    747       while ( parser->cursor < parser->limit )
    748       {
    749         T1_TokenRec  token;
    750 
    751 
    752         ps_parser_to_token( parser, &token );
    753         if ( !token.type )
    754           break;
    755 
    756         if ( tokens != NULL && cur < limit )
    757           *cur = token;
    758 
    759         cur++;
    760       }
    761 
    762       *pnum_tokens = (FT_Int)( cur - tokens );
    763 
    764       parser->cursor = old_cursor;
    765       parser->limit  = old_limit;
    766     }
    767   }
    768 
    769 
    770   /* first character must be a delimiter or a part of a number */
    771   /* NB: `coords' can be NULL if we just want to skip the      */
    772   /*     array; in this case we ignore `max_coords'            */
    773 
    774   static FT_Int
    775   ps_tocoordarray( FT_Byte*  *acur,
    776                    FT_Byte*   limit,
    777                    FT_Int     max_coords,
    778                    FT_Short*  coords )
    779   {
    780     FT_Byte*  cur   = *acur;
    781     FT_Int    count = 0;
    782     FT_Byte   c, ender;
    783 
    784 
    785     if ( cur >= limit )
    786       goto Exit;
    787 
    788     /* check for the beginning of an array; otherwise, only one number */
    789     /* will be read                                                    */
    790     c     = *cur;
    791     ender = 0;
    792 
    793     if ( c == '[' )
    794       ender = ']';
    795     else if ( c == '{' )
    796       ender = '}';
    797 
    798     if ( ender )
    799       cur++;
    800 
    801     /* now, read the coordinates */
    802     while ( cur < limit )
    803     {
    804       FT_Short  dummy;
    805       FT_Byte*  old_cur;
    806 
    807 
    808       /* skip whitespace in front of data */
    809       skip_spaces( &cur, limit );
    810       if ( cur >= limit )
    811         goto Exit;
    812 
    813       if ( *cur == ender )
    814       {
    815         cur++;
    816         break;
    817       }
    818 
    819       old_cur = cur;
    820 
    821       if ( coords != NULL && count >= max_coords )
    822         break;
    823 
    824       /* call PS_Conv_ToFixed() even if coords == NULL */
    825       /* to properly parse number at `cur'             */
    826       *( coords != NULL ? &coords[count] : &dummy ) =
    827         (FT_Short)( PS_Conv_ToFixed( &cur, limit, 0 ) >> 16 );
    828 
    829       if ( old_cur == cur )
    830       {
    831         count = -1;
    832         goto Exit;
    833       }
    834       else
    835         count++;
    836 
    837       if ( !ender )
    838         break;
    839     }
    840 
    841   Exit:
    842     *acur = cur;
    843     return count;
    844   }
    845 
    846 
    847   /* first character must be a delimiter or a part of a number */
    848   /* NB: `values' can be NULL if we just want to skip the      */
    849   /*     array; in this case we ignore `max_values'            */
    850 
    851   static FT_Int
    852   ps_tofixedarray( FT_Byte*  *acur,
    853                    FT_Byte*   limit,
    854                    FT_Int     max_values,
    855                    FT_Fixed*  values,
    856                    FT_Int     power_ten )
    857   {
    858     FT_Byte*  cur   = *acur;
    859     FT_Int    count = 0;
    860     FT_Byte   c, ender;
    861 
    862 
    863     if ( cur >= limit )
    864       goto Exit;
    865 
    866     /* Check for the beginning of an array.  Otherwise, only one number */
    867     /* will be read.                                                    */
    868     c     = *cur;
    869     ender = 0;
    870 
    871     if ( c == '[' )
    872       ender = ']';
    873     else if ( c == '{' )
    874       ender = '}';
    875 
    876     if ( ender )
    877       cur++;
    878 
    879     /* now, read the values */
    880     while ( cur < limit )
    881     {
    882       FT_Fixed  dummy;
    883       FT_Byte*  old_cur;
    884 
    885 
    886       /* skip whitespace in front of data */
    887       skip_spaces( &cur, limit );
    888       if ( cur >= limit )
    889         goto Exit;
    890 
    891       if ( *cur == ender )
    892       {
    893         cur++;
    894         break;
    895       }
    896 
    897       old_cur = cur;
    898 
    899       if ( values != NULL && count >= max_values )
    900         break;
    901 
    902       /* call PS_Conv_ToFixed() even if coords == NULL */
    903       /* to properly parse number at `cur'             */
    904       *( values != NULL ? &values[count] : &dummy ) =
    905         PS_Conv_ToFixed( &cur, limit, power_ten );
    906 
    907       if ( old_cur == cur )
    908       {
    909         count = -1;
    910         goto Exit;
    911       }
    912       else
    913         count++;
    914 
    915       if ( !ender )
    916         break;
    917     }
    918 
    919   Exit:
    920     *acur = cur;
    921     return count;
    922   }
    923 
    924 
    925 #if 0
    926 
    927   static FT_String*
    928   ps_tostring( FT_Byte**  cursor,
    929                FT_Byte*   limit,
    930                FT_Memory  memory )
    931   {
    932     FT_Byte*    cur = *cursor;
    933     FT_PtrDist  len = 0;
    934     FT_Int      count;
    935     FT_String*  result;
    936     FT_Error    error;
    937 
    938 
    939     /* XXX: some stupid fonts have a `Notice' or `Copyright' string     */
    940     /*      that simply doesn't begin with an opening parenthesis, even */
    941     /*      though they have a closing one!  E.g. "amuncial.pfb"        */
    942     /*                                                                  */
    943     /*      We must deal with these ill-fated cases there.  Note that   */
    944     /*      these fonts didn't work with the old Type 1 driver as the   */
    945     /*      notice/copyright was not recognized as a valid string token */
    946     /*      and made the old token parser commit errors.                */
    947 
    948     while ( cur < limit && ( *cur == ' ' || *cur == '\t' ) )
    949       cur++;
    950     if ( cur + 1 >= limit )
    951       return 0;
    952 
    953     if ( *cur == '(' )
    954       cur++;  /* skip the opening parenthesis, if there is one */
    955 
    956     *cursor = cur;
    957     count   = 0;
    958 
    959     /* then, count its length */
    960     for ( ; cur < limit; cur++ )
    961     {
    962       if ( *cur == '(' )
    963         count++;
    964 
    965       else if ( *cur == ')' )
    966       {
    967         count--;
    968         if ( count < 0 )
    969           break;
    970       }
    971     }
    972 
    973     len = cur - *cursor;
    974     if ( cur >= limit || FT_ALLOC( result, len + 1 ) )
    975       return 0;
    976 
    977     /* now copy the string */
    978     FT_MEM_COPY( result, *cursor, len );
    979     result[len] = '\0';
    980     *cursor = cur;
    981     return result;
    982   }
    983 
    984 #endif /* 0 */
    985 
    986 
    987   static int
    988   ps_tobool( FT_Byte*  *acur,
    989              FT_Byte*   limit )
    990   {
    991     FT_Byte*  cur    = *acur;
    992     FT_Bool   result = 0;
    993 
    994 
    995     /* return 1 if we find `true', 0 otherwise */
    996     if ( cur + 3 < limit &&
    997          cur[0] == 't'   &&
    998          cur[1] == 'r'   &&
    999          cur[2] == 'u'   &&
   1000          cur[3] == 'e'   )
   1001     {
   1002       result = 1;
   1003       cur   += 5;
   1004     }
   1005     else if ( cur + 4 < limit &&
   1006               cur[0] == 'f'   &&
   1007               cur[1] == 'a'   &&
   1008               cur[2] == 'l'   &&
   1009               cur[3] == 's'   &&
   1010               cur[4] == 'e'   )
   1011     {
   1012       result = 0;
   1013       cur   += 6;
   1014     }
   1015 
   1016     *acur = cur;
   1017     return result;
   1018   }
   1019 
   1020 
   1021   /* load a simple field (i.e. non-table) into the current list of objects */
   1022 
   1023   FT_LOCAL_DEF( FT_Error )
   1024   ps_parser_load_field( PS_Parser       parser,
   1025                         const T1_Field  field,
   1026                         void**          objects,
   1027                         FT_UInt         max_objects,
   1028                         FT_ULong*       pflags )
   1029   {
   1030     T1_TokenRec   token;
   1031     FT_Byte*      cur;
   1032     FT_Byte*      limit;
   1033     FT_UInt       count;
   1034     FT_UInt       idx;
   1035     FT_Error      error;
   1036     T1_FieldType  type;
   1037 
   1038 
   1039     /* this also skips leading whitespace */
   1040     ps_parser_to_token( parser, &token );
   1041     if ( !token.type )
   1042       goto Fail;
   1043 
   1044     count = 1;
   1045     idx   = 0;
   1046     cur   = token.start;
   1047     limit = token.limit;
   1048 
   1049     type = field->type;
   1050 
   1051     /* we must detect arrays in /FontBBox */
   1052     if ( type == T1_FIELD_TYPE_BBOX )
   1053     {
   1054       T1_TokenRec  token2;
   1055       FT_Byte*     old_cur   = parser->cursor;
   1056       FT_Byte*     old_limit = parser->limit;
   1057 
   1058 
   1059       /* don't include delimiters */
   1060       parser->cursor = token.start + 1;
   1061       parser->limit  = token.limit - 1;
   1062 
   1063       ps_parser_to_token( parser, &token2 );
   1064       parser->cursor = old_cur;
   1065       parser->limit  = old_limit;
   1066 
   1067       if ( token2.type == T1_TOKEN_TYPE_ARRAY )
   1068       {
   1069         type = T1_FIELD_TYPE_MM_BBOX;
   1070         goto FieldArray;
   1071       }
   1072     }
   1073     else if ( token.type == T1_TOKEN_TYPE_ARRAY )
   1074     {
   1075       count = max_objects;
   1076 
   1077     FieldArray:
   1078       /* if this is an array and we have no blend, an error occurs */
   1079       if ( max_objects == 0 )
   1080         goto Fail;
   1081 
   1082       idx = 1;
   1083 
   1084       /* don't include delimiters */
   1085       cur++;
   1086       limit--;
   1087     }
   1088 
   1089     for ( ; count > 0; count--, idx++ )
   1090     {
   1091       FT_Byte*    q = (FT_Byte*)objects[idx] + field->offset;
   1092       FT_Long     val;
   1093       FT_String*  string;
   1094 
   1095 
   1096       skip_spaces( &cur, limit );
   1097 
   1098       switch ( type )
   1099       {
   1100       case T1_FIELD_TYPE_BOOL:
   1101         val = ps_tobool( &cur, limit );
   1102         goto Store_Integer;
   1103 
   1104       case T1_FIELD_TYPE_FIXED:
   1105         val = PS_Conv_ToFixed( &cur, limit, 0 );
   1106         goto Store_Integer;
   1107 
   1108       case T1_FIELD_TYPE_FIXED_1000:
   1109         val = PS_Conv_ToFixed( &cur, limit, 3 );
   1110         goto Store_Integer;
   1111 
   1112       case T1_FIELD_TYPE_INTEGER:
   1113         val = PS_Conv_ToInt( &cur, limit );
   1114         /* fall through */
   1115 
   1116       Store_Integer:
   1117         switch ( field->size )
   1118         {
   1119         case (8 / FT_CHAR_BIT):
   1120           *(FT_Byte*)q = (FT_Byte)val;
   1121           break;
   1122 
   1123         case (16 / FT_CHAR_BIT):
   1124           *(FT_UShort*)q = (FT_UShort)val;
   1125           break;
   1126 
   1127         case (32 / FT_CHAR_BIT):
   1128           *(FT_UInt32*)q = (FT_UInt32)val;
   1129           break;
   1130 
   1131         default:                /* for 64-bit systems */
   1132           *(FT_Long*)q = val;
   1133         }
   1134         break;
   1135 
   1136       case T1_FIELD_TYPE_STRING:
   1137       case T1_FIELD_TYPE_KEY:
   1138         {
   1139           FT_Memory  memory = parser->memory;
   1140           FT_UInt    len    = (FT_UInt)( limit - cur );
   1141 
   1142 
   1143           if ( cur >= limit )
   1144             break;
   1145 
   1146           /* we allow both a string or a name   */
   1147           /* for cases like /FontName (foo) def */
   1148           if ( token.type == T1_TOKEN_TYPE_KEY )
   1149           {
   1150             /* don't include leading `/' */
   1151             len--;
   1152             cur++;
   1153           }
   1154           else if ( token.type == T1_TOKEN_TYPE_STRING )
   1155           {
   1156             /* don't include delimiting parentheses    */
   1157             /* XXX we don't handle <<...>> here        */
   1158             /* XXX should we convert octal escapes?    */
   1159             /*     if so, what encoding should we use? */
   1160             cur++;
   1161             len -= 2;
   1162           }
   1163           else
   1164           {
   1165             FT_ERROR(( "ps_parser_load_field:"
   1166                        " expected a name or string\n"
   1167                        "                     "
   1168                        " but found token of type %d instead\n",
   1169                        token.type ));
   1170             error = FT_THROW( Invalid_File_Format );
   1171             goto Exit;
   1172           }
   1173 
   1174           /* for this to work (FT_String**)q must have been */
   1175           /* initialized to NULL                            */
   1176           if ( *(FT_String**)q != NULL )
   1177           {
   1178             FT_TRACE0(( "ps_parser_load_field: overwriting field %s\n",
   1179                         field->ident ));
   1180             FT_FREE( *(FT_String**)q );
   1181             *(FT_String**)q = NULL;
   1182           }
   1183 
   1184           if ( FT_ALLOC( string, len + 1 ) )
   1185             goto Exit;
   1186 
   1187           FT_MEM_COPY( string, cur, len );
   1188           string[len] = 0;
   1189 
   1190           *(FT_String**)q = string;
   1191         }
   1192         break;
   1193 
   1194       case T1_FIELD_TYPE_BBOX:
   1195         {
   1196           FT_Fixed  temp[4];
   1197           FT_BBox*  bbox = (FT_BBox*)q;
   1198           FT_Int    result;
   1199 
   1200 
   1201           result = ps_tofixedarray( &cur, limit, 4, temp, 0 );
   1202 
   1203           if ( result < 0 )
   1204           {
   1205             FT_ERROR(( "ps_parser_load_field:"
   1206                        " expected four integers in bounding box\n" ));
   1207             error = FT_THROW( Invalid_File_Format );
   1208             goto Exit;
   1209           }
   1210 
   1211           bbox->xMin = FT_RoundFix( temp[0] );
   1212           bbox->yMin = FT_RoundFix( temp[1] );
   1213           bbox->xMax = FT_RoundFix( temp[2] );
   1214           bbox->yMax = FT_RoundFix( temp[3] );
   1215         }
   1216         break;
   1217 
   1218       case T1_FIELD_TYPE_MM_BBOX:
   1219         {
   1220           FT_Memory  memory = parser->memory;
   1221           FT_Fixed*  temp;
   1222           FT_Int     result;
   1223           FT_UInt    i;
   1224 
   1225 
   1226           if ( FT_NEW_ARRAY( temp, max_objects * 4 ) )
   1227             goto Exit;
   1228 
   1229           for ( i = 0; i < 4; i++ )
   1230           {
   1231             result = ps_tofixedarray( &cur, limit, max_objects,
   1232                                       temp + i * max_objects, 0 );
   1233             if ( result < 0 )
   1234             {
   1235               FT_ERROR(( "ps_parser_load_field:"
   1236                          " expected %d integers in the %s subarray\n"
   1237                          "                     "
   1238                          " of /FontBBox in the /Blend dictionary\n",
   1239                          max_objects,
   1240                          i == 0 ? "first"
   1241                                 : ( i == 1 ? "second"
   1242                                            : ( i == 2 ? "third"
   1243                                                       : "fourth" ) ) ));
   1244               error = FT_THROW( Invalid_File_Format );
   1245               goto Exit;
   1246             }
   1247 
   1248             skip_spaces( &cur, limit );
   1249           }
   1250 
   1251           for ( i = 0; i < max_objects; i++ )
   1252           {
   1253             FT_BBox*  bbox = (FT_BBox*)objects[i];
   1254 
   1255 
   1256             bbox->xMin = FT_RoundFix( temp[i                  ] );
   1257             bbox->yMin = FT_RoundFix( temp[i +     max_objects] );
   1258             bbox->xMax = FT_RoundFix( temp[i + 2 * max_objects] );
   1259             bbox->yMax = FT_RoundFix( temp[i + 3 * max_objects] );
   1260           }
   1261 
   1262           FT_FREE( temp );
   1263         }
   1264         break;
   1265 
   1266       default:
   1267         /* an error occurred */
   1268         goto Fail;
   1269       }
   1270     }
   1271 
   1272 #if 0  /* obsolete -- keep for reference */
   1273     if ( pflags )
   1274       *pflags |= 1L << field->flag_bit;
   1275 #else
   1276     FT_UNUSED( pflags );
   1277 #endif
   1278 
   1279     error = FT_Err_Ok;
   1280 
   1281   Exit:
   1282     return error;
   1283 
   1284   Fail:
   1285     error = FT_THROW( Invalid_File_Format );
   1286     goto Exit;
   1287   }
   1288 
   1289 
   1290 #define T1_MAX_TABLE_ELEMENTS  32
   1291 
   1292 
   1293   FT_LOCAL_DEF( FT_Error )
   1294   ps_parser_load_field_table( PS_Parser       parser,
   1295                               const T1_Field  field,
   1296                               void**          objects,
   1297                               FT_UInt         max_objects,
   1298                               FT_ULong*       pflags )
   1299   {
   1300     T1_TokenRec  elements[T1_MAX_TABLE_ELEMENTS];
   1301     T1_Token     token;
   1302     FT_Int       num_elements;
   1303     FT_Error     error = FT_Err_Ok;
   1304     FT_Byte*     old_cursor;
   1305     FT_Byte*     old_limit;
   1306     T1_FieldRec  fieldrec = *(T1_Field)field;
   1307 
   1308 
   1309     fieldrec.type = T1_FIELD_TYPE_INTEGER;
   1310     if ( field->type == T1_FIELD_TYPE_FIXED_ARRAY ||
   1311          field->type == T1_FIELD_TYPE_BBOX        )
   1312       fieldrec.type = T1_FIELD_TYPE_FIXED;
   1313 
   1314     ps_parser_to_token_array( parser, elements,
   1315                               T1_MAX_TABLE_ELEMENTS, &num_elements );
   1316     if ( num_elements < 0 )
   1317     {
   1318       error = FT_ERR( Ignore );
   1319       goto Exit;
   1320     }
   1321     if ( (FT_UInt)num_elements > field->array_max )
   1322       num_elements = field->array_max;
   1323 
   1324     old_cursor = parser->cursor;
   1325     old_limit  = parser->limit;
   1326 
   1327     /* we store the elements count if necessary;           */
   1328     /* we further assume that `count_offset' can't be zero */
   1329     if ( field->type != T1_FIELD_TYPE_BBOX && field->count_offset != 0 )
   1330       *(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) =
   1331         (FT_Byte)num_elements;
   1332 
   1333     /* we now load each element, adjusting the field.offset on each one */
   1334     token = elements;
   1335     for ( ; num_elements > 0; num_elements--, token++ )
   1336     {
   1337       parser->cursor = token->start;
   1338       parser->limit  = token->limit;
   1339       ps_parser_load_field( parser, &fieldrec, objects, max_objects, 0 );
   1340       fieldrec.offset += fieldrec.size;
   1341     }
   1342 
   1343 #if 0  /* obsolete -- keep for reference */
   1344     if ( pflags )
   1345       *pflags |= 1L << field->flag_bit;
   1346 #else
   1347     FT_UNUSED( pflags );
   1348 #endif
   1349 
   1350     parser->cursor = old_cursor;
   1351     parser->limit  = old_limit;
   1352 
   1353   Exit:
   1354     return error;
   1355   }
   1356 
   1357 
   1358   FT_LOCAL_DEF( FT_Long )
   1359   ps_parser_to_int( PS_Parser  parser )
   1360   {
   1361     ps_parser_skip_spaces( parser );
   1362     return PS_Conv_ToInt( &parser->cursor, parser->limit );
   1363   }
   1364 
   1365 
   1366   /* first character must be `<' if `delimiters' is non-zero */
   1367 
   1368   FT_LOCAL_DEF( FT_Error )
   1369   ps_parser_to_bytes( PS_Parser  parser,
   1370                       FT_Byte*   bytes,
   1371                       FT_Offset  max_bytes,
   1372                       FT_Long*   pnum_bytes,
   1373                       FT_Bool    delimiters )
   1374   {
   1375     FT_Error  error = FT_Err_Ok;
   1376     FT_Byte*  cur;
   1377 
   1378 
   1379     ps_parser_skip_spaces( parser );
   1380     cur = parser->cursor;
   1381 
   1382     if ( cur >= parser->limit )
   1383       goto Exit;
   1384 
   1385     if ( delimiters )
   1386     {
   1387       if ( *cur != '<' )
   1388       {
   1389         FT_ERROR(( "ps_parser_to_bytes: Missing starting delimiter `<'\n" ));
   1390         error = FT_THROW( Invalid_File_Format );
   1391         goto Exit;
   1392       }
   1393 
   1394       cur++;
   1395     }
   1396 
   1397     *pnum_bytes = PS_Conv_ASCIIHexDecode( &cur,
   1398                                           parser->limit,
   1399                                           bytes,
   1400                                           max_bytes );
   1401 
   1402     if ( delimiters )
   1403     {
   1404       if ( cur < parser->limit && *cur != '>' )
   1405       {
   1406         FT_ERROR(( "ps_parser_to_bytes: Missing closing delimiter `>'\n" ));
   1407         error = FT_THROW( Invalid_File_Format );
   1408         goto Exit;
   1409       }
   1410 
   1411       cur++;
   1412     }
   1413 
   1414     parser->cursor = cur;
   1415 
   1416   Exit:
   1417     return error;
   1418   }
   1419 
   1420 
   1421   FT_LOCAL_DEF( FT_Fixed )
   1422   ps_parser_to_fixed( PS_Parser  parser,
   1423                       FT_Int     power_ten )
   1424   {
   1425     ps_parser_skip_spaces( parser );
   1426     return PS_Conv_ToFixed( &parser->cursor, parser->limit, power_ten );
   1427   }
   1428 
   1429 
   1430   FT_LOCAL_DEF( FT_Int )
   1431   ps_parser_to_coord_array( PS_Parser  parser,
   1432                             FT_Int     max_coords,
   1433                             FT_Short*  coords )
   1434   {
   1435     ps_parser_skip_spaces( parser );
   1436     return ps_tocoordarray( &parser->cursor, parser->limit,
   1437                             max_coords, coords );
   1438   }
   1439 
   1440 
   1441   FT_LOCAL_DEF( FT_Int )
   1442   ps_parser_to_fixed_array( PS_Parser  parser,
   1443                             FT_Int     max_values,
   1444                             FT_Fixed*  values,
   1445                             FT_Int     power_ten )
   1446   {
   1447     ps_parser_skip_spaces( parser );
   1448     return ps_tofixedarray( &parser->cursor, parser->limit,
   1449                             max_values, values, power_ten );
   1450   }
   1451 
   1452 
   1453 #if 0
   1454 
   1455   FT_LOCAL_DEF( FT_String* )
   1456   T1_ToString( PS_Parser  parser )
   1457   {
   1458     return ps_tostring( &parser->cursor, parser->limit, parser->memory );
   1459   }
   1460 
   1461 
   1462   FT_LOCAL_DEF( FT_Bool )
   1463   T1_ToBool( PS_Parser  parser )
   1464   {
   1465     return ps_tobool( &parser->cursor, parser->limit );
   1466   }
   1467 
   1468 #endif /* 0 */
   1469 
   1470 
   1471   FT_LOCAL_DEF( void )
   1472   ps_parser_init( PS_Parser  parser,
   1473                   FT_Byte*   base,
   1474                   FT_Byte*   limit,
   1475                   FT_Memory  memory )
   1476   {
   1477     parser->error  = FT_Err_Ok;
   1478     parser->base   = base;
   1479     parser->limit  = limit;
   1480     parser->cursor = base;
   1481     parser->memory = memory;
   1482     parser->funcs  = ps_parser_funcs;
   1483   }
   1484 
   1485 
   1486   FT_LOCAL_DEF( void )
   1487   ps_parser_done( PS_Parser  parser )
   1488   {
   1489     FT_UNUSED( parser );
   1490   }
   1491 
   1492 
   1493   /*************************************************************************/
   1494   /*************************************************************************/
   1495   /*****                                                               *****/
   1496   /*****                            T1 BUILDER                         *****/
   1497   /*****                                                               *****/
   1498   /*************************************************************************/
   1499   /*************************************************************************/
   1500 
   1501   /*************************************************************************/
   1502   /*                                                                       */
   1503   /* <Function>                                                            */
   1504   /*    t1_builder_init                                                    */
   1505   /*                                                                       */
   1506   /* <Description>                                                         */
   1507   /*    Initializes a given glyph builder.                                 */
   1508   /*                                                                       */
   1509   /* <InOut>                                                               */
   1510   /*    builder :: A pointer to the glyph builder to initialize.           */
   1511   /*                                                                       */
   1512   /* <Input>                                                               */
   1513   /*    face    :: The current face object.                                */
   1514   /*                                                                       */
   1515   /*    size    :: The current size object.                                */
   1516   /*                                                                       */
   1517   /*    glyph   :: The current glyph object.                               */
   1518   /*                                                                       */
   1519   /*    hinting :: Whether hinting should be applied.                      */
   1520   /*                                                                       */
   1521   FT_LOCAL_DEF( void )
   1522   t1_builder_init( T1_Builder    builder,
   1523                    FT_Face       face,
   1524                    FT_Size       size,
   1525                    FT_GlyphSlot  glyph,
   1526                    FT_Bool       hinting )
   1527   {
   1528     builder->parse_state = T1_Parse_Start;
   1529     builder->load_points = 1;
   1530 
   1531     builder->face   = face;
   1532     builder->glyph  = glyph;
   1533     builder->memory = face->memory;
   1534 
   1535     if ( glyph )
   1536     {
   1537       FT_GlyphLoader  loader = glyph->internal->loader;
   1538 
   1539 
   1540       builder->loader  = loader;
   1541       builder->base    = &loader->base.outline;
   1542       builder->current = &loader->current.outline;
   1543       FT_GlyphLoader_Rewind( loader );
   1544 
   1545       builder->hints_globals = size->internal;
   1546       builder->hints_funcs   = 0;
   1547 
   1548       if ( hinting )
   1549         builder->hints_funcs = glyph->internal->glyph_hints;
   1550     }
   1551 
   1552     builder->pos_x = 0;
   1553     builder->pos_y = 0;
   1554 
   1555     builder->left_bearing.x = 0;
   1556     builder->left_bearing.y = 0;
   1557     builder->advance.x      = 0;
   1558     builder->advance.y      = 0;
   1559 
   1560     builder->funcs = t1_builder_funcs;
   1561   }
   1562 
   1563 
   1564   /*************************************************************************/
   1565   /*                                                                       */
   1566   /* <Function>                                                            */
   1567   /*    t1_builder_done                                                    */
   1568   /*                                                                       */
   1569   /* <Description>                                                         */
   1570   /*    Finalizes a given glyph builder.  Its contents can still be used   */
   1571   /*    after the call, but the function saves important information       */
   1572   /*    within the corresponding glyph slot.                               */
   1573   /*                                                                       */
   1574   /* <Input>                                                               */
   1575   /*    builder :: A pointer to the glyph builder to finalize.             */
   1576   /*                                                                       */
   1577   FT_LOCAL_DEF( void )
   1578   t1_builder_done( T1_Builder  builder )
   1579   {
   1580     FT_GlyphSlot  glyph = builder->glyph;
   1581 
   1582 
   1583     if ( glyph )
   1584       glyph->outline = *builder->base;
   1585   }
   1586 
   1587 
   1588   /* check that there is enough space for `count' more points */
   1589   FT_LOCAL_DEF( FT_Error )
   1590   t1_builder_check_points( T1_Builder  builder,
   1591                            FT_Int      count )
   1592   {
   1593     return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
   1594   }
   1595 
   1596 
   1597   /* add a new point, do not check space */
   1598   FT_LOCAL_DEF( void )
   1599   t1_builder_add_point( T1_Builder  builder,
   1600                         FT_Pos      x,
   1601                         FT_Pos      y,
   1602                         FT_Byte     flag )
   1603   {
   1604     FT_Outline*  outline = builder->current;
   1605 
   1606 
   1607     if ( builder->load_points )
   1608     {
   1609       FT_Vector*  point   = outline->points + outline->n_points;
   1610       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
   1611 
   1612 
   1613       point->x = FIXED_TO_INT( x );
   1614       point->y = FIXED_TO_INT( y );
   1615       *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
   1616     }
   1617     outline->n_points++;
   1618   }
   1619 
   1620 
   1621   /* check space for a new on-curve point, then add it */
   1622   FT_LOCAL_DEF( FT_Error )
   1623   t1_builder_add_point1( T1_Builder  builder,
   1624                          FT_Pos      x,
   1625                          FT_Pos      y )
   1626   {
   1627     FT_Error  error;
   1628 
   1629 
   1630     error = t1_builder_check_points( builder, 1 );
   1631     if ( !error )
   1632       t1_builder_add_point( builder, x, y, 1 );
   1633 
   1634     return error;
   1635   }
   1636 
   1637 
   1638   /* check space for a new contour, then add it */
   1639   FT_LOCAL_DEF( FT_Error )
   1640   t1_builder_add_contour( T1_Builder  builder )
   1641   {
   1642     FT_Outline*  outline = builder->current;
   1643     FT_Error     error;
   1644 
   1645 
   1646     /* this might happen in invalid fonts */
   1647     if ( !outline )
   1648     {
   1649       FT_ERROR(( "t1_builder_add_contour: no outline to add points to\n" ));
   1650       return FT_THROW( Invalid_File_Format );
   1651     }
   1652 
   1653     if ( !builder->load_points )
   1654     {
   1655       outline->n_contours++;
   1656       return FT_Err_Ok;
   1657     }
   1658 
   1659     error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
   1660     if ( !error )
   1661     {
   1662       if ( outline->n_contours > 0 )
   1663         outline->contours[outline->n_contours - 1] =
   1664           (short)( outline->n_points - 1 );
   1665 
   1666       outline->n_contours++;
   1667     }
   1668 
   1669     return error;
   1670   }
   1671 
   1672 
   1673   /* if a path was begun, add its first on-curve point */
   1674   FT_LOCAL_DEF( FT_Error )
   1675   t1_builder_start_point( T1_Builder  builder,
   1676                           FT_Pos      x,
   1677                           FT_Pos      y )
   1678   {
   1679     FT_Error  error = FT_ERR( Invalid_File_Format );
   1680 
   1681 
   1682     /* test whether we are building a new contour */
   1683 
   1684     if ( builder->parse_state == T1_Parse_Have_Path )
   1685       error = FT_Err_Ok;
   1686     else
   1687     {
   1688       builder->parse_state = T1_Parse_Have_Path;
   1689       error = t1_builder_add_contour( builder );
   1690       if ( !error )
   1691         error = t1_builder_add_point1( builder, x, y );
   1692     }
   1693 
   1694     return error;
   1695   }
   1696 
   1697 
   1698   /* close the current contour */
   1699   FT_LOCAL_DEF( void )
   1700   t1_builder_close_contour( T1_Builder  builder )
   1701   {
   1702     FT_Outline*  outline = builder->current;
   1703     FT_Int       first;
   1704 
   1705 
   1706     if ( !outline )
   1707       return;
   1708 
   1709     first = outline->n_contours <= 1
   1710             ? 0 : outline->contours[outline->n_contours - 2] + 1;
   1711 
   1712     /* We must not include the last point in the path if it */
   1713     /* is located on the first point.                       */
   1714     if ( outline->n_points > 1 )
   1715     {
   1716       FT_Vector*  p1      = outline->points + first;
   1717       FT_Vector*  p2      = outline->points + outline->n_points - 1;
   1718       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
   1719 
   1720 
   1721       /* `delete' last point only if it coincides with the first */
   1722       /* point and it is not a control point (which can happen). */
   1723       if ( p1->x == p2->x && p1->y == p2->y )
   1724         if ( *control == FT_CURVE_TAG_ON )
   1725           outline->n_points--;
   1726     }
   1727 
   1728     if ( outline->n_contours > 0 )
   1729     {
   1730       /* Don't add contours only consisting of one point, i.e.,  */
   1731       /* check whether the first and the last point is the same. */
   1732       if ( first == outline->n_points - 1 )
   1733       {
   1734         outline->n_contours--;
   1735         outline->n_points--;
   1736       }
   1737       else
   1738         outline->contours[outline->n_contours - 1] =
   1739           (short)( outline->n_points - 1 );
   1740     }
   1741   }
   1742 
   1743 
   1744   /*************************************************************************/
   1745   /*************************************************************************/
   1746   /*****                                                               *****/
   1747   /*****                            OTHER                              *****/
   1748   /*****                                                               *****/
   1749   /*************************************************************************/
   1750   /*************************************************************************/
   1751 
   1752   FT_LOCAL_DEF( void )
   1753   t1_decrypt( FT_Byte*   buffer,
   1754               FT_Offset  length,
   1755               FT_UShort  seed )
   1756   {
   1757     PS_Conv_EexecDecode( &buffer,
   1758                          buffer + length,
   1759                          buffer,
   1760                          length,
   1761                          &seed );
   1762   }
   1763 
   1764 
   1765 /* END */
   1766