Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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