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