Home | History | Annotate | Download | only in psaux
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  psobjs.c                                                               */
      4 /*                                                                         */
      5 /*    Auxiliary functions for PostScript fonts (body).                     */
      6 /*                                                                         */
      7 /*  Copyright 1996-2014 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   /* return number of successfully parsed values               */
    852 
    853   static FT_Int
    854   ps_tofixedarray( FT_Byte*  *acur,
    855                    FT_Byte*   limit,
    856                    FT_Int     max_values,
    857                    FT_Fixed*  values,
    858                    FT_Int     power_ten )
    859   {
    860     FT_Byte*  cur   = *acur;
    861     FT_Int    count = 0;
    862     FT_Byte   c, ender;
    863 
    864 
    865     if ( cur >= limit )
    866       goto Exit;
    867 
    868     /* Check for the beginning of an array.  Otherwise, only one number */
    869     /* will be read.                                                    */
    870     c     = *cur;
    871     ender = 0;
    872 
    873     if ( c == '[' )
    874       ender = ']';
    875     else if ( c == '{' )
    876       ender = '}';
    877 
    878     if ( ender )
    879       cur++;
    880 
    881     /* now, read the values */
    882     while ( cur < limit )
    883     {
    884       FT_Fixed  dummy;
    885       FT_Byte*  old_cur;
    886 
    887 
    888       /* skip whitespace in front of data */
    889       skip_spaces( &cur, limit );
    890       if ( cur >= limit )
    891         goto Exit;
    892 
    893       if ( *cur == ender )
    894       {
    895         cur++;
    896         break;
    897       }
    898 
    899       old_cur = cur;
    900 
    901       if ( values != NULL && count >= max_values )
    902         break;
    903 
    904       /* call PS_Conv_ToFixed() even if coords == NULL */
    905       /* to properly parse number at `cur'             */
    906       *( values != NULL ? &values[count] : &dummy ) =
    907         PS_Conv_ToFixed( &cur, limit, power_ten );
    908 
    909       if ( old_cur == cur )
    910       {
    911         count = -1;
    912         goto Exit;
    913       }
    914       else
    915         count++;
    916 
    917       if ( !ender )
    918         break;
    919     }
    920 
    921   Exit:
    922     *acur = cur;
    923     return count;
    924   }
    925 
    926 
    927 #if 0
    928 
    929   static FT_String*
    930   ps_tostring( FT_Byte**  cursor,
    931                FT_Byte*   limit,
    932                FT_Memory  memory )
    933   {
    934     FT_Byte*    cur = *cursor;
    935     FT_PtrDist  len = 0;
    936     FT_Int      count;
    937     FT_String*  result;
    938     FT_Error    error;
    939 
    940 
    941     /* XXX: some stupid fonts have a `Notice' or `Copyright' string     */
    942     /*      that simply doesn't begin with an opening parenthesis, even */
    943     /*      though they have a closing one!  E.g. "amuncial.pfb"        */
    944     /*                                                                  */
    945     /*      We must deal with these ill-fated cases there.  Note that   */
    946     /*      these fonts didn't work with the old Type 1 driver as the   */
    947     /*      notice/copyright was not recognized as a valid string token */
    948     /*      and made the old token parser commit errors.                */
    949 
    950     while ( cur < limit && ( *cur == ' ' || *cur == '\t' ) )
    951       cur++;
    952     if ( cur + 1 >= limit )
    953       return 0;
    954 
    955     if ( *cur == '(' )
    956       cur++;  /* skip the opening parenthesis, if there is one */
    957 
    958     *cursor = cur;
    959     count   = 0;
    960 
    961     /* then, count its length */
    962     for ( ; cur < limit; cur++ )
    963     {
    964       if ( *cur == '(' )
    965         count++;
    966 
    967       else if ( *cur == ')' )
    968       {
    969         count--;
    970         if ( count < 0 )
    971           break;
    972       }
    973     }
    974 
    975     len = cur - *cursor;
    976     if ( cur >= limit || FT_ALLOC( result, len + 1 ) )
    977       return 0;
    978 
    979     /* now copy the string */
    980     FT_MEM_COPY( result, *cursor, len );
    981     result[len] = '\0';
    982     *cursor = cur;
    983     return result;
    984   }
    985 
    986 #endif /* 0 */
    987 
    988 
    989   static int
    990   ps_tobool( FT_Byte*  *acur,
    991              FT_Byte*   limit )
    992   {
    993     FT_Byte*  cur    = *acur;
    994     FT_Bool   result = 0;
    995 
    996 
    997     /* return 1 if we find `true', 0 otherwise */
    998     if ( cur + 3 < limit &&
    999          cur[0] == 't'   &&
   1000          cur[1] == 'r'   &&
   1001          cur[2] == 'u'   &&
   1002          cur[3] == 'e'   )
   1003     {
   1004       result = 1;
   1005       cur   += 5;
   1006     }
   1007     else if ( cur + 4 < limit &&
   1008               cur[0] == 'f'   &&
   1009               cur[1] == 'a'   &&
   1010               cur[2] == 'l'   &&
   1011               cur[3] == 's'   &&
   1012               cur[4] == 'e'   )
   1013     {
   1014       result = 0;
   1015       cur   += 6;
   1016     }
   1017 
   1018     *acur = cur;
   1019     return result;
   1020   }
   1021 
   1022 
   1023   /* load a simple field (i.e. non-table) into the current list of objects */
   1024 
   1025   FT_LOCAL_DEF( FT_Error )
   1026   ps_parser_load_field( PS_Parser       parser,
   1027                         const T1_Field  field,
   1028                         void**          objects,
   1029                         FT_UInt         max_objects,
   1030                         FT_ULong*       pflags )
   1031   {
   1032     T1_TokenRec   token;
   1033     FT_Byte*      cur;
   1034     FT_Byte*      limit;
   1035     FT_UInt       count;
   1036     FT_UInt       idx;
   1037     FT_Error      error;
   1038     T1_FieldType  type;
   1039 
   1040 
   1041     /* this also skips leading whitespace */
   1042     ps_parser_to_token( parser, &token );
   1043     if ( !token.type )
   1044       goto Fail;
   1045 
   1046     count = 1;
   1047     idx   = 0;
   1048     cur   = token.start;
   1049     limit = token.limit;
   1050 
   1051     type = field->type;
   1052 
   1053     /* we must detect arrays in /FontBBox */
   1054     if ( type == T1_FIELD_TYPE_BBOX )
   1055     {
   1056       T1_TokenRec  token2;
   1057       FT_Byte*     old_cur   = parser->cursor;
   1058       FT_Byte*     old_limit = parser->limit;
   1059 
   1060 
   1061       /* don't include delimiters */
   1062       parser->cursor = token.start + 1;
   1063       parser->limit  = token.limit - 1;
   1064 
   1065       ps_parser_to_token( parser, &token2 );
   1066       parser->cursor = old_cur;
   1067       parser->limit  = old_limit;
   1068 
   1069       if ( token2.type == T1_TOKEN_TYPE_ARRAY )
   1070       {
   1071         type = T1_FIELD_TYPE_MM_BBOX;
   1072         goto FieldArray;
   1073       }
   1074     }
   1075     else if ( token.type == T1_TOKEN_TYPE_ARRAY )
   1076     {
   1077       count = max_objects;
   1078 
   1079     FieldArray:
   1080       /* if this is an array and we have no blend, an error occurs */
   1081       if ( max_objects == 0 )
   1082         goto Fail;
   1083 
   1084       idx = 1;
   1085 
   1086       /* don't include delimiters */
   1087       cur++;
   1088       limit--;
   1089     }
   1090 
   1091     for ( ; count > 0; count--, idx++ )
   1092     {
   1093       FT_Byte*    q = (FT_Byte*)objects[idx] + field->offset;
   1094       FT_Long     val;
   1095       FT_String*  string;
   1096 
   1097 
   1098       skip_spaces( &cur, limit );
   1099 
   1100       switch ( type )
   1101       {
   1102       case T1_FIELD_TYPE_BOOL:
   1103         val = ps_tobool( &cur, limit );
   1104         goto Store_Integer;
   1105 
   1106       case T1_FIELD_TYPE_FIXED:
   1107         val = PS_Conv_ToFixed( &cur, limit, 0 );
   1108         goto Store_Integer;
   1109 
   1110       case T1_FIELD_TYPE_FIXED_1000:
   1111         val = PS_Conv_ToFixed( &cur, limit, 3 );
   1112         goto Store_Integer;
   1113 
   1114       case T1_FIELD_TYPE_INTEGER:
   1115         val = PS_Conv_ToInt( &cur, limit );
   1116         /* fall through */
   1117 
   1118       Store_Integer:
   1119         switch ( field->size )
   1120         {
   1121         case (8 / FT_CHAR_BIT):
   1122           *(FT_Byte*)q = (FT_Byte)val;
   1123           break;
   1124 
   1125         case (16 / FT_CHAR_BIT):
   1126           *(FT_UShort*)q = (FT_UShort)val;
   1127           break;
   1128 
   1129         case (32 / FT_CHAR_BIT):
   1130           *(FT_UInt32*)q = (FT_UInt32)val;
   1131           break;
   1132 
   1133         default:                /* for 64-bit systems */
   1134           *(FT_Long*)q = val;
   1135         }
   1136         break;
   1137 
   1138       case T1_FIELD_TYPE_STRING:
   1139       case T1_FIELD_TYPE_KEY:
   1140         {
   1141           FT_Memory  memory = parser->memory;
   1142           FT_UInt    len    = (FT_UInt)( limit - cur );
   1143 
   1144 
   1145           if ( cur >= limit )
   1146             break;
   1147 
   1148           /* we allow both a string or a name   */
   1149           /* for cases like /FontName (foo) def */
   1150           if ( token.type == T1_TOKEN_TYPE_KEY )
   1151           {
   1152             /* don't include leading `/' */
   1153             len--;
   1154             cur++;
   1155           }
   1156           else if ( token.type == T1_TOKEN_TYPE_STRING )
   1157           {
   1158             /* don't include delimiting parentheses    */
   1159             /* XXX we don't handle <<...>> here        */
   1160             /* XXX should we convert octal escapes?    */
   1161             /*     if so, what encoding should we use? */
   1162             cur++;
   1163             len -= 2;
   1164           }
   1165           else
   1166           {
   1167             FT_ERROR(( "ps_parser_load_field:"
   1168                        " expected a name or string\n"
   1169                        "                     "
   1170                        " but found token of type %d instead\n",
   1171                        token.type ));
   1172             error = FT_THROW( Invalid_File_Format );
   1173             goto Exit;
   1174           }
   1175 
   1176           /* for this to work (FT_String**)q must have been */
   1177           /* initialized to NULL                            */
   1178           if ( *(FT_String**)q != NULL )
   1179           {
   1180             FT_TRACE0(( "ps_parser_load_field: overwriting field %s\n",
   1181                         field->ident ));
   1182             FT_FREE( *(FT_String**)q );
   1183             *(FT_String**)q = NULL;
   1184           }
   1185 
   1186           if ( FT_ALLOC( string, len + 1 ) )
   1187             goto Exit;
   1188 
   1189           FT_MEM_COPY( string, cur, len );
   1190           string[len] = 0;
   1191 
   1192           *(FT_String**)q = string;
   1193         }
   1194         break;
   1195 
   1196       case T1_FIELD_TYPE_BBOX:
   1197         {
   1198           FT_Fixed  temp[4];
   1199           FT_BBox*  bbox = (FT_BBox*)q;
   1200           FT_Int    result;
   1201 
   1202 
   1203           result = ps_tofixedarray( &cur, limit, 4, temp, 0 );
   1204 
   1205           if ( result < 4 )
   1206           {
   1207             FT_ERROR(( "ps_parser_load_field:"
   1208                        " expected four integers in bounding box\n" ));
   1209             error = FT_THROW( Invalid_File_Format );
   1210             goto Exit;
   1211           }
   1212 
   1213           bbox->xMin = FT_RoundFix( temp[0] );
   1214           bbox->yMin = FT_RoundFix( temp[1] );
   1215           bbox->xMax = FT_RoundFix( temp[2] );
   1216           bbox->yMax = FT_RoundFix( temp[3] );
   1217         }
   1218         break;
   1219 
   1220       case T1_FIELD_TYPE_MM_BBOX:
   1221         {
   1222           FT_Memory  memory = parser->memory;
   1223           FT_Fixed*  temp;
   1224           FT_Int     result;
   1225           FT_UInt    i;
   1226 
   1227 
   1228           if ( FT_NEW_ARRAY( temp, max_objects * 4 ) )
   1229             goto Exit;
   1230 
   1231           for ( i = 0; i < 4; i++ )
   1232           {
   1233             result = ps_tofixedarray( &cur, limit, max_objects,
   1234                                       temp + i * max_objects, 0 );
   1235             if ( result < 0 || (FT_UInt)result < max_objects )
   1236             {
   1237               FT_ERROR(( "ps_parser_load_field:"
   1238                          " expected %d integers in the %s subarray\n"
   1239                          "                     "
   1240                          " of /FontBBox in the /Blend dictionary\n",
   1241                          max_objects,
   1242                          i == 0 ? "first"
   1243                                 : ( i == 1 ? "second"
   1244                                            : ( i == 2 ? "third"
   1245                                                       : "fourth" ) ) ));
   1246               error = FT_THROW( Invalid_File_Format );
   1247               goto Exit;
   1248             }
   1249 
   1250             skip_spaces( &cur, limit );
   1251           }
   1252 
   1253           for ( i = 0; i < max_objects; i++ )
   1254           {
   1255             FT_BBox*  bbox = (FT_BBox*)objects[i];
   1256 
   1257 
   1258             bbox->xMin = FT_RoundFix( temp[i                  ] );
   1259             bbox->yMin = FT_RoundFix( temp[i +     max_objects] );
   1260             bbox->xMax = FT_RoundFix( temp[i + 2 * max_objects] );
   1261             bbox->yMax = FT_RoundFix( temp[i + 3 * max_objects] );
   1262           }
   1263 
   1264           FT_FREE( temp );
   1265         }
   1266         break;
   1267 
   1268       default:
   1269         /* an error occurred */
   1270         goto Fail;
   1271       }
   1272     }
   1273 
   1274 #if 0  /* obsolete -- keep for reference */
   1275     if ( pflags )
   1276       *pflags |= 1L << field->flag_bit;
   1277 #else
   1278     FT_UNUSED( pflags );
   1279 #endif
   1280 
   1281     error = FT_Err_Ok;
   1282 
   1283   Exit:
   1284     return error;
   1285 
   1286   Fail:
   1287     error = FT_THROW( Invalid_File_Format );
   1288     goto Exit;
   1289   }
   1290 
   1291 
   1292 #define T1_MAX_TABLE_ELEMENTS  32
   1293 
   1294 
   1295   FT_LOCAL_DEF( FT_Error )
   1296   ps_parser_load_field_table( PS_Parser       parser,
   1297                               const T1_Field  field,
   1298                               void**          objects,
   1299                               FT_UInt         max_objects,
   1300                               FT_ULong*       pflags )
   1301   {
   1302     T1_TokenRec  elements[T1_MAX_TABLE_ELEMENTS];
   1303     T1_Token     token;
   1304     FT_Int       num_elements;
   1305     FT_Error     error = FT_Err_Ok;
   1306     FT_Byte*     old_cursor;
   1307     FT_Byte*     old_limit;
   1308     T1_FieldRec  fieldrec = *(T1_Field)field;
   1309 
   1310 
   1311     fieldrec.type = T1_FIELD_TYPE_INTEGER;
   1312     if ( field->type == T1_FIELD_TYPE_FIXED_ARRAY ||
   1313          field->type == T1_FIELD_TYPE_BBOX        )
   1314       fieldrec.type = T1_FIELD_TYPE_FIXED;
   1315 
   1316     ps_parser_to_token_array( parser, elements,
   1317                               T1_MAX_TABLE_ELEMENTS, &num_elements );
   1318     if ( num_elements < 0 )
   1319     {
   1320       error = FT_ERR( Ignore );
   1321       goto Exit;
   1322     }
   1323     if ( (FT_UInt)num_elements > field->array_max )
   1324       num_elements = field->array_max;
   1325 
   1326     old_cursor = parser->cursor;
   1327     old_limit  = parser->limit;
   1328 
   1329     /* we store the elements count if necessary;           */
   1330     /* we further assume that `count_offset' can't be zero */
   1331     if ( field->type != T1_FIELD_TYPE_BBOX && field->count_offset != 0 )
   1332       *(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) =
   1333         (FT_Byte)num_elements;
   1334 
   1335     /* we now load each element, adjusting the field.offset on each one */
   1336     token = elements;
   1337     for ( ; num_elements > 0; num_elements--, token++ )
   1338     {
   1339       parser->cursor = token->start;
   1340       parser->limit  = token->limit;
   1341       ps_parser_load_field( parser, &fieldrec, objects, max_objects, 0 );
   1342       fieldrec.offset += fieldrec.size;
   1343     }
   1344 
   1345 #if 0  /* obsolete -- keep for reference */
   1346     if ( pflags )
   1347       *pflags |= 1L << field->flag_bit;
   1348 #else
   1349     FT_UNUSED( pflags );
   1350 #endif
   1351 
   1352     parser->cursor = old_cursor;
   1353     parser->limit  = old_limit;
   1354 
   1355   Exit:
   1356     return error;
   1357   }
   1358 
   1359 
   1360   FT_LOCAL_DEF( FT_Long )
   1361   ps_parser_to_int( PS_Parser  parser )
   1362   {
   1363     ps_parser_skip_spaces( parser );
   1364     return PS_Conv_ToInt( &parser->cursor, parser->limit );
   1365   }
   1366 
   1367 
   1368   /* first character must be `<' if `delimiters' is non-zero */
   1369 
   1370   FT_LOCAL_DEF( FT_Error )
   1371   ps_parser_to_bytes( PS_Parser  parser,
   1372                       FT_Byte*   bytes,
   1373                       FT_Offset  max_bytes,
   1374                       FT_Long*   pnum_bytes,
   1375                       FT_Bool    delimiters )
   1376   {
   1377     FT_Error  error = FT_Err_Ok;
   1378     FT_Byte*  cur;
   1379 
   1380 
   1381     ps_parser_skip_spaces( parser );
   1382     cur = parser->cursor;
   1383 
   1384     if ( cur >= parser->limit )
   1385       goto Exit;
   1386 
   1387     if ( delimiters )
   1388     {
   1389       if ( *cur != '<' )
   1390       {
   1391         FT_ERROR(( "ps_parser_to_bytes: Missing starting delimiter `<'\n" ));
   1392         error = FT_THROW( Invalid_File_Format );
   1393         goto Exit;
   1394       }
   1395 
   1396       cur++;
   1397     }
   1398 
   1399     *pnum_bytes = PS_Conv_ASCIIHexDecode( &cur,
   1400                                           parser->limit,
   1401                                           bytes,
   1402                                           max_bytes );
   1403 
   1404     if ( delimiters )
   1405     {
   1406       if ( cur < parser->limit && *cur != '>' )
   1407       {
   1408         FT_ERROR(( "ps_parser_to_bytes: Missing closing delimiter `>'\n" ));
   1409         error = FT_THROW( Invalid_File_Format );
   1410         goto Exit;
   1411       }
   1412 
   1413       cur++;
   1414     }
   1415 
   1416     parser->cursor = cur;
   1417 
   1418   Exit:
   1419     return error;
   1420   }
   1421 
   1422 
   1423   FT_LOCAL_DEF( FT_Fixed )
   1424   ps_parser_to_fixed( PS_Parser  parser,
   1425                       FT_Int     power_ten )
   1426   {
   1427     ps_parser_skip_spaces( parser );
   1428     return PS_Conv_ToFixed( &parser->cursor, parser->limit, power_ten );
   1429   }
   1430 
   1431 
   1432   FT_LOCAL_DEF( FT_Int )
   1433   ps_parser_to_coord_array( PS_Parser  parser,
   1434                             FT_Int     max_coords,
   1435                             FT_Short*  coords )
   1436   {
   1437     ps_parser_skip_spaces( parser );
   1438     return ps_tocoordarray( &parser->cursor, parser->limit,
   1439                             max_coords, coords );
   1440   }
   1441 
   1442 
   1443   FT_LOCAL_DEF( FT_Int )
   1444   ps_parser_to_fixed_array( PS_Parser  parser,
   1445                             FT_Int     max_values,
   1446                             FT_Fixed*  values,
   1447                             FT_Int     power_ten )
   1448   {
   1449     ps_parser_skip_spaces( parser );
   1450     return ps_tofixedarray( &parser->cursor, parser->limit,
   1451                             max_values, values, power_ten );
   1452   }
   1453 
   1454 
   1455 #if 0
   1456 
   1457   FT_LOCAL_DEF( FT_String* )
   1458   T1_ToString( PS_Parser  parser )
   1459   {
   1460     return ps_tostring( &parser->cursor, parser->limit, parser->memory );
   1461   }
   1462 
   1463 
   1464   FT_LOCAL_DEF( FT_Bool )
   1465   T1_ToBool( PS_Parser  parser )
   1466   {
   1467     return ps_tobool( &parser->cursor, parser->limit );
   1468   }
   1469 
   1470 #endif /* 0 */
   1471 
   1472 
   1473   FT_LOCAL_DEF( void )
   1474   ps_parser_init( PS_Parser  parser,
   1475                   FT_Byte*   base,
   1476                   FT_Byte*   limit,
   1477                   FT_Memory  memory )
   1478   {
   1479     parser->error  = FT_Err_Ok;
   1480     parser->base   = base;
   1481     parser->limit  = limit;
   1482     parser->cursor = base;
   1483     parser->memory = memory;
   1484     parser->funcs  = ps_parser_funcs;
   1485   }
   1486 
   1487 
   1488   FT_LOCAL_DEF( void )
   1489   ps_parser_done( PS_Parser  parser )
   1490   {
   1491     FT_UNUSED( parser );
   1492   }
   1493 
   1494 
   1495   /*************************************************************************/
   1496   /*************************************************************************/
   1497   /*****                                                               *****/
   1498   /*****                            T1 BUILDER                         *****/
   1499   /*****                                                               *****/
   1500   /*************************************************************************/
   1501   /*************************************************************************/
   1502 
   1503   /*************************************************************************/
   1504   /*                                                                       */
   1505   /* <Function>                                                            */
   1506   /*    t1_builder_init                                                    */
   1507   /*                                                                       */
   1508   /* <Description>                                                         */
   1509   /*    Initializes a given glyph builder.                                 */
   1510   /*                                                                       */
   1511   /* <InOut>                                                               */
   1512   /*    builder :: A pointer to the glyph builder to initialize.           */
   1513   /*                                                                       */
   1514   /* <Input>                                                               */
   1515   /*    face    :: The current face object.                                */
   1516   /*                                                                       */
   1517   /*    size    :: The current size object.                                */
   1518   /*                                                                       */
   1519   /*    glyph   :: The current glyph object.                               */
   1520   /*                                                                       */
   1521   /*    hinting :: Whether hinting should be applied.                      */
   1522   /*                                                                       */
   1523   FT_LOCAL_DEF( void )
   1524   t1_builder_init( T1_Builder    builder,
   1525                    FT_Face       face,
   1526                    FT_Size       size,
   1527                    FT_GlyphSlot  glyph,
   1528                    FT_Bool       hinting )
   1529   {
   1530     builder->parse_state = T1_Parse_Start;
   1531     builder->load_points = 1;
   1532 
   1533     builder->face   = face;
   1534     builder->glyph  = glyph;
   1535     builder->memory = face->memory;
   1536 
   1537     if ( glyph )
   1538     {
   1539       FT_GlyphLoader  loader = glyph->internal->loader;
   1540 
   1541 
   1542       builder->loader  = loader;
   1543       builder->base    = &loader->base.outline;
   1544       builder->current = &loader->current.outline;
   1545       FT_GlyphLoader_Rewind( loader );
   1546 
   1547       builder->hints_globals = size->internal;
   1548       builder->hints_funcs   = 0;
   1549 
   1550       if ( hinting )
   1551         builder->hints_funcs = glyph->internal->glyph_hints;
   1552     }
   1553 
   1554     builder->pos_x = 0;
   1555     builder->pos_y = 0;
   1556 
   1557     builder->left_bearing.x = 0;
   1558     builder->left_bearing.y = 0;
   1559     builder->advance.x      = 0;
   1560     builder->advance.y      = 0;
   1561 
   1562     builder->funcs = t1_builder_funcs;
   1563   }
   1564 
   1565 
   1566   /*************************************************************************/
   1567   /*                                                                       */
   1568   /* <Function>                                                            */
   1569   /*    t1_builder_done                                                    */
   1570   /*                                                                       */
   1571   /* <Description>                                                         */
   1572   /*    Finalizes a given glyph builder.  Its contents can still be used   */
   1573   /*    after the call, but the function saves important information       */
   1574   /*    within the corresponding glyph slot.                               */
   1575   /*                                                                       */
   1576   /* <Input>                                                               */
   1577   /*    builder :: A pointer to the glyph builder to finalize.             */
   1578   /*                                                                       */
   1579   FT_LOCAL_DEF( void )
   1580   t1_builder_done( T1_Builder  builder )
   1581   {
   1582     FT_GlyphSlot  glyph = builder->glyph;
   1583 
   1584 
   1585     if ( glyph )
   1586       glyph->outline = *builder->base;
   1587   }
   1588 
   1589 
   1590   /* check that there is enough space for `count' more points */
   1591   FT_LOCAL_DEF( FT_Error )
   1592   t1_builder_check_points( T1_Builder  builder,
   1593                            FT_Int      count )
   1594   {
   1595     return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
   1596   }
   1597 
   1598 
   1599   /* add a new point, do not check space */
   1600   FT_LOCAL_DEF( void )
   1601   t1_builder_add_point( T1_Builder  builder,
   1602                         FT_Pos      x,
   1603                         FT_Pos      y,
   1604                         FT_Byte     flag )
   1605   {
   1606     FT_Outline*  outline = builder->current;
   1607 
   1608 
   1609     if ( builder->load_points )
   1610     {
   1611       FT_Vector*  point   = outline->points + outline->n_points;
   1612       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
   1613 
   1614 
   1615       point->x = FIXED_TO_INT( x );
   1616       point->y = FIXED_TO_INT( y );
   1617       *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
   1618     }
   1619     outline->n_points++;
   1620   }
   1621 
   1622 
   1623   /* check space for a new on-curve point, then add it */
   1624   FT_LOCAL_DEF( FT_Error )
   1625   t1_builder_add_point1( T1_Builder  builder,
   1626                          FT_Pos      x,
   1627                          FT_Pos      y )
   1628   {
   1629     FT_Error  error;
   1630 
   1631 
   1632     error = t1_builder_check_points( builder, 1 );
   1633     if ( !error )
   1634       t1_builder_add_point( builder, x, y, 1 );
   1635 
   1636     return error;
   1637   }
   1638 
   1639 
   1640   /* check space for a new contour, then add it */
   1641   FT_LOCAL_DEF( FT_Error )
   1642   t1_builder_add_contour( T1_Builder  builder )
   1643   {
   1644     FT_Outline*  outline = builder->current;
   1645     FT_Error     error;
   1646 
   1647 
   1648     /* this might happen in invalid fonts */
   1649     if ( !outline )
   1650     {
   1651       FT_ERROR(( "t1_builder_add_contour: no outline to add points to\n" ));
   1652       return FT_THROW( Invalid_File_Format );
   1653     }
   1654 
   1655     if ( !builder->load_points )
   1656     {
   1657       outline->n_contours++;
   1658       return FT_Err_Ok;
   1659     }
   1660 
   1661     error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
   1662     if ( !error )
   1663     {
   1664       if ( outline->n_contours > 0 )
   1665         outline->contours[outline->n_contours - 1] =
   1666           (short)( outline->n_points - 1 );
   1667 
   1668       outline->n_contours++;
   1669     }
   1670 
   1671     return error;
   1672   }
   1673 
   1674 
   1675   /* if a path was begun, add its first on-curve point */
   1676   FT_LOCAL_DEF( FT_Error )
   1677   t1_builder_start_point( T1_Builder  builder,
   1678                           FT_Pos      x,
   1679                           FT_Pos      y )
   1680   {
   1681     FT_Error  error = FT_ERR( Invalid_File_Format );
   1682 
   1683 
   1684     /* test whether we are building a new contour */
   1685 
   1686     if ( builder->parse_state == T1_Parse_Have_Path )
   1687       error = FT_Err_Ok;
   1688     else
   1689     {
   1690       builder->parse_state = T1_Parse_Have_Path;
   1691       error = t1_builder_add_contour( builder );
   1692       if ( !error )
   1693         error = t1_builder_add_point1( builder, x, y );
   1694     }
   1695 
   1696     return error;
   1697   }
   1698 
   1699 
   1700   /* close the current contour */
   1701   FT_LOCAL_DEF( void )
   1702   t1_builder_close_contour( T1_Builder  builder )
   1703   {
   1704     FT_Outline*  outline = builder->current;
   1705     FT_Int       first;
   1706 
   1707 
   1708     if ( !outline )
   1709       return;
   1710 
   1711     first = outline->n_contours <= 1
   1712             ? 0 : outline->contours[outline->n_contours - 2] + 1;
   1713 
   1714     /* We must not include the last point in the path if it */
   1715     /* is located on the first point.                       */
   1716     if ( outline->n_points > 1 )
   1717     {
   1718       FT_Vector*  p1      = outline->points + first;
   1719       FT_Vector*  p2      = outline->points + outline->n_points - 1;
   1720       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
   1721 
   1722 
   1723       /* `delete' last point only if it coincides with the first */
   1724       /* point and it is not a control point (which can happen). */
   1725       if ( p1->x == p2->x && p1->y == p2->y )
   1726         if ( *control == FT_CURVE_TAG_ON )
   1727           outline->n_points--;
   1728     }
   1729 
   1730     if ( outline->n_contours > 0 )
   1731     {
   1732       /* Don't add contours only consisting of one point, i.e.,  */
   1733       /* check whether the first and the last point is the same. */
   1734       if ( first == outline->n_points - 1 )
   1735       {
   1736         outline->n_contours--;
   1737         outline->n_points--;
   1738       }
   1739       else
   1740         outline->contours[outline->n_contours - 1] =
   1741           (short)( outline->n_points - 1 );
   1742     }
   1743   }
   1744 
   1745 
   1746   /*************************************************************************/
   1747   /*************************************************************************/
   1748   /*****                                                               *****/
   1749   /*****                            OTHER                              *****/
   1750   /*****                                                               *****/
   1751   /*************************************************************************/
   1752   /*************************************************************************/
   1753 
   1754   FT_LOCAL_DEF( void )
   1755   t1_decrypt( FT_Byte*   buffer,
   1756               FT_Offset  length,
   1757               FT_UShort  seed )
   1758   {
   1759     PS_Conv_EexecDecode( &buffer,
   1760                          buffer + length,
   1761                          buffer,
   1762                          length,
   1763                          &seed );
   1764   }
   1765 
   1766 
   1767 /* END */
   1768