1a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/***************************************************************************/
2a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*                                                                         */
3a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  cf2intrp.c                                                             */
4a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*                                                                         */
5a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*    Adobe's CFF Interpreter (body).                                      */
6a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*                                                                         */
7a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  Copyright 2007-2013 Adobe Systems Incorporated.                        */
8a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*                                                                         */
9a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  This software, and all works of authorship, whether in source or       */
10a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  object code form as indicated by the copyright notice(s) included      */
11a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  herein (collectively, the "Work") is made available, and may only be   */
12a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  used, modified, and distributed under the FreeType Project License,    */
13a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
14a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  FreeType Project License, each contributor to the Work hereby grants   */
15a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  to any individual or legal entity exercising permissions granted by    */
16a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  the FreeType Project License and this section (hereafter, "You" or     */
17a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
18a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  royalty-free, irrevocable (except as stated in this section) patent    */
19a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  license to make, have made, use, offer to sell, sell, import, and      */
20a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  otherwise transfer the Work, where such license applies only to those  */
21a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  patent claims licensable by such contributor that are necessarily      */
22a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  infringed by their contribution(s) alone or by combination of their    */
23a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  contribution(s) with the Work to which such contribution(s) was        */
24a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  submitted.  If You institute patent litigation against any entity      */
25a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
26a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  the Work or a contribution incorporated within the Work constitutes    */
27a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  direct or contributory patent infringement, then any patent licenses   */
28a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  granted to You under this License for that Work shall terminate as of  */
29a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  the date such litigation is filed.                                     */
30a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*                                                                         */
31a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  By using, modifying, or distributing the Work you indicate that you    */
32a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  have read and understood the terms and conditions of the               */
33a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  FreeType Project License as well as those provided in this section,    */
34a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*  and you accept them fully.                                             */
35a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/*                                                                         */
36a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/***************************************************************************/
37a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
38a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
39a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#include "cf2ft.h"
40a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#include FT_INTERNAL_DEBUG_H
41a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
42a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#include "cf2glue.h"
43a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#include "cf2font.h"
44a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#include "cf2stack.h"
45a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#include "cf2hints.h"
46a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
47a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#include "cf2error.h"
48a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
49a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
50a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*************************************************************************/
51a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*                                                                       */
52a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
53a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
54a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /* messages during execution.                                            */
55a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*                                                                       */
56a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#undef  FT_COMPONENT
57a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define FT_COMPONENT  trace_cf2interp
58a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
59a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
60a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /* some operators are not implemented yet */
61a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#define CF2_FIXME  FT_TRACE4(( "cf2_interpT2CharString:"            \
62a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                               " operator not implemented yet\n" ))
63a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
64a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
65a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
66a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_LOCAL_DEF( void )
67a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  cf2_hintmask_init( CF2_HintMask  hintmask,
68a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     FT_Error*     error )
69a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
70a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_ZERO( hintmask );
71a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
72a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    hintmask->error = error;
73a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
74a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
75a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
76a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_LOCAL_DEF( FT_Bool )
77a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  cf2_hintmask_isValid( const CF2_HintMask  hintmask )
78a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
79a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return hintmask->isValid;
80a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
81a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
82a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
83a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_LOCAL_DEF( FT_Bool )
84a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  cf2_hintmask_isNew( const CF2_HintMask  hintmask )
85a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
86a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return hintmask->isNew;
87a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
88a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
89a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
90a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_LOCAL_DEF( void )
91a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  cf2_hintmask_setNew( CF2_HintMask  hintmask,
92a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                       FT_Bool       val )
93a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
94a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    hintmask->isNew = val;
95a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
96a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
97a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
98a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /* clients call `getMaskPtr' in order to iterate */
99a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /* through hint mask                             */
100a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
101a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_LOCAL_DEF( FT_Byte* )
102a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  cf2_hintmask_getMaskPtr( CF2_HintMask  hintmask )
103a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
104a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return hintmask->mask;
105a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
106a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
107a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
108a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  static size_t
109a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  cf2_hintmask_setCounts( CF2_HintMask  hintmask,
110a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          size_t        bitCount )
111a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
112a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( bitCount > CF2_MAX_HINTS )
113a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
114a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      /* total of h and v stems must be <= 96 */
115a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      CF2_SET_ERROR( hintmask->error, Invalid_Glyph_Format );
116a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return 0;
117a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    }
118a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
119a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    hintmask->bitCount  = bitCount;
120a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    hintmask->byteCount = ( hintmask->bitCount + 7 ) / 8;
121a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
122a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    hintmask->isValid = TRUE;
123a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    hintmask->isNew   = TRUE;
124a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
125a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return bitCount;
126a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
127a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
128a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
129a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /* consume the hintmask bytes from the charstring, advancing the src */
130a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /* pointer                                                           */
131a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  static void
132a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  cf2_hintmask_read( CF2_HintMask  hintmask,
133a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     CF2_Buffer    charstring,
134a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     size_t        bitCount )
135a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
136a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    size_t  i;
137a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
138a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#ifndef CF2_NDEBUG
139a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* these are the bits in the final mask byte that should be zero  */
140a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* Note: this variable is only used in an assert expression below */
141a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* and then only if CF2_NDEBUG is not defined                     */
142a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    CF2_UInt  mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1;
143a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#endif
144a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
145a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
146a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* initialize counts and isValid */
147a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 )
148a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return;
149a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
150a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_ASSERT( hintmask->byteCount > 0 );
151a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
152a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_TRACE4(( " (maskbytes:" ));
153a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
154a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* set mask and advance interpreter's charstring pointer */
155a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    for ( i = 0; i < hintmask->byteCount; i++ )
156a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
157a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      hintmask->mask[i] = (FT_Byte)cf2_buf_readByte( charstring );
158a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_TRACE4(( " 0x%02X", hintmask->mask[i] ));
159a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    }
160a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
161a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_TRACE4(( ")\n" ));
162a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
163a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* assert any unused bits in last byte are zero unless there's a prior */
164a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* error                                                               */
165a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1      */
166a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#ifndef CF2_NDEBUG
167a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_ASSERT( ( hintmask->mask[hintmask->byteCount - 1] & mask ) == 0 ||
168a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang               *hintmask->error                                        );
169a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang#endif
170a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
171a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
172a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
173a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_LOCAL_DEF( void )
174a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  cf2_hintmask_setAll( CF2_HintMask  hintmask,
175a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                       size_t        bitCount )
176a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
177a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    size_t    i;
178a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    CF2_UInt  mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1;
179a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
180a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
181a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* initialize counts and isValid */
182a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 )
183a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      return;
184a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
185a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_ASSERT( hintmask->byteCount > 0 );
186a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_ASSERT( hintmask->byteCount <
187a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                 sizeof ( hintmask->mask ) / sizeof ( hintmask->mask[0] ) );
188a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
189a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* set mask to all ones */
190a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    for ( i = 0; i < hintmask->byteCount; i++ )
191a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      hintmask->mask[i] = 0xFF;
192a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
193a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* clear unused bits                                              */
194a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1 */
195a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    hintmask->mask[hintmask->byteCount - 1] &= ~mask;
196a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
197a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
198a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
199a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /* Type2 charstring opcodes */
200a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  enum
201a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
202a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdRESERVED_0,   /* 0 */
203a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdHSTEM,        /* 1 */
204a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdRESERVED_2,   /* 2 */
205a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdVSTEM,        /* 3 */
206a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdVMOVETO,      /* 4 */
207a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdRLINETO,      /* 5 */
208a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdHLINETO,      /* 6 */
209a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdVLINETO,      /* 7 */
210a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdRRCURVETO,    /* 8 */
211a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdRESERVED_9,   /* 9 */
212a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdCALLSUBR,     /* 10 */
213a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdRETURN,       /* 11 */
214a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdESC,          /* 12 */
215a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdRESERVED_13,  /* 13 */
216a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdENDCHAR,      /* 14 */
217a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdRESERVED_15,  /* 15 */
218a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdRESERVED_16,  /* 16 */
219a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdRESERVED_17,  /* 17 */
220a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdHSTEMHM,      /* 18 */
221a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdHINTMASK,     /* 19 */
222a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdCNTRMASK,     /* 20 */
223a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdRMOVETO,      /* 21 */
224a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdHMOVETO,      /* 22 */
225a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdVSTEMHM,      /* 23 */
226a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdRCURVELINE,   /* 24 */
227a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdRLINECURVE,   /* 25 */
228a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdVVCURVETO,    /* 26 */
229a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdHHCURVETO,    /* 27 */
230a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdEXTENDEDNMBR, /* 28 */
231a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdCALLGSUBR,    /* 29 */
232a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdVHCURVETO,    /* 30 */
233a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_cmdHVCURVETO     /* 31 */
234a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  };
235a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
236a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  enum
237a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
238a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escDOTSECTION,   /* 0 */
239a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escRESERVED_1,   /* 1 */
240a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escRESERVED_2,   /* 2 */
241a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escAND,          /* 3 */
242a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escOR,           /* 4 */
243a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escNOT,          /* 5 */
244a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escRESERVED_6,   /* 6 */
245a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escRESERVED_7,   /* 7 */
246a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escRESERVED_8,   /* 8 */
247a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escABS,          /* 9 */
248a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escADD,          /* 10     like otherADD */
249a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escSUB,          /* 11     like otherSUB */
250a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escDIV,          /* 12 */
251a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escRESERVED_13,  /* 13 */
252a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escNEG,          /* 14 */
253a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escEQ,           /* 15 */
254a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escRESERVED_16,  /* 16 */
255a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escRESERVED_17,  /* 17 */
256a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escDROP,         /* 18 */
257a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escRESERVED_19,  /* 19 */
258a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escPUT,          /* 20     like otherPUT    */
259a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escGET,          /* 21     like otherGET    */
260a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escIFELSE,       /* 22     like otherIFELSE */
261a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escRANDOM,       /* 23     like otherRANDOM */
262a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escMUL,          /* 24     like otherMUL    */
263a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escRESERVED_25,  /* 25 */
264a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escSQRT,         /* 26 */
265a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escDUP,          /* 27     like otherDUP    */
266a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escEXCH,         /* 28     like otherEXCH   */
267a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escINDEX,        /* 29 */
268a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escROLL,         /* 30 */
269a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escRESERVED_31,  /* 31 */
270a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escRESERVED_32,  /* 32 */
271a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escRESERVED_33,  /* 33 */
272a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escHFLEX,        /* 34 */
273a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escFLEX,         /* 35 */
274a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escHFLEX1,       /* 36 */
275a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_escFLEX1         /* 37 */
276a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  };
277a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
278a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
279a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /* `stemHintArray' does not change once we start drawing the outline. */
280a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  static void
281a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  cf2_doStems( const CF2_Font  font,
282a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang               CF2_Stack       opStack,
283a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang               CF2_ArrStack    stemHintArray,
284a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang               CF2_Fixed*      width,
285a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang               FT_Bool*        haveWidth,
286a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang               CF2_Fixed       hintOffset )
287a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
288a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    CF2_UInt  i;
289a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    CF2_UInt  count       = cf2_stack_count( opStack );
290a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Bool   hasWidthArg = count & 1;
291a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
292a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* variable accumulates delta values from operand stack */
293a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    CF2_Fixed  position = hintOffset;
294a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
295a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( hasWidthArg && ! *haveWidth )
296a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      *width = cf2_stack_getReal( opStack, 0 ) +
297a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                 cf2_getNominalWidthX( font->decoder );
298a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
299a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( font->decoder->width_only )
300a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      goto exit;
301a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
302a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    for ( i = hasWidthArg ? 1 : 0; i < count; i += 2 )
303a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
304a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      /* construct a CF2_StemHint and push it onto the list */
305a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      CF2_StemHintRec  stemhint;
306a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
307a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
308a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      stemhint.min  =
309a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        position   += cf2_stack_getReal( opStack, i );
310a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      stemhint.max  =
311a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        position   += cf2_stack_getReal( opStack, i + 1 );
312a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
313a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      stemhint.used  = FALSE;
314a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      stemhint.maxDS =
315a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      stemhint.minDS = 0;
316a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
317a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      cf2_arrstack_push( stemHintArray, &stemhint ); /* defer error check */
318a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    }
319a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
320a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_stack_clear( opStack );
321a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
322a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  exit:
323a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* cf2_doStems must define a width (may be default) */
324a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    *haveWidth = TRUE;
325a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
326a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
327a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
328a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  static void
329a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  cf2_doFlex( CF2_Stack       opStack,
330a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              CF2_Fixed*      curX,
331a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              CF2_Fixed*      curY,
332a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              CF2_GlyphPath   glyphPath,
333a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              const FT_Bool*  readFromStack,
334a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              FT_Bool         doConditionalLastRead )
335a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
336a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    CF2_Fixed  vals[14];
337a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    CF2_UInt   index;
338a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Bool    isHFlex;
339a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    CF2_Int    top, i, j;
340a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
341a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
342a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    vals[0] = *curX;
343a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    vals[1] = *curY;
344a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    index   = 0;
345a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    isHFlex = readFromStack[9] == FALSE;
346a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    top     = isHFlex ? 9 : 10;
347a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
348a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    for ( i = 0; i < top; i++ )
349a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
350a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      vals[i + 2] = vals[i];
351a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( readFromStack[i] )
352a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        vals[i + 2] += cf2_stack_getReal( opStack, index++ );
353a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    }
354a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
355a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( isHFlex )
356a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      vals[9 + 2] = *curY;
357a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
358a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( doConditionalLastRead )
359a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
360a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      FT_Bool    lastIsX = cf2_fixedAbs( vals[10] - *curX ) >
361a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                             cf2_fixedAbs( vals[11] - *curY );
362a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      CF2_Fixed  lastVal = cf2_stack_getReal( opStack, index );
363a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
364a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
365a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( lastIsX )
366a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      {
367a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        vals[12] = vals[10] + lastVal;
368a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        vals[13] = *curY;
369a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      }
370a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      else
371a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      {
372a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        vals[12] = *curX;
373a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        vals[13] = vals[11] + lastVal;
374a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      }
375a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    }
376a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    else
377a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
378a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( readFromStack[10] )
379a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        vals[12] = vals[10] + cf2_stack_getReal( opStack, index++ );
380a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      else
381a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        vals[12] = *curX;
382a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
383a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( readFromStack[11] )
384a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        vals[13] = vals[11] + cf2_stack_getReal( opStack, index );
385a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      else
386a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        vals[13] = *curY;
387a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    }
388a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
389a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    for ( j = 0; j < 2; j++ )
390a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      cf2_glyphpath_curveTo( glyphPath, vals[j * 6 + 2],
391a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                        vals[j * 6 + 3],
392a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                        vals[j * 6 + 4],
393a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                        vals[j * 6 + 5],
394a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                        vals[j * 6 + 6],
395a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                        vals[j * 6 + 7] );
396a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
397a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_stack_clear( opStack );
398a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
399a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    *curX = vals[12];
400a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    *curY = vals[13];
401a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
402a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
403a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
404a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  /*
405a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   * `error' is a shared error code used by many objects in this
406a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   * routine.  Before the code continues from an error, it must check and
407a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   * record the error in `*error'.  The idea is that this shared
408a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   * error code will record the first error encountered.  If testing
409a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   * for an error anyway, the cost of `goto exit' is small, so we do it,
410a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   * even if continuing would be safe.  In this case, `lastError' is
411a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   * set, so the testing and storing can be done in one place, at `exit'.
412a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   *
413a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   * Continuing after an error is intended for objects which do their own
414a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   * testing of `*error', e.g., array stack functions.  This allows us to
415a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   * avoid an extra test after the call.
416a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   *
417a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   * Unimplemented opcodes are ignored.
418a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   *
419a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang   */
420a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  FT_LOCAL_DEF( void )
421a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  cf2_interpT2CharString( CF2_Font              font,
422a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          CF2_Buffer            buf,
423a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          CF2_OutlineCallbacks  callbacks,
424a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          const FT_Vector*      translation,
425a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          FT_Bool               doingSeac,
426a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          CF2_Fixed             curX,
427a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          CF2_Fixed             curY,
428a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          CF2_Fixed*            width )
429a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  {
430a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* lastError is used for errors that are immediately tested */
431a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error  lastError = FT_Err_Ok;
432a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
433a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* pointer to parsed font object */
434a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    CFF_Decoder*  decoder = font->decoder;
435a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
436a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Error*  error  = &font->error;
437a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Memory  memory = font->memory;
438a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
439a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    CF2_Fixed  scaleY        = font->innerTransform.d;
440a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    CF2_Fixed  nominalWidthX = cf2_getNominalWidthX( decoder );
441a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
442a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* save this for hinting seac accents */
443a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    CF2_Fixed  hintOriginY = curY;
444a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
445a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    CF2_Stack  opStack = NULL;
446a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Byte    op1;                       /* first opcode byte */
447a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
448a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* instruction limit; 20,000,000 matches Avalon */
449a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_UInt32  instructionLimit = 20000000UL;
450a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
451a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    CF2_ArrStackRec  subrStack;
452a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
453a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_Bool     haveWidth;
454a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    CF2_Buffer  charstring = NULL;
455a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
456a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    CF2_Int  charstringIndex = -1;       /* initialize to empty */
457a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
458a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* TODO: placeholders for hint structures */
459a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
460a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* objects used for hinting */
461a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    CF2_ArrStackRec  hStemHintArray;
462a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    CF2_ArrStackRec  vStemHintArray;
463a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
464a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    CF2_HintMaskRec   hintMask;
465a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    CF2_GlyphPathRec  glyphPath;
466a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
467a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
468a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* initialize the remaining objects */
469a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_arrstack_init( &subrStack,
470a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                       memory,
471a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                       error,
472a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                       sizeof ( CF2_BufferRec ) );
473a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_arrstack_init( &hStemHintArray,
474a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                       memory,
475a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                       error,
476a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                       sizeof ( CF2_StemHintRec ) );
477a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_arrstack_init( &vStemHintArray,
478a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                       memory,
479a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                       error,
480a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                       sizeof ( CF2_StemHintRec ) );
481a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
482a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* initialize CF2_StemHint arrays */
483a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_hintmask_init( &hintMask, error );
484a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
485a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* initialize path map to manage drawing operations */
486a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
487a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* Note: last 4 params are used to handle `MoveToPermissive', which */
488a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /*       may need to call `hintMap.Build'                           */
489a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* TODO: MoveToPermissive is gone; are these still needed?          */
490a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_glyphpath_init( &glyphPath,
491a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                        font,
492a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                        callbacks,
493a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                        scaleY,
494a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                        /* hShift, */
495a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                        &hStemHintArray,
496a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                        &vStemHintArray,
497a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                        &hintMask,
498a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                        hintOriginY,
499a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                        &font->blues,
500a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                        translation );
501a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
502a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /*
503a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang     * Initialize state for width parsing.  From the CFF Spec:
504a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang     *
505a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang     *   The first stack-clearing operator, which must be one of hstem,
506a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang     *   hstemhm, vstem, vstemhm, cntrmask, hintmask, hmoveto, vmoveto,
507a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang     *   rmoveto, or endchar, takes an additional argument - the width (as
508a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang     *   described earlier), which may be expressed as zero or one numeric
509a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang     *   argument.
510a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang     *
511a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang     * What we implement here uses the first validly specified width, but
512a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang     * does not detect errors for specifying more than one width.
513a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang     *
514a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang     * If one of the above operators occurs without explicitly specifying
515a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang     * a width, we assume the default width.
516a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang     *
517a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang     */
518a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    haveWidth = FALSE;
519a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    *width    = cf2_getDefaultWidthX( decoder );
520a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
521a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /*
522a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang     * Note: at this point, all pointers to resources must be NULL
523a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang     * and all local objects must be initialized.
524a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang     * There must be no branches to exit: above this point.
525a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang     *
526a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang     */
527a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
528a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* allocate an operand stack */
529a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    opStack = cf2_stack_init( memory, error );
530a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( !opStack )
531a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
532a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      lastError = FT_THROW( Out_Of_Memory );
533a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      goto exit;
534a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    }
535a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
536a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* initialize subroutine stack by placing top level charstring as */
537a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* first element (max depth plus one for the charstring)          */
538a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* Note: Caller owns and must finalize the first charstring.      */
539a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /*       Our copy of it does not change that requirement.         */
540a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_arrstack_setCount( &subrStack, CF2_MAX_SUBR + 1 );
541a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
542a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    charstring  = (CF2_Buffer)cf2_arrstack_getBuffer( &subrStack );
543a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    *charstring = *buf;    /* structure copy */
544a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
545a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    charstringIndex = 0;       /* entry is valid now */
546a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
547a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* catch errors so far */
548a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    if ( *error )
549a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      goto exit;
550a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
551a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* main interpreter loop */
552a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    while ( 1 )
553a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    {
554a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( cf2_buf_isEnd( charstring ) )
555a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      {
556a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        /* If we've reached the end of the charstring, simulate a */
557a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        /* cf2_cmdRETURN or cf2_cmdENDCHAR.                       */
558a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( charstringIndex )
559a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          op1 = cf2_cmdRETURN;  /* end of buffer for subroutine */
560a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        else
561a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          op1 = cf2_cmdENDCHAR; /* end of buffer for top level charstring */
562a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      }
563a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      else
564a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        op1 = (FT_Byte)cf2_buf_readByte( charstring );
565a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
566a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      /* check for errors once per loop */
567a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( *error )
568a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        goto exit;
569a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
570a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      instructionLimit--;
571a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      if ( instructionLimit == 0 )
572a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      {
573a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        lastError = FT_THROW( Invalid_Glyph_Format );
574a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        goto exit;
575a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      }
576a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
577a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      switch( op1 )
578a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      {
579a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdRESERVED_0:
580a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdRESERVED_2:
581a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdRESERVED_9:
582a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdRESERVED_13:
583a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdRESERVED_15:
584a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdRESERVED_16:
585a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdRESERVED_17:
586a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        /* we may get here if we have a prior error */
587a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        FT_TRACE4(( " unknown op (%d)\n", op1 ));
588a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        break;
589a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
590a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdHSTEMHM:
591a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdHSTEM:
592a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        FT_TRACE4(( op1 == cf2_cmdHSTEMHM ? " hstemhm\n" : " hstem\n" ));
593a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
594a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        /* never add hints after the mask is computed */
595a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( cf2_hintmask_isValid( &hintMask ) )
596a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          FT_TRACE4(( "cf2_interpT2CharString:"
597a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                      " invalid horizontal hint mask\n" ));
598a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
599a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        cf2_doStems( font,
600a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     opStack,
601a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     &hStemHintArray,
602a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     width,
603a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     &haveWidth,
604a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     0 );
605a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
606a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( font->decoder->width_only )
607a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            goto exit;
608a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
609a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        break;
610a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
611a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdVSTEMHM:
612a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdVSTEM:
613a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        FT_TRACE4(( op1 == cf2_cmdVSTEMHM ? " vstemhm\n" : " vstem\n" ));
614a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
615a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        /* never add hints after the mask is computed */
616a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( cf2_hintmask_isValid( &hintMask ) )
617a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          FT_TRACE4(( "cf2_interpT2CharString:"
618a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                      " invalid vertical hint mask\n" ));
619a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
620a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        cf2_doStems( font,
621a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     opStack,
622a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     &vStemHintArray,
623a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     width,
624a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     &haveWidth,
625a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     0 );
626a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
627a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( font->decoder->width_only )
628a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            goto exit;
629a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
630a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        break;
631a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
632a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdVMOVETO:
633a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        FT_TRACE4(( " vmoveto\n" ));
634a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
635a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( cf2_stack_count( opStack ) > 1 && !haveWidth )
636a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
637a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
638a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        /* width is defined or default after this */
639a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        haveWidth = TRUE;
640a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
641a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( font->decoder->width_only )
642a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            goto exit;
643a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
644a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        curY += cf2_stack_popFixed( opStack );
645a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
646a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        cf2_glyphpath_moveTo( &glyphPath, curX, curY );
647a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
648a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        break;
649a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
650a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdRLINETO:
651a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {
652a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          CF2_UInt  index;
653a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          CF2_UInt  count = cf2_stack_count( opStack );
654a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
655a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
656a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          FT_TRACE4(( " rlineto\n" ));
657a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
658a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          for ( index = 0; index < count; index += 2 )
659a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          {
660a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            curX += cf2_stack_getReal( opStack, index + 0 );
661a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            curY += cf2_stack_getReal( opStack, index + 1 );
662a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
663a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            cf2_glyphpath_lineTo( &glyphPath, curX, curY );
664a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          }
665a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
666a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          cf2_stack_clear( opStack );
667a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        }
668a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        continue; /* no need to clear stack again */
669a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
670a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdHLINETO:
671a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdVLINETO:
672a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {
673a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          CF2_UInt  index;
674a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          CF2_UInt  count = cf2_stack_count( opStack );
675a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
676a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          FT_Bool  isX = op1 == cf2_cmdHLINETO;
677a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
678a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
679a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          FT_TRACE4(( isX ? " hlineto\n" : " vlineto\n" ));
680a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
681a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          for ( index = 0; index < count; index++ )
682a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          {
683a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_Fixed  v = cf2_stack_getReal( opStack, index );
684a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
685a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
686a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            if ( isX )
687a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              curX += v;
688a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            else
689a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              curY += v;
690a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
691a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            isX = !isX;
692a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
693a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            cf2_glyphpath_lineTo( &glyphPath, curX, curY );
694a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          }
695a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
696a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          cf2_stack_clear( opStack );
697a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        }
698a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        continue;
699a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
700a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdRCURVELINE:
701a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdRRCURVETO:
702a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {
703a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          CF2_UInt  count = cf2_stack_count( opStack );
704a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          CF2_UInt  index = 0;
705a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
706a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
707a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          FT_TRACE4(( op1 == cf2_cmdRCURVELINE ? " rcurveline\n"
708a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                               : " rrcurveto\n" ));
709a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
710a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          while ( index + 6 <= count )
711a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          {
712a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_Fixed  x1 = cf2_stack_getReal( opStack, index + 0 ) + curX;
713a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_Fixed  y1 = cf2_stack_getReal( opStack, index + 1 ) + curY;
714a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_Fixed  x2 = cf2_stack_getReal( opStack, index + 2 ) + x1;
715a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_Fixed  y2 = cf2_stack_getReal( opStack, index + 3 ) + y1;
716a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_Fixed  x3 = cf2_stack_getReal( opStack, index + 4 ) + x2;
717a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_Fixed  y3 = cf2_stack_getReal( opStack, index + 5 ) + y2;
718a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
719a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
720a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
721a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
722a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            curX   = x3;
723a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            curY   = y3;
724a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            index += 6;
725a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          }
726a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
727a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          if ( op1 == cf2_cmdRCURVELINE )
728a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          {
729a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            curX += cf2_stack_getReal( opStack, index + 0 );
730a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            curY += cf2_stack_getReal( opStack, index + 1 );
731a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
732a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            cf2_glyphpath_lineTo( &glyphPath, curX, curY );
733a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          }
734a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
735a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          cf2_stack_clear( opStack );
736a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        }
737a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        continue; /* no need to clear stack again */
738a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
739a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdCALLGSUBR:
740a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdCALLSUBR:
741a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {
742a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          CF2_UInt  subrIndex;
743a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
744a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
745a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          FT_TRACE4(( op1 == cf2_cmdCALLGSUBR ? " callgsubr"
746a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                              : " callsubr" ));
747a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
748a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          if ( charstringIndex > CF2_MAX_SUBR )
749a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          {
750a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            /* max subr plus one for charstring */
751a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            lastError = FT_THROW( Invalid_Glyph_Format );
752a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            goto exit;                      /* overflow of stack */
753a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          }
754a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
755a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          /* push our current CFF charstring region on subrStack */
756a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          charstring = (CF2_Buffer)
757a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                         cf2_arrstack_getPointer( &subrStack,
758a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                                  charstringIndex + 1 );
759a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
760a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          /* set up the new CFF region and pointer */
761a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          subrIndex = cf2_stack_popInt( opStack );
762a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
763a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          switch ( op1 )
764a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          {
765a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_cmdCALLGSUBR:
766a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( "(%d)\n", subrIndex + decoder->globals_bias ));
767a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
768a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            if ( cf2_initGlobalRegionBuffer( decoder,
769a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                             subrIndex,
770a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                             charstring ) )
771a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            {
772a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              lastError = FT_THROW( Invalid_Glyph_Format );
773a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              goto exit;  /* subroutine lookup or stream error */
774a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            }
775a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
776a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
777a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          default:
778a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            /* cf2_cmdCALLSUBR */
779a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( "(%d)\n", subrIndex + decoder->locals_bias ));
780a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
781a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            if ( cf2_initLocalRegionBuffer( decoder,
782a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                            subrIndex,
783a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                            charstring ) )
784a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            {
785a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              lastError = FT_THROW( Invalid_Glyph_Format );
786a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              goto exit;  /* subroutine lookup or stream error */
787a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            }
788a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          }
789a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
790a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          charstringIndex += 1;       /* entry is valid now */
791a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        }
792a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        continue; /* do not clear the stack */
793a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
794a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdRETURN:
795a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        FT_TRACE4(( " return\n" ));
796a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
797a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( charstringIndex < 1 )
798a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {
799a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          /* Note: cannot return from top charstring */
800a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          lastError = FT_THROW( Invalid_Glyph_Format );
801a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          goto exit;                      /* underflow of stack */
802a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        }
803a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
804a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        /* restore position in previous charstring */
805a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        charstring = (CF2_Buffer)
806a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                       cf2_arrstack_getPointer( &subrStack,
807a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                                --charstringIndex );
808a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        continue;     /* do not clear the stack */
809a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
810a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdESC:
811a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {
812a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          FT_Byte  op2 = (FT_Byte)cf2_buf_readByte( charstring );
813a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
814a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
815a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          switch ( op2 )
816a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          {
817a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escDOTSECTION:
818a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            /* something about `flip type of locking' -- ignore it */
819a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " dotsection\n" ));
820a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
821a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
822a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
823a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          /* TODO: should these operators be supported? */
824a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escAND: /* in spec */
825a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " and\n" ));
826a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
827a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_FIXME;
828a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
829a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
830a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escOR: /* in spec */
831a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " or\n" ));
832a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
833a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_FIXME;
834a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
835a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
836a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escNOT: /* in spec */
837a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " not\n" ));
838a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
839a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_FIXME;
840a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
841a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
842a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escABS: /* in spec */
843a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " abs\n" ));
844a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
845a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_FIXME;
846a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
847a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
848a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escADD: /* in spec */
849a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " add\n" ));
850a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
851a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_FIXME;
852a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
853a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
854a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escSUB: /* in spec */
855a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " sub\n" ));
856a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
857a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_FIXME;
858a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
859a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
860a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escDIV: /* in spec */
861a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " div\n" ));
862a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
863a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_FIXME;
864a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
865a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
866a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escNEG: /* in spec */
867a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " neg\n" ));
868a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
869a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_FIXME;
870a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
871a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
872a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escEQ: /* in spec */
873a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " eq\n" ));
874a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
875a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_FIXME;
876a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
877a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
878a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escDROP: /* in spec */
879a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " drop\n" ));
880a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
881a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_FIXME;
882a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
883a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
884a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escPUT: /* in spec */
885a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " put\n" ));
886a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
887a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_FIXME;
888a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
889a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
890a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escGET: /* in spec */
891a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " get\n" ));
892a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
893a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_FIXME;
894a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
895a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
896a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escIFELSE: /* in spec */
897a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " ifelse\n" ));
898a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
899a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_FIXME;
900a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
901a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
902a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escRANDOM: /* in spec */
903a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " random\n" ));
904a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
905a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_FIXME;
906a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
907a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
908a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escMUL: /* in spec */
909a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " mul\n" ));
910a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
911a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_FIXME;
912a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
913a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
914a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escSQRT: /* in spec */
915a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " sqrt\n" ));
916a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
917a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_FIXME;
918a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
919a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
920a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escDUP: /* in spec */
921a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " dup\n" ));
922a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
923a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_FIXME;
924a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
925a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
926a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escEXCH: /* in spec */
927a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " exch\n" ));
928a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
929a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_FIXME;
930a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
931a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
932a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escINDEX: /* in spec */
933a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " index\n" ));
934a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
935a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_FIXME;
936a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
937a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
938a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escROLL: /* in spec */
939a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " roll\n" ));
940a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
941a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_FIXME;
942a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;
943a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
944a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escHFLEX:
945a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            {
946a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              static const FT_Bool  readFromStack[12] =
947a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              {
948a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                TRUE /* dx1 */, FALSE /* dy1 */,
949a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                TRUE /* dx2 */, TRUE  /* dy2 */,
950a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                TRUE /* dx3 */, FALSE /* dy3 */,
951a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                TRUE /* dx4 */, FALSE /* dy4 */,
952a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                TRUE /* dx5 */, FALSE /* dy5 */,
953a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                TRUE /* dx6 */, FALSE /* dy6 */
954a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              };
955a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
956a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
957a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              FT_TRACE4(( " hflex\n" ));
958a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
959a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              cf2_doFlex( opStack,
960a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          &curX,
961a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          &curY,
962a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          &glyphPath,
963a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          readFromStack,
964a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          FALSE /* doConditionalLastRead */ );
965a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            }
966a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            continue;
967a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
968a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escFLEX:
969a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            {
970a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              static const FT_Bool  readFromStack[12] =
971a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              {
972a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                TRUE /* dx1 */, TRUE /* dy1 */,
973a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                TRUE /* dx2 */, TRUE /* dy2 */,
974a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                TRUE /* dx3 */, TRUE /* dy3 */,
975a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                TRUE /* dx4 */, TRUE /* dy4 */,
976a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                TRUE /* dx5 */, TRUE /* dy5 */,
977a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                TRUE /* dx6 */, TRUE /* dy6 */
978a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              };
979a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
980a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
981a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              FT_TRACE4(( " flex\n" ));
982a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
983a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              cf2_doFlex( opStack,
984a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          &curX,
985a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          &curY,
986a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          &glyphPath,
987a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          readFromStack,
988a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          FALSE /* doConditionalLastRead */ );
989a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            }
990a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            break;      /* TODO: why is this not a continue? */
991a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
992a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escHFLEX1:
993a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            {
994a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              static const FT_Bool  readFromStack[12] =
995a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              {
996a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                TRUE /* dx1 */, TRUE  /* dy1 */,
997a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                TRUE /* dx2 */, TRUE  /* dy2 */,
998a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                TRUE /* dx3 */, FALSE /* dy3 */,
999a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                TRUE /* dx4 */, FALSE /* dy4 */,
1000a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                TRUE /* dx5 */, TRUE  /* dy5 */,
1001a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                TRUE /* dx6 */, FALSE /* dy6 */
1002a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              };
1003a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1004a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1005a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              FT_TRACE4(( " hflex1\n" ));
1006a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1007a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              cf2_doFlex( opStack,
1008a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          &curX,
1009a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          &curY,
1010a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          &glyphPath,
1011a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          readFromStack,
1012a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          FALSE /* doConditionalLastRead */ );
1013a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            }
1014a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            continue;
1015a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1016a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escFLEX1:
1017a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            {
1018a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              static const FT_Bool  readFromStack[12] =
1019a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              {
1020a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                TRUE  /* dx1 */, TRUE  /* dy1 */,
1021a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                TRUE  /* dx2 */, TRUE  /* dy2 */,
1022a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                TRUE  /* dx3 */, TRUE  /* dy3 */,
1023a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                TRUE  /* dx4 */, TRUE  /* dy4 */,
1024a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                TRUE  /* dx5 */, TRUE  /* dy5 */,
1025a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                FALSE /* dx6 */, FALSE /* dy6 */
1026a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              };
1027a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1028a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1029a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              FT_TRACE4(( " flex1\n" ));
1030a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1031a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              cf2_doFlex( opStack,
1032a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          &curX,
1033a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          &curY,
1034a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          &glyphPath,
1035a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          readFromStack,
1036a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                          TRUE /* doConditionalLastRead */ );
1037a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            }
1038a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            continue;
1039a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1040a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escRESERVED_1:
1041a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escRESERVED_2:
1042a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escRESERVED_6:
1043a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escRESERVED_7:
1044a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escRESERVED_8:
1045a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escRESERVED_13:
1046a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escRESERVED_16:
1047a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escRESERVED_17:
1048a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escRESERVED_19:
1049a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escRESERVED_25:
1050a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escRESERVED_31:
1051a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escRESERVED_32:
1052a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          case cf2_escRESERVED_33:
1053a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          default:
1054a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
1055a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1056a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          }; /* end of switch statement checking `op2' */
1057a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1058a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        } /* case cf2_cmdESC */
1059a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        break;
1060a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1061a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdENDCHAR:
1062a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        FT_TRACE4(( " endchar\n" ));
1063a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1064a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( cf2_stack_count( opStack ) == 1 ||
1065a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang             cf2_stack_count( opStack ) == 5 )
1066a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {
1067a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          if ( !haveWidth )
1068a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
1069a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        }
1070a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1071a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        /* width is defined or default after this */
1072a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        haveWidth = TRUE;
1073a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1074a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( font->decoder->width_only )
1075a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            goto exit;
1076a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1077a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        /* close path if still open */
1078a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        cf2_glyphpath_closeOpenPath( &glyphPath );
1079a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1080a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( cf2_stack_count( opStack ) > 1 )
1081a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {
1082a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          /* must be either 4 or 5 --                       */
1083a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          /* this is a (deprecated) implied `seac' operator */
1084a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1085a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          CF2_UInt       achar;
1086a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          CF2_UInt       bchar;
1087a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          CF2_BufferRec  component;
1088a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          CF2_Fixed      dummyWidth;   /* ignore component width */
1089a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          FT_Error       error2;
1090a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1091a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1092a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          if ( doingSeac )
1093a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          {
1094a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            lastError = FT_THROW( Invalid_Glyph_Format );
1095a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            goto exit;      /* nested seac */
1096a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          }
1097a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1098a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          achar = cf2_stack_popInt( opStack );
1099a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          bchar = cf2_stack_popInt( opStack );
1100a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1101a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          curY = cf2_stack_popFixed( opStack );
1102a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          curX = cf2_stack_popFixed( opStack );
1103a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1104a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          error2 = cf2_getSeacComponent( decoder, achar, &component );
1105a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          if ( error2 )
1106a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          {
1107a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang             lastError = error2;      /* pass FreeType error through */
1108a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang             goto exit;
1109a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          }
1110a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          cf2_interpT2CharString( font,
1111a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                  &component,
1112a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                  callbacks,
1113a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                  translation,
1114a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                  TRUE,
1115a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                  curX,
1116a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                  curY,
1117a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                  &dummyWidth );
1118a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          cf2_freeSeacComponent( decoder, &component );
1119a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1120a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          error2 = cf2_getSeacComponent( decoder, bchar, &component );
1121a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          if ( error2 )
1122a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          {
1123a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            lastError = error2;      /* pass FreeType error through */
1124a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            goto exit;
1125a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          }
1126a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          cf2_interpT2CharString( font,
1127a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                  &component,
1128a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                  callbacks,
1129a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                  translation,
1130a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                  TRUE,
1131a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                  0,
1132a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                  0,
1133a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                                  &dummyWidth );
1134a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          cf2_freeSeacComponent( decoder, &component );
1135a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        }
1136a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        goto exit;
1137a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1138a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdCNTRMASK:
1139a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdHINTMASK:
1140a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        /* the final \n in the tracing message gets added in      */
1141a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        /* `cf2_hintmask_read' (which also traces the mask bytes) */
1142a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        FT_TRACE4(( op1 == cf2_cmdCNTRMASK ? " cntrmask" : " hintmask" ));
1143a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1144a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        /* if there are arguments on the stack, there this is an */
1145a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        /* implied cf2_cmdVSTEMHM                                */
1146a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( cf2_stack_count( opStack ) != 0 )
1147a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {
1148a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          /* never add hints after the mask is computed */
1149a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          if ( cf2_hintmask_isValid( &hintMask ) )
1150a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( "cf2_interpT2CharString: invalid hint mask\n" ));
1151a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        }
1152a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1153a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        cf2_doStems( font,
1154a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     opStack,
1155a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     &vStemHintArray,
1156a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     width,
1157a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     &haveWidth,
1158a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                     0 );
1159a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1160a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( font->decoder->width_only )
1161a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            goto exit;
1162a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1163a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( op1 == cf2_cmdHINTMASK )
1164a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {
1165a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          /* consume the hint mask bytes which follow the operator */
1166a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          cf2_hintmask_read( &hintMask,
1167a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                             charstring,
1168a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                             cf2_arrstack_size( &hStemHintArray ) +
1169a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                               cf2_arrstack_size( &vStemHintArray ) );
1170a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        }
1171a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        else
1172a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {
1173a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          /*
1174a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang           * Consume the counter mask bytes which follow the operator:
1175a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang           * Build a temporary hint map, just to place and lock those
1176a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang           * stems participating in the counter mask.  These are most
1177a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang           * likely the dominant hstems, and are grouped together in a
1178a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang           * few counter groups, not necessarily in correspondence
1179a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang           * with the hint groups.  This reduces the chances of
1180a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang           * conflicts between hstems that are initially placed in
1181a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang           * separate hint groups and then brought together.  The
1182a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang           * positions are copied back to `hStemHintArray', so we can
1183a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang           * discard `counterMask' and `counterHintMap'.
1184a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang           *
1185a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang           */
1186a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          CF2_HintMapRec   counterHintMap;
1187a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          CF2_HintMaskRec  counterMask;
1188a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1189a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1190a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          cf2_hintmap_init( &counterHintMap,
1191a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                            font,
1192a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                            &glyphPath.initialHintMap,
1193a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                            &glyphPath.hintMoves,
1194a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                            scaleY );
1195a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          cf2_hintmask_init( &counterMask, error );
1196a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1197a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          cf2_hintmask_read( &counterMask,
1198a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                             charstring,
1199a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                             cf2_arrstack_size( &hStemHintArray ) +
1200a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                               cf2_arrstack_size( &vStemHintArray ) );
1201a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          cf2_hintmap_build( &counterHintMap,
1202a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                             &hStemHintArray,
1203a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                             &vStemHintArray,
1204a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                             &counterMask,
1205a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                             0,
1206a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                             FALSE );
1207a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        }
1208a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        break;
1209a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1210a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdRMOVETO:
1211a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        FT_TRACE4(( " rmoveto\n" ));
1212a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1213a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( cf2_stack_count( opStack ) > 2 && !haveWidth )
1214a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
1215a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1216a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        /* width is defined or default after this */
1217a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        haveWidth = TRUE;
1218a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1219a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( font->decoder->width_only )
1220a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            goto exit;
1221a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1222a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        curY += cf2_stack_popFixed( opStack );
1223a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        curX += cf2_stack_popFixed( opStack );
1224a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1225a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        cf2_glyphpath_moveTo( &glyphPath, curX, curY );
1226a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1227a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        break;
1228a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1229a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdHMOVETO:
1230a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        FT_TRACE4(( " hmoveto\n" ));
1231a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1232a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( cf2_stack_count( opStack ) > 1 && !haveWidth )
1233a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
1234a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1235a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        /* width is defined or default after this */
1236a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        haveWidth = TRUE;
1237a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1238a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        if ( font->decoder->width_only )
1239a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            goto exit;
1240a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1241a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        curX += cf2_stack_popFixed( opStack );
1242a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1243a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        cf2_glyphpath_moveTo( &glyphPath, curX, curY );
1244a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1245a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        break;
1246a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1247a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdRLINECURVE:
1248a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {
1249a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          CF2_UInt  count = cf2_stack_count( opStack );
1250a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          CF2_UInt  index = 0;
1251a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1252a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1253a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          FT_TRACE4(( " rlinecurve\n" ));
1254a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1255a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          while ( index + 6 < count )
1256a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          {
1257a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            curX += cf2_stack_getReal( opStack, index + 0 );
1258a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            curY += cf2_stack_getReal( opStack, index + 1 );
1259a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1260a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            cf2_glyphpath_lineTo( &glyphPath, curX, curY );
1261a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            index += 2;
1262a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          }
1263a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1264a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          while ( index < count )
1265a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          {
1266a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_Fixed  x1 = cf2_stack_getReal( opStack, index + 0 ) + curX;
1267a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_Fixed  y1 = cf2_stack_getReal( opStack, index + 1 ) + curY;
1268a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_Fixed  x2 = cf2_stack_getReal( opStack, index + 2 ) + x1;
1269a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_Fixed  y2 = cf2_stack_getReal( opStack, index + 3 ) + y1;
1270a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_Fixed  x3 = cf2_stack_getReal( opStack, index + 4 ) + x2;
1271a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_Fixed  y3 = cf2_stack_getReal( opStack, index + 5 ) + y2;
1272a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1273a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1274a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
1275a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1276a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            curX   = x3;
1277a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            curY   = y3;
1278a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            index += 6;
1279a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          }
1280a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1281a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          cf2_stack_clear( opStack );
1282a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        }
1283a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        continue; /* no need to clear stack again */
1284a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1285a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdVVCURVETO:
1286a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {
1287a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          CF2_UInt  count = cf2_stack_count( opStack );
1288a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          CF2_UInt  index = 0;
1289a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1290a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1291a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          FT_TRACE4(( " vvcurveto\n" ));
1292a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1293a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          while ( index < count )
1294a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          {
1295a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_Fixed  x1, y1, x2, y2, x3, y3;
1296a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1297a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1298a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            if ( ( count - index ) & 1 )
1299a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            {
1300a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              x1 = cf2_stack_getReal( opStack, index ) + curX;
1301a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1302a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              ++index;
1303a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            }
1304a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            else
1305a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              x1 = curX;
1306a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1307a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            y1 = cf2_stack_getReal( opStack, index + 0 ) + curY;
1308a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            x2 = cf2_stack_getReal( opStack, index + 1 ) + x1;
1309a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            y2 = cf2_stack_getReal( opStack, index + 2 ) + y1;
1310a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            x3 = x2;
1311a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            y3 = cf2_stack_getReal( opStack, index + 3 ) + y2;
1312a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1313a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
1314a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1315a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            curX   = x3;
1316a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            curY   = y3;
1317a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            index += 4;
1318a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          }
1319a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1320a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          cf2_stack_clear( opStack );
1321a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        }
1322a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        continue; /* no need to clear stack again */
1323a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1324a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdHHCURVETO:
1325a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {
1326a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          CF2_UInt  count = cf2_stack_count( opStack );
1327a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          CF2_UInt  index = 0;
1328a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1329a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1330a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          FT_TRACE4(( " hhcurveto\n" ));
1331a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1332a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          while ( index < count )
1333a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          {
1334a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_Fixed  x1, y1, x2, y2, x3, y3;
1335a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1336a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1337a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            if ( ( count - index ) & 1 )
1338a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            {
1339a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              y1 = cf2_stack_getReal( opStack, index ) + curY;
1340a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1341a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              ++index;
1342a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            }
1343a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            else
1344a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              y1 = curY;
1345a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1346a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            x1 = cf2_stack_getReal( opStack, index + 0 ) + curX;
1347a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            x2 = cf2_stack_getReal( opStack, index + 1 ) + x1;
1348a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            y2 = cf2_stack_getReal( opStack, index + 2 ) + y1;
1349a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            x3 = cf2_stack_getReal( opStack, index + 3 ) + x2;
1350a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            y3 = y2;
1351a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1352a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
1353a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1354a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            curX   = x3;
1355a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            curY   = y3;
1356a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            index += 4;
1357a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          }
1358a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1359a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          cf2_stack_clear( opStack );
1360a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        }
1361a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        continue; /* no need to clear stack again */
1362a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1363a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdVHCURVETO:
1364a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdHVCURVETO:
1365a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {
1366a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          CF2_UInt  count = cf2_stack_count( opStack );
1367a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          CF2_UInt  index = 0;
1368a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1369a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          FT_Bool  alternate = op1 == cf2_cmdHVCURVETO;
1370a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1371a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1372a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          FT_TRACE4(( alternate ? " hvcurveto\n" : " vhcurveto\n" ));
1373a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1374a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          while ( index < count )
1375a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          {
1376a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_Fixed x1, x2, x3, y1, y2, y3;
1377a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1378a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1379a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            if ( alternate )
1380a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            {
1381a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              x1 = cf2_stack_getReal( opStack, index + 0 ) + curX;
1382a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              y1 = curY;
1383a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              x2 = cf2_stack_getReal( opStack, index + 1 ) + x1;
1384a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              y2 = cf2_stack_getReal( opStack, index + 2 ) + y1;
1385a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              y3 = cf2_stack_getReal( opStack, index + 3 ) + y2;
1386a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1387a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              if ( count - index == 5 )
1388a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              {
1389a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                x3 = cf2_stack_getReal( opStack, index + 4 ) + x2;
1390a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1391a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                ++index;
1392a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              }
1393a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              else
1394a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                x3 = x2;
1395a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1396a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              alternate = FALSE;
1397a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            }
1398a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            else
1399a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            {
1400a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              x1 = curX;
1401a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              y1 = cf2_stack_getReal( opStack, index + 0 ) + curY;
1402a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              x2 = cf2_stack_getReal( opStack, index + 1 ) + x1;
1403a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              y2 = cf2_stack_getReal( opStack, index + 2 ) + y1;
1404a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              x3 = cf2_stack_getReal( opStack, index + 3 ) + x2;
1405a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1406a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              if ( count - index == 5 )
1407a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              {
1408a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                y3 = cf2_stack_getReal( opStack, index + 4 ) + y2;
1409a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1410a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                ++index;
1411a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              }
1412a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              else
1413a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                y3 = y2;
1414a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1415a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang              alternate = TRUE;
1416a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            }
1417a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1418a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
1419a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1420a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            curX   = x3;
1421a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            curY   = y3;
1422a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            index += 4;
1423a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          }
1424a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1425a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          cf2_stack_clear( opStack );
1426a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        }
1427a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        continue;     /* no need to clear stack again */
1428a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1429a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      case cf2_cmdEXTENDEDNMBR:
1430a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {
1431a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          CF2_Int  v;
1432a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1433a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1434a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          v = (FT_Short)( ( cf2_buf_readByte( charstring ) << 8 ) |
1435a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                            cf2_buf_readByte( charstring )        );
1436a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1437a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          FT_TRACE4(( " %d", v ));
1438a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1439a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          cf2_stack_pushInt( opStack, v );
1440a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        }
1441a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        continue;
1442a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1443a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      default:
1444a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        /* numbers */
1445a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        {
1446a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          if ( /* op1 >= 32 && */ op1 <= 246 )
1447a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          {
1448a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_Int  v;
1449a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1450a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1451a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            v = op1 - 139;
1452a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1453a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " %d", v ));
1454a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1455a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            /* -107 .. 107 */
1456a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            cf2_stack_pushInt( opStack, v );
1457a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          }
1458a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1459a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          else if ( /* op1 >= 247 && */ op1 <= 250 )
1460a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          {
1461a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_Int  v;
1462a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1463a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1464a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            v  = op1;
1465a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            v -= 247;
1466a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            v *= 256;
1467a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            v += cf2_buf_readByte( charstring );
1468a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            v += 108;
1469a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1470a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " %d", v ));
1471a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1472a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            /* 108 .. 1131 */
1473a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            cf2_stack_pushInt( opStack, v );
1474a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          }
1475a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1476a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          else if ( /* op1 >= 251 && */ op1 <= 254 )
1477a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          {
1478a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_Int  v;
1479a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1480a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1481a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            v  = op1;
1482a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            v -= 251;
1483a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            v *= 256;
1484a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            v += cf2_buf_readByte( charstring );
1485a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            v  = -v - 108;
1486a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1487a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " %d", v ));
1488a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1489a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            /* -1131 .. -108 */
1490a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            cf2_stack_pushInt( opStack, v );
1491a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          }
1492a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1493a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          else /* op1 == 255 */
1494a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          {
1495a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            CF2_Fixed  v;
1496a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1497a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1498a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            v = (CF2_Fixed)
1499a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                  ( ( (FT_UInt32)cf2_buf_readByte( charstring ) << 24 ) |
1500a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                    ( (FT_UInt32)cf2_buf_readByte( charstring ) << 16 ) |
1501a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                    ( (FT_UInt32)cf2_buf_readByte( charstring ) <<  8 ) |
1502a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                      (FT_UInt32)cf2_buf_readByte( charstring )         );
1503a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1504a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            FT_TRACE4(( " %.2f", v / 65536.0 ));
1505a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1506a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang            cf2_stack_pushFixed( opStack, v );
1507a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang          }
1508a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        }
1509a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang        continue;   /* don't clear stack */
1510a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1511a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      } /* end of switch statement checking `op1' */
1512a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1513a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang      cf2_stack_clear( opStack );
1514a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1515a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    } /* end of main interpreter loop */
1516a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1517a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* we get here if the charstring ends without cf2_cmdENDCHAR */
1518a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_TRACE4(( "cf2_interpT2CharString:"
1519a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang                "  charstring ends without ENDCHAR\n" ));
1520a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1521a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  exit:
1522a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* check whether last error seen is also the first one */
1523a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_setError( error, lastError );
1524a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1525a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    /* free resources from objects we've used */
1526a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_glyphpath_finalize( &glyphPath );
1527a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_arrstack_finalize( &vStemHintArray );
1528a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_arrstack_finalize( &hStemHintArray );
1529a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_arrstack_finalize( &subrStack );
1530a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    cf2_stack_free( opStack );
1531a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1532a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    FT_TRACE4(( "\n" ));
1533a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1534a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang    return;
1535a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang  }
1536a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1537a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang
1538a2b9955b49034a51dfbc8bf9f4e9d312149cecacXianzhu Wang/* END */
1539