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