tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

psobjs.c (66497B)


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