xref: /inferno-os/libfreetype/cffgload.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /***************************************************************************/
2*37da2899SCharles.Forsyth /*                                                                         */
3*37da2899SCharles.Forsyth /*  cffgload.c                                                             */
4*37da2899SCharles.Forsyth /*                                                                         */
5*37da2899SCharles.Forsyth /*    OpenType Glyph Loader (body).                                        */
6*37da2899SCharles.Forsyth /*                                                                         */
7*37da2899SCharles.Forsyth /*  Copyright 1996-2001, 2002 by                                           */
8*37da2899SCharles.Forsyth /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9*37da2899SCharles.Forsyth /*                                                                         */
10*37da2899SCharles.Forsyth /*  This file is part of the FreeType project, and may only be used,       */
11*37da2899SCharles.Forsyth /*  modified, and distributed under the terms of the FreeType project      */
12*37da2899SCharles.Forsyth /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13*37da2899SCharles.Forsyth /*  this file you indicate that you have read the license and              */
14*37da2899SCharles.Forsyth /*  understand and accept it fully.                                        */
15*37da2899SCharles.Forsyth /*                                                                         */
16*37da2899SCharles.Forsyth /***************************************************************************/
17*37da2899SCharles.Forsyth 
18*37da2899SCharles.Forsyth 
19*37da2899SCharles.Forsyth #include <ft2build.h>
20*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H
21*37da2899SCharles.Forsyth #include FT_INTERNAL_CALC_H
22*37da2899SCharles.Forsyth #include FT_INTERNAL_STREAM_H
23*37da2899SCharles.Forsyth #include FT_INTERNAL_SFNT_H
24*37da2899SCharles.Forsyth #include FT_OUTLINE_H
25*37da2899SCharles.Forsyth #include FT_TRUETYPE_TAGS_H
26*37da2899SCharles.Forsyth #include FT_INTERNAL_POSTSCRIPT_HINTS_H
27*37da2899SCharles.Forsyth 
28*37da2899SCharles.Forsyth #include "cffobjs.h"
29*37da2899SCharles.Forsyth #include "cffload.h"
30*37da2899SCharles.Forsyth #include "cffgload.h"
31*37da2899SCharles.Forsyth 
32*37da2899SCharles.Forsyth #include "cfferrs.h"
33*37da2899SCharles.Forsyth 
34*37da2899SCharles.Forsyth 
35*37da2899SCharles.Forsyth   /*************************************************************************/
36*37da2899SCharles.Forsyth   /*                                                                       */
37*37da2899SCharles.Forsyth   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
38*37da2899SCharles.Forsyth   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
39*37da2899SCharles.Forsyth   /* messages during execution.                                            */
40*37da2899SCharles.Forsyth   /*                                                                       */
41*37da2899SCharles.Forsyth #undef  FT_COMPONENT
42*37da2899SCharles.Forsyth #define FT_COMPONENT  trace_cffgload
43*37da2899SCharles.Forsyth 
44*37da2899SCharles.Forsyth 
45*37da2899SCharles.Forsyth   typedef enum  CFF_Operator_
46*37da2899SCharles.Forsyth   {
47*37da2899SCharles.Forsyth     cff_op_unknown = 0,
48*37da2899SCharles.Forsyth 
49*37da2899SCharles.Forsyth     cff_op_rmoveto,
50*37da2899SCharles.Forsyth     cff_op_hmoveto,
51*37da2899SCharles.Forsyth     cff_op_vmoveto,
52*37da2899SCharles.Forsyth 
53*37da2899SCharles.Forsyth     cff_op_rlineto,
54*37da2899SCharles.Forsyth     cff_op_hlineto,
55*37da2899SCharles.Forsyth     cff_op_vlineto,
56*37da2899SCharles.Forsyth 
57*37da2899SCharles.Forsyth     cff_op_rrcurveto,
58*37da2899SCharles.Forsyth     cff_op_hhcurveto,
59*37da2899SCharles.Forsyth     cff_op_hvcurveto,
60*37da2899SCharles.Forsyth     cff_op_rcurveline,
61*37da2899SCharles.Forsyth     cff_op_rlinecurve,
62*37da2899SCharles.Forsyth     cff_op_vhcurveto,
63*37da2899SCharles.Forsyth     cff_op_vvcurveto,
64*37da2899SCharles.Forsyth 
65*37da2899SCharles.Forsyth     cff_op_flex,
66*37da2899SCharles.Forsyth     cff_op_hflex,
67*37da2899SCharles.Forsyth     cff_op_hflex1,
68*37da2899SCharles.Forsyth     cff_op_flex1,
69*37da2899SCharles.Forsyth 
70*37da2899SCharles.Forsyth     cff_op_endchar,
71*37da2899SCharles.Forsyth 
72*37da2899SCharles.Forsyth     cff_op_hstem,
73*37da2899SCharles.Forsyth     cff_op_vstem,
74*37da2899SCharles.Forsyth     cff_op_hstemhm,
75*37da2899SCharles.Forsyth     cff_op_vstemhm,
76*37da2899SCharles.Forsyth 
77*37da2899SCharles.Forsyth     cff_op_hintmask,
78*37da2899SCharles.Forsyth     cff_op_cntrmask,
79*37da2899SCharles.Forsyth     cff_op_dotsection,  /* deprecated, acts as no-op */
80*37da2899SCharles.Forsyth 
81*37da2899SCharles.Forsyth     cff_op_abs,
82*37da2899SCharles.Forsyth     cff_op_add,
83*37da2899SCharles.Forsyth     cff_op_sub,
84*37da2899SCharles.Forsyth     cff_op_div,
85*37da2899SCharles.Forsyth     cff_op_neg,
86*37da2899SCharles.Forsyth     cff_op_random,
87*37da2899SCharles.Forsyth     cff_op_mul,
88*37da2899SCharles.Forsyth     cff_op_sqrt,
89*37da2899SCharles.Forsyth 
90*37da2899SCharles.Forsyth     cff_op_blend,
91*37da2899SCharles.Forsyth 
92*37da2899SCharles.Forsyth     cff_op_drop,
93*37da2899SCharles.Forsyth     cff_op_exch,
94*37da2899SCharles.Forsyth     cff_op_index,
95*37da2899SCharles.Forsyth     cff_op_roll,
96*37da2899SCharles.Forsyth     cff_op_dup,
97*37da2899SCharles.Forsyth 
98*37da2899SCharles.Forsyth     cff_op_put,
99*37da2899SCharles.Forsyth     cff_op_get,
100*37da2899SCharles.Forsyth     cff_op_store,
101*37da2899SCharles.Forsyth     cff_op_load,
102*37da2899SCharles.Forsyth 
103*37da2899SCharles.Forsyth     cff_op_and,
104*37da2899SCharles.Forsyth     cff_op_or,
105*37da2899SCharles.Forsyth     cff_op_not,
106*37da2899SCharles.Forsyth     cff_op_eq,
107*37da2899SCharles.Forsyth     cff_op_ifelse,
108*37da2899SCharles.Forsyth 
109*37da2899SCharles.Forsyth     cff_op_callsubr,
110*37da2899SCharles.Forsyth     cff_op_callgsubr,
111*37da2899SCharles.Forsyth     cff_op_return,
112*37da2899SCharles.Forsyth 
113*37da2899SCharles.Forsyth     /* do not remove */
114*37da2899SCharles.Forsyth     cff_op_max
115*37da2899SCharles.Forsyth 
116*37da2899SCharles.Forsyth   } CFF_Operator;
117*37da2899SCharles.Forsyth 
118*37da2899SCharles.Forsyth 
119*37da2899SCharles.Forsyth #define CFF_COUNT_CHECK_WIDTH  0x80
120*37da2899SCharles.Forsyth #define CFF_COUNT_EXACT        0x40
121*37da2899SCharles.Forsyth #define CFF_COUNT_CLEAR_STACK  0x20
122*37da2899SCharles.Forsyth 
123*37da2899SCharles.Forsyth 
124*37da2899SCharles.Forsyth   static const FT_Byte  cff_argument_counts[] =
125*37da2899SCharles.Forsyth   {
126*37da2899SCharles.Forsyth     0,  /* unknown */
127*37da2899SCharles.Forsyth 
128*37da2899SCharles.Forsyth     2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */
129*37da2899SCharles.Forsyth     1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
130*37da2899SCharles.Forsyth     1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
131*37da2899SCharles.Forsyth 
132*37da2899SCharles.Forsyth     0 | CFF_COUNT_CLEAR_STACK, /* rlineto */
133*37da2899SCharles.Forsyth     0 | CFF_COUNT_CLEAR_STACK,
134*37da2899SCharles.Forsyth     0 | CFF_COUNT_CLEAR_STACK,
135*37da2899SCharles.Forsyth 
136*37da2899SCharles.Forsyth     0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */
137*37da2899SCharles.Forsyth     0 | CFF_COUNT_CLEAR_STACK,
138*37da2899SCharles.Forsyth     0 | CFF_COUNT_CLEAR_STACK,
139*37da2899SCharles.Forsyth     0 | CFF_COUNT_CLEAR_STACK,
140*37da2899SCharles.Forsyth     0 | CFF_COUNT_CLEAR_STACK,
141*37da2899SCharles.Forsyth     0 | CFF_COUNT_CLEAR_STACK,
142*37da2899SCharles.Forsyth     0 | CFF_COUNT_CLEAR_STACK,
143*37da2899SCharles.Forsyth 
144*37da2899SCharles.Forsyth     13, /* flex */
145*37da2899SCharles.Forsyth     7,
146*37da2899SCharles.Forsyth     9,
147*37da2899SCharles.Forsyth     11,
148*37da2899SCharles.Forsyth 
149*37da2899SCharles.Forsyth     0 | CFF_COUNT_CHECK_WIDTH, /* endchar */
150*37da2899SCharles.Forsyth 
151*37da2899SCharles.Forsyth     2 | CFF_COUNT_CHECK_WIDTH, /* hstem */
152*37da2899SCharles.Forsyth     2 | CFF_COUNT_CHECK_WIDTH,
153*37da2899SCharles.Forsyth     2 | CFF_COUNT_CHECK_WIDTH,
154*37da2899SCharles.Forsyth     2 | CFF_COUNT_CHECK_WIDTH,
155*37da2899SCharles.Forsyth 
156*37da2899SCharles.Forsyth     0 | CFF_COUNT_CHECK_WIDTH, /* hintmask */
157*37da2899SCharles.Forsyth     0 | CFF_COUNT_CHECK_WIDTH, /* cntrmask */
158*37da2899SCharles.Forsyth     0, /* dotsection */
159*37da2899SCharles.Forsyth 
160*37da2899SCharles.Forsyth     1, /* abs */
161*37da2899SCharles.Forsyth     2,
162*37da2899SCharles.Forsyth     2,
163*37da2899SCharles.Forsyth     2,
164*37da2899SCharles.Forsyth     1,
165*37da2899SCharles.Forsyth     0,
166*37da2899SCharles.Forsyth     2,
167*37da2899SCharles.Forsyth     1,
168*37da2899SCharles.Forsyth 
169*37da2899SCharles.Forsyth     1, /* blend */
170*37da2899SCharles.Forsyth 
171*37da2899SCharles.Forsyth     1, /* drop */
172*37da2899SCharles.Forsyth     2,
173*37da2899SCharles.Forsyth     1,
174*37da2899SCharles.Forsyth     2,
175*37da2899SCharles.Forsyth     1,
176*37da2899SCharles.Forsyth 
177*37da2899SCharles.Forsyth     2, /* put */
178*37da2899SCharles.Forsyth     1,
179*37da2899SCharles.Forsyth     4,
180*37da2899SCharles.Forsyth     3,
181*37da2899SCharles.Forsyth 
182*37da2899SCharles.Forsyth     2, /* and */
183*37da2899SCharles.Forsyth     2,
184*37da2899SCharles.Forsyth     1,
185*37da2899SCharles.Forsyth     2,
186*37da2899SCharles.Forsyth     4,
187*37da2899SCharles.Forsyth 
188*37da2899SCharles.Forsyth     1, /* callsubr */
189*37da2899SCharles.Forsyth     1,
190*37da2899SCharles.Forsyth     0
191*37da2899SCharles.Forsyth   };
192*37da2899SCharles.Forsyth 
193*37da2899SCharles.Forsyth 
194*37da2899SCharles.Forsyth   /*************************************************************************/
195*37da2899SCharles.Forsyth   /*************************************************************************/
196*37da2899SCharles.Forsyth   /*************************************************************************/
197*37da2899SCharles.Forsyth   /**********                                                      *********/
198*37da2899SCharles.Forsyth   /**********                                                      *********/
199*37da2899SCharles.Forsyth   /**********             GENERIC CHARSTRING PARSING               *********/
200*37da2899SCharles.Forsyth   /**********                                                      *********/
201*37da2899SCharles.Forsyth   /**********                                                      *********/
202*37da2899SCharles.Forsyth   /*************************************************************************/
203*37da2899SCharles.Forsyth   /*************************************************************************/
204*37da2899SCharles.Forsyth   /*************************************************************************/
205*37da2899SCharles.Forsyth 
206*37da2899SCharles.Forsyth 
207*37da2899SCharles.Forsyth   /*************************************************************************/
208*37da2899SCharles.Forsyth   /*                                                                       */
209*37da2899SCharles.Forsyth   /* <Function>                                                            */
210*37da2899SCharles.Forsyth   /*    cff_builder_init                                                   */
211*37da2899SCharles.Forsyth   /*                                                                       */
212*37da2899SCharles.Forsyth   /* <Description>                                                         */
213*37da2899SCharles.Forsyth   /*    Initializes a given glyph builder.                                 */
214*37da2899SCharles.Forsyth   /*                                                                       */
215*37da2899SCharles.Forsyth   /* <InOut>                                                               */
216*37da2899SCharles.Forsyth   /*    builder :: A pointer to the glyph builder to initialize.           */
217*37da2899SCharles.Forsyth   /*                                                                       */
218*37da2899SCharles.Forsyth   /* <Input>                                                               */
219*37da2899SCharles.Forsyth   /*    face    :: The current face object.                                */
220*37da2899SCharles.Forsyth   /*                                                                       */
221*37da2899SCharles.Forsyth   /*    size    :: The current size object.                                */
222*37da2899SCharles.Forsyth   /*                                                                       */
223*37da2899SCharles.Forsyth   /*    glyph   :: The current glyph object.                               */
224*37da2899SCharles.Forsyth   /*                                                                       */
225*37da2899SCharles.Forsyth   static void
cff_builder_init(CFF_Builder * builder,TT_Face face,CFF_Size size,CFF_GlyphSlot glyph,FT_Bool hinting)226*37da2899SCharles.Forsyth   cff_builder_init( CFF_Builder*   builder,
227*37da2899SCharles.Forsyth                     TT_Face        face,
228*37da2899SCharles.Forsyth                     CFF_Size       size,
229*37da2899SCharles.Forsyth                     CFF_GlyphSlot  glyph,
230*37da2899SCharles.Forsyth                     FT_Bool        hinting )
231*37da2899SCharles.Forsyth   {
232*37da2899SCharles.Forsyth     builder->path_begun  = 0;
233*37da2899SCharles.Forsyth     builder->load_points = 1;
234*37da2899SCharles.Forsyth 
235*37da2899SCharles.Forsyth     builder->face   = face;
236*37da2899SCharles.Forsyth     builder->glyph  = glyph;
237*37da2899SCharles.Forsyth     builder->memory = face->root.memory;
238*37da2899SCharles.Forsyth 
239*37da2899SCharles.Forsyth     if ( glyph )
240*37da2899SCharles.Forsyth     {
241*37da2899SCharles.Forsyth       FT_GlyphLoader  loader = glyph->root.internal->loader;
242*37da2899SCharles.Forsyth 
243*37da2899SCharles.Forsyth 
244*37da2899SCharles.Forsyth       builder->loader  = loader;
245*37da2899SCharles.Forsyth       builder->base    = &loader->base.outline;
246*37da2899SCharles.Forsyth       builder->current = &loader->current.outline;
247*37da2899SCharles.Forsyth       FT_GlyphLoader_Rewind( loader );
248*37da2899SCharles.Forsyth 
249*37da2899SCharles.Forsyth       builder->hint_flags    = FT_FACE(face)->internal->hint_flags;
250*37da2899SCharles.Forsyth       builder->hints_globals = 0;
251*37da2899SCharles.Forsyth       builder->hints_funcs   = 0;
252*37da2899SCharles.Forsyth 
253*37da2899SCharles.Forsyth       if ( hinting && size )
254*37da2899SCharles.Forsyth       {
255*37da2899SCharles.Forsyth         builder->hints_globals = size->internal;
256*37da2899SCharles.Forsyth         builder->hints_funcs   = glyph->root.internal->glyph_hints;
257*37da2899SCharles.Forsyth       }
258*37da2899SCharles.Forsyth     }
259*37da2899SCharles.Forsyth 
260*37da2899SCharles.Forsyth     if ( size )
261*37da2899SCharles.Forsyth     {
262*37da2899SCharles.Forsyth       builder->scale_x = size->metrics.x_scale;
263*37da2899SCharles.Forsyth       builder->scale_y = size->metrics.y_scale;
264*37da2899SCharles.Forsyth     }
265*37da2899SCharles.Forsyth 
266*37da2899SCharles.Forsyth     builder->pos_x = 0;
267*37da2899SCharles.Forsyth     builder->pos_y = 0;
268*37da2899SCharles.Forsyth 
269*37da2899SCharles.Forsyth     builder->left_bearing.x = 0;
270*37da2899SCharles.Forsyth     builder->left_bearing.y = 0;
271*37da2899SCharles.Forsyth     builder->advance.x      = 0;
272*37da2899SCharles.Forsyth     builder->advance.y      = 0;
273*37da2899SCharles.Forsyth   }
274*37da2899SCharles.Forsyth 
275*37da2899SCharles.Forsyth 
276*37da2899SCharles.Forsyth   /*************************************************************************/
277*37da2899SCharles.Forsyth   /*                                                                       */
278*37da2899SCharles.Forsyth   /* <Function>                                                            */
279*37da2899SCharles.Forsyth   /*    cff_builder_done                                                   */
280*37da2899SCharles.Forsyth   /*                                                                       */
281*37da2899SCharles.Forsyth   /* <Description>                                                         */
282*37da2899SCharles.Forsyth   /*    Finalizes a given glyph builder.  Its contents can still be used   */
283*37da2899SCharles.Forsyth   /*    after the call, but the function saves important information       */
284*37da2899SCharles.Forsyth   /*    within the corresponding glyph slot.                               */
285*37da2899SCharles.Forsyth   /*                                                                       */
286*37da2899SCharles.Forsyth   /* <Input>                                                               */
287*37da2899SCharles.Forsyth   /*    builder :: A pointer to the glyph builder to finalize.             */
288*37da2899SCharles.Forsyth   /*                                                                       */
289*37da2899SCharles.Forsyth   static void
cff_builder_done(CFF_Builder * builder)290*37da2899SCharles.Forsyth   cff_builder_done( CFF_Builder*  builder )
291*37da2899SCharles.Forsyth   {
292*37da2899SCharles.Forsyth     CFF_GlyphSlot  glyph = builder->glyph;
293*37da2899SCharles.Forsyth 
294*37da2899SCharles.Forsyth 
295*37da2899SCharles.Forsyth     if ( glyph )
296*37da2899SCharles.Forsyth       glyph->root.outline = *builder->base;
297*37da2899SCharles.Forsyth   }
298*37da2899SCharles.Forsyth 
299*37da2899SCharles.Forsyth 
300*37da2899SCharles.Forsyth   /*************************************************************************/
301*37da2899SCharles.Forsyth   /*                                                                       */
302*37da2899SCharles.Forsyth   /* <Function>                                                            */
303*37da2899SCharles.Forsyth   /*    cff_compute_bias                                                   */
304*37da2899SCharles.Forsyth   /*                                                                       */
305*37da2899SCharles.Forsyth   /* <Description>                                                         */
306*37da2899SCharles.Forsyth   /*    Computes the bias value in dependence of the number of glyph       */
307*37da2899SCharles.Forsyth   /*    subroutines.                                                       */
308*37da2899SCharles.Forsyth   /*                                                                       */
309*37da2899SCharles.Forsyth   /* <Input>                                                               */
310*37da2899SCharles.Forsyth   /*    num_subrs :: The number of glyph subroutines.                      */
311*37da2899SCharles.Forsyth   /*                                                                       */
312*37da2899SCharles.Forsyth   /* <Return>                                                              */
313*37da2899SCharles.Forsyth   /*    The bias value.                                                    */
314*37da2899SCharles.Forsyth   static FT_Int
cff_compute_bias(FT_UInt num_subrs)315*37da2899SCharles.Forsyth   cff_compute_bias( FT_UInt  num_subrs )
316*37da2899SCharles.Forsyth   {
317*37da2899SCharles.Forsyth     FT_Int  result;
318*37da2899SCharles.Forsyth 
319*37da2899SCharles.Forsyth 
320*37da2899SCharles.Forsyth     if ( num_subrs < 1240 )
321*37da2899SCharles.Forsyth       result = 107;
322*37da2899SCharles.Forsyth     else if ( num_subrs < 33900U )
323*37da2899SCharles.Forsyth       result = 1131;
324*37da2899SCharles.Forsyth     else
325*37da2899SCharles.Forsyth       result = 32768U;
326*37da2899SCharles.Forsyth 
327*37da2899SCharles.Forsyth     return result;
328*37da2899SCharles.Forsyth   }
329*37da2899SCharles.Forsyth 
330*37da2899SCharles.Forsyth 
331*37da2899SCharles.Forsyth   /*************************************************************************/
332*37da2899SCharles.Forsyth   /*                                                                       */
333*37da2899SCharles.Forsyth   /* <Function>                                                            */
334*37da2899SCharles.Forsyth   /*    cff_decoder_init                                                   */
335*37da2899SCharles.Forsyth   /*                                                                       */
336*37da2899SCharles.Forsyth   /* <Description>                                                         */
337*37da2899SCharles.Forsyth   /*    Initializes a given glyph decoder.                                 */
338*37da2899SCharles.Forsyth   /*                                                                       */
339*37da2899SCharles.Forsyth   /* <InOut>                                                               */
340*37da2899SCharles.Forsyth   /*    decoder :: A pointer to the glyph builder to initialize.           */
341*37da2899SCharles.Forsyth   /*                                                                       */
342*37da2899SCharles.Forsyth   /* <Input>                                                               */
343*37da2899SCharles.Forsyth   /*    face    :: The current face object.                                */
344*37da2899SCharles.Forsyth   /*                                                                       */
345*37da2899SCharles.Forsyth   /*    size    :: The current size object.                                */
346*37da2899SCharles.Forsyth   /*                                                                       */
347*37da2899SCharles.Forsyth   /*    slot    :: The current glyph object.                               */
348*37da2899SCharles.Forsyth   /*                                                                       */
349*37da2899SCharles.Forsyth   FT_LOCAL_DEF( void )
cff_decoder_init(CFF_Decoder * decoder,TT_Face face,CFF_Size size,CFF_GlyphSlot slot,FT_Bool hinting,FT_Render_Mode hint_mode)350*37da2899SCharles.Forsyth   cff_decoder_init( CFF_Decoder*    decoder,
351*37da2899SCharles.Forsyth                     TT_Face         face,
352*37da2899SCharles.Forsyth                     CFF_Size        size,
353*37da2899SCharles.Forsyth                     CFF_GlyphSlot   slot,
354*37da2899SCharles.Forsyth                     FT_Bool         hinting,
355*37da2899SCharles.Forsyth                     FT_Render_Mode  hint_mode )
356*37da2899SCharles.Forsyth   {
357*37da2899SCharles.Forsyth     CFF_Font  cff = (CFF_Font)face->extra.data;
358*37da2899SCharles.Forsyth 
359*37da2899SCharles.Forsyth 
360*37da2899SCharles.Forsyth     /* clear everything */
361*37da2899SCharles.Forsyth     FT_MEM_ZERO( decoder, sizeof ( *decoder ) );
362*37da2899SCharles.Forsyth 
363*37da2899SCharles.Forsyth     /* initialize builder */
364*37da2899SCharles.Forsyth     cff_builder_init( &decoder->builder, face, size, slot, hinting );
365*37da2899SCharles.Forsyth 
366*37da2899SCharles.Forsyth     /* initialize Type2 decoder */
367*37da2899SCharles.Forsyth     decoder->num_globals  = cff->num_global_subrs;
368*37da2899SCharles.Forsyth     decoder->globals      = cff->global_subrs;
369*37da2899SCharles.Forsyth     decoder->globals_bias = cff_compute_bias( decoder->num_globals );
370*37da2899SCharles.Forsyth 
371*37da2899SCharles.Forsyth     decoder->hint_mode    = hint_mode;
372*37da2899SCharles.Forsyth   }
373*37da2899SCharles.Forsyth 
374*37da2899SCharles.Forsyth 
375*37da2899SCharles.Forsyth   /* this function is used to select the locals subrs array */
376*37da2899SCharles.Forsyth   FT_LOCAL_DEF( void )
cff_decoder_prepare(CFF_Decoder * decoder,FT_UInt glyph_index)377*37da2899SCharles.Forsyth   cff_decoder_prepare( CFF_Decoder*  decoder,
378*37da2899SCharles.Forsyth                        FT_UInt       glyph_index )
379*37da2899SCharles.Forsyth   {
380*37da2899SCharles.Forsyth     CFF_Font     cff = (CFF_Font)decoder->builder.face->extra.data;
381*37da2899SCharles.Forsyth     CFF_SubFont  sub = &cff->top_font;
382*37da2899SCharles.Forsyth 
383*37da2899SCharles.Forsyth 
384*37da2899SCharles.Forsyth     /* manage CID fonts */
385*37da2899SCharles.Forsyth     if ( cff->num_subfonts >= 1 )
386*37da2899SCharles.Forsyth     {
387*37da2899SCharles.Forsyth       FT_Byte  fd_index = cff_fd_select_get( &cff->fd_select, glyph_index );
388*37da2899SCharles.Forsyth 
389*37da2899SCharles.Forsyth 
390*37da2899SCharles.Forsyth       sub = cff->subfonts[fd_index];
391*37da2899SCharles.Forsyth     }
392*37da2899SCharles.Forsyth 
393*37da2899SCharles.Forsyth     decoder->num_locals    = sub->num_local_subrs;
394*37da2899SCharles.Forsyth     decoder->locals        = sub->local_subrs;
395*37da2899SCharles.Forsyth     decoder->locals_bias   = cff_compute_bias( decoder->num_locals );
396*37da2899SCharles.Forsyth 
397*37da2899SCharles.Forsyth     decoder->glyph_width   = sub->private_dict.default_width;
398*37da2899SCharles.Forsyth     decoder->nominal_width = sub->private_dict.nominal_width;
399*37da2899SCharles.Forsyth   }
400*37da2899SCharles.Forsyth 
401*37da2899SCharles.Forsyth 
402*37da2899SCharles.Forsyth   /* check that there is enough room for `count' more points */
403*37da2899SCharles.Forsyth   static FT_Error
check_points(CFF_Builder * builder,FT_Int count)404*37da2899SCharles.Forsyth   check_points( CFF_Builder*  builder,
405*37da2899SCharles.Forsyth                 FT_Int        count )
406*37da2899SCharles.Forsyth   {
407*37da2899SCharles.Forsyth     return FT_GlyphLoader_CheckPoints( builder->loader, count, 0 );
408*37da2899SCharles.Forsyth   }
409*37da2899SCharles.Forsyth 
410*37da2899SCharles.Forsyth 
411*37da2899SCharles.Forsyth   /* add a new point, do not check space */
412*37da2899SCharles.Forsyth   static void
cff_builder_add_point(CFF_Builder * builder,FT_Pos x,FT_Pos y,FT_Byte flag)413*37da2899SCharles.Forsyth   cff_builder_add_point( CFF_Builder*  builder,
414*37da2899SCharles.Forsyth                          FT_Pos        x,
415*37da2899SCharles.Forsyth                          FT_Pos        y,
416*37da2899SCharles.Forsyth                          FT_Byte       flag )
417*37da2899SCharles.Forsyth   {
418*37da2899SCharles.Forsyth     FT_Outline*  outline = builder->current;
419*37da2899SCharles.Forsyth 
420*37da2899SCharles.Forsyth 
421*37da2899SCharles.Forsyth     if ( builder->load_points )
422*37da2899SCharles.Forsyth     {
423*37da2899SCharles.Forsyth       FT_Vector*  point   = outline->points + outline->n_points;
424*37da2899SCharles.Forsyth       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
425*37da2899SCharles.Forsyth 
426*37da2899SCharles.Forsyth 
427*37da2899SCharles.Forsyth       point->x = x >> 16;
428*37da2899SCharles.Forsyth       point->y = y >> 16;
429*37da2899SCharles.Forsyth       *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
430*37da2899SCharles.Forsyth 
431*37da2899SCharles.Forsyth       builder->last = *point;
432*37da2899SCharles.Forsyth     }
433*37da2899SCharles.Forsyth 
434*37da2899SCharles.Forsyth     outline->n_points++;
435*37da2899SCharles.Forsyth   }
436*37da2899SCharles.Forsyth 
437*37da2899SCharles.Forsyth 
438*37da2899SCharles.Forsyth   /* check space for a new on-curve point, then add it */
439*37da2899SCharles.Forsyth   static FT_Error
cff_builder_add_point1(CFF_Builder * builder,FT_Pos x,FT_Pos y)440*37da2899SCharles.Forsyth   cff_builder_add_point1( CFF_Builder*  builder,
441*37da2899SCharles.Forsyth                           FT_Pos        x,
442*37da2899SCharles.Forsyth                           FT_Pos        y )
443*37da2899SCharles.Forsyth   {
444*37da2899SCharles.Forsyth     FT_Error  error;
445*37da2899SCharles.Forsyth 
446*37da2899SCharles.Forsyth 
447*37da2899SCharles.Forsyth     error = check_points( builder, 1 );
448*37da2899SCharles.Forsyth     if ( !error )
449*37da2899SCharles.Forsyth       cff_builder_add_point( builder, x, y, 1 );
450*37da2899SCharles.Forsyth 
451*37da2899SCharles.Forsyth     return error;
452*37da2899SCharles.Forsyth   }
453*37da2899SCharles.Forsyth 
454*37da2899SCharles.Forsyth 
455*37da2899SCharles.Forsyth   /* check room for a new contour, then add it */
456*37da2899SCharles.Forsyth   static FT_Error
cff_builder_add_contour(CFF_Builder * builder)457*37da2899SCharles.Forsyth   cff_builder_add_contour( CFF_Builder*  builder )
458*37da2899SCharles.Forsyth   {
459*37da2899SCharles.Forsyth     FT_Outline*  outline = builder->current;
460*37da2899SCharles.Forsyth     FT_Error     error;
461*37da2899SCharles.Forsyth 
462*37da2899SCharles.Forsyth 
463*37da2899SCharles.Forsyth     if ( !builder->load_points )
464*37da2899SCharles.Forsyth     {
465*37da2899SCharles.Forsyth       outline->n_contours++;
466*37da2899SCharles.Forsyth       return CFF_Err_Ok;
467*37da2899SCharles.Forsyth     }
468*37da2899SCharles.Forsyth 
469*37da2899SCharles.Forsyth     error = FT_GlyphLoader_CheckPoints( builder->loader, 0, 1 );
470*37da2899SCharles.Forsyth     if ( !error )
471*37da2899SCharles.Forsyth     {
472*37da2899SCharles.Forsyth       if ( outline->n_contours > 0 )
473*37da2899SCharles.Forsyth         outline->contours[outline->n_contours - 1] =
474*37da2899SCharles.Forsyth           (short)( outline->n_points - 1 );
475*37da2899SCharles.Forsyth 
476*37da2899SCharles.Forsyth       outline->n_contours++;
477*37da2899SCharles.Forsyth     }
478*37da2899SCharles.Forsyth 
479*37da2899SCharles.Forsyth     return error;
480*37da2899SCharles.Forsyth   }
481*37da2899SCharles.Forsyth 
482*37da2899SCharles.Forsyth 
483*37da2899SCharles.Forsyth   /* if a path was begun, add its first on-curve point */
484*37da2899SCharles.Forsyth   static FT_Error
cff_builder_start_point(CFF_Builder * builder,FT_Pos x,FT_Pos y)485*37da2899SCharles.Forsyth   cff_builder_start_point( CFF_Builder*  builder,
486*37da2899SCharles.Forsyth                            FT_Pos        x,
487*37da2899SCharles.Forsyth                            FT_Pos        y )
488*37da2899SCharles.Forsyth   {
489*37da2899SCharles.Forsyth     FT_Error  error = 0;
490*37da2899SCharles.Forsyth 
491*37da2899SCharles.Forsyth 
492*37da2899SCharles.Forsyth     /* test whether we are building a new contour */
493*37da2899SCharles.Forsyth     if ( !builder->path_begun )
494*37da2899SCharles.Forsyth     {
495*37da2899SCharles.Forsyth       builder->path_begun = 1;
496*37da2899SCharles.Forsyth       error = cff_builder_add_contour( builder );
497*37da2899SCharles.Forsyth       if ( !error )
498*37da2899SCharles.Forsyth         error = cff_builder_add_point1( builder, x, y );
499*37da2899SCharles.Forsyth     }
500*37da2899SCharles.Forsyth 
501*37da2899SCharles.Forsyth     return error;
502*37da2899SCharles.Forsyth   }
503*37da2899SCharles.Forsyth 
504*37da2899SCharles.Forsyth 
505*37da2899SCharles.Forsyth   /* close the current contour */
506*37da2899SCharles.Forsyth   static void
cff_builder_close_contour(CFF_Builder * builder)507*37da2899SCharles.Forsyth   cff_builder_close_contour( CFF_Builder*  builder )
508*37da2899SCharles.Forsyth   {
509*37da2899SCharles.Forsyth     FT_Outline*  outline = builder->current;
510*37da2899SCharles.Forsyth 
511*37da2899SCharles.Forsyth 
512*37da2899SCharles.Forsyth     /* XXXX: We must not include the last point in the path if it */
513*37da2899SCharles.Forsyth     /*       is located on the first point.                       */
514*37da2899SCharles.Forsyth     if ( outline->n_points > 1 )
515*37da2899SCharles.Forsyth     {
516*37da2899SCharles.Forsyth       FT_Int      first   = 0;
517*37da2899SCharles.Forsyth       FT_Vector*  p1      = outline->points + first;
518*37da2899SCharles.Forsyth       FT_Vector*  p2      = outline->points + outline->n_points - 1;
519*37da2899SCharles.Forsyth       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points - 1;
520*37da2899SCharles.Forsyth 
521*37da2899SCharles.Forsyth 
522*37da2899SCharles.Forsyth       if ( outline->n_contours > 1 )
523*37da2899SCharles.Forsyth       {
524*37da2899SCharles.Forsyth         first = outline->contours[outline->n_contours - 2] + 1;
525*37da2899SCharles.Forsyth         p1    = outline->points + first;
526*37da2899SCharles.Forsyth       }
527*37da2899SCharles.Forsyth 
528*37da2899SCharles.Forsyth       /* `delete' last point only if it coincides with the first    */
529*37da2899SCharles.Forsyth       /* point and if it is not a control point (which can happen). */
530*37da2899SCharles.Forsyth       if ( p1->x == p2->x && p1->y == p2->y )
531*37da2899SCharles.Forsyth         if ( *control == FT_CURVE_TAG_ON )
532*37da2899SCharles.Forsyth           outline->n_points--;
533*37da2899SCharles.Forsyth     }
534*37da2899SCharles.Forsyth 
535*37da2899SCharles.Forsyth     if ( outline->n_contours > 0 )
536*37da2899SCharles.Forsyth       outline->contours[outline->n_contours - 1] =
537*37da2899SCharles.Forsyth         (short)( outline->n_points - 1 );
538*37da2899SCharles.Forsyth   }
539*37da2899SCharles.Forsyth 
540*37da2899SCharles.Forsyth 
541*37da2899SCharles.Forsyth   static FT_Int
cff_lookup_glyph_by_stdcharcode(CFF_Font cff,FT_Int charcode)542*37da2899SCharles.Forsyth   cff_lookup_glyph_by_stdcharcode( CFF_Font  cff,
543*37da2899SCharles.Forsyth                                    FT_Int    charcode )
544*37da2899SCharles.Forsyth   {
545*37da2899SCharles.Forsyth     FT_UInt    n;
546*37da2899SCharles.Forsyth     FT_UShort  glyph_sid;
547*37da2899SCharles.Forsyth 
548*37da2899SCharles.Forsyth 
549*37da2899SCharles.Forsyth     /* check range of standard char code */
550*37da2899SCharles.Forsyth     if ( charcode < 0 || charcode > 255 )
551*37da2899SCharles.Forsyth       return -1;
552*37da2899SCharles.Forsyth 
553*37da2899SCharles.Forsyth     /* Get code to SID mapping from `cff_standard_encoding'. */
554*37da2899SCharles.Forsyth     glyph_sid = cff_get_standard_encoding( (FT_UInt)charcode );
555*37da2899SCharles.Forsyth 
556*37da2899SCharles.Forsyth     for ( n = 0; n < cff->num_glyphs; n++ )
557*37da2899SCharles.Forsyth     {
558*37da2899SCharles.Forsyth       if ( cff->charset.sids[n] == glyph_sid )
559*37da2899SCharles.Forsyth         return n;
560*37da2899SCharles.Forsyth     }
561*37da2899SCharles.Forsyth 
562*37da2899SCharles.Forsyth     return -1;
563*37da2899SCharles.Forsyth   }
564*37da2899SCharles.Forsyth 
565*37da2899SCharles.Forsyth 
566*37da2899SCharles.Forsyth   static FT_Error
cff_get_glyph_data(TT_Face face,FT_UInt glyph_index,FT_Byte ** pointer,FT_ULong * length)567*37da2899SCharles.Forsyth   cff_get_glyph_data( TT_Face    face,
568*37da2899SCharles.Forsyth                       FT_UInt    glyph_index,
569*37da2899SCharles.Forsyth                       FT_Byte**  pointer,
570*37da2899SCharles.Forsyth                       FT_ULong*  length )
571*37da2899SCharles.Forsyth   {
572*37da2899SCharles.Forsyth #ifdef FT_CONFIG_OPTION_INCREMENTAL
573*37da2899SCharles.Forsyth     /* For incremental fonts get the character data using the */
574*37da2899SCharles.Forsyth     /* callback function.                                     */
575*37da2899SCharles.Forsyth     if ( face->root.internal->incremental_interface )
576*37da2899SCharles.Forsyth     {
577*37da2899SCharles.Forsyth       FT_Data   data;
578*37da2899SCharles.Forsyth       FT_Error  error =
579*37da2899SCharles.Forsyth                   face->root.internal->incremental_interface->funcs->get_glyph_data(
580*37da2899SCharles.Forsyth                     face->root.internal->incremental_interface->object,
581*37da2899SCharles.Forsyth                     glyph_index, &data );
582*37da2899SCharles.Forsyth 
583*37da2899SCharles.Forsyth 
584*37da2899SCharles.Forsyth       *pointer = (FT_Byte*)data.pointer;
585*37da2899SCharles.Forsyth       *length = data.length;
586*37da2899SCharles.Forsyth 
587*37da2899SCharles.Forsyth       return error;
588*37da2899SCharles.Forsyth     }
589*37da2899SCharles.Forsyth     else
590*37da2899SCharles.Forsyth #endif /* FT_CONFIG_OPTION_INCREMENTAL */
591*37da2899SCharles.Forsyth 
592*37da2899SCharles.Forsyth     {
593*37da2899SCharles.Forsyth       CFF_Font  cff  = (CFF_Font)(face->extra.data);
594*37da2899SCharles.Forsyth 
595*37da2899SCharles.Forsyth 
596*37da2899SCharles.Forsyth       return cff_index_access_element( &cff->charstrings_index, glyph_index,
597*37da2899SCharles.Forsyth                                        pointer, length );
598*37da2899SCharles.Forsyth     }
599*37da2899SCharles.Forsyth   }
600*37da2899SCharles.Forsyth 
601*37da2899SCharles.Forsyth 
602*37da2899SCharles.Forsyth   static void
cff_free_glyph_data(TT_Face face,FT_Byte ** pointer,FT_ULong length)603*37da2899SCharles.Forsyth   cff_free_glyph_data( TT_Face    face,
604*37da2899SCharles.Forsyth                        FT_Byte**  pointer,
605*37da2899SCharles.Forsyth                        FT_ULong   length )
606*37da2899SCharles.Forsyth   {
607*37da2899SCharles.Forsyth #ifndef FT_CONFIG_OPTION_INCREMENTAL
608*37da2899SCharles.Forsyth     FT_UNUSED( length );
609*37da2899SCharles.Forsyth #endif
610*37da2899SCharles.Forsyth 
611*37da2899SCharles.Forsyth #ifdef FT_CONFIG_OPTION_INCREMENTAL
612*37da2899SCharles.Forsyth     /* For incremental fonts get the character data using the */
613*37da2899SCharles.Forsyth     /* callback function.                                     */
614*37da2899SCharles.Forsyth     if ( face->root.internal->incremental_interface )
615*37da2899SCharles.Forsyth     {
616*37da2899SCharles.Forsyth       FT_Data data;
617*37da2899SCharles.Forsyth 
618*37da2899SCharles.Forsyth 
619*37da2899SCharles.Forsyth       data.pointer = *pointer;
620*37da2899SCharles.Forsyth       data.length  = length;
621*37da2899SCharles.Forsyth 
622*37da2899SCharles.Forsyth       face->root.internal->incremental_interface->funcs->free_glyph_data(
623*37da2899SCharles.Forsyth         face->root.internal->incremental_interface->object,&data );
624*37da2899SCharles.Forsyth     }
625*37da2899SCharles.Forsyth     else
626*37da2899SCharles.Forsyth #endif /* FT_CONFIG_OPTION_INCREMENTAL */
627*37da2899SCharles.Forsyth 
628*37da2899SCharles.Forsyth     {
629*37da2899SCharles.Forsyth       CFF_Font  cff = (CFF_Font)(face->extra.data);
630*37da2899SCharles.Forsyth 
631*37da2899SCharles.Forsyth 
632*37da2899SCharles.Forsyth       cff_index_forget_element( &cff->charstrings_index, pointer );
633*37da2899SCharles.Forsyth     }
634*37da2899SCharles.Forsyth   }
635*37da2899SCharles.Forsyth 
636*37da2899SCharles.Forsyth 
637*37da2899SCharles.Forsyth   static FT_Error
cff_operator_seac(CFF_Decoder * decoder,FT_Pos adx,FT_Pos ady,FT_Int bchar,FT_Int achar)638*37da2899SCharles.Forsyth   cff_operator_seac( CFF_Decoder*  decoder,
639*37da2899SCharles.Forsyth                      FT_Pos        adx,
640*37da2899SCharles.Forsyth                      FT_Pos        ady,
641*37da2899SCharles.Forsyth                      FT_Int        bchar,
642*37da2899SCharles.Forsyth                      FT_Int        achar )
643*37da2899SCharles.Forsyth   {
644*37da2899SCharles.Forsyth     FT_Error     error;
645*37da2899SCharles.Forsyth     FT_Int       bchar_index, achar_index, n_base_points;
646*37da2899SCharles.Forsyth     FT_Outline*  base = decoder->builder.base;
647*37da2899SCharles.Forsyth     TT_Face      face = decoder->builder.face;
648*37da2899SCharles.Forsyth     FT_Vector    left_bearing, advance;
649*37da2899SCharles.Forsyth     FT_Byte*     charstring;
650*37da2899SCharles.Forsyth     FT_ULong     charstring_len;
651*37da2899SCharles.Forsyth 
652*37da2899SCharles.Forsyth 
653*37da2899SCharles.Forsyth #ifdef FT_CONFIG_OPTION_INCREMENTAL
654*37da2899SCharles.Forsyth     /* Incremental fonts don't necessarily have valid charsets.        */
655*37da2899SCharles.Forsyth     /* They use the character code, not the glyph index, in this case. */
656*37da2899SCharles.Forsyth     if ( face->root.internal->incremental_interface )
657*37da2899SCharles.Forsyth     {
658*37da2899SCharles.Forsyth       bchar_index = bchar;
659*37da2899SCharles.Forsyth       achar_index = achar;
660*37da2899SCharles.Forsyth     }
661*37da2899SCharles.Forsyth     else
662*37da2899SCharles.Forsyth #endif /* FT_CONFIG_OPTION_INCREMENTAL */
663*37da2899SCharles.Forsyth     {
664*37da2899SCharles.Forsyth       CFF_Font cff = (CFF_Font)(face->extra.data);
665*37da2899SCharles.Forsyth 
666*37da2899SCharles.Forsyth 
667*37da2899SCharles.Forsyth       bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar );
668*37da2899SCharles.Forsyth       achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar );
669*37da2899SCharles.Forsyth     }
670*37da2899SCharles.Forsyth 
671*37da2899SCharles.Forsyth     if ( bchar_index < 0 || achar_index < 0 )
672*37da2899SCharles.Forsyth     {
673*37da2899SCharles.Forsyth       FT_ERROR(( "cff_operator_seac:" ));
674*37da2899SCharles.Forsyth       FT_ERROR(( " invalid seac character code arguments\n" ));
675*37da2899SCharles.Forsyth       return CFF_Err_Syntax_Error;
676*37da2899SCharles.Forsyth     }
677*37da2899SCharles.Forsyth 
678*37da2899SCharles.Forsyth     /* If we are trying to load a composite glyph, do not load the */
679*37da2899SCharles.Forsyth     /* accent character and return the array of subglyphs.         */
680*37da2899SCharles.Forsyth     if ( decoder->builder.no_recurse )
681*37da2899SCharles.Forsyth     {
682*37da2899SCharles.Forsyth       FT_GlyphSlot    glyph  = (FT_GlyphSlot)decoder->builder.glyph;
683*37da2899SCharles.Forsyth       FT_GlyphLoader  loader = glyph->internal->loader;
684*37da2899SCharles.Forsyth       FT_SubGlyph     subg;
685*37da2899SCharles.Forsyth 
686*37da2899SCharles.Forsyth 
687*37da2899SCharles.Forsyth       /* reallocate subglyph array if necessary */
688*37da2899SCharles.Forsyth       error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
689*37da2899SCharles.Forsyth       if ( error )
690*37da2899SCharles.Forsyth         goto Exit;
691*37da2899SCharles.Forsyth 
692*37da2899SCharles.Forsyth       subg = loader->current.subglyphs;
693*37da2899SCharles.Forsyth 
694*37da2899SCharles.Forsyth       /* subglyph 0 = base character */
695*37da2899SCharles.Forsyth       subg->index = bchar_index;
696*37da2899SCharles.Forsyth       subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
697*37da2899SCharles.Forsyth                     FT_SUBGLYPH_FLAG_USE_MY_METRICS;
698*37da2899SCharles.Forsyth       subg->arg1  = 0;
699*37da2899SCharles.Forsyth       subg->arg2  = 0;
700*37da2899SCharles.Forsyth       subg++;
701*37da2899SCharles.Forsyth 
702*37da2899SCharles.Forsyth       /* subglyph 1 = accent character */
703*37da2899SCharles.Forsyth       subg->index = achar_index;
704*37da2899SCharles.Forsyth       subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
705*37da2899SCharles.Forsyth       subg->arg1  = (FT_Int)adx;
706*37da2899SCharles.Forsyth       subg->arg2  = (FT_Int)ady;
707*37da2899SCharles.Forsyth 
708*37da2899SCharles.Forsyth       /* set up remaining glyph fields */
709*37da2899SCharles.Forsyth       glyph->num_subglyphs = 2;
710*37da2899SCharles.Forsyth       glyph->subglyphs     = loader->base.subglyphs;
711*37da2899SCharles.Forsyth       glyph->format        = FT_GLYPH_FORMAT_COMPOSITE;
712*37da2899SCharles.Forsyth 
713*37da2899SCharles.Forsyth       loader->current.num_subglyphs = 2;
714*37da2899SCharles.Forsyth     }
715*37da2899SCharles.Forsyth 
716*37da2899SCharles.Forsyth     /* First load `bchar' in builder */
717*37da2899SCharles.Forsyth     error = cff_get_glyph_data( face, bchar_index,
718*37da2899SCharles.Forsyth                                 &charstring, &charstring_len );
719*37da2899SCharles.Forsyth     if ( !error )
720*37da2899SCharles.Forsyth     {
721*37da2899SCharles.Forsyth       error = cff_decoder_parse_charstrings( decoder, charstring,
722*37da2899SCharles.Forsyth                                              charstring_len );
723*37da2899SCharles.Forsyth 
724*37da2899SCharles.Forsyth       if ( error )
725*37da2899SCharles.Forsyth         goto Exit;
726*37da2899SCharles.Forsyth 
727*37da2899SCharles.Forsyth       cff_free_glyph_data( face, &charstring, charstring_len );
728*37da2899SCharles.Forsyth     }
729*37da2899SCharles.Forsyth 
730*37da2899SCharles.Forsyth     n_base_points = base->n_points;
731*37da2899SCharles.Forsyth 
732*37da2899SCharles.Forsyth     /* Save the left bearing and width of the base character */
733*37da2899SCharles.Forsyth     /* as they will be erased by the next load.              */
734*37da2899SCharles.Forsyth 
735*37da2899SCharles.Forsyth     left_bearing = decoder->builder.left_bearing;
736*37da2899SCharles.Forsyth     advance      = decoder->builder.advance;
737*37da2899SCharles.Forsyth 
738*37da2899SCharles.Forsyth     decoder->builder.left_bearing.x = 0;
739*37da2899SCharles.Forsyth     decoder->builder.left_bearing.y = 0;
740*37da2899SCharles.Forsyth 
741*37da2899SCharles.Forsyth     /* Now load `achar' on top of the base outline. */
742*37da2899SCharles.Forsyth     error = cff_get_glyph_data( face, achar_index,
743*37da2899SCharles.Forsyth                                 &charstring, &charstring_len );
744*37da2899SCharles.Forsyth     if ( !error )
745*37da2899SCharles.Forsyth     {
746*37da2899SCharles.Forsyth       error = cff_decoder_parse_charstrings( decoder, charstring,
747*37da2899SCharles.Forsyth                                              charstring_len );
748*37da2899SCharles.Forsyth 
749*37da2899SCharles.Forsyth       if ( error )
750*37da2899SCharles.Forsyth         goto Exit;
751*37da2899SCharles.Forsyth 
752*37da2899SCharles.Forsyth       cff_free_glyph_data( face, &charstring, charstring_len );
753*37da2899SCharles.Forsyth     }
754*37da2899SCharles.Forsyth 
755*37da2899SCharles.Forsyth     /* Restore the left side bearing and advance width */
756*37da2899SCharles.Forsyth     /* of the base character.                          */
757*37da2899SCharles.Forsyth     decoder->builder.left_bearing = left_bearing;
758*37da2899SCharles.Forsyth     decoder->builder.advance      = advance;
759*37da2899SCharles.Forsyth 
760*37da2899SCharles.Forsyth     /* Finally, move the accent. */
761*37da2899SCharles.Forsyth     if ( decoder->builder.load_points )
762*37da2899SCharles.Forsyth     {
763*37da2899SCharles.Forsyth       FT_Outline  dummy;
764*37da2899SCharles.Forsyth 
765*37da2899SCharles.Forsyth 
766*37da2899SCharles.Forsyth       dummy.n_points = (short)( base->n_points - n_base_points );
767*37da2899SCharles.Forsyth       dummy.points   = base->points   + n_base_points;
768*37da2899SCharles.Forsyth 
769*37da2899SCharles.Forsyth       FT_Outline_Translate( &dummy, adx, ady );
770*37da2899SCharles.Forsyth     }
771*37da2899SCharles.Forsyth 
772*37da2899SCharles.Forsyth   Exit:
773*37da2899SCharles.Forsyth     return error;
774*37da2899SCharles.Forsyth   }
775*37da2899SCharles.Forsyth 
776*37da2899SCharles.Forsyth 
777*37da2899SCharles.Forsyth   /*************************************************************************/
778*37da2899SCharles.Forsyth   /*                                                                       */
779*37da2899SCharles.Forsyth   /* <Function>                                                            */
780*37da2899SCharles.Forsyth   /*    cff_decoder_parse_charstrings                                      */
781*37da2899SCharles.Forsyth   /*                                                                       */
782*37da2899SCharles.Forsyth   /* <Description>                                                         */
783*37da2899SCharles.Forsyth   /*    Parses a given Type 2 charstrings program.                         */
784*37da2899SCharles.Forsyth   /*                                                                       */
785*37da2899SCharles.Forsyth   /* <InOut>                                                               */
786*37da2899SCharles.Forsyth   /*    decoder         :: The current Type 1 decoder.                     */
787*37da2899SCharles.Forsyth   /*                                                                       */
788*37da2899SCharles.Forsyth   /* <Input>                                                               */
789*37da2899SCharles.Forsyth   /*    charstring_base :: The base of the charstring stream.              */
790*37da2899SCharles.Forsyth   /*                                                                       */
791*37da2899SCharles.Forsyth   /*    charstring_len  :: The length in bytes of the charstring stream.   */
792*37da2899SCharles.Forsyth   /*                                                                       */
793*37da2899SCharles.Forsyth   /* <Return>                                                              */
794*37da2899SCharles.Forsyth   /*    FreeType error code.  0 means success.                             */
795*37da2899SCharles.Forsyth   /*                                                                       */
796*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
cff_decoder_parse_charstrings(CFF_Decoder * decoder,FT_Byte * charstring_base,FT_ULong charstring_len)797*37da2899SCharles.Forsyth   cff_decoder_parse_charstrings( CFF_Decoder*  decoder,
798*37da2899SCharles.Forsyth                                  FT_Byte*      charstring_base,
799*37da2899SCharles.Forsyth                                  FT_ULong      charstring_len )
800*37da2899SCharles.Forsyth   {
801*37da2899SCharles.Forsyth     FT_Error           error;
802*37da2899SCharles.Forsyth     CFF_Decoder_Zone*  zone;
803*37da2899SCharles.Forsyth     FT_Byte*           ip;
804*37da2899SCharles.Forsyth     FT_Byte*           limit;
805*37da2899SCharles.Forsyth     CFF_Builder*       builder = &decoder->builder;
806*37da2899SCharles.Forsyth     FT_Pos             x, y;
807*37da2899SCharles.Forsyth     FT_Fixed           seed;
808*37da2899SCharles.Forsyth     FT_Fixed*          stack;
809*37da2899SCharles.Forsyth 
810*37da2899SCharles.Forsyth     T2_Hints_Funcs     hinter;
811*37da2899SCharles.Forsyth 
812*37da2899SCharles.Forsyth 
813*37da2899SCharles.Forsyth     /* set default width */
814*37da2899SCharles.Forsyth     decoder->num_hints  = 0;
815*37da2899SCharles.Forsyth     decoder->read_width = 1;
816*37da2899SCharles.Forsyth 
817*37da2899SCharles.Forsyth     /* compute random seed from stack address of parameter */
818*37da2899SCharles.Forsyth     seed = (FT_Fixed)(char*)&seed           ^
819*37da2899SCharles.Forsyth            (FT_Fixed)(char*)&decoder        ^
820*37da2899SCharles.Forsyth            (FT_Fixed)(char*)&charstring_base;
821*37da2899SCharles.Forsyth     seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFF;
822*37da2899SCharles.Forsyth     if ( seed == 0 )
823*37da2899SCharles.Forsyth       seed = 0x7384;
824*37da2899SCharles.Forsyth 
825*37da2899SCharles.Forsyth     /* initialize the decoder */
826*37da2899SCharles.Forsyth     decoder->top  = decoder->stack;
827*37da2899SCharles.Forsyth     decoder->zone = decoder->zones;
828*37da2899SCharles.Forsyth     zone          = decoder->zones;
829*37da2899SCharles.Forsyth     stack         = decoder->top;
830*37da2899SCharles.Forsyth 
831*37da2899SCharles.Forsyth     hinter = (T2_Hints_Funcs) builder->hints_funcs;
832*37da2899SCharles.Forsyth 
833*37da2899SCharles.Forsyth     builder->path_begun = 0;
834*37da2899SCharles.Forsyth 
835*37da2899SCharles.Forsyth     zone->base           = charstring_base;
836*37da2899SCharles.Forsyth     limit = zone->limit  = charstring_base + charstring_len;
837*37da2899SCharles.Forsyth     ip    = zone->cursor = zone->base;
838*37da2899SCharles.Forsyth 
839*37da2899SCharles.Forsyth     error = CFF_Err_Ok;
840*37da2899SCharles.Forsyth 
841*37da2899SCharles.Forsyth     x = builder->pos_x;
842*37da2899SCharles.Forsyth     y = builder->pos_y;
843*37da2899SCharles.Forsyth 
844*37da2899SCharles.Forsyth     /* begin hints recording session, if any */
845*37da2899SCharles.Forsyth     if ( hinter )
846*37da2899SCharles.Forsyth       hinter->open( hinter->hints );
847*37da2899SCharles.Forsyth 
848*37da2899SCharles.Forsyth     /* now, execute loop */
849*37da2899SCharles.Forsyth     while ( ip < limit )
850*37da2899SCharles.Forsyth     {
851*37da2899SCharles.Forsyth       CFF_Operator  op;
852*37da2899SCharles.Forsyth       FT_Byte       v;
853*37da2899SCharles.Forsyth 
854*37da2899SCharles.Forsyth 
855*37da2899SCharles.Forsyth       /********************************************************************/
856*37da2899SCharles.Forsyth       /*                                                                  */
857*37da2899SCharles.Forsyth       /* Decode operator or operand                                       */
858*37da2899SCharles.Forsyth       /*                                                                  */
859*37da2899SCharles.Forsyth       v = *ip++;
860*37da2899SCharles.Forsyth       if ( v >= 32 || v == 28 )
861*37da2899SCharles.Forsyth       {
862*37da2899SCharles.Forsyth         FT_Int    shift = 16;
863*37da2899SCharles.Forsyth         FT_Int32  val;
864*37da2899SCharles.Forsyth 
865*37da2899SCharles.Forsyth 
866*37da2899SCharles.Forsyth         /* this is an operand, push it on the stack */
867*37da2899SCharles.Forsyth         if ( v == 28 )
868*37da2899SCharles.Forsyth         {
869*37da2899SCharles.Forsyth           if ( ip + 1 >= limit )
870*37da2899SCharles.Forsyth             goto Syntax_Error;
871*37da2899SCharles.Forsyth           val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] );
872*37da2899SCharles.Forsyth           ip += 2;
873*37da2899SCharles.Forsyth         }
874*37da2899SCharles.Forsyth         else if ( v < 247 )
875*37da2899SCharles.Forsyth           val = (FT_Long)v - 139;
876*37da2899SCharles.Forsyth         else if ( v < 251 )
877*37da2899SCharles.Forsyth         {
878*37da2899SCharles.Forsyth           if ( ip >= limit )
879*37da2899SCharles.Forsyth             goto Syntax_Error;
880*37da2899SCharles.Forsyth           val = ( (FT_Long)v - 247 ) * 256 + *ip++ + 108;
881*37da2899SCharles.Forsyth         }
882*37da2899SCharles.Forsyth         else if ( v < 255 )
883*37da2899SCharles.Forsyth         {
884*37da2899SCharles.Forsyth           if ( ip >= limit )
885*37da2899SCharles.Forsyth             goto Syntax_Error;
886*37da2899SCharles.Forsyth           val = -( (FT_Long)v - 251 ) * 256 - *ip++ - 108;
887*37da2899SCharles.Forsyth         }
888*37da2899SCharles.Forsyth         else
889*37da2899SCharles.Forsyth         {
890*37da2899SCharles.Forsyth           if ( ip + 3 >= limit )
891*37da2899SCharles.Forsyth             goto Syntax_Error;
892*37da2899SCharles.Forsyth           val = ( (FT_Int32)ip[0] << 24 ) |
893*37da2899SCharles.Forsyth                 ( (FT_Int32)ip[1] << 16 ) |
894*37da2899SCharles.Forsyth                 ( (FT_Int32)ip[2] <<  8 ) |
895*37da2899SCharles.Forsyth                             ip[3];
896*37da2899SCharles.Forsyth           ip    += 4;
897*37da2899SCharles.Forsyth           shift  = 0;
898*37da2899SCharles.Forsyth         }
899*37da2899SCharles.Forsyth         if ( decoder->top - stack >= CFF_MAX_OPERANDS )
900*37da2899SCharles.Forsyth           goto Stack_Overflow;
901*37da2899SCharles.Forsyth 
902*37da2899SCharles.Forsyth         val           <<= shift;
903*37da2899SCharles.Forsyth         *decoder->top++ = val;
904*37da2899SCharles.Forsyth 
905*37da2899SCharles.Forsyth #ifdef FT_DEBUG_LEVEL_TRACE
906*37da2899SCharles.Forsyth         if ( !( val & 0xFFFF ) )
907*37da2899SCharles.Forsyth           FT_TRACE4(( " %d", (FT_Int32)( val >> 16 ) ));
908*37da2899SCharles.Forsyth         else
909*37da2899SCharles.Forsyth           FT_TRACE4(( " %.2f", val / 65536.0 ));
910*37da2899SCharles.Forsyth #endif
911*37da2899SCharles.Forsyth 
912*37da2899SCharles.Forsyth       }
913*37da2899SCharles.Forsyth       else
914*37da2899SCharles.Forsyth       {
915*37da2899SCharles.Forsyth         FT_Fixed*  args     = decoder->top;
916*37da2899SCharles.Forsyth         FT_Int     num_args = (FT_Int)( args - decoder->stack );
917*37da2899SCharles.Forsyth         FT_Int     req_args;
918*37da2899SCharles.Forsyth 
919*37da2899SCharles.Forsyth 
920*37da2899SCharles.Forsyth         /* find operator */
921*37da2899SCharles.Forsyth         op = cff_op_unknown;
922*37da2899SCharles.Forsyth 
923*37da2899SCharles.Forsyth         switch ( v )
924*37da2899SCharles.Forsyth         {
925*37da2899SCharles.Forsyth         case 1:
926*37da2899SCharles.Forsyth           op = cff_op_hstem;
927*37da2899SCharles.Forsyth           break;
928*37da2899SCharles.Forsyth         case 3:
929*37da2899SCharles.Forsyth           op = cff_op_vstem;
930*37da2899SCharles.Forsyth           break;
931*37da2899SCharles.Forsyth         case 4:
932*37da2899SCharles.Forsyth           op = cff_op_vmoveto;
933*37da2899SCharles.Forsyth           break;
934*37da2899SCharles.Forsyth         case 5:
935*37da2899SCharles.Forsyth           op = cff_op_rlineto;
936*37da2899SCharles.Forsyth           break;
937*37da2899SCharles.Forsyth         case 6:
938*37da2899SCharles.Forsyth           op = cff_op_hlineto;
939*37da2899SCharles.Forsyth           break;
940*37da2899SCharles.Forsyth         case 7:
941*37da2899SCharles.Forsyth           op = cff_op_vlineto;
942*37da2899SCharles.Forsyth           break;
943*37da2899SCharles.Forsyth         case 8:
944*37da2899SCharles.Forsyth           op = cff_op_rrcurveto;
945*37da2899SCharles.Forsyth           break;
946*37da2899SCharles.Forsyth         case 10:
947*37da2899SCharles.Forsyth           op = cff_op_callsubr;
948*37da2899SCharles.Forsyth           break;
949*37da2899SCharles.Forsyth         case 11:
950*37da2899SCharles.Forsyth           op = cff_op_return;
951*37da2899SCharles.Forsyth           break;
952*37da2899SCharles.Forsyth         case 12:
953*37da2899SCharles.Forsyth           {
954*37da2899SCharles.Forsyth             if ( ip >= limit )
955*37da2899SCharles.Forsyth               goto Syntax_Error;
956*37da2899SCharles.Forsyth             v = *ip++;
957*37da2899SCharles.Forsyth 
958*37da2899SCharles.Forsyth             switch ( v )
959*37da2899SCharles.Forsyth             {
960*37da2899SCharles.Forsyth             case 0:
961*37da2899SCharles.Forsyth               op = cff_op_dotsection;
962*37da2899SCharles.Forsyth               break;
963*37da2899SCharles.Forsyth             case 3:
964*37da2899SCharles.Forsyth               op = cff_op_and;
965*37da2899SCharles.Forsyth               break;
966*37da2899SCharles.Forsyth             case 4:
967*37da2899SCharles.Forsyth               op = cff_op_or;
968*37da2899SCharles.Forsyth               break;
969*37da2899SCharles.Forsyth             case 5:
970*37da2899SCharles.Forsyth               op = cff_op_not;
971*37da2899SCharles.Forsyth               break;
972*37da2899SCharles.Forsyth             case 8:
973*37da2899SCharles.Forsyth               op = cff_op_store;
974*37da2899SCharles.Forsyth               break;
975*37da2899SCharles.Forsyth             case 9:
976*37da2899SCharles.Forsyth               op = cff_op_abs;
977*37da2899SCharles.Forsyth               break;
978*37da2899SCharles.Forsyth             case 10:
979*37da2899SCharles.Forsyth               op = cff_op_add;
980*37da2899SCharles.Forsyth               break;
981*37da2899SCharles.Forsyth             case 11:
982*37da2899SCharles.Forsyth               op = cff_op_sub;
983*37da2899SCharles.Forsyth               break;
984*37da2899SCharles.Forsyth             case 12:
985*37da2899SCharles.Forsyth               op = cff_op_div;
986*37da2899SCharles.Forsyth               break;
987*37da2899SCharles.Forsyth             case 13:
988*37da2899SCharles.Forsyth               op = cff_op_load;
989*37da2899SCharles.Forsyth               break;
990*37da2899SCharles.Forsyth             case 14:
991*37da2899SCharles.Forsyth               op = cff_op_neg;
992*37da2899SCharles.Forsyth               break;
993*37da2899SCharles.Forsyth             case 15:
994*37da2899SCharles.Forsyth               op = cff_op_eq;
995*37da2899SCharles.Forsyth               break;
996*37da2899SCharles.Forsyth             case 18:
997*37da2899SCharles.Forsyth               op = cff_op_drop;
998*37da2899SCharles.Forsyth               break;
999*37da2899SCharles.Forsyth             case 20:
1000*37da2899SCharles.Forsyth               op = cff_op_put;
1001*37da2899SCharles.Forsyth               break;
1002*37da2899SCharles.Forsyth             case 21:
1003*37da2899SCharles.Forsyth               op = cff_op_get;
1004*37da2899SCharles.Forsyth               break;
1005*37da2899SCharles.Forsyth             case 22:
1006*37da2899SCharles.Forsyth               op = cff_op_ifelse;
1007*37da2899SCharles.Forsyth               break;
1008*37da2899SCharles.Forsyth             case 23:
1009*37da2899SCharles.Forsyth               op = cff_op_random;
1010*37da2899SCharles.Forsyth               break;
1011*37da2899SCharles.Forsyth             case 24:
1012*37da2899SCharles.Forsyth               op = cff_op_mul;
1013*37da2899SCharles.Forsyth               break;
1014*37da2899SCharles.Forsyth             case 26:
1015*37da2899SCharles.Forsyth               op = cff_op_sqrt;
1016*37da2899SCharles.Forsyth               break;
1017*37da2899SCharles.Forsyth             case 27:
1018*37da2899SCharles.Forsyth               op = cff_op_dup;
1019*37da2899SCharles.Forsyth               break;
1020*37da2899SCharles.Forsyth             case 28:
1021*37da2899SCharles.Forsyth               op = cff_op_exch;
1022*37da2899SCharles.Forsyth               break;
1023*37da2899SCharles.Forsyth             case 29:
1024*37da2899SCharles.Forsyth               op = cff_op_index;
1025*37da2899SCharles.Forsyth               break;
1026*37da2899SCharles.Forsyth             case 30:
1027*37da2899SCharles.Forsyth               op = cff_op_roll;
1028*37da2899SCharles.Forsyth               break;
1029*37da2899SCharles.Forsyth             case 34:
1030*37da2899SCharles.Forsyth               op = cff_op_hflex;
1031*37da2899SCharles.Forsyth               break;
1032*37da2899SCharles.Forsyth             case 35:
1033*37da2899SCharles.Forsyth               op = cff_op_flex;
1034*37da2899SCharles.Forsyth               break;
1035*37da2899SCharles.Forsyth             case 36:
1036*37da2899SCharles.Forsyth               op = cff_op_hflex1;
1037*37da2899SCharles.Forsyth               break;
1038*37da2899SCharles.Forsyth             case 37:
1039*37da2899SCharles.Forsyth               op = cff_op_flex1;
1040*37da2899SCharles.Forsyth               break;
1041*37da2899SCharles.Forsyth             default:
1042*37da2899SCharles.Forsyth               /* decrement ip for syntax error message */
1043*37da2899SCharles.Forsyth               ip--;
1044*37da2899SCharles.Forsyth             }
1045*37da2899SCharles.Forsyth           }
1046*37da2899SCharles.Forsyth           break;
1047*37da2899SCharles.Forsyth         case 14:
1048*37da2899SCharles.Forsyth           op = cff_op_endchar;
1049*37da2899SCharles.Forsyth           break;
1050*37da2899SCharles.Forsyth         case 16:
1051*37da2899SCharles.Forsyth           op = cff_op_blend;
1052*37da2899SCharles.Forsyth           break;
1053*37da2899SCharles.Forsyth         case 18:
1054*37da2899SCharles.Forsyth           op = cff_op_hstemhm;
1055*37da2899SCharles.Forsyth           break;
1056*37da2899SCharles.Forsyth         case 19:
1057*37da2899SCharles.Forsyth           op = cff_op_hintmask;
1058*37da2899SCharles.Forsyth           break;
1059*37da2899SCharles.Forsyth         case 20:
1060*37da2899SCharles.Forsyth           op = cff_op_cntrmask;
1061*37da2899SCharles.Forsyth           break;
1062*37da2899SCharles.Forsyth         case 21:
1063*37da2899SCharles.Forsyth           op = cff_op_rmoveto;
1064*37da2899SCharles.Forsyth           break;
1065*37da2899SCharles.Forsyth         case 22:
1066*37da2899SCharles.Forsyth           op = cff_op_hmoveto;
1067*37da2899SCharles.Forsyth           break;
1068*37da2899SCharles.Forsyth         case 23:
1069*37da2899SCharles.Forsyth           op = cff_op_vstemhm;
1070*37da2899SCharles.Forsyth           break;
1071*37da2899SCharles.Forsyth         case 24:
1072*37da2899SCharles.Forsyth           op = cff_op_rcurveline;
1073*37da2899SCharles.Forsyth           break;
1074*37da2899SCharles.Forsyth         case 25:
1075*37da2899SCharles.Forsyth           op = cff_op_rlinecurve;
1076*37da2899SCharles.Forsyth           break;
1077*37da2899SCharles.Forsyth         case 26:
1078*37da2899SCharles.Forsyth           op = cff_op_vvcurveto;
1079*37da2899SCharles.Forsyth           break;
1080*37da2899SCharles.Forsyth         case 27:
1081*37da2899SCharles.Forsyth           op = cff_op_hhcurveto;
1082*37da2899SCharles.Forsyth           break;
1083*37da2899SCharles.Forsyth         case 29:
1084*37da2899SCharles.Forsyth           op = cff_op_callgsubr;
1085*37da2899SCharles.Forsyth           break;
1086*37da2899SCharles.Forsyth         case 30:
1087*37da2899SCharles.Forsyth           op = cff_op_vhcurveto;
1088*37da2899SCharles.Forsyth           break;
1089*37da2899SCharles.Forsyth         case 31:
1090*37da2899SCharles.Forsyth           op = cff_op_hvcurveto;
1091*37da2899SCharles.Forsyth           break;
1092*37da2899SCharles.Forsyth         default:
1093*37da2899SCharles.Forsyth           ;
1094*37da2899SCharles.Forsyth         }
1095*37da2899SCharles.Forsyth         if ( op == cff_op_unknown )
1096*37da2899SCharles.Forsyth           goto Syntax_Error;
1097*37da2899SCharles.Forsyth 
1098*37da2899SCharles.Forsyth         /* check arguments */
1099*37da2899SCharles.Forsyth         req_args = cff_argument_counts[op];
1100*37da2899SCharles.Forsyth         if ( req_args & CFF_COUNT_CHECK_WIDTH )
1101*37da2899SCharles.Forsyth         {
1102*37da2899SCharles.Forsyth           args = stack;
1103*37da2899SCharles.Forsyth 
1104*37da2899SCharles.Forsyth           if ( num_args > 0 && decoder->read_width )
1105*37da2899SCharles.Forsyth           {
1106*37da2899SCharles.Forsyth             /* If `nominal_width' is non-zero, the number is really a      */
1107*37da2899SCharles.Forsyth             /* difference against `nominal_width'.  Else, the number here  */
1108*37da2899SCharles.Forsyth             /* is truly a width, not a difference against `nominal_width'. */
1109*37da2899SCharles.Forsyth             /* If the font does not set `nominal_width', then              */
1110*37da2899SCharles.Forsyth             /* `nominal_width' defaults to zero, and so we can set         */
1111*37da2899SCharles.Forsyth             /* `glyph_width' to `nominal_width' plus number on the stack   */
1112*37da2899SCharles.Forsyth             /* -- for either case.                                         */
1113*37da2899SCharles.Forsyth 
1114*37da2899SCharles.Forsyth             FT_Int set_width_ok;
1115*37da2899SCharles.Forsyth 
1116*37da2899SCharles.Forsyth 
1117*37da2899SCharles.Forsyth             switch ( op )
1118*37da2899SCharles.Forsyth             {
1119*37da2899SCharles.Forsyth             case cff_op_hmoveto:
1120*37da2899SCharles.Forsyth             case cff_op_vmoveto:
1121*37da2899SCharles.Forsyth               set_width_ok = num_args & 2;
1122*37da2899SCharles.Forsyth               break;
1123*37da2899SCharles.Forsyth 
1124*37da2899SCharles.Forsyth             case cff_op_hstem:
1125*37da2899SCharles.Forsyth             case cff_op_vstem:
1126*37da2899SCharles.Forsyth             case cff_op_hstemhm:
1127*37da2899SCharles.Forsyth             case cff_op_vstemhm:
1128*37da2899SCharles.Forsyth             case cff_op_rmoveto:
1129*37da2899SCharles.Forsyth               set_width_ok = num_args & 1;
1130*37da2899SCharles.Forsyth               break;
1131*37da2899SCharles.Forsyth 
1132*37da2899SCharles.Forsyth             case cff_op_endchar:
1133*37da2899SCharles.Forsyth               /* If there is a width specified for endchar, we either have */
1134*37da2899SCharles.Forsyth               /* 1 argument or 5 arguments.  We like to argue.             */
1135*37da2899SCharles.Forsyth               set_width_ok = ( ( num_args == 5 ) || ( num_args == 1 ) );
1136*37da2899SCharles.Forsyth               break;
1137*37da2899SCharles.Forsyth 
1138*37da2899SCharles.Forsyth             default:
1139*37da2899SCharles.Forsyth               set_width_ok = 0;
1140*37da2899SCharles.Forsyth               break;
1141*37da2899SCharles.Forsyth             }
1142*37da2899SCharles.Forsyth 
1143*37da2899SCharles.Forsyth             if ( set_width_ok )
1144*37da2899SCharles.Forsyth             {
1145*37da2899SCharles.Forsyth               decoder->glyph_width = decoder->nominal_width +
1146*37da2899SCharles.Forsyth                                        ( stack[0] >> 16 );
1147*37da2899SCharles.Forsyth 
1148*37da2899SCharles.Forsyth               /* Consumed an argument. */
1149*37da2899SCharles.Forsyth               num_args--;
1150*37da2899SCharles.Forsyth               args++;
1151*37da2899SCharles.Forsyth             }
1152*37da2899SCharles.Forsyth           }
1153*37da2899SCharles.Forsyth 
1154*37da2899SCharles.Forsyth           decoder->read_width = 0;
1155*37da2899SCharles.Forsyth           req_args            = 0;
1156*37da2899SCharles.Forsyth         }
1157*37da2899SCharles.Forsyth 
1158*37da2899SCharles.Forsyth         req_args &= 15;
1159*37da2899SCharles.Forsyth         if ( num_args < req_args )
1160*37da2899SCharles.Forsyth           goto Stack_Underflow;
1161*37da2899SCharles.Forsyth         args     -= req_args;
1162*37da2899SCharles.Forsyth         num_args -= req_args;
1163*37da2899SCharles.Forsyth 
1164*37da2899SCharles.Forsyth         switch ( op )
1165*37da2899SCharles.Forsyth         {
1166*37da2899SCharles.Forsyth         case cff_op_hstem:
1167*37da2899SCharles.Forsyth         case cff_op_vstem:
1168*37da2899SCharles.Forsyth         case cff_op_hstemhm:
1169*37da2899SCharles.Forsyth         case cff_op_vstemhm:
1170*37da2899SCharles.Forsyth           /* the number of arguments is always even here */
1171*37da2899SCharles.Forsyth           FT_TRACE4(( op == cff_op_hstem   ? " hstem"   :
1172*37da2899SCharles.Forsyth                     ( op == cff_op_vstem   ? " vstem"   :
1173*37da2899SCharles.Forsyth                     ( op == cff_op_hstemhm ? " hstemhm" : " vstemhm" ) ) ));
1174*37da2899SCharles.Forsyth 
1175*37da2899SCharles.Forsyth           if ( hinter )
1176*37da2899SCharles.Forsyth             hinter->stems( hinter->hints,
1177*37da2899SCharles.Forsyth                            ( op == cff_op_hstem || op == cff_op_hstemhm ),
1178*37da2899SCharles.Forsyth                            num_args / 2,
1179*37da2899SCharles.Forsyth                            args );
1180*37da2899SCharles.Forsyth 
1181*37da2899SCharles.Forsyth           decoder->num_hints += num_args / 2;
1182*37da2899SCharles.Forsyth           args = stack;
1183*37da2899SCharles.Forsyth           break;
1184*37da2899SCharles.Forsyth 
1185*37da2899SCharles.Forsyth         case cff_op_hintmask:
1186*37da2899SCharles.Forsyth         case cff_op_cntrmask:
1187*37da2899SCharles.Forsyth           FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" ));
1188*37da2899SCharles.Forsyth 
1189*37da2899SCharles.Forsyth           /* implement vstem when needed --                        */
1190*37da2899SCharles.Forsyth           /* the specification doesn't say it, but this also works */
1191*37da2899SCharles.Forsyth           /* with the 'cntrmask' operator                          */
1192*37da2899SCharles.Forsyth           /*                                                       */
1193*37da2899SCharles.Forsyth           if ( num_args > 0 )
1194*37da2899SCharles.Forsyth           {
1195*37da2899SCharles.Forsyth             if ( hinter )
1196*37da2899SCharles.Forsyth               hinter->stems( hinter->hints,
1197*37da2899SCharles.Forsyth                              0,
1198*37da2899SCharles.Forsyth                              num_args / 2,
1199*37da2899SCharles.Forsyth                              args );
1200*37da2899SCharles.Forsyth 
1201*37da2899SCharles.Forsyth             decoder->num_hints += num_args / 2;
1202*37da2899SCharles.Forsyth           }
1203*37da2899SCharles.Forsyth 
1204*37da2899SCharles.Forsyth           if ( hinter )
1205*37da2899SCharles.Forsyth           {
1206*37da2899SCharles.Forsyth             if ( op == cff_op_hintmask )
1207*37da2899SCharles.Forsyth               hinter->hintmask( hinter->hints,
1208*37da2899SCharles.Forsyth                                 builder->current->n_points,
1209*37da2899SCharles.Forsyth                                 decoder->num_hints,
1210*37da2899SCharles.Forsyth                                 ip );
1211*37da2899SCharles.Forsyth             else
1212*37da2899SCharles.Forsyth               hinter->counter( hinter->hints,
1213*37da2899SCharles.Forsyth                                decoder->num_hints,
1214*37da2899SCharles.Forsyth                                ip );
1215*37da2899SCharles.Forsyth           }
1216*37da2899SCharles.Forsyth 
1217*37da2899SCharles.Forsyth #ifdef FT_DEBUG_LEVEL_TRACE
1218*37da2899SCharles.Forsyth           {
1219*37da2899SCharles.Forsyth             FT_UInt maskbyte;
1220*37da2899SCharles.Forsyth 
1221*37da2899SCharles.Forsyth 
1222*37da2899SCharles.Forsyth             FT_TRACE4(( " " ));
1223*37da2899SCharles.Forsyth 
1224*37da2899SCharles.Forsyth             for ( maskbyte = 0;
1225*37da2899SCharles.Forsyth                   maskbyte < (FT_UInt)(( decoder->num_hints + 7 ) >> 3);
1226*37da2899SCharles.Forsyth                   maskbyte++, ip++ )
1227*37da2899SCharles.Forsyth               FT_TRACE4(( "%02X", *ip ));
1228*37da2899SCharles.Forsyth           }
1229*37da2899SCharles.Forsyth #else
1230*37da2899SCharles.Forsyth           ip += ( decoder->num_hints + 7 ) >> 3;
1231*37da2899SCharles.Forsyth #endif
1232*37da2899SCharles.Forsyth           if ( ip >= limit )
1233*37da2899SCharles.Forsyth             goto Syntax_Error;
1234*37da2899SCharles.Forsyth           args = stack;
1235*37da2899SCharles.Forsyth           break;
1236*37da2899SCharles.Forsyth 
1237*37da2899SCharles.Forsyth         case cff_op_rmoveto:
1238*37da2899SCharles.Forsyth           FT_TRACE4(( " rmoveto" ));
1239*37da2899SCharles.Forsyth 
1240*37da2899SCharles.Forsyth           cff_builder_close_contour( builder );
1241*37da2899SCharles.Forsyth           builder->path_begun = 0;
1242*37da2899SCharles.Forsyth           x   += args[0];
1243*37da2899SCharles.Forsyth           y   += args[1];
1244*37da2899SCharles.Forsyth           args = stack;
1245*37da2899SCharles.Forsyth           break;
1246*37da2899SCharles.Forsyth 
1247*37da2899SCharles.Forsyth         case cff_op_vmoveto:
1248*37da2899SCharles.Forsyth           FT_TRACE4(( " vmoveto" ));
1249*37da2899SCharles.Forsyth 
1250*37da2899SCharles.Forsyth           cff_builder_close_contour( builder );
1251*37da2899SCharles.Forsyth           builder->path_begun = 0;
1252*37da2899SCharles.Forsyth           y   += args[0];
1253*37da2899SCharles.Forsyth           args = stack;
1254*37da2899SCharles.Forsyth           break;
1255*37da2899SCharles.Forsyth 
1256*37da2899SCharles.Forsyth         case cff_op_hmoveto:
1257*37da2899SCharles.Forsyth           FT_TRACE4(( " hmoveto" ));
1258*37da2899SCharles.Forsyth 
1259*37da2899SCharles.Forsyth           cff_builder_close_contour( builder );
1260*37da2899SCharles.Forsyth           builder->path_begun = 0;
1261*37da2899SCharles.Forsyth           x   += args[0];
1262*37da2899SCharles.Forsyth           args = stack;
1263*37da2899SCharles.Forsyth           break;
1264*37da2899SCharles.Forsyth 
1265*37da2899SCharles.Forsyth         case cff_op_rlineto:
1266*37da2899SCharles.Forsyth           FT_TRACE4(( " rlineto" ));
1267*37da2899SCharles.Forsyth 
1268*37da2899SCharles.Forsyth           if ( cff_builder_start_point ( builder, x, y ) ||
1269*37da2899SCharles.Forsyth                check_points( builder, num_args / 2 )     )
1270*37da2899SCharles.Forsyth             goto Memory_Error;
1271*37da2899SCharles.Forsyth 
1272*37da2899SCharles.Forsyth           if ( num_args < 2 || num_args & 1 )
1273*37da2899SCharles.Forsyth             goto Stack_Underflow;
1274*37da2899SCharles.Forsyth 
1275*37da2899SCharles.Forsyth           args = stack;
1276*37da2899SCharles.Forsyth           while ( args < decoder->top )
1277*37da2899SCharles.Forsyth           {
1278*37da2899SCharles.Forsyth             x += args[0];
1279*37da2899SCharles.Forsyth             y += args[1];
1280*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 1 );
1281*37da2899SCharles.Forsyth             args += 2;
1282*37da2899SCharles.Forsyth           }
1283*37da2899SCharles.Forsyth           args = stack;
1284*37da2899SCharles.Forsyth           break;
1285*37da2899SCharles.Forsyth 
1286*37da2899SCharles.Forsyth         case cff_op_hlineto:
1287*37da2899SCharles.Forsyth         case cff_op_vlineto:
1288*37da2899SCharles.Forsyth           {
1289*37da2899SCharles.Forsyth             FT_Int  phase = ( op == cff_op_hlineto );
1290*37da2899SCharles.Forsyth 
1291*37da2899SCharles.Forsyth 
1292*37da2899SCharles.Forsyth             FT_TRACE4(( op == cff_op_hlineto ? " hlineto"
1293*37da2899SCharles.Forsyth                                              : " vlineto" ));
1294*37da2899SCharles.Forsyth 
1295*37da2899SCharles.Forsyth             if ( cff_builder_start_point ( builder, x, y )     ||
1296*37da2899SCharles.Forsyth                  check_points( builder, num_args ) )
1297*37da2899SCharles.Forsyth               goto Memory_Error;
1298*37da2899SCharles.Forsyth 
1299*37da2899SCharles.Forsyth             args = stack;
1300*37da2899SCharles.Forsyth             while (args < decoder->top )
1301*37da2899SCharles.Forsyth             {
1302*37da2899SCharles.Forsyth               if ( phase )
1303*37da2899SCharles.Forsyth                 x += args[0];
1304*37da2899SCharles.Forsyth               else
1305*37da2899SCharles.Forsyth                 y += args[0];
1306*37da2899SCharles.Forsyth 
1307*37da2899SCharles.Forsyth               if ( cff_builder_add_point1( builder, x, y ) )
1308*37da2899SCharles.Forsyth                 goto Memory_Error;
1309*37da2899SCharles.Forsyth 
1310*37da2899SCharles.Forsyth               args++;
1311*37da2899SCharles.Forsyth               phase ^= 1;
1312*37da2899SCharles.Forsyth             }
1313*37da2899SCharles.Forsyth             args = stack;
1314*37da2899SCharles.Forsyth           }
1315*37da2899SCharles.Forsyth           break;
1316*37da2899SCharles.Forsyth 
1317*37da2899SCharles.Forsyth         case cff_op_rrcurveto:
1318*37da2899SCharles.Forsyth           FT_TRACE4(( " rrcurveto" ));
1319*37da2899SCharles.Forsyth 
1320*37da2899SCharles.Forsyth           /* check number of arguments; must be a multiple of 6 */
1321*37da2899SCharles.Forsyth           if ( num_args % 6 != 0 )
1322*37da2899SCharles.Forsyth             goto Stack_Underflow;
1323*37da2899SCharles.Forsyth 
1324*37da2899SCharles.Forsyth           if ( cff_builder_start_point ( builder, x, y ) ||
1325*37da2899SCharles.Forsyth                check_points( builder, num_args / 2 )     )
1326*37da2899SCharles.Forsyth             goto Memory_Error;
1327*37da2899SCharles.Forsyth 
1328*37da2899SCharles.Forsyth           args = stack;
1329*37da2899SCharles.Forsyth           while ( args < decoder->top )
1330*37da2899SCharles.Forsyth           {
1331*37da2899SCharles.Forsyth             x += args[0];
1332*37da2899SCharles.Forsyth             y += args[1];
1333*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 0 );
1334*37da2899SCharles.Forsyth             x += args[2];
1335*37da2899SCharles.Forsyth             y += args[3];
1336*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 0 );
1337*37da2899SCharles.Forsyth             x += args[4];
1338*37da2899SCharles.Forsyth             y += args[5];
1339*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 1 );
1340*37da2899SCharles.Forsyth             args += 6;
1341*37da2899SCharles.Forsyth           }
1342*37da2899SCharles.Forsyth           args = stack;
1343*37da2899SCharles.Forsyth           break;
1344*37da2899SCharles.Forsyth 
1345*37da2899SCharles.Forsyth         case cff_op_vvcurveto:
1346*37da2899SCharles.Forsyth           FT_TRACE4(( " vvcurveto" ));
1347*37da2899SCharles.Forsyth 
1348*37da2899SCharles.Forsyth           if ( cff_builder_start_point ( builder, x, y ) )
1349*37da2899SCharles.Forsyth             goto Memory_Error;
1350*37da2899SCharles.Forsyth 
1351*37da2899SCharles.Forsyth           args = stack;
1352*37da2899SCharles.Forsyth           if ( num_args & 1 )
1353*37da2899SCharles.Forsyth           {
1354*37da2899SCharles.Forsyth             x += args[0];
1355*37da2899SCharles.Forsyth             args++;
1356*37da2899SCharles.Forsyth             num_args--;
1357*37da2899SCharles.Forsyth           }
1358*37da2899SCharles.Forsyth 
1359*37da2899SCharles.Forsyth           if ( num_args % 4 != 0 )
1360*37da2899SCharles.Forsyth             goto Stack_Underflow;
1361*37da2899SCharles.Forsyth 
1362*37da2899SCharles.Forsyth           if ( check_points( builder, 3 * ( num_args / 4 ) ) )
1363*37da2899SCharles.Forsyth             goto Memory_Error;
1364*37da2899SCharles.Forsyth 
1365*37da2899SCharles.Forsyth           while ( args < decoder->top )
1366*37da2899SCharles.Forsyth           {
1367*37da2899SCharles.Forsyth             y += args[0];
1368*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 0 );
1369*37da2899SCharles.Forsyth             x += args[1];
1370*37da2899SCharles.Forsyth             y += args[2];
1371*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 0 );
1372*37da2899SCharles.Forsyth             y += args[3];
1373*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 1 );
1374*37da2899SCharles.Forsyth             args += 4;
1375*37da2899SCharles.Forsyth           }
1376*37da2899SCharles.Forsyth           args = stack;
1377*37da2899SCharles.Forsyth           break;
1378*37da2899SCharles.Forsyth 
1379*37da2899SCharles.Forsyth         case cff_op_hhcurveto:
1380*37da2899SCharles.Forsyth           FT_TRACE4(( " hhcurveto" ));
1381*37da2899SCharles.Forsyth 
1382*37da2899SCharles.Forsyth           if ( cff_builder_start_point ( builder, x, y ) )
1383*37da2899SCharles.Forsyth             goto Memory_Error;
1384*37da2899SCharles.Forsyth 
1385*37da2899SCharles.Forsyth           args = stack;
1386*37da2899SCharles.Forsyth           if ( num_args & 1 )
1387*37da2899SCharles.Forsyth           {
1388*37da2899SCharles.Forsyth             y += args[0];
1389*37da2899SCharles.Forsyth             args++;
1390*37da2899SCharles.Forsyth             num_args--;
1391*37da2899SCharles.Forsyth           }
1392*37da2899SCharles.Forsyth 
1393*37da2899SCharles.Forsyth           if ( num_args % 4 != 0 )
1394*37da2899SCharles.Forsyth             goto Stack_Underflow;
1395*37da2899SCharles.Forsyth 
1396*37da2899SCharles.Forsyth           if ( check_points( builder, 3 * ( num_args / 4 ) ) )
1397*37da2899SCharles.Forsyth             goto Memory_Error;
1398*37da2899SCharles.Forsyth 
1399*37da2899SCharles.Forsyth           while ( args < decoder->top )
1400*37da2899SCharles.Forsyth           {
1401*37da2899SCharles.Forsyth             x += args[0];
1402*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 0 );
1403*37da2899SCharles.Forsyth             x += args[1];
1404*37da2899SCharles.Forsyth             y += args[2];
1405*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 0 );
1406*37da2899SCharles.Forsyth             x += args[3];
1407*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 1 );
1408*37da2899SCharles.Forsyth             args += 4;
1409*37da2899SCharles.Forsyth           }
1410*37da2899SCharles.Forsyth           args = stack;
1411*37da2899SCharles.Forsyth           break;
1412*37da2899SCharles.Forsyth 
1413*37da2899SCharles.Forsyth         case cff_op_vhcurveto:
1414*37da2899SCharles.Forsyth         case cff_op_hvcurveto:
1415*37da2899SCharles.Forsyth           {
1416*37da2899SCharles.Forsyth             FT_Int  phase;
1417*37da2899SCharles.Forsyth 
1418*37da2899SCharles.Forsyth 
1419*37da2899SCharles.Forsyth             FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto"
1420*37da2899SCharles.Forsyth                                                : " hvcurveto" ));
1421*37da2899SCharles.Forsyth 
1422*37da2899SCharles.Forsyth             if ( cff_builder_start_point ( builder, x, y ) )
1423*37da2899SCharles.Forsyth               goto Memory_Error;
1424*37da2899SCharles.Forsyth 
1425*37da2899SCharles.Forsyth             args = stack;
1426*37da2899SCharles.Forsyth             if (num_args < 4 || ( num_args % 4 ) > 1 )
1427*37da2899SCharles.Forsyth               goto Stack_Underflow;
1428*37da2899SCharles.Forsyth 
1429*37da2899SCharles.Forsyth             if ( check_points( builder, ( num_args / 4 ) * 3 ) )
1430*37da2899SCharles.Forsyth               goto Stack_Underflow;
1431*37da2899SCharles.Forsyth 
1432*37da2899SCharles.Forsyth             phase = ( op == cff_op_hvcurveto );
1433*37da2899SCharles.Forsyth 
1434*37da2899SCharles.Forsyth             while ( num_args >= 4 )
1435*37da2899SCharles.Forsyth             {
1436*37da2899SCharles.Forsyth               num_args -= 4;
1437*37da2899SCharles.Forsyth               if ( phase )
1438*37da2899SCharles.Forsyth               {
1439*37da2899SCharles.Forsyth                 x += args[0];
1440*37da2899SCharles.Forsyth                 cff_builder_add_point( builder, x, y, 0 );
1441*37da2899SCharles.Forsyth                 x += args[1];
1442*37da2899SCharles.Forsyth                 y += args[2];
1443*37da2899SCharles.Forsyth                 cff_builder_add_point( builder, x, y, 0 );
1444*37da2899SCharles.Forsyth                 y += args[3];
1445*37da2899SCharles.Forsyth                 if ( num_args == 1 )
1446*37da2899SCharles.Forsyth                   x += args[4];
1447*37da2899SCharles.Forsyth                 cff_builder_add_point( builder, x, y, 1 );
1448*37da2899SCharles.Forsyth               }
1449*37da2899SCharles.Forsyth               else
1450*37da2899SCharles.Forsyth               {
1451*37da2899SCharles.Forsyth                 y += args[0];
1452*37da2899SCharles.Forsyth                 cff_builder_add_point( builder, x, y, 0 );
1453*37da2899SCharles.Forsyth                 x += args[1];
1454*37da2899SCharles.Forsyth                 y += args[2];
1455*37da2899SCharles.Forsyth                 cff_builder_add_point( builder, x, y, 0 );
1456*37da2899SCharles.Forsyth                 x += args[3];
1457*37da2899SCharles.Forsyth                 if ( num_args == 1 )
1458*37da2899SCharles.Forsyth                   y += args[4];
1459*37da2899SCharles.Forsyth                 cff_builder_add_point( builder, x, y, 1 );
1460*37da2899SCharles.Forsyth               }
1461*37da2899SCharles.Forsyth               args  += 4;
1462*37da2899SCharles.Forsyth               phase ^= 1;
1463*37da2899SCharles.Forsyth             }
1464*37da2899SCharles.Forsyth             args = stack;
1465*37da2899SCharles.Forsyth           }
1466*37da2899SCharles.Forsyth           break;
1467*37da2899SCharles.Forsyth 
1468*37da2899SCharles.Forsyth         case cff_op_rlinecurve:
1469*37da2899SCharles.Forsyth           {
1470*37da2899SCharles.Forsyth             FT_Int  num_lines = ( num_args - 6 ) / 2;
1471*37da2899SCharles.Forsyth 
1472*37da2899SCharles.Forsyth 
1473*37da2899SCharles.Forsyth             FT_TRACE4(( " rlinecurve" ));
1474*37da2899SCharles.Forsyth 
1475*37da2899SCharles.Forsyth             if ( num_args < 8 || ( num_args - 6 ) & 1 )
1476*37da2899SCharles.Forsyth               goto Stack_Underflow;
1477*37da2899SCharles.Forsyth 
1478*37da2899SCharles.Forsyth             if ( cff_builder_start_point( builder, x, y ) ||
1479*37da2899SCharles.Forsyth                  check_points( builder, num_lines + 3 )   )
1480*37da2899SCharles.Forsyth               goto Memory_Error;
1481*37da2899SCharles.Forsyth 
1482*37da2899SCharles.Forsyth             args = stack;
1483*37da2899SCharles.Forsyth 
1484*37da2899SCharles.Forsyth             /* first, add the line segments */
1485*37da2899SCharles.Forsyth             while ( num_lines > 0 )
1486*37da2899SCharles.Forsyth             {
1487*37da2899SCharles.Forsyth               x += args[0];
1488*37da2899SCharles.Forsyth               y += args[1];
1489*37da2899SCharles.Forsyth               cff_builder_add_point( builder, x, y, 1 );
1490*37da2899SCharles.Forsyth               args += 2;
1491*37da2899SCharles.Forsyth               num_lines--;
1492*37da2899SCharles.Forsyth             }
1493*37da2899SCharles.Forsyth 
1494*37da2899SCharles.Forsyth             /* then the curve */
1495*37da2899SCharles.Forsyth             x += args[0];
1496*37da2899SCharles.Forsyth             y += args[1];
1497*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 0 );
1498*37da2899SCharles.Forsyth             x += args[2];
1499*37da2899SCharles.Forsyth             y += args[3];
1500*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 0 );
1501*37da2899SCharles.Forsyth             x += args[4];
1502*37da2899SCharles.Forsyth             y += args[5];
1503*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 1 );
1504*37da2899SCharles.Forsyth             args = stack;
1505*37da2899SCharles.Forsyth           }
1506*37da2899SCharles.Forsyth           break;
1507*37da2899SCharles.Forsyth 
1508*37da2899SCharles.Forsyth         case cff_op_rcurveline:
1509*37da2899SCharles.Forsyth           {
1510*37da2899SCharles.Forsyth             FT_Int  num_curves = ( num_args - 2 ) / 6;
1511*37da2899SCharles.Forsyth 
1512*37da2899SCharles.Forsyth 
1513*37da2899SCharles.Forsyth             FT_TRACE4(( " rcurveline" ));
1514*37da2899SCharles.Forsyth 
1515*37da2899SCharles.Forsyth             if ( num_args < 8 || ( num_args - 2 ) % 6 )
1516*37da2899SCharles.Forsyth               goto Stack_Underflow;
1517*37da2899SCharles.Forsyth 
1518*37da2899SCharles.Forsyth             if ( cff_builder_start_point ( builder, x, y ) ||
1519*37da2899SCharles.Forsyth                  check_points( builder, num_curves*3 + 2 ) )
1520*37da2899SCharles.Forsyth               goto Memory_Error;
1521*37da2899SCharles.Forsyth 
1522*37da2899SCharles.Forsyth             args = stack;
1523*37da2899SCharles.Forsyth 
1524*37da2899SCharles.Forsyth             /* first, add the curves */
1525*37da2899SCharles.Forsyth             while ( num_curves > 0 )
1526*37da2899SCharles.Forsyth             {
1527*37da2899SCharles.Forsyth               x += args[0];
1528*37da2899SCharles.Forsyth               y += args[1];
1529*37da2899SCharles.Forsyth               cff_builder_add_point( builder, x, y, 0 );
1530*37da2899SCharles.Forsyth               x += args[2];
1531*37da2899SCharles.Forsyth               y += args[3];
1532*37da2899SCharles.Forsyth               cff_builder_add_point( builder, x, y, 0 );
1533*37da2899SCharles.Forsyth               x += args[4];
1534*37da2899SCharles.Forsyth               y += args[5];
1535*37da2899SCharles.Forsyth               cff_builder_add_point( builder, x, y, 1 );
1536*37da2899SCharles.Forsyth               args += 6;
1537*37da2899SCharles.Forsyth               num_curves--;
1538*37da2899SCharles.Forsyth             }
1539*37da2899SCharles.Forsyth 
1540*37da2899SCharles.Forsyth             /* then the final line */
1541*37da2899SCharles.Forsyth             x += args[0];
1542*37da2899SCharles.Forsyth             y += args[1];
1543*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 1 );
1544*37da2899SCharles.Forsyth             args = stack;
1545*37da2899SCharles.Forsyth           }
1546*37da2899SCharles.Forsyth           break;
1547*37da2899SCharles.Forsyth 
1548*37da2899SCharles.Forsyth         case cff_op_hflex1:
1549*37da2899SCharles.Forsyth           {
1550*37da2899SCharles.Forsyth             FT_Pos start_y;
1551*37da2899SCharles.Forsyth 
1552*37da2899SCharles.Forsyth 
1553*37da2899SCharles.Forsyth             FT_TRACE4(( " hflex1" ));
1554*37da2899SCharles.Forsyth 
1555*37da2899SCharles.Forsyth             args = stack;
1556*37da2899SCharles.Forsyth 
1557*37da2899SCharles.Forsyth             /* adding five more points; 4 control points, 1 on-curve point */
1558*37da2899SCharles.Forsyth             /* make sure we have enough space for the start point if it    */
1559*37da2899SCharles.Forsyth             /* needs to be added..                                         */
1560*37da2899SCharles.Forsyth             if ( cff_builder_start_point( builder, x, y ) ||
1561*37da2899SCharles.Forsyth                  check_points( builder, 6 )               )
1562*37da2899SCharles.Forsyth               goto Memory_Error;
1563*37da2899SCharles.Forsyth 
1564*37da2899SCharles.Forsyth             /* Record the starting point's y postion for later use */
1565*37da2899SCharles.Forsyth             start_y = y;
1566*37da2899SCharles.Forsyth 
1567*37da2899SCharles.Forsyth             /* first control point */
1568*37da2899SCharles.Forsyth             x += args[0];
1569*37da2899SCharles.Forsyth             y += args[1];
1570*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 0 );
1571*37da2899SCharles.Forsyth 
1572*37da2899SCharles.Forsyth             /* second control point */
1573*37da2899SCharles.Forsyth             x += args[2];
1574*37da2899SCharles.Forsyth             y += args[3];
1575*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 0 );
1576*37da2899SCharles.Forsyth 
1577*37da2899SCharles.Forsyth             /* join point; on curve, with y-value the same as the last */
1578*37da2899SCharles.Forsyth             /* control point's y-value                                 */
1579*37da2899SCharles.Forsyth             x += args[4];
1580*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 1 );
1581*37da2899SCharles.Forsyth 
1582*37da2899SCharles.Forsyth             /* third control point, with y-value the same as the join */
1583*37da2899SCharles.Forsyth             /* point's y-value                                        */
1584*37da2899SCharles.Forsyth             x += args[5];
1585*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 0 );
1586*37da2899SCharles.Forsyth 
1587*37da2899SCharles.Forsyth             /* fourth control point */
1588*37da2899SCharles.Forsyth             x += args[6];
1589*37da2899SCharles.Forsyth             y += args[7];
1590*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 0 );
1591*37da2899SCharles.Forsyth 
1592*37da2899SCharles.Forsyth             /* ending point, with y-value the same as the start   */
1593*37da2899SCharles.Forsyth             x += args[8];
1594*37da2899SCharles.Forsyth             y  = start_y;
1595*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 1 );
1596*37da2899SCharles.Forsyth 
1597*37da2899SCharles.Forsyth             args = stack;
1598*37da2899SCharles.Forsyth             break;
1599*37da2899SCharles.Forsyth           }
1600*37da2899SCharles.Forsyth 
1601*37da2899SCharles.Forsyth         case cff_op_hflex:
1602*37da2899SCharles.Forsyth           {
1603*37da2899SCharles.Forsyth             FT_Pos start_y;
1604*37da2899SCharles.Forsyth 
1605*37da2899SCharles.Forsyth 
1606*37da2899SCharles.Forsyth             FT_TRACE4(( " hflex" ));
1607*37da2899SCharles.Forsyth 
1608*37da2899SCharles.Forsyth             args = stack;
1609*37da2899SCharles.Forsyth 
1610*37da2899SCharles.Forsyth             /* adding six more points; 4 control points, 2 on-curve points */
1611*37da2899SCharles.Forsyth             if ( cff_builder_start_point( builder, x, y ) ||
1612*37da2899SCharles.Forsyth                  check_points ( builder, 6 )              )
1613*37da2899SCharles.Forsyth               goto Memory_Error;
1614*37da2899SCharles.Forsyth 
1615*37da2899SCharles.Forsyth             /* record the starting point's y-position for later use */
1616*37da2899SCharles.Forsyth             start_y = y;
1617*37da2899SCharles.Forsyth 
1618*37da2899SCharles.Forsyth             /* first control point */
1619*37da2899SCharles.Forsyth             x += args[0];
1620*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 0 );
1621*37da2899SCharles.Forsyth 
1622*37da2899SCharles.Forsyth             /* second control point */
1623*37da2899SCharles.Forsyth             x += args[1];
1624*37da2899SCharles.Forsyth             y += args[2];
1625*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 0 );
1626*37da2899SCharles.Forsyth 
1627*37da2899SCharles.Forsyth             /* join point; on curve, with y-value the same as the last */
1628*37da2899SCharles.Forsyth             /* control point's y-value                                 */
1629*37da2899SCharles.Forsyth             x += args[3];
1630*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 1 );
1631*37da2899SCharles.Forsyth 
1632*37da2899SCharles.Forsyth             /* third control point, with y-value the same as the join */
1633*37da2899SCharles.Forsyth             /* point's y-value                                        */
1634*37da2899SCharles.Forsyth             x += args[4];
1635*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 0 );
1636*37da2899SCharles.Forsyth 
1637*37da2899SCharles.Forsyth             /* fourth control point */
1638*37da2899SCharles.Forsyth             x += args[5];
1639*37da2899SCharles.Forsyth             y  = start_y;
1640*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 0 );
1641*37da2899SCharles.Forsyth 
1642*37da2899SCharles.Forsyth             /* ending point, with y-value the same as the start point's */
1643*37da2899SCharles.Forsyth             /* y-value -- we don't add this point, though               */
1644*37da2899SCharles.Forsyth             x += args[6];
1645*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 1 );
1646*37da2899SCharles.Forsyth 
1647*37da2899SCharles.Forsyth             args = stack;
1648*37da2899SCharles.Forsyth             break;
1649*37da2899SCharles.Forsyth           }
1650*37da2899SCharles.Forsyth 
1651*37da2899SCharles.Forsyth         case cff_op_flex1:
1652*37da2899SCharles.Forsyth           {
1653*37da2899SCharles.Forsyth             FT_Pos  start_x, start_y; /* record start x, y values for alter */
1654*37da2899SCharles.Forsyth                                       /* use                                */
1655*37da2899SCharles.Forsyth             FT_Int  dx = 0, dy = 0;   /* used in horizontal/vertical        */
1656*37da2899SCharles.Forsyth                                       /* algorithm below                    */
1657*37da2899SCharles.Forsyth             FT_Int  horizontal, count;
1658*37da2899SCharles.Forsyth 
1659*37da2899SCharles.Forsyth 
1660*37da2899SCharles.Forsyth             FT_TRACE4(( " flex1" ));
1661*37da2899SCharles.Forsyth 
1662*37da2899SCharles.Forsyth             /* adding six more points; 4 control points, 2 on-curve points */
1663*37da2899SCharles.Forsyth             if ( cff_builder_start_point( builder, x, y ) ||
1664*37da2899SCharles.Forsyth                  check_points( builder, 6 )               )
1665*37da2899SCharles.Forsyth                goto Memory_Error;
1666*37da2899SCharles.Forsyth 
1667*37da2899SCharles.Forsyth             /* record the starting point's x, y postion for later use */
1668*37da2899SCharles.Forsyth             start_x = x;
1669*37da2899SCharles.Forsyth             start_y = y;
1670*37da2899SCharles.Forsyth 
1671*37da2899SCharles.Forsyth             /* XXX: figure out whether this is supposed to be a horizontal */
1672*37da2899SCharles.Forsyth             /*      or vertical flex; the Type 2 specification is vague... */
1673*37da2899SCharles.Forsyth 
1674*37da2899SCharles.Forsyth             args = stack;
1675*37da2899SCharles.Forsyth 
1676*37da2899SCharles.Forsyth             /* grab up to the last argument */
1677*37da2899SCharles.Forsyth             for ( count = 5; count > 0; count-- )
1678*37da2899SCharles.Forsyth             {
1679*37da2899SCharles.Forsyth               dx += (FT_Int)args[0];
1680*37da2899SCharles.Forsyth               dy += (FT_Int)args[1];
1681*37da2899SCharles.Forsyth               args += 2;
1682*37da2899SCharles.Forsyth             }
1683*37da2899SCharles.Forsyth 
1684*37da2899SCharles.Forsyth             /* rewind */
1685*37da2899SCharles.Forsyth             args = stack;
1686*37da2899SCharles.Forsyth 
1687*37da2899SCharles.Forsyth             if ( dx < 0 ) dx = -dx;
1688*37da2899SCharles.Forsyth             if ( dy < 0 ) dy = -dy;
1689*37da2899SCharles.Forsyth 
1690*37da2899SCharles.Forsyth             /* strange test, but here it is... */
1691*37da2899SCharles.Forsyth             horizontal = ( dx > dy );
1692*37da2899SCharles.Forsyth 
1693*37da2899SCharles.Forsyth             for ( count = 5; count > 0; count-- )
1694*37da2899SCharles.Forsyth             {
1695*37da2899SCharles.Forsyth               x += args[0];
1696*37da2899SCharles.Forsyth               y += args[1];
1697*37da2899SCharles.Forsyth               cff_builder_add_point( builder, x, y, (FT_Bool)( count == 3 ) );
1698*37da2899SCharles.Forsyth               args += 2;
1699*37da2899SCharles.Forsyth             }
1700*37da2899SCharles.Forsyth 
1701*37da2899SCharles.Forsyth             /* is last operand an x- or y-delta? */
1702*37da2899SCharles.Forsyth             if ( horizontal )
1703*37da2899SCharles.Forsyth             {
1704*37da2899SCharles.Forsyth               x += args[0];
1705*37da2899SCharles.Forsyth               y  = start_y;
1706*37da2899SCharles.Forsyth             }
1707*37da2899SCharles.Forsyth             else
1708*37da2899SCharles.Forsyth             {
1709*37da2899SCharles.Forsyth               x  = start_x;
1710*37da2899SCharles.Forsyth               y += args[0];
1711*37da2899SCharles.Forsyth             }
1712*37da2899SCharles.Forsyth 
1713*37da2899SCharles.Forsyth             cff_builder_add_point( builder, x, y, 1 );
1714*37da2899SCharles.Forsyth 
1715*37da2899SCharles.Forsyth             args = stack;
1716*37da2899SCharles.Forsyth             break;
1717*37da2899SCharles.Forsyth            }
1718*37da2899SCharles.Forsyth 
1719*37da2899SCharles.Forsyth         case cff_op_flex:
1720*37da2899SCharles.Forsyth           {
1721*37da2899SCharles.Forsyth             FT_UInt  count;
1722*37da2899SCharles.Forsyth 
1723*37da2899SCharles.Forsyth 
1724*37da2899SCharles.Forsyth             FT_TRACE4(( " flex" ));
1725*37da2899SCharles.Forsyth 
1726*37da2899SCharles.Forsyth             if ( cff_builder_start_point( builder, x, y ) ||
1727*37da2899SCharles.Forsyth                  check_points( builder, 6 )               )
1728*37da2899SCharles.Forsyth               goto Memory_Error;
1729*37da2899SCharles.Forsyth 
1730*37da2899SCharles.Forsyth             args = stack;
1731*37da2899SCharles.Forsyth             for ( count = 6; count > 0; count-- )
1732*37da2899SCharles.Forsyth             {
1733*37da2899SCharles.Forsyth               x += args[0];
1734*37da2899SCharles.Forsyth               y += args[1];
1735*37da2899SCharles.Forsyth               cff_builder_add_point( builder, x, y,
1736*37da2899SCharles.Forsyth                                      (FT_Bool)( count == 3 || count == 0 ) );
1737*37da2899SCharles.Forsyth               args += 2;
1738*37da2899SCharles.Forsyth             }
1739*37da2899SCharles.Forsyth 
1740*37da2899SCharles.Forsyth             args = stack;
1741*37da2899SCharles.Forsyth           }
1742*37da2899SCharles.Forsyth           break;
1743*37da2899SCharles.Forsyth 
1744*37da2899SCharles.Forsyth         case cff_op_endchar:
1745*37da2899SCharles.Forsyth           FT_TRACE4(( " endchar" ));
1746*37da2899SCharles.Forsyth 
1747*37da2899SCharles.Forsyth           /* We are going to emulate the seac operator. */
1748*37da2899SCharles.Forsyth           if ( num_args == 4 )
1749*37da2899SCharles.Forsyth           {
1750*37da2899SCharles.Forsyth             error = cff_operator_seac( decoder,
1751*37da2899SCharles.Forsyth                                        args[0] >> 16,
1752*37da2899SCharles.Forsyth                                        args[1] >> 16,
1753*37da2899SCharles.Forsyth                                        (FT_Int)( args[2] >> 16 ),
1754*37da2899SCharles.Forsyth                                        (FT_Int)( args[3] >> 16 ) );
1755*37da2899SCharles.Forsyth             args += 4;
1756*37da2899SCharles.Forsyth           }
1757*37da2899SCharles.Forsyth 
1758*37da2899SCharles.Forsyth           if ( !error )
1759*37da2899SCharles.Forsyth             error = CFF_Err_Ok;
1760*37da2899SCharles.Forsyth 
1761*37da2899SCharles.Forsyth           cff_builder_close_contour( builder );
1762*37da2899SCharles.Forsyth 
1763*37da2899SCharles.Forsyth           /* close hints recording session */
1764*37da2899SCharles.Forsyth           if ( hinter )
1765*37da2899SCharles.Forsyth           {
1766*37da2899SCharles.Forsyth             if (hinter->close( hinter->hints, builder->current->n_points ) )
1767*37da2899SCharles.Forsyth               goto Syntax_Error;
1768*37da2899SCharles.Forsyth 
1769*37da2899SCharles.Forsyth             /* apply hints to the loaded glyph outline now */
1770*37da2899SCharles.Forsyth             hinter->apply( hinter->hints,
1771*37da2899SCharles.Forsyth                            builder->current,
1772*37da2899SCharles.Forsyth                            (PSH_Globals)builder->hints_globals,
1773*37da2899SCharles.Forsyth                            builder->hint_flags );
1774*37da2899SCharles.Forsyth           }
1775*37da2899SCharles.Forsyth 
1776*37da2899SCharles.Forsyth           /* add current outline to the glyph slot */
1777*37da2899SCharles.Forsyth           FT_GlyphLoader_Add( builder->loader );
1778*37da2899SCharles.Forsyth 
1779*37da2899SCharles.Forsyth           /* return now! */
1780*37da2899SCharles.Forsyth           FT_TRACE4(( "\n\n" ));
1781*37da2899SCharles.Forsyth           return error;
1782*37da2899SCharles.Forsyth 
1783*37da2899SCharles.Forsyth         case cff_op_abs:
1784*37da2899SCharles.Forsyth           FT_TRACE4(( " abs" ));
1785*37da2899SCharles.Forsyth 
1786*37da2899SCharles.Forsyth           if ( args[0] < 0 )
1787*37da2899SCharles.Forsyth             args[0] = -args[0];
1788*37da2899SCharles.Forsyth           args++;
1789*37da2899SCharles.Forsyth           break;
1790*37da2899SCharles.Forsyth 
1791*37da2899SCharles.Forsyth         case cff_op_add:
1792*37da2899SCharles.Forsyth           FT_TRACE4(( " add" ));
1793*37da2899SCharles.Forsyth 
1794*37da2899SCharles.Forsyth           args[0] += args[1];
1795*37da2899SCharles.Forsyth           args++;
1796*37da2899SCharles.Forsyth           break;
1797*37da2899SCharles.Forsyth 
1798*37da2899SCharles.Forsyth         case cff_op_sub:
1799*37da2899SCharles.Forsyth           FT_TRACE4(( " sub" ));
1800*37da2899SCharles.Forsyth 
1801*37da2899SCharles.Forsyth           args[0] -= args[1];
1802*37da2899SCharles.Forsyth           args++;
1803*37da2899SCharles.Forsyth           break;
1804*37da2899SCharles.Forsyth 
1805*37da2899SCharles.Forsyth         case cff_op_div:
1806*37da2899SCharles.Forsyth           FT_TRACE4(( " div" ));
1807*37da2899SCharles.Forsyth 
1808*37da2899SCharles.Forsyth           args[0] = FT_DivFix( args[0], args[1] );
1809*37da2899SCharles.Forsyth           args++;
1810*37da2899SCharles.Forsyth           break;
1811*37da2899SCharles.Forsyth 
1812*37da2899SCharles.Forsyth         case cff_op_neg:
1813*37da2899SCharles.Forsyth           FT_TRACE4(( " neg" ));
1814*37da2899SCharles.Forsyth 
1815*37da2899SCharles.Forsyth           args[0] = -args[0];
1816*37da2899SCharles.Forsyth           args++;
1817*37da2899SCharles.Forsyth           break;
1818*37da2899SCharles.Forsyth 
1819*37da2899SCharles.Forsyth         case cff_op_random:
1820*37da2899SCharles.Forsyth           {
1821*37da2899SCharles.Forsyth             FT_Fixed  Rand;
1822*37da2899SCharles.Forsyth 
1823*37da2899SCharles.Forsyth 
1824*37da2899SCharles.Forsyth             FT_TRACE4(( " rand" ));
1825*37da2899SCharles.Forsyth 
1826*37da2899SCharles.Forsyth             Rand = seed;
1827*37da2899SCharles.Forsyth             if ( Rand >= 0x8000 )
1828*37da2899SCharles.Forsyth               Rand++;
1829*37da2899SCharles.Forsyth 
1830*37da2899SCharles.Forsyth             args[0] = Rand;
1831*37da2899SCharles.Forsyth             seed    = FT_MulFix( seed, 0x10000L - seed );
1832*37da2899SCharles.Forsyth             if ( seed == 0 )
1833*37da2899SCharles.Forsyth               seed += 0x2873;
1834*37da2899SCharles.Forsyth             args++;
1835*37da2899SCharles.Forsyth           }
1836*37da2899SCharles.Forsyth           break;
1837*37da2899SCharles.Forsyth 
1838*37da2899SCharles.Forsyth         case cff_op_mul:
1839*37da2899SCharles.Forsyth           FT_TRACE4(( " mul" ));
1840*37da2899SCharles.Forsyth 
1841*37da2899SCharles.Forsyth           args[0] = FT_MulFix( args[0], args[1] );
1842*37da2899SCharles.Forsyth           args++;
1843*37da2899SCharles.Forsyth           break;
1844*37da2899SCharles.Forsyth 
1845*37da2899SCharles.Forsyth         case cff_op_sqrt:
1846*37da2899SCharles.Forsyth           FT_TRACE4(( " sqrt" ));
1847*37da2899SCharles.Forsyth 
1848*37da2899SCharles.Forsyth           if ( args[0] > 0 )
1849*37da2899SCharles.Forsyth           {
1850*37da2899SCharles.Forsyth             FT_Int    count = 9;
1851*37da2899SCharles.Forsyth             FT_Fixed  root  = args[0];
1852*37da2899SCharles.Forsyth             FT_Fixed  new_root;
1853*37da2899SCharles.Forsyth 
1854*37da2899SCharles.Forsyth 
1855*37da2899SCharles.Forsyth             for (;;)
1856*37da2899SCharles.Forsyth             {
1857*37da2899SCharles.Forsyth               new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1;
1858*37da2899SCharles.Forsyth               if ( new_root == root || count <= 0 )
1859*37da2899SCharles.Forsyth                 break;
1860*37da2899SCharles.Forsyth               root = new_root;
1861*37da2899SCharles.Forsyth             }
1862*37da2899SCharles.Forsyth             args[0] = new_root;
1863*37da2899SCharles.Forsyth           }
1864*37da2899SCharles.Forsyth           else
1865*37da2899SCharles.Forsyth             args[0] = 0;
1866*37da2899SCharles.Forsyth           args++;
1867*37da2899SCharles.Forsyth           break;
1868*37da2899SCharles.Forsyth 
1869*37da2899SCharles.Forsyth         case cff_op_drop:
1870*37da2899SCharles.Forsyth           /* nothing */
1871*37da2899SCharles.Forsyth           FT_TRACE4(( " drop" ));
1872*37da2899SCharles.Forsyth 
1873*37da2899SCharles.Forsyth           break;
1874*37da2899SCharles.Forsyth 
1875*37da2899SCharles.Forsyth         case cff_op_exch:
1876*37da2899SCharles.Forsyth           {
1877*37da2899SCharles.Forsyth             FT_Fixed  tmp;
1878*37da2899SCharles.Forsyth 
1879*37da2899SCharles.Forsyth 
1880*37da2899SCharles.Forsyth             FT_TRACE4(( " exch" ));
1881*37da2899SCharles.Forsyth 
1882*37da2899SCharles.Forsyth             tmp     = args[0];
1883*37da2899SCharles.Forsyth             args[0] = args[1];
1884*37da2899SCharles.Forsyth             args[1] = tmp;
1885*37da2899SCharles.Forsyth             args   += 2;
1886*37da2899SCharles.Forsyth           }
1887*37da2899SCharles.Forsyth           break;
1888*37da2899SCharles.Forsyth 
1889*37da2899SCharles.Forsyth         case cff_op_index:
1890*37da2899SCharles.Forsyth           {
1891*37da2899SCharles.Forsyth             FT_Int  idx = (FT_Int)( args[0] >> 16 );
1892*37da2899SCharles.Forsyth 
1893*37da2899SCharles.Forsyth 
1894*37da2899SCharles.Forsyth             FT_TRACE4(( " index" ));
1895*37da2899SCharles.Forsyth 
1896*37da2899SCharles.Forsyth             if ( idx < 0 )
1897*37da2899SCharles.Forsyth               idx = 0;
1898*37da2899SCharles.Forsyth             else if ( idx > num_args - 2 )
1899*37da2899SCharles.Forsyth               idx = num_args - 2;
1900*37da2899SCharles.Forsyth             args[0] = args[-( idx + 1 )];
1901*37da2899SCharles.Forsyth             args++;
1902*37da2899SCharles.Forsyth           }
1903*37da2899SCharles.Forsyth           break;
1904*37da2899SCharles.Forsyth 
1905*37da2899SCharles.Forsyth         case cff_op_roll:
1906*37da2899SCharles.Forsyth           {
1907*37da2899SCharles.Forsyth             FT_Int  count = (FT_Int)( args[0] >> 16 );
1908*37da2899SCharles.Forsyth             FT_Int  idx   = (FT_Int)( args[1] >> 16 );
1909*37da2899SCharles.Forsyth 
1910*37da2899SCharles.Forsyth 
1911*37da2899SCharles.Forsyth             FT_TRACE4(( " roll" ));
1912*37da2899SCharles.Forsyth 
1913*37da2899SCharles.Forsyth             if ( count <= 0 )
1914*37da2899SCharles.Forsyth               count = 1;
1915*37da2899SCharles.Forsyth 
1916*37da2899SCharles.Forsyth             args -= count;
1917*37da2899SCharles.Forsyth             if ( args < stack )
1918*37da2899SCharles.Forsyth               goto Stack_Underflow;
1919*37da2899SCharles.Forsyth 
1920*37da2899SCharles.Forsyth             if ( idx >= 0 )
1921*37da2899SCharles.Forsyth             {
1922*37da2899SCharles.Forsyth               while ( idx > 0 )
1923*37da2899SCharles.Forsyth               {
1924*37da2899SCharles.Forsyth                 FT_Fixed  tmp = args[count - 1];
1925*37da2899SCharles.Forsyth                 FT_Int    i;
1926*37da2899SCharles.Forsyth 
1927*37da2899SCharles.Forsyth 
1928*37da2899SCharles.Forsyth                 for ( i = count - 2; i >= 0; i-- )
1929*37da2899SCharles.Forsyth                   args[i + 1] = args[i];
1930*37da2899SCharles.Forsyth                 args[0] = tmp;
1931*37da2899SCharles.Forsyth                 idx--;
1932*37da2899SCharles.Forsyth               }
1933*37da2899SCharles.Forsyth             }
1934*37da2899SCharles.Forsyth             else
1935*37da2899SCharles.Forsyth             {
1936*37da2899SCharles.Forsyth               while ( idx < 0 )
1937*37da2899SCharles.Forsyth               {
1938*37da2899SCharles.Forsyth                 FT_Fixed  tmp = args[0];
1939*37da2899SCharles.Forsyth                 FT_Int    i;
1940*37da2899SCharles.Forsyth 
1941*37da2899SCharles.Forsyth 
1942*37da2899SCharles.Forsyth                 for ( i = 0; i < count - 1; i++ )
1943*37da2899SCharles.Forsyth                   args[i] = args[i + 1];
1944*37da2899SCharles.Forsyth                 args[count - 1] = tmp;
1945*37da2899SCharles.Forsyth                 idx++;
1946*37da2899SCharles.Forsyth               }
1947*37da2899SCharles.Forsyth             }
1948*37da2899SCharles.Forsyth             args += count;
1949*37da2899SCharles.Forsyth           }
1950*37da2899SCharles.Forsyth           break;
1951*37da2899SCharles.Forsyth 
1952*37da2899SCharles.Forsyth         case cff_op_dup:
1953*37da2899SCharles.Forsyth           FT_TRACE4(( " dup" ));
1954*37da2899SCharles.Forsyth 
1955*37da2899SCharles.Forsyth           args[1] = args[0];
1956*37da2899SCharles.Forsyth           args++;
1957*37da2899SCharles.Forsyth           break;
1958*37da2899SCharles.Forsyth 
1959*37da2899SCharles.Forsyth         case cff_op_put:
1960*37da2899SCharles.Forsyth           {
1961*37da2899SCharles.Forsyth             FT_Fixed  val = args[0];
1962*37da2899SCharles.Forsyth             FT_Int    idx = (FT_Int)( args[1] >> 16 );
1963*37da2899SCharles.Forsyth 
1964*37da2899SCharles.Forsyth 
1965*37da2899SCharles.Forsyth             FT_TRACE4(( " put" ));
1966*37da2899SCharles.Forsyth 
1967*37da2899SCharles.Forsyth             if ( idx >= 0 && idx < decoder->len_buildchar )
1968*37da2899SCharles.Forsyth               decoder->buildchar[idx] = val;
1969*37da2899SCharles.Forsyth           }
1970*37da2899SCharles.Forsyth           break;
1971*37da2899SCharles.Forsyth 
1972*37da2899SCharles.Forsyth         case cff_op_get:
1973*37da2899SCharles.Forsyth           {
1974*37da2899SCharles.Forsyth             FT_Int    idx = (FT_Int)( args[0] >> 16 );
1975*37da2899SCharles.Forsyth             FT_Fixed  val = 0;
1976*37da2899SCharles.Forsyth 
1977*37da2899SCharles.Forsyth 
1978*37da2899SCharles.Forsyth             FT_TRACE4(( " get" ));
1979*37da2899SCharles.Forsyth 
1980*37da2899SCharles.Forsyth             if ( idx >= 0 && idx < decoder->len_buildchar )
1981*37da2899SCharles.Forsyth               val = decoder->buildchar[idx];
1982*37da2899SCharles.Forsyth 
1983*37da2899SCharles.Forsyth             args[0] = val;
1984*37da2899SCharles.Forsyth             args++;
1985*37da2899SCharles.Forsyth           }
1986*37da2899SCharles.Forsyth           break;
1987*37da2899SCharles.Forsyth 
1988*37da2899SCharles.Forsyth         case cff_op_store:
1989*37da2899SCharles.Forsyth           FT_TRACE4(( " store "));
1990*37da2899SCharles.Forsyth 
1991*37da2899SCharles.Forsyth           goto Unimplemented;
1992*37da2899SCharles.Forsyth 
1993*37da2899SCharles.Forsyth         case cff_op_load:
1994*37da2899SCharles.Forsyth           FT_TRACE4(( " load" ));
1995*37da2899SCharles.Forsyth 
1996*37da2899SCharles.Forsyth           goto Unimplemented;
1997*37da2899SCharles.Forsyth 
1998*37da2899SCharles.Forsyth         case cff_op_dotsection:
1999*37da2899SCharles.Forsyth           /* this operator is deprecated and ignored by the parser */
2000*37da2899SCharles.Forsyth           FT_TRACE4(( " dotsection" ));
2001*37da2899SCharles.Forsyth           break;
2002*37da2899SCharles.Forsyth 
2003*37da2899SCharles.Forsyth         case cff_op_and:
2004*37da2899SCharles.Forsyth           {
2005*37da2899SCharles.Forsyth             FT_Fixed  cond = args[0] && args[1];
2006*37da2899SCharles.Forsyth 
2007*37da2899SCharles.Forsyth 
2008*37da2899SCharles.Forsyth             FT_TRACE4(( " and" ));
2009*37da2899SCharles.Forsyth 
2010*37da2899SCharles.Forsyth             args[0] = cond ? 0x10000L : 0;
2011*37da2899SCharles.Forsyth             args++;
2012*37da2899SCharles.Forsyth           }
2013*37da2899SCharles.Forsyth           break;
2014*37da2899SCharles.Forsyth 
2015*37da2899SCharles.Forsyth         case cff_op_or:
2016*37da2899SCharles.Forsyth           {
2017*37da2899SCharles.Forsyth             FT_Fixed  cond = args[0] || args[1];
2018*37da2899SCharles.Forsyth 
2019*37da2899SCharles.Forsyth 
2020*37da2899SCharles.Forsyth             FT_TRACE4(( " or" ));
2021*37da2899SCharles.Forsyth 
2022*37da2899SCharles.Forsyth             args[0] = cond ? 0x10000L : 0;
2023*37da2899SCharles.Forsyth             args++;
2024*37da2899SCharles.Forsyth           }
2025*37da2899SCharles.Forsyth           break;
2026*37da2899SCharles.Forsyth 
2027*37da2899SCharles.Forsyth         case cff_op_eq:
2028*37da2899SCharles.Forsyth           {
2029*37da2899SCharles.Forsyth             FT_Fixed  cond = !args[0];
2030*37da2899SCharles.Forsyth 
2031*37da2899SCharles.Forsyth 
2032*37da2899SCharles.Forsyth             FT_TRACE4(( " eq" ));
2033*37da2899SCharles.Forsyth 
2034*37da2899SCharles.Forsyth             args[0] = cond ? 0x10000L : 0;
2035*37da2899SCharles.Forsyth             args++;
2036*37da2899SCharles.Forsyth           }
2037*37da2899SCharles.Forsyth           break;
2038*37da2899SCharles.Forsyth 
2039*37da2899SCharles.Forsyth         case cff_op_ifelse:
2040*37da2899SCharles.Forsyth           {
2041*37da2899SCharles.Forsyth             FT_Fixed  cond = (args[2] <= args[3]);
2042*37da2899SCharles.Forsyth 
2043*37da2899SCharles.Forsyth 
2044*37da2899SCharles.Forsyth             FT_TRACE4(( " ifelse" ));
2045*37da2899SCharles.Forsyth 
2046*37da2899SCharles.Forsyth             if ( !cond )
2047*37da2899SCharles.Forsyth               args[0] = args[1];
2048*37da2899SCharles.Forsyth             args++;
2049*37da2899SCharles.Forsyth           }
2050*37da2899SCharles.Forsyth           break;
2051*37da2899SCharles.Forsyth 
2052*37da2899SCharles.Forsyth         case cff_op_callsubr:
2053*37da2899SCharles.Forsyth           {
2054*37da2899SCharles.Forsyth             FT_UInt  idx = (FT_UInt)( ( args[0] >> 16 ) +
2055*37da2899SCharles.Forsyth                                       decoder->locals_bias );
2056*37da2899SCharles.Forsyth 
2057*37da2899SCharles.Forsyth 
2058*37da2899SCharles.Forsyth             FT_TRACE4(( " callsubr(%d)", idx ));
2059*37da2899SCharles.Forsyth 
2060*37da2899SCharles.Forsyth             if ( idx >= decoder->num_locals )
2061*37da2899SCharles.Forsyth             {
2062*37da2899SCharles.Forsyth               FT_ERROR(( "cff_decoder_parse_charstrings:" ));
2063*37da2899SCharles.Forsyth               FT_ERROR(( "  invalid local subr index\n" ));
2064*37da2899SCharles.Forsyth               goto Syntax_Error;
2065*37da2899SCharles.Forsyth             }
2066*37da2899SCharles.Forsyth 
2067*37da2899SCharles.Forsyth             if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
2068*37da2899SCharles.Forsyth             {
2069*37da2899SCharles.Forsyth               FT_ERROR(( "cff_decoder_parse_charstrings:"
2070*37da2899SCharles.Forsyth                          " too many nested subrs\n" ));
2071*37da2899SCharles.Forsyth               goto Syntax_Error;
2072*37da2899SCharles.Forsyth             }
2073*37da2899SCharles.Forsyth 
2074*37da2899SCharles.Forsyth             zone->cursor = ip;  /* save current instruction pointer */
2075*37da2899SCharles.Forsyth 
2076*37da2899SCharles.Forsyth             zone++;
2077*37da2899SCharles.Forsyth             zone->base   = decoder->locals[idx];
2078*37da2899SCharles.Forsyth             zone->limit  = decoder->locals[idx + 1];
2079*37da2899SCharles.Forsyth             zone->cursor = zone->base;
2080*37da2899SCharles.Forsyth 
2081*37da2899SCharles.Forsyth             if ( !zone->base )
2082*37da2899SCharles.Forsyth             {
2083*37da2899SCharles.Forsyth               FT_ERROR(( "cff_decoder_parse_charstrings:"
2084*37da2899SCharles.Forsyth                          " invoking empty subrs!\n" ));
2085*37da2899SCharles.Forsyth               goto Syntax_Error;
2086*37da2899SCharles.Forsyth             }
2087*37da2899SCharles.Forsyth 
2088*37da2899SCharles.Forsyth             decoder->zone = zone;
2089*37da2899SCharles.Forsyth             ip            = zone->base;
2090*37da2899SCharles.Forsyth             limit         = zone->limit;
2091*37da2899SCharles.Forsyth           }
2092*37da2899SCharles.Forsyth           break;
2093*37da2899SCharles.Forsyth 
2094*37da2899SCharles.Forsyth         case cff_op_callgsubr:
2095*37da2899SCharles.Forsyth           {
2096*37da2899SCharles.Forsyth             FT_UInt  idx = (FT_UInt)( ( args[0] >> 16 ) +
2097*37da2899SCharles.Forsyth                                       decoder->globals_bias );
2098*37da2899SCharles.Forsyth 
2099*37da2899SCharles.Forsyth 
2100*37da2899SCharles.Forsyth             FT_TRACE4(( " callgsubr(%d)", idx ));
2101*37da2899SCharles.Forsyth 
2102*37da2899SCharles.Forsyth             if ( idx >= decoder->num_globals )
2103*37da2899SCharles.Forsyth             {
2104*37da2899SCharles.Forsyth               FT_ERROR(( "cff_decoder_parse_charstrings:" ));
2105*37da2899SCharles.Forsyth               FT_ERROR(( " invalid global subr index\n" ));
2106*37da2899SCharles.Forsyth               goto Syntax_Error;
2107*37da2899SCharles.Forsyth             }
2108*37da2899SCharles.Forsyth 
2109*37da2899SCharles.Forsyth             if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
2110*37da2899SCharles.Forsyth             {
2111*37da2899SCharles.Forsyth               FT_ERROR(( "cff_decoder_parse_charstrings:"
2112*37da2899SCharles.Forsyth                          " too many nested subrs\n" ));
2113*37da2899SCharles.Forsyth               goto Syntax_Error;
2114*37da2899SCharles.Forsyth             }
2115*37da2899SCharles.Forsyth 
2116*37da2899SCharles.Forsyth             zone->cursor = ip;  /* save current instruction pointer */
2117*37da2899SCharles.Forsyth 
2118*37da2899SCharles.Forsyth             zone++;
2119*37da2899SCharles.Forsyth             zone->base   = decoder->globals[idx];
2120*37da2899SCharles.Forsyth             zone->limit  = decoder->globals[idx + 1];
2121*37da2899SCharles.Forsyth             zone->cursor = zone->base;
2122*37da2899SCharles.Forsyth 
2123*37da2899SCharles.Forsyth             if ( !zone->base )
2124*37da2899SCharles.Forsyth             {
2125*37da2899SCharles.Forsyth               FT_ERROR(( "cff_decoder_parse_charstrings:"
2126*37da2899SCharles.Forsyth                          " invoking empty subrs!\n" ));
2127*37da2899SCharles.Forsyth               goto Syntax_Error;
2128*37da2899SCharles.Forsyth             }
2129*37da2899SCharles.Forsyth 
2130*37da2899SCharles.Forsyth             decoder->zone = zone;
2131*37da2899SCharles.Forsyth             ip            = zone->base;
2132*37da2899SCharles.Forsyth             limit         = zone->limit;
2133*37da2899SCharles.Forsyth           }
2134*37da2899SCharles.Forsyth           break;
2135*37da2899SCharles.Forsyth 
2136*37da2899SCharles.Forsyth         case cff_op_return:
2137*37da2899SCharles.Forsyth           FT_TRACE4(( " return" ));
2138*37da2899SCharles.Forsyth 
2139*37da2899SCharles.Forsyth           if ( decoder->zone <= decoder->zones )
2140*37da2899SCharles.Forsyth           {
2141*37da2899SCharles.Forsyth             FT_ERROR(( "cff_decoder_parse_charstrings:"
2142*37da2899SCharles.Forsyth                        " unexpected return\n" ));
2143*37da2899SCharles.Forsyth             goto Syntax_Error;
2144*37da2899SCharles.Forsyth           }
2145*37da2899SCharles.Forsyth 
2146*37da2899SCharles.Forsyth           decoder->zone--;
2147*37da2899SCharles.Forsyth           zone  = decoder->zone;
2148*37da2899SCharles.Forsyth           ip    = zone->cursor;
2149*37da2899SCharles.Forsyth           limit = zone->limit;
2150*37da2899SCharles.Forsyth           break;
2151*37da2899SCharles.Forsyth 
2152*37da2899SCharles.Forsyth         default:
2153*37da2899SCharles.Forsyth         Unimplemented:
2154*37da2899SCharles.Forsyth           FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));
2155*37da2899SCharles.Forsyth 
2156*37da2899SCharles.Forsyth           if ( ip[-1] == 12 )
2157*37da2899SCharles.Forsyth             FT_ERROR(( " %d", ip[0] ));
2158*37da2899SCharles.Forsyth           FT_ERROR(( "\n" ));
2159*37da2899SCharles.Forsyth 
2160*37da2899SCharles.Forsyth           return CFF_Err_Unimplemented_Feature;
2161*37da2899SCharles.Forsyth         }
2162*37da2899SCharles.Forsyth 
2163*37da2899SCharles.Forsyth       decoder->top = args;
2164*37da2899SCharles.Forsyth 
2165*37da2899SCharles.Forsyth       } /* general operator processing */
2166*37da2899SCharles.Forsyth 
2167*37da2899SCharles.Forsyth     } /* while ip < limit */
2168*37da2899SCharles.Forsyth 
2169*37da2899SCharles.Forsyth     FT_TRACE4(( "..end..\n\n" ));
2170*37da2899SCharles.Forsyth 
2171*37da2899SCharles.Forsyth     return error;
2172*37da2899SCharles.Forsyth 
2173*37da2899SCharles.Forsyth   Syntax_Error:
2174*37da2899SCharles.Forsyth     FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error!" ));
2175*37da2899SCharles.Forsyth     return CFF_Err_Invalid_File_Format;
2176*37da2899SCharles.Forsyth 
2177*37da2899SCharles.Forsyth   Stack_Underflow:
2178*37da2899SCharles.Forsyth     FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow!" ));
2179*37da2899SCharles.Forsyth     return CFF_Err_Too_Few_Arguments;
2180*37da2899SCharles.Forsyth 
2181*37da2899SCharles.Forsyth   Stack_Overflow:
2182*37da2899SCharles.Forsyth     FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow!" ));
2183*37da2899SCharles.Forsyth     return CFF_Err_Stack_Overflow;
2184*37da2899SCharles.Forsyth 
2185*37da2899SCharles.Forsyth   Memory_Error:
2186*37da2899SCharles.Forsyth     return builder->error;
2187*37da2899SCharles.Forsyth   }
2188*37da2899SCharles.Forsyth 
2189*37da2899SCharles.Forsyth 
2190*37da2899SCharles.Forsyth   /*************************************************************************/
2191*37da2899SCharles.Forsyth   /*************************************************************************/
2192*37da2899SCharles.Forsyth   /*************************************************************************/
2193*37da2899SCharles.Forsyth   /**********                                                      *********/
2194*37da2899SCharles.Forsyth   /**********                                                      *********/
2195*37da2899SCharles.Forsyth   /**********            COMPUTE THE MAXIMUM ADVANCE WIDTH         *********/
2196*37da2899SCharles.Forsyth   /**********                                                      *********/
2197*37da2899SCharles.Forsyth   /**********    The following code is in charge of computing      *********/
2198*37da2899SCharles.Forsyth   /**********    the maximum advance width of the font.  It        *********/
2199*37da2899SCharles.Forsyth   /**********    quickly processes each glyph charstring to        *********/
2200*37da2899SCharles.Forsyth   /**********    extract the value from either a `sbw' or `seac'   *********/
2201*37da2899SCharles.Forsyth   /**********    operator.                                         *********/
2202*37da2899SCharles.Forsyth   /**********                                                      *********/
2203*37da2899SCharles.Forsyth   /*************************************************************************/
2204*37da2899SCharles.Forsyth   /*************************************************************************/
2205*37da2899SCharles.Forsyth   /*************************************************************************/
2206*37da2899SCharles.Forsyth 
2207*37da2899SCharles.Forsyth 
2208*37da2899SCharles.Forsyth #if 0 /* unused until we support pure CFF fonts */
2209*37da2899SCharles.Forsyth 
2210*37da2899SCharles.Forsyth 
2211*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
2212*37da2899SCharles.Forsyth   cff_compute_max_advance( TT_Face  face,
2213*37da2899SCharles.Forsyth                            FT_Int*  max_advance )
2214*37da2899SCharles.Forsyth   {
2215*37da2899SCharles.Forsyth     FT_Error     error = 0;
2216*37da2899SCharles.Forsyth     CFF_Decoder  decoder;
2217*37da2899SCharles.Forsyth     FT_Int       glyph_index;
2218*37da2899SCharles.Forsyth     CFF_Font     cff = (CFF_Font)face->other;
2219*37da2899SCharles.Forsyth 
2220*37da2899SCharles.Forsyth 
2221*37da2899SCharles.Forsyth     *max_advance = 0;
2222*37da2899SCharles.Forsyth 
2223*37da2899SCharles.Forsyth     /* Initialize load decoder */
2224*37da2899SCharles.Forsyth     cff_decoder_init( &decoder, face, 0, 0, 0, 0 );
2225*37da2899SCharles.Forsyth 
2226*37da2899SCharles.Forsyth     decoder.builder.metrics_only = 1;
2227*37da2899SCharles.Forsyth     decoder.builder.load_points  = 0;
2228*37da2899SCharles.Forsyth 
2229*37da2899SCharles.Forsyth     /* For each glyph, parse the glyph charstring and extract */
2230*37da2899SCharles.Forsyth     /* the advance width.                                     */
2231*37da2899SCharles.Forsyth     for ( glyph_index = 0; glyph_index < face->root.num_glyphs;
2232*37da2899SCharles.Forsyth           glyph_index++ )
2233*37da2899SCharles.Forsyth     {
2234*37da2899SCharles.Forsyth       FT_Byte*  charstring;
2235*37da2899SCharles.Forsyth       FT_ULong  charstring_len;
2236*37da2899SCharles.Forsyth 
2237*37da2899SCharles.Forsyth 
2238*37da2899SCharles.Forsyth       /* now get load the unscaled outline */
2239*37da2899SCharles.Forsyth       error = cff_get_glyph_data( face, glyph_index,
2240*37da2899SCharles.Forsyth                                   &charstring, &charstring_len );
2241*37da2899SCharles.Forsyth       if ( !error )
2242*37da2899SCharles.Forsyth       {
2243*37da2899SCharles.Forsyth         cff_decoder_prepare( &decoder, glyph_index );
2244*37da2899SCharles.Forsyth         error = cff_decoder_parse_charstrings( &decoder,
2245*37da2899SCharles.Forsyth                                                charstring, charstring_len );
2246*37da2899SCharles.Forsyth 
2247*37da2899SCharles.Forsyth         cff_free_glyph_data( face, &charstring, &charstring_len );
2248*37da2899SCharles.Forsyth       }
2249*37da2899SCharles.Forsyth 
2250*37da2899SCharles.Forsyth       /* ignore the error if one has occurred -- skip to next glyph */
2251*37da2899SCharles.Forsyth       error = 0;
2252*37da2899SCharles.Forsyth     }
2253*37da2899SCharles.Forsyth 
2254*37da2899SCharles.Forsyth     *max_advance = decoder.builder.advance.x;
2255*37da2899SCharles.Forsyth 
2256*37da2899SCharles.Forsyth     return CFF_Err_Ok;
2257*37da2899SCharles.Forsyth   }
2258*37da2899SCharles.Forsyth 
2259*37da2899SCharles.Forsyth 
2260*37da2899SCharles.Forsyth #endif /* 0 */
2261*37da2899SCharles.Forsyth 
2262*37da2899SCharles.Forsyth 
2263*37da2899SCharles.Forsyth   /*************************************************************************/
2264*37da2899SCharles.Forsyth   /*************************************************************************/
2265*37da2899SCharles.Forsyth   /*************************************************************************/
2266*37da2899SCharles.Forsyth   /**********                                                      *********/
2267*37da2899SCharles.Forsyth   /**********                                                      *********/
2268*37da2899SCharles.Forsyth   /**********               UNHINTED GLYPH LOADER                  *********/
2269*37da2899SCharles.Forsyth   /**********                                                      *********/
2270*37da2899SCharles.Forsyth   /**********    The following code is in charge of loading a      *********/
2271*37da2899SCharles.Forsyth   /**********    single outline.  It completely ignores hinting    *********/
2272*37da2899SCharles.Forsyth   /**********    and is used when FT_LOAD_NO_HINTING is set.       *********/
2273*37da2899SCharles.Forsyth   /**********                                                      *********/
2274*37da2899SCharles.Forsyth   /*************************************************************************/
2275*37da2899SCharles.Forsyth   /*************************************************************************/
2276*37da2899SCharles.Forsyth   /*************************************************************************/
2277*37da2899SCharles.Forsyth 
2278*37da2899SCharles.Forsyth 
2279*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
cff_slot_load(CFF_GlyphSlot glyph,CFF_Size size,FT_Int glyph_index,FT_Int32 load_flags)2280*37da2899SCharles.Forsyth   cff_slot_load( CFF_GlyphSlot  glyph,
2281*37da2899SCharles.Forsyth                  CFF_Size       size,
2282*37da2899SCharles.Forsyth                  FT_Int         glyph_index,
2283*37da2899SCharles.Forsyth                  FT_Int32       load_flags )
2284*37da2899SCharles.Forsyth   {
2285*37da2899SCharles.Forsyth     FT_Error     error;
2286*37da2899SCharles.Forsyth     CFF_Decoder  decoder;
2287*37da2899SCharles.Forsyth     TT_Face      face = (TT_Face)glyph->root.face;
2288*37da2899SCharles.Forsyth     FT_Bool      hinting;
2289*37da2899SCharles.Forsyth     CFF_Font     cff = (CFF_Font)face->extra.data;
2290*37da2899SCharles.Forsyth 
2291*37da2899SCharles.Forsyth     FT_Matrix    font_matrix;
2292*37da2899SCharles.Forsyth     FT_Vector    font_offset;
2293*37da2899SCharles.Forsyth 
2294*37da2899SCharles.Forsyth 
2295*37da2899SCharles.Forsyth     if ( load_flags & FT_LOAD_NO_RECURSE )
2296*37da2899SCharles.Forsyth       load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
2297*37da2899SCharles.Forsyth 
2298*37da2899SCharles.Forsyth     glyph->x_scale = 0x10000L;
2299*37da2899SCharles.Forsyth     glyph->y_scale = 0x10000L;
2300*37da2899SCharles.Forsyth     if ( size )
2301*37da2899SCharles.Forsyth     {
2302*37da2899SCharles.Forsyth       glyph->x_scale = size->metrics.x_scale;
2303*37da2899SCharles.Forsyth       glyph->y_scale = size->metrics.y_scale;
2304*37da2899SCharles.Forsyth     }
2305*37da2899SCharles.Forsyth 
2306*37da2899SCharles.Forsyth     glyph->root.outline.n_points   = 0;
2307*37da2899SCharles.Forsyth     glyph->root.outline.n_contours = 0;
2308*37da2899SCharles.Forsyth 
2309*37da2899SCharles.Forsyth     hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE   ) == 0 &&
2310*37da2899SCharles.Forsyth                        ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
2311*37da2899SCharles.Forsyth 
2312*37da2899SCharles.Forsyth     glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;  /* by default */
2313*37da2899SCharles.Forsyth 
2314*37da2899SCharles.Forsyth     {
2315*37da2899SCharles.Forsyth       FT_Byte*  charstring;
2316*37da2899SCharles.Forsyth       FT_ULong  charstring_len;
2317*37da2899SCharles.Forsyth 
2318*37da2899SCharles.Forsyth 
2319*37da2899SCharles.Forsyth       cff_decoder_init( &decoder, face, size, glyph, hinting,
2320*37da2899SCharles.Forsyth                         FT_LOAD_TARGET_MODE(load_flags) );
2321*37da2899SCharles.Forsyth 
2322*37da2899SCharles.Forsyth       decoder.builder.no_recurse =
2323*37da2899SCharles.Forsyth         (FT_Bool)( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 );
2324*37da2899SCharles.Forsyth 
2325*37da2899SCharles.Forsyth       /* now load the unscaled outline */
2326*37da2899SCharles.Forsyth       error = cff_get_glyph_data( face, glyph_index,
2327*37da2899SCharles.Forsyth                                   &charstring, &charstring_len );
2328*37da2899SCharles.Forsyth       if ( !error )
2329*37da2899SCharles.Forsyth       {
2330*37da2899SCharles.Forsyth         cff_decoder_prepare( &decoder, glyph_index );
2331*37da2899SCharles.Forsyth         error = cff_decoder_parse_charstrings( &decoder,
2332*37da2899SCharles.Forsyth                                                charstring, charstring_len );
2333*37da2899SCharles.Forsyth 
2334*37da2899SCharles.Forsyth         cff_free_glyph_data( face, &charstring, charstring_len );
2335*37da2899SCharles.Forsyth 
2336*37da2899SCharles.Forsyth 
2337*37da2899SCharles.Forsyth #ifdef FT_CONFIG_OPTION_INCREMENTAL
2338*37da2899SCharles.Forsyth         /* Control data and length may not be available for incremental   */
2339*37da2899SCharles.Forsyth         /* fonts.                                                         */
2340*37da2899SCharles.Forsyth         if ( face->root.internal->incremental_interface )
2341*37da2899SCharles.Forsyth         {
2342*37da2899SCharles.Forsyth           glyph->root.control_data = 0;
2343*37da2899SCharles.Forsyth           glyph->root.control_len = 0;
2344*37da2899SCharles.Forsyth         }
2345*37da2899SCharles.Forsyth         else
2346*37da2899SCharles.Forsyth #endif /* FT_CONFIG_OPTION_INCREMENTAL */
2347*37da2899SCharles.Forsyth 
2348*37da2899SCharles.Forsyth         /* We set control_data and control_len if charstrings is loaded.  */
2349*37da2899SCharles.Forsyth         /* See how charstring loads at cff_index_access_element() in      */
2350*37da2899SCharles.Forsyth         /* cffload.c.                                                     */
2351*37da2899SCharles.Forsyth         {
2352*37da2899SCharles.Forsyth           CFF_IndexRec csindex = cff->charstrings_index;
2353*37da2899SCharles.Forsyth 
2354*37da2899SCharles.Forsyth 
2355*37da2899SCharles.Forsyth           glyph->root.control_data =
2356*37da2899SCharles.Forsyth             csindex.bytes + csindex.offsets[glyph_index] - 1;
2357*37da2899SCharles.Forsyth           glyph->root.control_len =
2358*37da2899SCharles.Forsyth             charstring_len;
2359*37da2899SCharles.Forsyth         }
2360*37da2899SCharles.Forsyth       }
2361*37da2899SCharles.Forsyth 
2362*37da2899SCharles.Forsyth       /* save new glyph tables */
2363*37da2899SCharles.Forsyth       cff_builder_done( &decoder.builder );
2364*37da2899SCharles.Forsyth     }
2365*37da2899SCharles.Forsyth 
2366*37da2899SCharles.Forsyth     font_matrix = cff->top_font.font_dict.font_matrix;
2367*37da2899SCharles.Forsyth     font_offset = cff->top_font.font_dict.font_offset;
2368*37da2899SCharles.Forsyth 
2369*37da2899SCharles.Forsyth     /* Now, set the metrics -- this is rather simple, as   */
2370*37da2899SCharles.Forsyth     /* the left side bearing is the xMin, and the top side */
2371*37da2899SCharles.Forsyth     /* bearing the yMax.                                   */
2372*37da2899SCharles.Forsyth     if ( !error )
2373*37da2899SCharles.Forsyth     {
2374*37da2899SCharles.Forsyth       /* For composite glyphs, return only left side bearing and */
2375*37da2899SCharles.Forsyth       /* advance width.                                          */
2376*37da2899SCharles.Forsyth       if ( load_flags & FT_LOAD_NO_RECURSE )
2377*37da2899SCharles.Forsyth       {
2378*37da2899SCharles.Forsyth         FT_Slot_Internal  internal = glyph->root.internal;
2379*37da2899SCharles.Forsyth 
2380*37da2899SCharles.Forsyth 
2381*37da2899SCharles.Forsyth         glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
2382*37da2899SCharles.Forsyth         glyph->root.metrics.horiAdvance  = decoder.glyph_width;
2383*37da2899SCharles.Forsyth         internal->glyph_matrix           = font_matrix;
2384*37da2899SCharles.Forsyth         internal->glyph_delta            = font_offset;
2385*37da2899SCharles.Forsyth         internal->glyph_transformed      = 1;
2386*37da2899SCharles.Forsyth       }
2387*37da2899SCharles.Forsyth       else
2388*37da2899SCharles.Forsyth       {
2389*37da2899SCharles.Forsyth         FT_BBox            cbox;
2390*37da2899SCharles.Forsyth         FT_Glyph_Metrics*  metrics = &glyph->root.metrics;
2391*37da2899SCharles.Forsyth 
2392*37da2899SCharles.Forsyth 
2393*37da2899SCharles.Forsyth         /* copy the _unscaled_ advance width */
2394*37da2899SCharles.Forsyth         metrics->horiAdvance                    = decoder.glyph_width;
2395*37da2899SCharles.Forsyth         glyph->root.linearHoriAdvance           = decoder.glyph_width;
2396*37da2899SCharles.Forsyth         glyph->root.internal->glyph_transformed = 0;
2397*37da2899SCharles.Forsyth 
2398*37da2899SCharles.Forsyth         /* make up vertical metrics */
2399*37da2899SCharles.Forsyth         metrics->vertBearingX = 0;
2400*37da2899SCharles.Forsyth         metrics->vertBearingY = 0;
2401*37da2899SCharles.Forsyth         metrics->vertAdvance  = 0;
2402*37da2899SCharles.Forsyth 
2403*37da2899SCharles.Forsyth         glyph->root.linearVertAdvance = 0;
2404*37da2899SCharles.Forsyth 
2405*37da2899SCharles.Forsyth         glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;
2406*37da2899SCharles.Forsyth 
2407*37da2899SCharles.Forsyth         glyph->root.outline.flags = 0;
2408*37da2899SCharles.Forsyth         if ( size && size->metrics.y_ppem < 24 )
2409*37da2899SCharles.Forsyth           glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION;
2410*37da2899SCharles.Forsyth 
2411*37da2899SCharles.Forsyth         glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL;
2412*37da2899SCharles.Forsyth 
2413*37da2899SCharles.Forsyth         /* apply the font matrix */
2414*37da2899SCharles.Forsyth         FT_Outline_Transform( &glyph->root.outline, &font_matrix );
2415*37da2899SCharles.Forsyth 
2416*37da2899SCharles.Forsyth         FT_Outline_Translate( &glyph->root.outline,
2417*37da2899SCharles.Forsyth                               font_offset.x,
2418*37da2899SCharles.Forsyth                               font_offset.y );
2419*37da2899SCharles.Forsyth 
2420*37da2899SCharles.Forsyth         if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
2421*37da2899SCharles.Forsyth         {
2422*37da2899SCharles.Forsyth           /* scale the outline and the metrics */
2423*37da2899SCharles.Forsyth           FT_Int       n;
2424*37da2899SCharles.Forsyth           FT_Outline*  cur     = &glyph->root.outline;
2425*37da2899SCharles.Forsyth           FT_Vector*   vec     = cur->points;
2426*37da2899SCharles.Forsyth           FT_Fixed     x_scale = glyph->x_scale;
2427*37da2899SCharles.Forsyth           FT_Fixed     y_scale = glyph->y_scale;
2428*37da2899SCharles.Forsyth 
2429*37da2899SCharles.Forsyth 
2430*37da2899SCharles.Forsyth           /* First of all, scale the points */
2431*37da2899SCharles.Forsyth           if ( !hinting )
2432*37da2899SCharles.Forsyth             for ( n = cur->n_points; n > 0; n--, vec++ )
2433*37da2899SCharles.Forsyth             {
2434*37da2899SCharles.Forsyth               vec->x = FT_MulFix( vec->x, x_scale );
2435*37da2899SCharles.Forsyth               vec->y = FT_MulFix( vec->y, y_scale );
2436*37da2899SCharles.Forsyth             }
2437*37da2899SCharles.Forsyth 
2438*37da2899SCharles.Forsyth           FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
2439*37da2899SCharles.Forsyth 
2440*37da2899SCharles.Forsyth           /* Then scale the metrics */
2441*37da2899SCharles.Forsyth           metrics->horiAdvance  = FT_MulFix( metrics->horiAdvance,  x_scale );
2442*37da2899SCharles.Forsyth           metrics->vertAdvance  = FT_MulFix( metrics->vertAdvance,  y_scale );
2443*37da2899SCharles.Forsyth 
2444*37da2899SCharles.Forsyth           metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
2445*37da2899SCharles.Forsyth           metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
2446*37da2899SCharles.Forsyth 
2447*37da2899SCharles.Forsyth           if ( hinting )
2448*37da2899SCharles.Forsyth           {
2449*37da2899SCharles.Forsyth             metrics->horiAdvance  = ( metrics->horiAdvance + 32 ) & -64;
2450*37da2899SCharles.Forsyth             metrics->vertAdvance  = ( metrics->vertAdvance + 32 ) & -64;
2451*37da2899SCharles.Forsyth 
2452*37da2899SCharles.Forsyth             metrics->vertBearingX = ( metrics->vertBearingX + 32 ) & -64;
2453*37da2899SCharles.Forsyth             metrics->vertBearingY = ( metrics->vertBearingY + 32 ) & -64;
2454*37da2899SCharles.Forsyth           }
2455*37da2899SCharles.Forsyth         }
2456*37da2899SCharles.Forsyth 
2457*37da2899SCharles.Forsyth         /* compute the other metrics */
2458*37da2899SCharles.Forsyth         FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
2459*37da2899SCharles.Forsyth 
2460*37da2899SCharles.Forsyth         /* grid fit the bounding box if necessary */
2461*37da2899SCharles.Forsyth         if ( hinting )
2462*37da2899SCharles.Forsyth         {
2463*37da2899SCharles.Forsyth           cbox.xMin &= -64;
2464*37da2899SCharles.Forsyth           cbox.yMin &= -64;
2465*37da2899SCharles.Forsyth           cbox.xMax  = ( cbox.xMax + 63 ) & -64;
2466*37da2899SCharles.Forsyth           cbox.yMax  = ( cbox.yMax + 63 ) & -64;
2467*37da2899SCharles.Forsyth         }
2468*37da2899SCharles.Forsyth 
2469*37da2899SCharles.Forsyth         metrics->width  = cbox.xMax - cbox.xMin;
2470*37da2899SCharles.Forsyth         metrics->height = cbox.yMax - cbox.yMin;
2471*37da2899SCharles.Forsyth 
2472*37da2899SCharles.Forsyth         metrics->horiBearingX = cbox.xMin;
2473*37da2899SCharles.Forsyth         metrics->horiBearingY = cbox.yMax;
2474*37da2899SCharles.Forsyth       }
2475*37da2899SCharles.Forsyth     }
2476*37da2899SCharles.Forsyth 
2477*37da2899SCharles.Forsyth     return error;
2478*37da2899SCharles.Forsyth   }
2479*37da2899SCharles.Forsyth 
2480*37da2899SCharles.Forsyth 
2481*37da2899SCharles.Forsyth /* END */
2482