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