• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  *
3  * psintrp.c
4  *
5  *   Adobe's CFF Interpreter (body).
6  *
7  * Copyright 2007-2014 Adobe Systems Incorporated.
8  *
9  * This software, and all works of authorship, whether in source or
10  * object code form as indicated by the copyright notice(s) included
11  * herein (collectively, the "Work") is made available, and may only be
12  * used, modified, and distributed under the FreeType Project License,
13  * LICENSE.TXT.  Additionally, subject to the terms and conditions of the
14  * FreeType Project License, each contributor to the Work hereby grants
15  * to any individual or legal entity exercising permissions granted by
16  * the FreeType Project License and this section (hereafter, "You" or
17  * "Your") a perpetual, worldwide, non-exclusive, no-charge,
18  * royalty-free, irrevocable (except as stated in this section) patent
19  * license to make, have made, use, offer to sell, sell, import, and
20  * otherwise transfer the Work, where such license applies only to those
21  * patent claims licensable by such contributor that are necessarily
22  * infringed by their contribution(s) alone or by combination of their
23  * contribution(s) with the Work to which such contribution(s) was
24  * submitted.  If You institute patent litigation against any entity
25  * (including a cross-claim or counterclaim in a lawsuit) alleging that
26  * the Work or a contribution incorporated within the Work constitutes
27  * direct or contributory patent infringement, then any patent licenses
28  * granted to You under this License for that Work shall terminate as of
29  * the date such litigation is filed.
30  *
31  * By using, modifying, or distributing the Work you indicate that you
32  * have read and understood the terms and conditions of the
33  * FreeType Project License as well as those provided in this section,
34  * and you accept them fully.
35  *
36  */
37 
38 
39 #include "psft.h"
40 #include FT_INTERNAL_DEBUG_H
41 #include FT_SERVICE_CFF_TABLE_LOAD_H
42 
43 #include "psglue.h"
44 #include "psfont.h"
45 #include "psstack.h"
46 #include "pshints.h"
47 #include "psintrp.h"
48 
49 #include "pserror.h"
50 
51 #include "psobjs.h"   /* for cff_random */
52 #include "t1decode.h" /* for t1 seac    */
53 
54 
55   /**************************************************************************
56    *
57    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
58    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
59    * messages during execution.
60    */
61 #undef  FT_COMPONENT
62 #define FT_COMPONENT  trace_cf2interp
63 
64 
65   FT_LOCAL_DEF( void )
cf2_hintmask_init(CF2_HintMask hintmask,FT_Error * error)66   cf2_hintmask_init( CF2_HintMask  hintmask,
67                      FT_Error*     error )
68   {
69     FT_ZERO( hintmask );
70 
71     hintmask->error = error;
72   }
73 
74 
75   FT_LOCAL_DEF( FT_Bool )
cf2_hintmask_isValid(const CF2_HintMask hintmask)76   cf2_hintmask_isValid( const CF2_HintMask  hintmask )
77   {
78     return hintmask->isValid;
79   }
80 
81 
82   FT_LOCAL_DEF( FT_Bool )
cf2_hintmask_isNew(const CF2_HintMask hintmask)83   cf2_hintmask_isNew( const CF2_HintMask  hintmask )
84   {
85     return hintmask->isNew;
86   }
87 
88 
89   FT_LOCAL_DEF( void )
cf2_hintmask_setNew(CF2_HintMask hintmask,FT_Bool val)90   cf2_hintmask_setNew( CF2_HintMask  hintmask,
91                        FT_Bool       val )
92   {
93     hintmask->isNew = val;
94   }
95 
96 
97   /* clients call `getMaskPtr' in order to iterate */
98   /* through hint mask                             */
99 
100   FT_LOCAL_DEF( FT_Byte* )
cf2_hintmask_getMaskPtr(CF2_HintMask hintmask)101   cf2_hintmask_getMaskPtr( CF2_HintMask  hintmask )
102   {
103     return hintmask->mask;
104   }
105 
106 
107   static size_t
cf2_hintmask_setCounts(CF2_HintMask hintmask,size_t bitCount)108   cf2_hintmask_setCounts( CF2_HintMask  hintmask,
109                           size_t        bitCount )
110   {
111     if ( bitCount > CF2_MAX_HINTS )
112     {
113       /* total of h and v stems must be <= 96 */
114       CF2_SET_ERROR( hintmask->error, Invalid_Glyph_Format );
115       return 0;
116     }
117 
118     hintmask->bitCount  = bitCount;
119     hintmask->byteCount = ( hintmask->bitCount + 7 ) / 8;
120 
121     hintmask->isValid = TRUE;
122     hintmask->isNew   = TRUE;
123 
124     return bitCount;
125   }
126 
127 
128   /* consume the hintmask bytes from the charstring, advancing the src */
129   /* pointer                                                           */
130   static void
cf2_hintmask_read(CF2_HintMask hintmask,CF2_Buffer charstring,size_t bitCount)131   cf2_hintmask_read( CF2_HintMask  hintmask,
132                      CF2_Buffer    charstring,
133                      size_t        bitCount )
134   {
135     size_t  i;
136 
137 #ifndef CF2_NDEBUG
138     /* these are the bits in the final mask byte that should be zero  */
139     /* Note: this variable is only used in an assert expression below */
140     /* and then only if CF2_NDEBUG is not defined                     */
141     CF2_UInt  mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1;
142 #endif
143 
144 
145     /* initialize counts and isValid */
146     if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 )
147       return;
148 
149     FT_ASSERT( hintmask->byteCount > 0 );
150 
151     FT_TRACE4(( " (maskbytes:" ));
152 
153     /* set mask and advance interpreter's charstring pointer */
154     for ( i = 0; i < hintmask->byteCount; i++ )
155     {
156       hintmask->mask[i] = (FT_Byte)cf2_buf_readByte( charstring );
157       FT_TRACE4(( " 0x%02X", hintmask->mask[i] ));
158     }
159 
160     FT_TRACE4(( ")\n" ));
161 
162     /* assert any unused bits in last byte are zero unless there's a prior */
163     /* error                                                               */
164     /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1      */
165 #ifndef CF2_NDEBUG
166     FT_ASSERT( ( hintmask->mask[hintmask->byteCount - 1] & mask ) == 0 ||
167                *hintmask->error                                        );
168 #endif
169   }
170 
171 
172   FT_LOCAL_DEF( void )
cf2_hintmask_setAll(CF2_HintMask hintmask,size_t bitCount)173   cf2_hintmask_setAll( CF2_HintMask  hintmask,
174                        size_t        bitCount )
175   {
176     size_t    i;
177     CF2_UInt  mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1;
178 
179 
180     /* initialize counts and isValid */
181     if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 )
182       return;
183 
184     FT_ASSERT( hintmask->byteCount > 0 );
185     FT_ASSERT( hintmask->byteCount <=
186                  sizeof ( hintmask->mask ) / sizeof ( hintmask->mask[0] ) );
187 
188     /* set mask to all ones */
189     for ( i = 0; i < hintmask->byteCount; i++ )
190       hintmask->mask[i] = 0xFF;
191 
192     /* clear unused bits                                              */
193     /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1 */
194     hintmask->mask[hintmask->byteCount - 1] &= ~mask;
195   }
196 
197 
198   /* Type2 charstring opcodes */
199   enum
200   {
201     cf2_cmdRESERVED_0,   /* 0 */
202     cf2_cmdHSTEM,        /* 1 */
203     cf2_cmdRESERVED_2,   /* 2 */
204     cf2_cmdVSTEM,        /* 3 */
205     cf2_cmdVMOVETO,      /* 4 */
206     cf2_cmdRLINETO,      /* 5 */
207     cf2_cmdHLINETO,      /* 6 */
208     cf2_cmdVLINETO,      /* 7 */
209     cf2_cmdRRCURVETO,    /* 8 */
210     cf2_cmdCLOSEPATH,    /* 9      T1 only */
211     cf2_cmdCALLSUBR,     /* 10 */
212     cf2_cmdRETURN,       /* 11 */
213     cf2_cmdESC,          /* 12 */
214     cf2_cmdHSBW,         /* 13     T1 only */
215     cf2_cmdENDCHAR,      /* 14 */
216     cf2_cmdVSINDEX,      /* 15 */
217     cf2_cmdBLEND,        /* 16 */
218     cf2_cmdRESERVED_17,  /* 17 */
219     cf2_cmdHSTEMHM,      /* 18 */
220     cf2_cmdHINTMASK,     /* 19 */
221     cf2_cmdCNTRMASK,     /* 20 */
222     cf2_cmdRMOVETO,      /* 21 */
223     cf2_cmdHMOVETO,      /* 22 */
224     cf2_cmdVSTEMHM,      /* 23 */
225     cf2_cmdRCURVELINE,   /* 24 */
226     cf2_cmdRLINECURVE,   /* 25 */
227     cf2_cmdVVCURVETO,    /* 26 */
228     cf2_cmdHHCURVETO,    /* 27 */
229     cf2_cmdEXTENDEDNMBR, /* 28 */
230     cf2_cmdCALLGSUBR,    /* 29 */
231     cf2_cmdVHCURVETO,    /* 30 */
232     cf2_cmdHVCURVETO     /* 31 */
233   };
234 
235   enum
236   {
237     cf2_escDOTSECTION,   /* 0 */
238     cf2_escVSTEM3,       /* 1      T1 only */
239     cf2_escHSTEM3,       /* 2      T1 only */
240     cf2_escAND,          /* 3 */
241     cf2_escOR,           /* 4 */
242     cf2_escNOT,          /* 5 */
243     cf2_escSEAC,         /* 6      T1 only */
244     cf2_escSBW,          /* 7      T1 only */
245     cf2_escRESERVED_8,   /* 8 */
246     cf2_escABS,          /* 9 */
247     cf2_escADD,          /* 10     like otherADD */
248     cf2_escSUB,          /* 11     like otherSUB */
249     cf2_escDIV,          /* 12 */
250     cf2_escRESERVED_13,  /* 13 */
251     cf2_escNEG,          /* 14 */
252     cf2_escEQ,           /* 15 */
253     cf2_escCALLOTHERSUBR,/* 16     T1 only */
254     cf2_escPOP,          /* 17     T1 only */
255     cf2_escDROP,         /* 18 */
256     cf2_escRESERVED_19,  /* 19 */
257     cf2_escPUT,          /* 20     like otherPUT    */
258     cf2_escGET,          /* 21     like otherGET    */
259     cf2_escIFELSE,       /* 22     like otherIFELSE */
260     cf2_escRANDOM,       /* 23     like otherRANDOM */
261     cf2_escMUL,          /* 24     like otherMUL    */
262     cf2_escRESERVED_25,  /* 25 */
263     cf2_escSQRT,         /* 26 */
264     cf2_escDUP,          /* 27     like otherDUP    */
265     cf2_escEXCH,         /* 28     like otherEXCH   */
266     cf2_escINDEX,        /* 29 */
267     cf2_escROLL,         /* 30 */
268     cf2_escRESERVED_31,  /* 31 */
269     cf2_escRESERVED_32,  /* 32 */
270     cf2_escSETCURRENTPT, /* 33     T1 only */
271     cf2_escHFLEX,        /* 34 */
272     cf2_escFLEX,         /* 35 */
273     cf2_escHFLEX1,       /* 36 */
274     cf2_escFLEX1,        /* 37 */
275     cf2_escRESERVED_38   /* 38     & all higher     */
276   };
277 
278 
279   /* `stemHintArray' does not change once we start drawing the outline. */
280   static void
cf2_doStems(const CF2_Font font,CF2_Stack opStack,CF2_ArrStack stemHintArray,CF2_Fixed * width,FT_Bool * haveWidth,CF2_Fixed hintOffset)281   cf2_doStems( const CF2_Font  font,
282                CF2_Stack       opStack,
283                CF2_ArrStack    stemHintArray,
284                CF2_Fixed*      width,
285                FT_Bool*        haveWidth,
286                CF2_Fixed       hintOffset )
287   {
288     CF2_UInt  i;
289     CF2_UInt  count       = cf2_stack_count( opStack );
290     FT_Bool   hasWidthArg = (FT_Bool)( count & 1 );
291 
292     /* variable accumulates delta values from operand stack */
293     CF2_Fixed  position = hintOffset;
294 
295     if ( font->isT1 && !font->decoder->flex_state && !*haveWidth )
296       FT_ERROR(( "cf2_doStems (Type 1 mode):"
297                  " No width. Use hsbw/sbw as first op\n" ));
298 
299     if ( !font->isT1 && hasWidthArg && !*haveWidth )
300       *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
301                           cf2_getNominalWidthX( font->decoder ) );
302 
303     if ( font->decoder->width_only )
304       goto exit;
305 
306     for ( i = hasWidthArg ? 1 : 0; i < count; i += 2 )
307     {
308       /* construct a CF2_StemHint and push it onto the list */
309       CF2_StemHintRec  stemhint;
310 
311 
312       stemhint.min =
313       position     = ADD_INT32( position,
314                                 cf2_stack_getReal( opStack, i ) );
315       stemhint.max =
316       position     = ADD_INT32( position,
317                                 cf2_stack_getReal( opStack, i + 1 ) );
318 
319       stemhint.used  = FALSE;
320       stemhint.maxDS =
321       stemhint.minDS = 0;
322 
323       cf2_arrstack_push( stemHintArray, &stemhint ); /* defer error check */
324     }
325 
326     cf2_stack_clear( opStack );
327 
328   exit:
329     /* cf2_doStems must define a width (may be default) */
330     *haveWidth = TRUE;
331   }
332 
333 
334   static void
cf2_doFlex(CF2_Stack opStack,CF2_Fixed * curX,CF2_Fixed * curY,CF2_GlyphPath glyphPath,const FT_Bool * readFromStack,FT_Bool doConditionalLastRead)335   cf2_doFlex( CF2_Stack       opStack,
336               CF2_Fixed*      curX,
337               CF2_Fixed*      curY,
338               CF2_GlyphPath   glyphPath,
339               const FT_Bool*  readFromStack,
340               FT_Bool         doConditionalLastRead )
341   {
342     CF2_Fixed  vals[14];
343     CF2_UInt   idx;
344     FT_Bool    isHFlex;
345     CF2_Int    top, i, j;
346 
347 
348     vals[0] = *curX;
349     vals[1] = *curY;
350     idx     = 0;
351     isHFlex = FT_BOOL( readFromStack[9] == FALSE );
352     top     = isHFlex ? 9 : 10;
353 
354     for ( i = 0; i < top; i++ )
355     {
356       vals[i + 2] = vals[i];
357       if ( readFromStack[i] )
358         vals[i + 2] = ADD_INT32( vals[i + 2], cf2_stack_getReal( opStack,
359                                                                  idx++ ) );
360     }
361 
362     if ( isHFlex )
363       vals[9 + 2] = *curY;
364 
365     if ( doConditionalLastRead )
366     {
367       FT_Bool    lastIsX = (FT_Bool)(
368                              cf2_fixedAbs( SUB_INT32( vals[10], *curX ) ) >
369                              cf2_fixedAbs( SUB_INT32( vals[11], *curY ) ) );
370       CF2_Fixed  lastVal = cf2_stack_getReal( opStack, idx );
371 
372 
373       if ( lastIsX )
374       {
375         vals[12] = ADD_INT32( vals[10], lastVal );
376         vals[13] = *curY;
377       }
378       else
379       {
380         vals[12] = *curX;
381         vals[13] = ADD_INT32( vals[11], lastVal );
382       }
383     }
384     else
385     {
386       if ( readFromStack[10] )
387         vals[12] = ADD_INT32( vals[10],
388                               cf2_stack_getReal( opStack, idx++ ) );
389       else
390         vals[12] = *curX;
391 
392       if ( readFromStack[11] )
393         vals[13] = ADD_INT32( vals[11],
394                               cf2_stack_getReal( opStack, idx ) );
395       else
396         vals[13] = *curY;
397     }
398 
399     for ( j = 0; j < 2; j++ )
400       cf2_glyphpath_curveTo( glyphPath, vals[j * 6 + 2],
401                                         vals[j * 6 + 3],
402                                         vals[j * 6 + 4],
403                                         vals[j * 6 + 5],
404                                         vals[j * 6 + 6],
405                                         vals[j * 6 + 7] );
406 
407     cf2_stack_clear( opStack );
408 
409     *curX = vals[12];
410     *curY = vals[13];
411   }
412 
413 
414   /* Blend numOperands on the stack,                */
415   /* store results into the first numBlends values, */
416   /* then pop remaining arguments.                  */
417   static void
cf2_doBlend(const CFF_Blend blend,CF2_Stack opStack,CF2_UInt numBlends)418   cf2_doBlend( const CFF_Blend  blend,
419                CF2_Stack        opStack,
420                CF2_UInt         numBlends )
421   {
422     CF2_UInt  delta;
423     CF2_UInt  base;
424     CF2_UInt  i, j;
425     CF2_UInt  numOperands = (CF2_UInt)( numBlends * blend->lenBV );
426 
427 
428     base  = cf2_stack_count( opStack ) - numOperands;
429     delta = base + numBlends;
430 
431     for ( i = 0; i < numBlends; i++ )
432     {
433       const CF2_Fixed*  weight = &blend->BV[1];
434 
435       /* start with first term */
436       CF2_Fixed  sum = cf2_stack_getReal( opStack, i + base );
437 
438 
439       for ( j = 1; j < blend->lenBV; j++ )
440         sum = ADD_INT32( sum,
441                          FT_MulFix( *weight++,
442                                     cf2_stack_getReal( opStack,
443                                                        delta++ ) ) );
444 
445       /* store blended result  */
446       cf2_stack_setReal( opStack, i + base, sum );
447     }
448 
449     /* leave only `numBlends' results on stack */
450     cf2_stack_pop( opStack, numOperands - numBlends );
451   }
452 
453 
454   /*
455    * `error' is a shared error code used by many objects in this
456    * routine.  Before the code continues from an error, it must check and
457    * record the error in `*error'.  The idea is that this shared
458    * error code will record the first error encountered.  If testing
459    * for an error anyway, the cost of `goto exit' is small, so we do it,
460    * even if continuing would be safe.  In this case, `lastError' is
461    * set, so the testing and storing can be done in one place, at `exit'.
462    *
463    * Continuing after an error is intended for objects which do their own
464    * testing of `*error', e.g., array stack functions.  This allows us to
465    * avoid an extra test after the call.
466    *
467    * Unimplemented opcodes are ignored.
468    *
469    */
470   FT_LOCAL_DEF( void )
cf2_interpT2CharString(CF2_Font font,CF2_Buffer buf,CF2_OutlineCallbacks callbacks,const FT_Vector * translation,FT_Bool doingSeac,CF2_Fixed curX,CF2_Fixed curY,CF2_Fixed * width)471   cf2_interpT2CharString( CF2_Font              font,
472                           CF2_Buffer            buf,
473                           CF2_OutlineCallbacks  callbacks,
474                           const FT_Vector*      translation,
475                           FT_Bool               doingSeac,
476                           CF2_Fixed             curX,
477                           CF2_Fixed             curY,
478                           CF2_Fixed*            width )
479   {
480     /* lastError is used for errors that are immediately tested */
481     FT_Error  lastError = FT_Err_Ok;
482 
483     /* pointer to parsed font object */
484     PS_Decoder*  decoder = font->decoder;
485 
486     FT_Error*  error  = &font->error;
487     FT_Memory  memory = font->memory;
488 
489     CF2_Fixed  scaleY        = font->innerTransform.d;
490     CF2_Fixed  nominalWidthX = cf2_getNominalWidthX( decoder );
491 
492     /* stuff for Type 1 */
493     FT_Int   known_othersubr_result_cnt = 0;
494     FT_Bool  large_int                  = FALSE;
495     FT_Bool  initial_map_ready          = FALSE;
496 
497 #define PS_STORAGE_SIZE 3
498     CF2_F16Dot16  results[PS_STORAGE_SIZE];   /* for othersubr results */
499     FT_Int        result_cnt = 0;
500 
501     /* save this for hinting seac accents */
502     CF2_Fixed  hintOriginY = curY;
503 
504     CF2_Stack  opStack = NULL;
505     FT_UInt    stackSize;
506     FT_Byte    op1;                       /* first opcode byte */
507 
508     CF2_F16Dot16  storage[CF2_STORAGE_SIZE];    /* for `put' and `get' */
509     CF2_F16Dot16  flexStore[6];                 /* for Type 1 flex     */
510 
511     /* instruction limit; 20,000,000 matches Avalon */
512     FT_UInt32  instructionLimit = 20000000UL;
513 
514     CF2_ArrStackRec  subrStack;
515 
516     FT_Bool     haveWidth;
517     CF2_Buffer  charstring = NULL;
518 
519     CF2_Int  charstringIndex = -1;       /* initialize to empty */
520 
521     /* TODO: placeholders for hint structures */
522 
523     /* objects used for hinting */
524     CF2_ArrStackRec  hStemHintArray;
525     CF2_ArrStackRec  vStemHintArray;
526 
527     CF2_HintMaskRec   hintMask;
528     CF2_GlyphPathRec  glyphPath;
529 
530 
531     FT_ZERO( &storage );
532     FT_ZERO( &results );
533     FT_ZERO( &flexStore );
534 
535     /* initialize the remaining objects */
536     cf2_arrstack_init( &subrStack,
537                        memory,
538                        error,
539                        sizeof ( CF2_BufferRec ) );
540     cf2_arrstack_init( &hStemHintArray,
541                        memory,
542                        error,
543                        sizeof ( CF2_StemHintRec ) );
544     cf2_arrstack_init( &vStemHintArray,
545                        memory,
546                        error,
547                        sizeof ( CF2_StemHintRec ) );
548 
549     /* initialize CF2_StemHint arrays */
550     cf2_hintmask_init( &hintMask, error );
551 
552     /* initialize path map to manage drawing operations */
553 
554     /* Note: last 4 params are used to handle `MoveToPermissive', which */
555     /*       may need to call `hintMap.Build'                           */
556     /* TODO: MoveToPermissive is gone; are these still needed?          */
557     cf2_glyphpath_init( &glyphPath,
558                         font,
559                         callbacks,
560                         scaleY,
561                         /* hShift, */
562                         &hStemHintArray,
563                         &vStemHintArray,
564                         &hintMask,
565                         hintOriginY,
566                         &font->blues,
567                         translation );
568 
569     /*
570      * Initialize state for width parsing.  From the CFF Spec:
571      *
572      *   The first stack-clearing operator, which must be one of hstem,
573      *   hstemhm, vstem, vstemhm, cntrmask, hintmask, hmoveto, vmoveto,
574      *   rmoveto, or endchar, takes an additional argument - the width (as
575      *   described earlier), which may be expressed as zero or one numeric
576      *   argument.
577      *
578      * What we implement here uses the first validly specified width, but
579      * does not detect errors for specifying more than one width.
580      *
581      * If one of the above operators occurs without explicitly specifying
582      * a width, we assume the default width.
583      *
584      * CFF2 charstrings always return the default width (0).
585      *
586      */
587     haveWidth = font->isCFF2 ? TRUE : FALSE;
588     *width    = cf2_getDefaultWidthX( decoder );
589 
590     /*
591      * Note: At this point, all pointers to resources must be NULL
592      *       and all local objects must be initialized.
593      *       There must be no branches to `exit:' above this point.
594      *
595      */
596 
597     /* allocate an operand stack */
598     stackSize = font->isCFF2 ? cf2_getMaxstack( decoder )
599                              : CF2_OPERAND_STACK_SIZE;
600     opStack   = cf2_stack_init( memory, error, stackSize );
601 
602     if ( !opStack )
603     {
604       lastError = FT_THROW( Out_Of_Memory );
605       goto exit;
606     }
607 
608     /* initialize subroutine stack by placing top level charstring as */
609     /* first element (max depth plus one for the charstring)          */
610     /* Note: Caller owns and must finalize the first charstring.      */
611     /*       Our copy of it does not change that requirement.         */
612     cf2_arrstack_setCount( &subrStack, CF2_MAX_SUBR + 1 );
613 
614     charstring  = (CF2_Buffer)cf2_arrstack_getBuffer( &subrStack );
615     *charstring = *buf;    /* structure copy */
616 
617     charstringIndex = 0;       /* entry is valid now */
618 
619     /* catch errors so far */
620     if ( *error )
621       goto exit;
622 
623     /* main interpreter loop */
624     while ( 1 )
625     {
626       if ( font->isT1 )
627         FT_ASSERT( known_othersubr_result_cnt == 0 ||
628                    result_cnt == 0                 );
629 
630       if ( cf2_buf_isEnd( charstring ) )
631       {
632         /* If we've reached the end of the charstring, simulate a */
633         /* cf2_cmdRETURN or cf2_cmdENDCHAR.                       */
634         /* We do this for both CFF and CFF2.                      */
635         if ( charstringIndex )
636           op1 = cf2_cmdRETURN;  /* end of buffer for subroutine */
637         else
638           op1 = cf2_cmdENDCHAR; /* end of buffer for top level charstring */
639       }
640       else
641       {
642         op1 = (FT_Byte)cf2_buf_readByte( charstring );
643 
644         /* Explicit RETURN and ENDCHAR in CFF2 should be ignored. */
645         /* Note: Trace message will report 0 instead of 11 or 14. */
646         if ( ( op1 == cf2_cmdRETURN || op1 == cf2_cmdENDCHAR ) &&
647              font->isCFF2                                      )
648           op1 = cf2_cmdRESERVED_0;
649       }
650 
651       if ( font->isT1 )
652       {
653         if ( !initial_map_ready           &&
654              !( op1 == cf2_cmdHSTEM     ||
655                 op1 == cf2_cmdVSTEM     ||
656                 op1 == cf2_cmdHSBW      ||
657                 op1 == cf2_cmdCALLSUBR  ||
658                 op1 == cf2_cmdRETURN    ||
659                 op1 == cf2_cmdESC       ||
660                 op1 == cf2_cmdENDCHAR   ||
661                 op1 >= 32 /* Numbers */ ) )
662         {
663           /* Skip outline commands first time round.       */
664           /* `endchar' will trigger initial hintmap build  */
665           /* and rewind the charstring.                    */
666           FT_TRACE4(( " <outline command skipped>\n" ));
667           cf2_stack_clear( opStack );
668           continue;
669         }
670 
671         if ( result_cnt > 0               &&
672              !( op1 == cf2_cmdCALLSUBR  ||
673                 op1 == cf2_cmdRETURN    ||
674                 op1 == cf2_cmdESC       ||
675                 op1 >= 32 /* Numbers */ ) )
676         {
677           /* all operands have been transferred by previous pops */
678           result_cnt = 0;
679         }
680 
681         if ( large_int && !( op1 >= 32 || op1 == cf2_escDIV ) )
682         {
683           FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
684                      " no `div' after large integer\n" ));
685 
686           large_int = FALSE;
687         }
688       }
689 
690       /* check for errors once per loop */
691       if ( *error )
692         goto exit;
693 
694       instructionLimit--;
695       if ( instructionLimit == 0 )
696       {
697         lastError = FT_THROW( Invalid_Glyph_Format );
698         goto exit;
699       }
700 
701       switch( op1 )
702       {
703       case cf2_cmdRESERVED_0:
704       case cf2_cmdRESERVED_2:
705       case cf2_cmdRESERVED_17:
706         /* we may get here if we have a prior error */
707         FT_TRACE4(( " unknown op (%d)\n", op1 ));
708         break;
709 
710       case cf2_cmdVSINDEX:
711         FT_TRACE4(( " vsindex\n" ));
712 
713         if ( !font->isCFF2 )
714           break;    /* clear stack & ignore */
715 
716         if ( font->blend.usedBV )
717         {
718           /* vsindex not allowed after blend */
719           lastError = FT_THROW( Invalid_Glyph_Format );
720           goto exit;
721         }
722 
723         {
724           FT_Int  temp = cf2_stack_popInt( opStack );
725 
726 
727           if ( temp >= 0 )
728             font->vsindex = (FT_UInt)temp;
729         }
730         break;
731 
732       case cf2_cmdBLEND:
733         {
734           FT_UInt  numBlends;
735 
736 
737           FT_TRACE4(( " blend\n" ));
738 
739           if ( !font->isCFF2 )
740             break;    /* clear stack & ignore */
741 
742           /* do we have a `blend' op in a non-variant font? */
743           if ( !font->blend.font )
744           {
745             lastError = FT_THROW( Invalid_Glyph_Format );
746             goto exit;
747           }
748 
749           /* check cached blend vector */
750           if ( font->cffload->blend_check_vector( &font->blend,
751                                                   font->vsindex,
752                                                   font->lenNDV,
753                                                   font->NDV ) )
754           {
755             lastError = font->cffload->blend_build_vector( &font->blend,
756                                                            font->vsindex,
757                                                            font->lenNDV,
758                                                            font->NDV );
759             if ( lastError )
760               goto exit;
761           }
762 
763           /* do the blend */
764           numBlends = (FT_UInt)cf2_stack_popInt( opStack );
765           if ( numBlends > stackSize )
766           {
767             lastError = FT_THROW( Invalid_Glyph_Format );
768             goto exit;
769           }
770 
771           cf2_doBlend( &font->blend, opStack, numBlends );
772 
773           font->blend.usedBV = TRUE;
774         }
775         continue;     /* do not clear the stack */
776 
777       case cf2_cmdHSTEMHM:
778       case cf2_cmdHSTEM:
779         FT_TRACE4(( op1 == cf2_cmdHSTEMHM ? " hstemhm\n" : " hstem\n" ));
780 
781         if ( !font->isT1 )
782         {
783           /* never add hints after the mask is computed */
784           /* except if in Type 1 mode (no hintmask op)  */
785           if ( cf2_hintmask_isValid( &hintMask ) )
786           {
787             FT_TRACE4(( "cf2_interpT2CharString:"
788                         " invalid horizontal hint mask\n" ));
789             break;
790           }
791         }
792 
793         /* add left-sidebearing correction in Type 1 mode */
794         cf2_doStems( font,
795                      opStack,
796                      &hStemHintArray,
797                      width,
798                      &haveWidth,
799                      font->isT1 ? decoder->builder.left_bearing->y
800                                 : 0 );
801 
802         if ( decoder->width_only )
803           goto exit;
804 
805         break;
806 
807       case cf2_cmdVSTEMHM:
808       case cf2_cmdVSTEM:
809         FT_TRACE4(( op1 == cf2_cmdVSTEMHM ? " vstemhm\n" : " vstem\n" ));
810 
811         if ( !font->isT1 )
812         {
813           /* never add hints after the mask is computed */
814           /* except if in Type 1 mode (no hintmask op)  */
815           if ( cf2_hintmask_isValid( &hintMask ) )
816           {
817             FT_TRACE4(( "cf2_interpT2CharString:"
818                         " invalid vertical hint mask\n" ));
819             break;
820           }
821         }
822 
823         /* add left-sidebearing correction in Type 1 mode */
824         cf2_doStems( font,
825                      opStack,
826                      &vStemHintArray,
827                      width,
828                      &haveWidth,
829                      font->isT1 ? decoder->builder.left_bearing->x
830                                 : 0 );
831 
832         if ( decoder->width_only )
833           goto exit;
834 
835         break;
836 
837       case cf2_cmdVMOVETO:
838         FT_TRACE4(( " vmoveto\n" ));
839 
840         if ( font->isT1 && !decoder->flex_state && !haveWidth )
841           FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
842                      " No width. Use hsbw/sbw as first op\n" ));
843 
844         if ( cf2_stack_count( opStack ) > 1 && !haveWidth )
845           *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
846                               nominalWidthX );
847 
848         /* width is defined or default after this */
849         haveWidth = TRUE;
850 
851         if ( decoder->width_only )
852           goto exit;
853 
854         curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) );
855 
856         if ( !decoder->flex_state )
857           cf2_glyphpath_moveTo( &glyphPath, curX, curY );
858 
859         break;
860 
861       case cf2_cmdRLINETO:
862         {
863           CF2_UInt  idx;
864           CF2_UInt  count = cf2_stack_count( opStack );
865 
866 
867           FT_TRACE4(( " rlineto\n" ));
868 
869           for ( idx = 0; idx < count; idx += 2 )
870           {
871             curX = ADD_INT32( curX, cf2_stack_getReal( opStack,
872                                                        idx + 0 ) );
873             curY = ADD_INT32( curY, cf2_stack_getReal( opStack,
874                                                        idx + 1 ) );
875 
876             cf2_glyphpath_lineTo( &glyphPath, curX, curY );
877           }
878 
879           cf2_stack_clear( opStack );
880         }
881         continue; /* no need to clear stack again */
882 
883       case cf2_cmdHLINETO:
884       case cf2_cmdVLINETO:
885         {
886           CF2_UInt  idx;
887           CF2_UInt  count = cf2_stack_count( opStack );
888 
889           FT_Bool  isX = FT_BOOL( op1 == cf2_cmdHLINETO );
890 
891 
892           FT_TRACE4(( isX ? " hlineto\n" : " vlineto\n" ));
893 
894           for ( idx = 0; idx < count; idx++ )
895           {
896             CF2_Fixed  v = cf2_stack_getReal( opStack, idx );
897 
898 
899             if ( isX )
900               curX = ADD_INT32( curX, v );
901             else
902               curY = ADD_INT32( curY, v );
903 
904             isX = !isX;
905 
906             cf2_glyphpath_lineTo( &glyphPath, curX, curY );
907           }
908 
909           cf2_stack_clear( opStack );
910         }
911         continue;
912 
913       case cf2_cmdRCURVELINE:
914       case cf2_cmdRRCURVETO:
915         {
916           CF2_UInt  count = cf2_stack_count( opStack );
917           CF2_UInt  idx   = 0;
918 
919 
920           FT_TRACE4(( op1 == cf2_cmdRCURVELINE ? " rcurveline\n"
921                                                : " rrcurveto\n" ));
922 
923           while ( idx + 6 <= count )
924           {
925             CF2_Fixed  x1, y1, x2, y2, x3, y3;
926 
927 
928             x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
929             y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), curY );
930             x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), x1 );
931             y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y1 );
932             x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 );
933             y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 5 ), y2 );
934 
935             cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
936 
937             curX  = x3;
938             curY  = y3;
939             idx  += 6;
940           }
941 
942           if ( op1 == cf2_cmdRCURVELINE )
943           {
944             curX = ADD_INT32( curX, cf2_stack_getReal( opStack,
945                                                        idx + 0 ) );
946             curY = ADD_INT32( curY, cf2_stack_getReal( opStack,
947                                                        idx + 1 ) );
948 
949             cf2_glyphpath_lineTo( &glyphPath, curX, curY );
950           }
951 
952           cf2_stack_clear( opStack );
953         }
954         continue; /* no need to clear stack again */
955 
956       case cf2_cmdCLOSEPATH:
957         if ( !font->isT1 )
958           FT_TRACE4(( " unknown op (%d)\n", op1 ));
959         else
960         {
961           FT_TRACE4(( " closepath" ));
962 
963           /* if there is no path, `closepath' is a no-op */
964           ps_builder_close_contour( &decoder->builder );
965 
966           haveWidth = TRUE;
967         }
968         break;
969 
970       case cf2_cmdCALLGSUBR:
971       case cf2_cmdCALLSUBR:
972         {
973           CF2_Int  subrNum;
974 
975 
976           FT_TRACE4(( op1 == cf2_cmdCALLGSUBR ? " callgsubr"
977                                               : " callsubr" ));
978 
979           if ( ( !font->isT1 && charstringIndex > CF2_MAX_SUBR )       ||
980                (  font->isT1 && charstringIndex > T1_MAX_SUBRS_CALLS ) )
981           {
982             /* max subr plus one for charstring */
983             lastError = FT_THROW( Invalid_Glyph_Format );
984             goto exit;                      /* overflow of stack */
985           }
986 
987           /* push our current CFF charstring region on subrStack */
988           charstring = (CF2_Buffer)
989                          cf2_arrstack_getPointer(
990                            &subrStack,
991                            (size_t)charstringIndex + 1 );
992 
993           /* set up the new CFF region and pointer */
994           subrNum = cf2_stack_popInt( opStack );
995 
996           if ( font->isT1 && decoder->locals_hash )
997           {
998             size_t*  val = ft_hash_num_lookup( subrNum,
999                                                decoder->locals_hash );
1000 
1001 
1002             if ( val )
1003               subrNum = *val;
1004             else
1005               subrNum = -1;
1006           }
1007 
1008           switch ( op1 )
1009           {
1010           case cf2_cmdCALLGSUBR:
1011             FT_TRACE4(( " (idx %d, entering level %d)\n",
1012                         subrNum + decoder->globals_bias,
1013                         charstringIndex + 1 ));
1014 
1015             if ( cf2_initGlobalRegionBuffer( decoder,
1016                                              subrNum,
1017                                              charstring ) )
1018             {
1019               lastError = FT_THROW( Invalid_Glyph_Format );
1020               goto exit;  /* subroutine lookup or stream error */
1021             }
1022             break;
1023 
1024           default:
1025             /* cf2_cmdCALLSUBR */
1026             FT_TRACE4(( " (idx %d, entering level %d)\n",
1027                         subrNum + decoder->locals_bias,
1028                         charstringIndex + 1 ));
1029 
1030             if ( cf2_initLocalRegionBuffer( decoder,
1031                                             subrNum,
1032                                             charstring ) )
1033             {
1034               lastError = FT_THROW( Invalid_Glyph_Format );
1035               goto exit;  /* subroutine lookup or stream error */
1036             }
1037           }
1038 
1039           charstringIndex += 1;       /* entry is valid now */
1040         }
1041         continue; /* do not clear the stack */
1042 
1043       case cf2_cmdRETURN:
1044         FT_TRACE4(( " return (leaving level %d)\n", charstringIndex ));
1045 
1046         if ( charstringIndex < 1 )
1047         {
1048           /* Note: cannot return from top charstring */
1049           lastError = FT_THROW( Invalid_Glyph_Format );
1050           goto exit;                      /* underflow of stack */
1051         }
1052 
1053         /* restore position in previous charstring */
1054         charstring = (CF2_Buffer)
1055                        cf2_arrstack_getPointer(
1056                          &subrStack,
1057                          (CF2_UInt)--charstringIndex );
1058         continue;     /* do not clear the stack */
1059 
1060       case cf2_cmdESC:
1061         {
1062           FT_Byte  op2 = (FT_Byte)cf2_buf_readByte( charstring );
1063 
1064 
1065           /* first switch for 2-byte operators handles CFF2      */
1066           /* and opcodes that are reserved for both CFF and CFF2 */
1067           switch ( op2 )
1068           {
1069           case cf2_escHFLEX:
1070             {
1071               static const FT_Bool  readFromStack[12] =
1072               {
1073                 TRUE /* dx1 */, FALSE /* dy1 */,
1074                 TRUE /* dx2 */, TRUE  /* dy2 */,
1075                 TRUE /* dx3 */, FALSE /* dy3 */,
1076                 TRUE /* dx4 */, FALSE /* dy4 */,
1077                 TRUE /* dx5 */, FALSE /* dy5 */,
1078                 TRUE /* dx6 */, FALSE /* dy6 */
1079               };
1080 
1081 
1082               FT_TRACE4(( " hflex\n" ));
1083 
1084               cf2_doFlex( opStack,
1085                           &curX,
1086                           &curY,
1087                           &glyphPath,
1088                           readFromStack,
1089                           FALSE /* doConditionalLastRead */ );
1090             }
1091             continue;
1092 
1093           case cf2_escFLEX:
1094             {
1095               static const FT_Bool  readFromStack[12] =
1096               {
1097                 TRUE /* dx1 */, TRUE /* dy1 */,
1098                 TRUE /* dx2 */, TRUE /* dy2 */,
1099                 TRUE /* dx3 */, TRUE /* dy3 */,
1100                 TRUE /* dx4 */, TRUE /* dy4 */,
1101                 TRUE /* dx5 */, TRUE /* dy5 */,
1102                 TRUE /* dx6 */, TRUE /* dy6 */
1103               };
1104 
1105 
1106               FT_TRACE4(( " flex\n" ));
1107 
1108               cf2_doFlex( opStack,
1109                           &curX,
1110                           &curY,
1111                           &glyphPath,
1112                           readFromStack,
1113                           FALSE /* doConditionalLastRead */ );
1114             }
1115             break;      /* TODO: why is this not a continue? */
1116 
1117           case cf2_escHFLEX1:
1118             {
1119               static const FT_Bool  readFromStack[12] =
1120               {
1121                 TRUE /* dx1 */, TRUE  /* dy1 */,
1122                 TRUE /* dx2 */, TRUE  /* dy2 */,
1123                 TRUE /* dx3 */, FALSE /* dy3 */,
1124                 TRUE /* dx4 */, FALSE /* dy4 */,
1125                 TRUE /* dx5 */, TRUE  /* dy5 */,
1126                 TRUE /* dx6 */, FALSE /* dy6 */
1127               };
1128 
1129 
1130               FT_TRACE4(( " hflex1\n" ));
1131 
1132               cf2_doFlex( opStack,
1133                           &curX,
1134                           &curY,
1135                           &glyphPath,
1136                           readFromStack,
1137                           FALSE /* doConditionalLastRead */ );
1138             }
1139             continue;
1140 
1141           case cf2_escFLEX1:
1142             {
1143               static const FT_Bool  readFromStack[12] =
1144               {
1145                 TRUE  /* dx1 */, TRUE  /* dy1 */,
1146                 TRUE  /* dx2 */, TRUE  /* dy2 */,
1147                 TRUE  /* dx3 */, TRUE  /* dy3 */,
1148                 TRUE  /* dx4 */, TRUE  /* dy4 */,
1149                 TRUE  /* dx5 */, TRUE  /* dy5 */,
1150                 FALSE /* dx6 */, FALSE /* dy6 */
1151               };
1152 
1153 
1154               FT_TRACE4(( " flex1\n" ));
1155 
1156               cf2_doFlex( opStack,
1157                           &curX,
1158                           &curY,
1159                           &glyphPath,
1160                           readFromStack,
1161                           TRUE /* doConditionalLastRead */ );
1162             }
1163             continue;
1164 
1165           /* these opcodes are always reserved */
1166           case cf2_escRESERVED_8:
1167           case cf2_escRESERVED_13:
1168           case cf2_escRESERVED_19:
1169           case cf2_escRESERVED_25:
1170           case cf2_escRESERVED_31:
1171           case cf2_escRESERVED_32:
1172             FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
1173             break;
1174 
1175           default:
1176             {
1177               if ( font->isCFF2 || op2 >= cf2_escRESERVED_38 )
1178                 FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
1179               else if ( font->isT1 && result_cnt > 0 && op2 != cf2_escPOP )
1180               {
1181                 /* all operands have been transferred by previous pops */
1182                 result_cnt = 0;
1183               }
1184               else
1185               {
1186                 /* second switch for 2-byte operators handles */
1187                 /* CFF and Type 1                             */
1188                 switch ( op2 )
1189                 {
1190 
1191                 case cf2_escDOTSECTION:
1192                   /* something about `flip type of locking' -- ignore it */
1193                   FT_TRACE4(( " dotsection\n" ));
1194 
1195                   break;
1196 
1197                 case cf2_escVSTEM3:
1198                 case cf2_escHSTEM3:
1199                   /*
1200                    * Type 1:                          Type 2:
1201                    *   x0 dx0 x1 dx1 x2 dx2 vstem3      x dx {dxa dxb}* vstem
1202                    *   y0 dy0 y1 dy1 y2 dy2 hstem3      y dy {dya dyb}* hstem
1203                    *   relative to lsb point            relative to zero
1204                    *
1205                    */
1206                   {
1207                     if ( !font->isT1 )
1208                       FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
1209                     else
1210                     {
1211                       CF2_F16Dot16  v0, v1, v2;
1212 
1213                       FT_Bool  isV = FT_BOOL( op2 == cf2_escVSTEM3 );
1214 
1215 
1216                       FT_TRACE4(( isV ? " vstem3\n"
1217                                       : " hstem3\n" ));
1218 
1219                       FT_ASSERT( cf2_stack_count( opStack ) == 6 );
1220 
1221                       v0 = cf2_stack_getReal( opStack, 0 );
1222                       v1 = cf2_stack_getReal( opStack, 2 );
1223                       v2 = cf2_stack_getReal( opStack, 4 );
1224 
1225                       cf2_stack_setReal(
1226                         opStack, 2,
1227                         SUB_INT32( SUB_INT32( v1, v0 ),
1228                                    cf2_stack_getReal( opStack, 1 ) ) );
1229                       cf2_stack_setReal(
1230                         opStack, 4,
1231                         SUB_INT32( SUB_INT32( v2, v1 ),
1232                                    cf2_stack_getReal( opStack, 3 ) ) );
1233 
1234                       /* add left-sidebearing correction */
1235                       cf2_doStems( font,
1236                                    opStack,
1237                                    isV ? &vStemHintArray : &hStemHintArray,
1238                                    width,
1239                                    &haveWidth,
1240                                    isV ? decoder->builder.left_bearing->x
1241                                        : decoder->builder.left_bearing->y );
1242 
1243                       if ( decoder->width_only )
1244                         goto exit;
1245                     }
1246                   }
1247                   break;
1248 
1249                 case cf2_escAND:
1250                   {
1251                     CF2_F16Dot16  arg1;
1252                     CF2_F16Dot16  arg2;
1253 
1254 
1255                     FT_TRACE4(( " and\n" ));
1256 
1257                     arg2 = cf2_stack_popFixed( opStack );
1258                     arg1 = cf2_stack_popFixed( opStack );
1259 
1260                     cf2_stack_pushInt( opStack, arg1 && arg2 );
1261                   }
1262                   continue; /* do not clear the stack */
1263 
1264                 case cf2_escOR:
1265                   {
1266                     CF2_F16Dot16  arg1;
1267                     CF2_F16Dot16  arg2;
1268 
1269 
1270                     FT_TRACE4(( " or\n" ));
1271 
1272                     arg2 = cf2_stack_popFixed( opStack );
1273                     arg1 = cf2_stack_popFixed( opStack );
1274 
1275                     cf2_stack_pushInt( opStack, arg1 || arg2 );
1276                   }
1277                   continue; /* do not clear the stack */
1278 
1279                 case cf2_escNOT:
1280                   {
1281                     CF2_F16Dot16  arg;
1282 
1283 
1284                     FT_TRACE4(( " not\n" ));
1285 
1286                     arg = cf2_stack_popFixed( opStack );
1287 
1288                     cf2_stack_pushInt( opStack, !arg );
1289                   }
1290                   continue; /* do not clear the stack */
1291 
1292                 case cf2_escSEAC:
1293                   if ( !font->isT1 )
1294                     FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
1295                   else
1296                   {
1297                     FT_Error   error2;
1298                     CF2_Int    bchar_index, achar_index;
1299                     FT_Vector  left_bearing, advance;
1300 
1301 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1302                     T1_Face  face = (T1_Face)decoder->builder.face;
1303 #endif
1304                     CF2_BufferRec  component;
1305                     CF2_Fixed      dummyWidth;
1306 
1307                     CF2_Int  achar = cf2_stack_popInt( opStack );
1308                     CF2_Int  bchar = cf2_stack_popInt( opStack );
1309 
1310                     FT_Pos  ady = cf2_stack_popFixed ( opStack );
1311                     FT_Pos  adx = cf2_stack_popFixed ( opStack );
1312                     FT_Pos  asb = cf2_stack_popFixed ( opStack );
1313 
1314 
1315                     FT_TRACE4(( " seac\n" ));
1316 
1317                     if ( doingSeac )
1318                     {
1319                       FT_ERROR(( " nested seac\n" ));
1320                       lastError = FT_THROW( Invalid_Glyph_Format );
1321                       goto exit;      /* nested seac */
1322                     }
1323 
1324                     if ( decoder->builder.metrics_only )
1325                     {
1326                       FT_ERROR(( " unexpected seac\n" ));
1327                       lastError = FT_THROW( Invalid_Glyph_Format );
1328                       goto exit;      /* unexpected seac */
1329                     }
1330 
1331                     /* `glyph_names' is set to 0 for CID fonts which do */
1332                     /* not include an encoding.  How can we deal with   */
1333                     /* these?                                           */
1334 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1335                     if ( decoder->glyph_names == 0                   &&
1336                          !face->root.internal->incremental_interface )
1337 #else
1338                       if ( decoder->glyph_names == 0 )
1339 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
1340                       {
1341                         FT_ERROR((
1342                           "cf2_interpT2CharString: (Type 1 seac)"
1343                           " glyph names table not available in this font\n" ));
1344                         lastError = FT_THROW( Invalid_Glyph_Format );
1345                         goto exit;
1346                       }
1347 
1348                     /* seac weirdness */
1349                     adx += decoder->builder.left_bearing->x;
1350 
1351 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1352                     if ( face->root.internal->incremental_interface )
1353                     {
1354                       /* the caller must handle the font encoding also */
1355                       bchar_index = bchar;
1356                       achar_index = achar;
1357                     }
1358                     else
1359 #endif
1360                     {
1361                       bchar_index = t1_lookup_glyph_by_stdcharcode_ps(
1362                                       decoder, bchar );
1363                       achar_index = t1_lookup_glyph_by_stdcharcode_ps(
1364                                       decoder, achar );
1365                     }
1366 
1367                     if ( bchar_index < 0 || achar_index < 0 )
1368                     {
1369                       FT_ERROR((
1370                         "cf2_interpT2CharString: (Type 1 seac)"
1371                         " invalid seac character code arguments\n" ));
1372                       lastError = FT_THROW( Invalid_Glyph_Format );
1373                       goto exit;
1374                     }
1375 
1376                     /* if we are trying to load a composite glyph, */
1377                     /* do not load the accent character and return */
1378                     /* the array of subglyphs.                     */
1379                     if ( decoder->builder.no_recurse )
1380                     {
1381                       FT_GlyphSlot    glyph  = (FT_GlyphSlot)decoder->builder.glyph;
1382                       FT_GlyphLoader  loader = glyph->internal->loader;
1383                       FT_SubGlyph     subg;
1384 
1385 
1386                       /* reallocate subglyph array if necessary */
1387                       error2 = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
1388                       if ( error2 )
1389                       {
1390                         lastError = error2; /* pass FreeType error through */
1391                         goto exit;
1392                       }
1393 
1394                       subg = loader->current.subglyphs;
1395 
1396                       /* subglyph 0 = base character */
1397                       subg->index = bchar_index;
1398                       subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
1399                                     FT_SUBGLYPH_FLAG_USE_MY_METRICS;
1400                       subg->arg1  = 0;
1401                       subg->arg2  = 0;
1402                       subg++;
1403 
1404                       /* subglyph 1 = accent character */
1405                       subg->index = achar_index;
1406                       subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
1407                       subg->arg1  = (FT_Int)FIXED_TO_INT( adx - asb );
1408                       subg->arg2  = (FT_Int)FIXED_TO_INT( ady );
1409 
1410                       /* set up remaining glyph fields */
1411                       glyph->num_subglyphs = 2;
1412                       glyph->subglyphs     = loader->base.subglyphs;
1413                       glyph->format        = FT_GLYPH_FORMAT_COMPOSITE;
1414 
1415                       loader->current.num_subglyphs = 2;
1416 
1417                       goto exit;
1418                     }
1419 
1420                     /* First load `bchar' in builder */
1421                     /* now load the unscaled outline */
1422 
1423                     /* prepare loader */
1424                     FT_GlyphLoader_Prepare( decoder->builder.loader );
1425 
1426                     error2 = cf2_getT1SeacComponent( decoder,
1427                                                      (FT_UInt)bchar_index,
1428                                                      &component );
1429                     if ( error2 )
1430                     {
1431                       lastError = error2; /* pass FreeType error through */
1432                       goto exit;
1433                     }
1434                     cf2_interpT2CharString( font,
1435                                             &component,
1436                                             callbacks,
1437                                             translation,
1438                                             TRUE,
1439                                             0,
1440                                             0,
1441                                             &dummyWidth );
1442                     cf2_freeT1SeacComponent( decoder, &component );
1443 
1444                     /* save the left bearing and width of the base       */
1445                     /* character as they will be erased by the next load */
1446 
1447                     left_bearing = *decoder->builder.left_bearing;
1448                     advance      = *decoder->builder.advance;
1449 
1450                     decoder->builder.left_bearing->x = 0;
1451                     decoder->builder.left_bearing->y = 0;
1452 
1453                     /* Now load `achar' on top of */
1454                     /* the base outline           */
1455 
1456                     error2 = cf2_getT1SeacComponent( decoder,
1457                                                      (FT_UInt)achar_index,
1458                                                      &component );
1459                     if ( error2 )
1460                     {
1461                       lastError = error2; /* pass FreeType error through */
1462                       goto exit;
1463                     }
1464                     cf2_interpT2CharString( font,
1465                                             &component,
1466                                             callbacks,
1467                                             translation,
1468                                             TRUE,
1469                                             adx - asb,
1470                                             ady,
1471                                             &dummyWidth );
1472                     cf2_freeT1SeacComponent( decoder, &component );
1473 
1474                     /* restore the left side bearing and   */
1475                     /* advance width of the base character */
1476 
1477                     *decoder->builder.left_bearing = left_bearing;
1478                     *decoder->builder.advance      = advance;
1479 
1480                     goto exit;
1481                   }
1482                   break;
1483 
1484                 case cf2_escSBW:
1485                   if ( !font->isT1 )
1486                     FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
1487                   else
1488                   {
1489                     CF2_Fixed    lsb_x, lsb_y;
1490                     PS_Builder*  builder;
1491 
1492 
1493                     FT_TRACE4(( " sbw" ));
1494 
1495                     builder = &decoder->builder;
1496 
1497                     builder->advance->y = cf2_stack_popFixed( opStack );
1498                     builder->advance->x = cf2_stack_popFixed( opStack );
1499 
1500                     lsb_y = cf2_stack_popFixed( opStack );
1501                     lsb_x = cf2_stack_popFixed( opStack );
1502 
1503                     builder->left_bearing->x =
1504                       ADD_INT32( builder->left_bearing->x, lsb_x );
1505                     builder->left_bearing->y =
1506                       ADD_INT32( builder->left_bearing->y, lsb_y );
1507 
1508                     haveWidth = TRUE;
1509 
1510                     /* the `metrics_only' indicates that we only want */
1511                     /* to compute the glyph's metrics (lsb + advance  */
1512                     /* width), not load the  rest of it; so exit      */
1513                     /* immediately                                    */
1514                     if ( builder->metrics_only )
1515                       goto exit;
1516 
1517                     if ( initial_map_ready )
1518                     {
1519                       curX = ADD_INT32( curX, lsb_x );
1520                       curY = ADD_INT32( curY, lsb_y );
1521                     }
1522                   }
1523                   break;
1524 
1525                 case cf2_escABS:
1526                   {
1527                     CF2_F16Dot16  arg;
1528 
1529 
1530                     FT_TRACE4(( " abs\n" ));
1531 
1532                     arg = cf2_stack_popFixed( opStack );
1533 
1534                     if ( arg < -CF2_FIXED_MAX )
1535                       cf2_stack_pushFixed( opStack, CF2_FIXED_MAX );
1536                     else
1537                       cf2_stack_pushFixed( opStack, FT_ABS( arg ) );
1538                   }
1539                   continue; /* do not clear the stack */
1540 
1541                 case cf2_escADD:
1542                   {
1543                     CF2_F16Dot16  summand1;
1544                     CF2_F16Dot16  summand2;
1545 
1546 
1547                     FT_TRACE4(( " add\n" ));
1548 
1549                     summand2 = cf2_stack_popFixed( opStack );
1550                     summand1 = cf2_stack_popFixed( opStack );
1551 
1552                     cf2_stack_pushFixed( opStack,
1553                                          ADD_INT32( summand1,
1554                                                     summand2 ) );
1555                   }
1556                   continue; /* do not clear the stack */
1557 
1558                 case cf2_escSUB:
1559                   {
1560                     CF2_F16Dot16  minuend;
1561                     CF2_F16Dot16  subtrahend;
1562 
1563 
1564                     FT_TRACE4(( " sub\n" ));
1565 
1566                     subtrahend = cf2_stack_popFixed( opStack );
1567                     minuend    = cf2_stack_popFixed( opStack );
1568 
1569                     cf2_stack_pushFixed( opStack,
1570                                          SUB_INT32( minuend, subtrahend ) );
1571                   }
1572                   continue; /* do not clear the stack */
1573 
1574                 case cf2_escDIV:
1575                   {
1576                     CF2_F16Dot16  dividend;
1577                     CF2_F16Dot16  divisor;
1578 
1579 
1580                     FT_TRACE4(( " div\n" ));
1581 
1582                     if ( font->isT1 && large_int )
1583                     {
1584                       divisor  = (CF2_F16Dot16)cf2_stack_popInt( opStack );
1585                       dividend = (CF2_F16Dot16)cf2_stack_popInt( opStack );
1586 
1587                       large_int = FALSE;
1588                     }
1589                     else
1590                     {
1591                       divisor  = cf2_stack_popFixed( opStack );
1592                       dividend = cf2_stack_popFixed( opStack );
1593                     }
1594 
1595                     cf2_stack_pushFixed( opStack,
1596                                          FT_DivFix( dividend, divisor ) );
1597 
1598                   }
1599                   continue; /* do not clear the stack */
1600 
1601                 case cf2_escNEG:
1602                   {
1603                     CF2_F16Dot16  arg;
1604 
1605 
1606                     FT_TRACE4(( " neg\n" ));
1607 
1608                     arg = cf2_stack_popFixed( opStack );
1609 
1610                     if ( arg < -CF2_FIXED_MAX )
1611                       cf2_stack_pushFixed( opStack, CF2_FIXED_MAX );
1612                     else
1613                       cf2_stack_pushFixed( opStack, -arg );
1614                   }
1615                   continue; /* do not clear the stack */
1616 
1617                 case cf2_escEQ:
1618                   {
1619                     CF2_F16Dot16  arg1;
1620                     CF2_F16Dot16  arg2;
1621 
1622 
1623                     FT_TRACE4(( " eq\n" ));
1624 
1625                     arg2 = cf2_stack_popFixed( opStack );
1626                     arg1 = cf2_stack_popFixed( opStack );
1627 
1628                     cf2_stack_pushInt( opStack, arg1 == arg2 );
1629                   }
1630                   continue; /* do not clear the stack */
1631 
1632                 case cf2_escCALLOTHERSUBR:
1633                   if ( !font->isT1 )
1634                     FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
1635                   else
1636                   {
1637                     CF2_Int   subr_no;
1638                     CF2_Int   arg_cnt;
1639                     CF2_UInt  count;
1640                     CF2_UInt  opIdx = 0;
1641 
1642 
1643                     FT_TRACE4(( " callothersubr\n" ));
1644 
1645                     subr_no = cf2_stack_popInt( opStack );
1646                     arg_cnt = cf2_stack_popInt( opStack );
1647 
1648                     /********************************************************
1649                      *
1650                      * remove all operands to callothersubr from the stack
1651                      *
1652                      * for handled othersubrs, where we know the number of
1653                      * arguments, we increase the stack by the value of
1654                      * known_othersubr_result_cnt
1655                      *
1656                      * for unhandled othersubrs the following pops adjust
1657                      * the stack pointer as necessary
1658                      */
1659 
1660                     count = cf2_stack_count( opStack );
1661                     FT_ASSERT( (CF2_UInt)arg_cnt <= count );
1662 
1663                     opIdx += count - (CF2_UInt)arg_cnt;
1664 
1665                     known_othersubr_result_cnt = 0;
1666                     result_cnt                 = 0;
1667 
1668                     /* XXX TODO: The checks to `arg_count == <whatever>'   */
1669                     /* might not be correct; an othersubr expects a        */
1670                     /* certain number of operands on the PostScript stack  */
1671                     /* (as opposed to the T1 stack) but it doesn't have to */
1672                     /* put them there by itself; previous othersubrs might */
1673                     /* have left the operands there if they were not       */
1674                     /* followed by an appropriate number of pops           */
1675                     /*                                                     */
1676                     /* On the other hand, Adobe Reader 7.0.8 for Linux     */
1677                     /* doesn't accept a font that contains charstrings     */
1678                     /* like                                                */
1679                     /*                                                     */
1680                     /*     100 200 2 20 callothersubr                      */
1681                     /*     300 1 20 callothersubr pop                      */
1682                     /*                                                     */
1683                     /* Perhaps this is the reason why BuildCharArray       */
1684                     /* exists.                                             */
1685 
1686                     switch ( subr_no )
1687                     {
1688                     case 0:                     /* end flex feature */
1689                       if ( arg_cnt != 3 )
1690                         goto Unexpected_OtherSubr;
1691 
1692                       if ( initial_map_ready &&
1693                            ( !decoder->flex_state           ||
1694                              decoder->num_flex_vectors != 7 ) )
1695                       {
1696                         FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
1697                                    " unexpected flex end\n" ));
1698                         lastError = FT_THROW( Invalid_Glyph_Format );
1699                         goto exit;
1700                       }
1701 
1702                       /* the two `results' are popped     */
1703                       /* by the following setcurrentpoint */
1704                       cf2_stack_pushFixed( opStack, curX );
1705                       cf2_stack_pushFixed( opStack, curY );
1706                       known_othersubr_result_cnt = 2;
1707                       break;
1708 
1709                     case 1:                     /* start flex feature */
1710                       if ( arg_cnt != 0 )
1711                         goto Unexpected_OtherSubr;
1712 
1713                       if ( !initial_map_ready )
1714                         break;
1715 
1716                       if ( ps_builder_check_points( &decoder->builder, 6 ) )
1717                         goto exit;
1718 
1719                       decoder->flex_state        = 1;
1720                       decoder->num_flex_vectors  = 0;
1721                       break;
1722 
1723                     case 2:                     /* add flex vectors */
1724                       {
1725                         FT_Int  idx;
1726                         FT_Int  idx2;
1727 
1728 
1729                         if ( arg_cnt != 0 )
1730                           goto Unexpected_OtherSubr;
1731 
1732                         if ( !initial_map_ready )
1733                           break;
1734 
1735                         if ( !decoder->flex_state )
1736                         {
1737                           FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
1738                                      " missing flex start\n" ));
1739                           lastError = FT_THROW( Invalid_Glyph_Format );
1740                           goto exit;
1741                         }
1742 
1743                         /* note that we should not add a point for      */
1744                         /* index 0; this will move our current position */
1745                         /* to the flex point without adding any point   */
1746                         /* to the outline                               */
1747                         idx = decoder->num_flex_vectors++;
1748                         if ( idx > 0 && idx < 7 )
1749                         {
1750                           /* in malformed fonts it is possible to have    */
1751                           /* other opcodes in the middle of a flex (which */
1752                           /* don't increase `num_flex_vectors'); we thus  */
1753                           /* have to check whether we can add a point     */
1754 
1755                           if ( ps_builder_check_points( &decoder->builder,
1756                                                         1 ) )
1757                           {
1758                             lastError = FT_THROW( Invalid_Glyph_Format );
1759                             goto exit;
1760                           }
1761 
1762                           /* map: 1->2 2->4 3->6 4->2 5->4 6->6 */
1763                           idx2 = ( idx > 3 ? idx - 3 : idx ) * 2;
1764 
1765                           flexStore[idx2 - 2] = curX;
1766                           flexStore[idx2 - 1] = curY;
1767 
1768                           if ( idx == 3 || idx == 6 )
1769                             cf2_glyphpath_curveTo( &glyphPath,
1770                                                    flexStore[0],
1771                                                    flexStore[1],
1772                                                    flexStore[2],
1773                                                    flexStore[3],
1774                                                    flexStore[4],
1775                                                    flexStore[5] );
1776                         }
1777                       }
1778                       break;
1779 
1780                     case 3:                     /* change hints */
1781                       if ( arg_cnt != 1 )
1782                         goto Unexpected_OtherSubr;
1783 
1784                       if ( initial_map_ready )
1785                       {
1786                         /* do not clear hints if initial hintmap */
1787                         /* is not ready - we need to collate all */
1788                         cf2_arrstack_clear( &vStemHintArray );
1789                         cf2_arrstack_clear( &hStemHintArray );
1790 
1791                         cf2_hintmask_init( &hintMask, error );
1792                         hintMask.isValid = FALSE;
1793                         hintMask.isNew   = TRUE;
1794                       }
1795 
1796                       known_othersubr_result_cnt = 1;
1797                       break;
1798 
1799                     case 12:
1800                     case 13:
1801                       /* counter control hints, clear stack */
1802                       cf2_stack_clear( opStack );
1803                       break;
1804 
1805                     case 14:
1806                     case 15:
1807                     case 16:
1808                     case 17:
1809                     case 18:                    /* multiple masters */
1810                       {
1811                         PS_Blend  blend = decoder->blend;
1812                         FT_UInt   num_points, nn, mm;
1813                         CF2_UInt  delta;
1814                         CF2_UInt  values;
1815 
1816 
1817                         if ( !blend )
1818                         {
1819                           FT_ERROR((
1820                             "cf2_interpT2CharString:"
1821                             " unexpected multiple masters operator\n" ));
1822                           lastError = FT_THROW( Invalid_Glyph_Format );
1823                           goto exit;
1824                         }
1825 
1826                         num_points = (FT_UInt)subr_no - 13 +
1827                                        ( subr_no == 18 );
1828                         if ( arg_cnt != (FT_Int)( num_points *
1829                                                   blend->num_designs ) )
1830                         {
1831                           FT_ERROR((
1832                             "cf2_interpT2CharString:"
1833                             " incorrect number of multiple masters arguments\n" ));
1834                           lastError = FT_THROW( Invalid_Glyph_Format );
1835                           goto exit;
1836                         }
1837 
1838                         /* We want to compute                                */
1839                         /*                                                   */
1840                         /*   a0*w0 + a1*w1 + ... + ak*wk                     */
1841                         /*                                                   */
1842                         /* but we only have a0, a1-a0, a2-a0, ..., ak-a0.    */
1843                         /*                                                   */
1844                         /* However, given that w0 + w1 + ... + wk == 1, we   */
1845                         /* can rewrite it easily as                          */
1846                         /*                                                   */
1847                         /*   a0 + (a1-a0)*w1 + (a2-a0)*w2 + ... + (ak-a0)*wk */
1848                         /*                                                   */
1849                         /* where k == num_designs-1.                         */
1850                         /*                                                   */
1851                         /* I guess that's why it's written in this `compact' */
1852                         /* form.                                             */
1853                         /*                                                   */
1854                         delta  = opIdx + num_points;
1855                         values = opIdx;
1856                         for ( nn = 0; nn < num_points; nn++ )
1857                         {
1858                           CF2_Fixed  tmp = cf2_stack_getReal( opStack,
1859                                                               values );
1860 
1861 
1862                           for ( mm = 1; mm < blend->num_designs; mm++ )
1863                             tmp = ADD_INT32( tmp,
1864                                              FT_MulFix(
1865                                                cf2_stack_getReal( opStack,
1866                                                                   delta++ ),
1867                                                blend->weight_vector[mm] ) );
1868 
1869                           cf2_stack_setReal( opStack, values++, tmp );
1870                         }
1871                         cf2_stack_pop( opStack,
1872                                        (CF2_UInt)arg_cnt - num_points );
1873 
1874                         known_othersubr_result_cnt = (FT_Int)num_points;
1875                         break;
1876                       }
1877 
1878                     case 19:
1879                       /* <idx> 1 19 callothersubr                 */
1880                       /* ==> replace elements starting from index */
1881                       /*     cvi( <idx> ) of BuildCharArray with  */
1882                       /*     WeightVector                         */
1883                       {
1884                         FT_Int    idx;
1885                         PS_Blend  blend = decoder->blend;
1886 
1887 
1888                         if ( arg_cnt != 1 || !blend )
1889                           goto Unexpected_OtherSubr;
1890 
1891                         idx = cf2_stack_popInt( opStack );
1892 
1893                         if ( idx < 0                             ||
1894                              (FT_UInt)idx + blend->num_designs >
1895                                decoder->len_buildchar            )
1896                           goto Unexpected_OtherSubr;
1897 
1898                         ft_memcpy( &decoder->buildchar[idx],
1899                                    blend->weight_vector,
1900                                    blend->num_designs *
1901                                    sizeof ( blend->weight_vector[0] ) );
1902                       }
1903                       break;
1904 
1905                     case 20:
1906                       /* <arg1> <arg2> 2 20 callothersubr pop   */
1907                       /* ==> push <arg1> + <arg2> onto T1 stack */
1908                       {
1909                         CF2_F16Dot16  summand1;
1910                         CF2_F16Dot16  summand2;
1911 
1912 
1913                         if ( arg_cnt != 2 )
1914                           goto Unexpected_OtherSubr;
1915 
1916                         summand2 = cf2_stack_popFixed( opStack );
1917                         summand1 = cf2_stack_popFixed( opStack );
1918 
1919                         cf2_stack_pushFixed( opStack,
1920                                              ADD_INT32( summand1,
1921                                                         summand2 ) );
1922                         known_othersubr_result_cnt = 1;
1923                       }
1924                       break;
1925 
1926                     case 21:
1927                       /* <arg1> <arg2> 2 21 callothersubr pop   */
1928                       /* ==> push <arg1> - <arg2> onto T1 stack */
1929                       {
1930                         CF2_F16Dot16  minuend;
1931                         CF2_F16Dot16  subtrahend;
1932 
1933 
1934                         if ( arg_cnt != 2 )
1935                           goto Unexpected_OtherSubr;
1936 
1937                         subtrahend = cf2_stack_popFixed( opStack );
1938                         minuend    = cf2_stack_popFixed( opStack );
1939 
1940                         cf2_stack_pushFixed( opStack,
1941                                              SUB_INT32( minuend,
1942                                                         subtrahend ) );
1943                         known_othersubr_result_cnt = 1;
1944                       }
1945                       break;
1946 
1947                     case 22:
1948                       /* <arg1> <arg2> 2 22 callothersubr pop   */
1949                       /* ==> push <arg1> * <arg2> onto T1 stack */
1950                       {
1951                         CF2_F16Dot16  factor1;
1952                         CF2_F16Dot16  factor2;
1953 
1954 
1955                         if ( arg_cnt != 2 )
1956                           goto Unexpected_OtherSubr;
1957 
1958                         factor2 = cf2_stack_popFixed( opStack );
1959                         factor1 = cf2_stack_popFixed( opStack );
1960 
1961                         cf2_stack_pushFixed( opStack,
1962                                              FT_MulFix( factor1, factor2 ) );
1963                         known_othersubr_result_cnt = 1;
1964                       }
1965                       break;
1966 
1967                     case 23:
1968                       /* <arg1> <arg2> 2 23 callothersubr pop   */
1969                       /* ==> push <arg1> / <arg2> onto T1 stack */
1970                       {
1971                         CF2_F16Dot16  dividend;
1972                         CF2_F16Dot16  divisor;
1973 
1974 
1975                         if ( arg_cnt != 2 )
1976                           goto Unexpected_OtherSubr;
1977 
1978                         divisor  = cf2_stack_popFixed( opStack );
1979                         dividend = cf2_stack_popFixed( opStack );
1980 
1981                         if ( divisor == 0 )
1982                           goto Unexpected_OtherSubr;
1983 
1984                         cf2_stack_pushFixed( opStack,
1985                                              FT_DivFix( dividend,
1986                                                         divisor ) );
1987                         known_othersubr_result_cnt = 1;
1988                       }
1989                       break;
1990 
1991                     case 24:
1992                       /* <val> <idx> 2 24 callothersubr               */
1993                       /* ==> set BuildCharArray[cvi( <idx> )] = <val> */
1994                       {
1995                         CF2_Int   idx;
1996                         PS_Blend  blend = decoder->blend;
1997 
1998 
1999                         if ( arg_cnt != 2 || !blend )
2000                           goto Unexpected_OtherSubr;
2001 
2002                         idx = cf2_stack_popInt( opStack );
2003 
2004                         if ( idx < 0                                ||
2005                              (FT_UInt)idx >= decoder->len_buildchar )
2006                           goto Unexpected_OtherSubr;
2007 
2008                         decoder->buildchar[idx] =
2009                           cf2_stack_popFixed( opStack );
2010                       }
2011                       break;
2012 
2013                     case 25:
2014                       /* <idx> 1 25 callothersubr pop        */
2015                       /* ==> push BuildCharArray[cvi( idx )] */
2016                       /*     onto T1 stack                   */
2017                       {
2018                         CF2_Int   idx;
2019                         PS_Blend  blend = decoder->blend;
2020 
2021 
2022                         if ( arg_cnt != 1 || !blend )
2023                           goto Unexpected_OtherSubr;
2024 
2025                         idx = cf2_stack_popInt( opStack );
2026 
2027                         if ( idx < 0                                ||
2028                              (FT_UInt)idx >= decoder->len_buildchar )
2029                           goto Unexpected_OtherSubr;
2030 
2031                         cf2_stack_pushFixed( opStack,
2032                                              decoder->buildchar[idx] );
2033                         known_othersubr_result_cnt = 1;
2034                       }
2035                       break;
2036 
2037 #if 0
2038                     case 26:
2039                       /* <val> mark <idx>                              */
2040                       /* ==> set BuildCharArray[cvi( <idx> )] = <val>, */
2041                       /*     leave mark on T1 stack                    */
2042                       /* <val> <idx>                                   */
2043                       /* ==> set BuildCharArray[cvi( <idx> )] = <val>  */
2044                       XXX which routine has left its mark on the
2045                       XXX (PostScript) stack?;
2046                       break;
2047 #endif
2048 
2049                     case 27:
2050                       /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */
2051                       /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */
2052                       /*     otherwise push <res2>                          */
2053                       {
2054                         CF2_F16Dot16  arg1;
2055                         CF2_F16Dot16  arg2;
2056                         CF2_F16Dot16  cond1;
2057                         CF2_F16Dot16  cond2;
2058 
2059 
2060                         if ( arg_cnt != 4 )
2061                           goto Unexpected_OtherSubr;
2062 
2063                         cond2 = cf2_stack_popFixed( opStack );
2064                         cond1 = cf2_stack_popFixed( opStack );
2065                         arg2  = cf2_stack_popFixed( opStack );
2066                         arg1  = cf2_stack_popFixed( opStack );
2067 
2068                         cf2_stack_pushFixed( opStack,
2069                                              cond1 <= cond2 ? arg1 : arg2 );
2070                         known_othersubr_result_cnt = 1;
2071                       }
2072                       break;
2073 
2074                     case 28:
2075                       /* 0 28 callothersubr pop                     */
2076                       /* ==> push random value from interval [0, 1) */
2077                       /*     onto stack                             */
2078                       {
2079                         CF2_F16Dot16  r;
2080 
2081 
2082                         if ( arg_cnt != 0 )
2083                           goto Unexpected_OtherSubr;
2084 
2085                         /* only use the lower 16 bits of `random'  */
2086                         /* to generate a number in the range (0;1] */
2087                         r = (CF2_F16Dot16)
2088                               ( ( decoder->current_subfont->random & 0xFFFF ) + 1 );
2089 
2090                         decoder->current_subfont->random =
2091                           cff_random( decoder->current_subfont->random );
2092 
2093                         cf2_stack_pushFixed( opStack, r );
2094                         known_othersubr_result_cnt = 1;
2095                       }
2096                       break;
2097 
2098                     default:
2099                       if ( arg_cnt >= 0 && subr_no >= 0 )
2100                       {
2101                         FT_Int  i;
2102 
2103 
2104                         FT_ERROR((
2105                           "cf2_interpT2CharString (Type 1 mode):"
2106                           " unknown othersubr [%d %d], wish me luck\n",
2107                           arg_cnt, subr_no ));
2108 
2109                         /* store the unused args        */
2110                         /* for this unhandled OtherSubr */
2111 
2112                         if ( arg_cnt > PS_STORAGE_SIZE )
2113                           arg_cnt = PS_STORAGE_SIZE;
2114                         result_cnt = arg_cnt;
2115 
2116                         for ( i = 1; i <= arg_cnt; i++ )
2117                           results[result_cnt - i] =
2118                             cf2_stack_popFixed( opStack );
2119 
2120                         break;
2121                       }
2122                       /* fall through */
2123 
2124                     Unexpected_OtherSubr:
2125                       FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
2126                                  " invalid othersubr [%d %d]\n",
2127                                  arg_cnt, subr_no ));
2128                       lastError = FT_THROW( Invalid_Glyph_Format );
2129                       goto exit;
2130                     }
2131                   }
2132                   continue; /* do not clear the stack */
2133 
2134                 case cf2_escPOP:
2135                   if ( !font->isT1 )
2136                     FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
2137                   else
2138                   {
2139                     FT_TRACE4(( " pop" ));
2140 
2141                     if ( known_othersubr_result_cnt > 0 )
2142                     {
2143                       known_othersubr_result_cnt--;
2144                       /* ignore, we pushed the operands ourselves */
2145                       continue;
2146                     }
2147 
2148                     if ( result_cnt == 0 )
2149                     {
2150                       FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
2151                                  " no more operands for othersubr\n" ));
2152                       lastError = FT_THROW( Invalid_Glyph_Format );
2153                       goto exit;
2154                     }
2155 
2156                     result_cnt--;
2157                     cf2_stack_pushFixed( opStack, results[result_cnt] );
2158                   }
2159                   continue; /* do not clear the stack */
2160 
2161                 case cf2_escDROP:
2162                   FT_TRACE4(( " drop\n" ));
2163 
2164                   (void)cf2_stack_popFixed( opStack );
2165                   continue; /* do not clear the stack */
2166 
2167                 case cf2_escPUT:
2168                   {
2169                     CF2_F16Dot16  val;
2170                     CF2_Int       idx;
2171 
2172 
2173                     FT_TRACE4(( " put\n" ));
2174 
2175                     idx = cf2_stack_popInt( opStack );
2176                     val = cf2_stack_popFixed( opStack );
2177 
2178                     if ( idx >= 0 && idx < CF2_STORAGE_SIZE )
2179                       storage[idx] = val;
2180                   }
2181                   continue; /* do not clear the stack */
2182 
2183                 case cf2_escGET:
2184                   {
2185                     CF2_Int  idx;
2186 
2187 
2188                     FT_TRACE4(( " get\n" ));
2189 
2190                     idx = cf2_stack_popInt( opStack );
2191 
2192                     if ( idx >= 0 && idx < CF2_STORAGE_SIZE )
2193                       cf2_stack_pushFixed( opStack, storage[idx] );
2194                   }
2195                   continue; /* do not clear the stack */
2196 
2197                 case cf2_escIFELSE:
2198                   {
2199                     CF2_F16Dot16  arg1;
2200                     CF2_F16Dot16  arg2;
2201                     CF2_F16Dot16  cond1;
2202                     CF2_F16Dot16  cond2;
2203 
2204 
2205                     FT_TRACE4(( " ifelse\n" ));
2206 
2207                     cond2 = cf2_stack_popFixed( opStack );
2208                     cond1 = cf2_stack_popFixed( opStack );
2209                     arg2  = cf2_stack_popFixed( opStack );
2210                     arg1  = cf2_stack_popFixed( opStack );
2211 
2212                     cf2_stack_pushFixed( opStack,
2213                                          cond1 <= cond2 ? arg1 : arg2 );
2214                   }
2215                   continue; /* do not clear the stack */
2216 
2217                 case cf2_escRANDOM: /* in spec */
2218                   {
2219                     CF2_F16Dot16  r;
2220 
2221 
2222                     FT_TRACE4(( " random\n" ));
2223 
2224                     /* only use the lower 16 bits of `random'  */
2225                     /* to generate a number in the range (0;1] */
2226                     r = (CF2_F16Dot16)
2227                           ( ( decoder->current_subfont->random & 0xFFFF ) + 1 );
2228 
2229                     decoder->current_subfont->random =
2230                       cff_random( decoder->current_subfont->random );
2231 
2232                     cf2_stack_pushFixed( opStack, r );
2233                   }
2234                   continue; /* do not clear the stack */
2235 
2236                 case cf2_escMUL:
2237                   {
2238                     CF2_F16Dot16  factor1;
2239                     CF2_F16Dot16  factor2;
2240 
2241 
2242                     FT_TRACE4(( " mul\n" ));
2243 
2244                     factor2 = cf2_stack_popFixed( opStack );
2245                     factor1 = cf2_stack_popFixed( opStack );
2246 
2247                     cf2_stack_pushFixed( opStack,
2248                                          FT_MulFix( factor1, factor2 ) );
2249                   }
2250                   continue; /* do not clear the stack */
2251 
2252                 case cf2_escSQRT:
2253                   {
2254                     CF2_F16Dot16  arg;
2255 
2256 
2257                     FT_TRACE4(( " sqrt\n" ));
2258 
2259                     arg = cf2_stack_popFixed( opStack );
2260                     if ( arg > 0 )
2261                     {
2262                       /* use a start value that doesn't make */
2263                       /* the algorithm's addition overflow   */
2264                       FT_Fixed  root = arg < 10 ? arg : arg >> 1;
2265                       FT_Fixed  new_root;
2266 
2267 
2268                       /* Babylonian method */
2269                       for (;;)
2270                       {
2271                         new_root = ( root + FT_DivFix( arg, root ) + 1 ) >> 1;
2272                         if ( new_root == root )
2273                           break;
2274                         root = new_root;
2275                       }
2276                       arg = new_root;
2277                     }
2278                     else
2279                       arg = 0;
2280 
2281                     cf2_stack_pushFixed( opStack, arg );
2282                   }
2283                   continue; /* do not clear the stack */
2284 
2285                 case cf2_escDUP:
2286                   {
2287                     CF2_F16Dot16  arg;
2288 
2289 
2290                     FT_TRACE4(( " dup\n" ));
2291 
2292                     arg = cf2_stack_popFixed( opStack );
2293 
2294                     cf2_stack_pushFixed( opStack, arg );
2295                     cf2_stack_pushFixed( opStack, arg );
2296                   }
2297                   continue; /* do not clear the stack */
2298 
2299                 case cf2_escEXCH:
2300                   {
2301                     CF2_F16Dot16  arg1;
2302                     CF2_F16Dot16  arg2;
2303 
2304 
2305                     FT_TRACE4(( " exch\n" ));
2306 
2307                     arg2 = cf2_stack_popFixed( opStack );
2308                     arg1 = cf2_stack_popFixed( opStack );
2309 
2310                     cf2_stack_pushFixed( opStack, arg2 );
2311                     cf2_stack_pushFixed( opStack, arg1 );
2312                   }
2313                   continue; /* do not clear the stack */
2314 
2315                 case cf2_escINDEX:
2316                   {
2317                     CF2_Int   idx;
2318                     CF2_UInt  size;
2319 
2320 
2321                     FT_TRACE4(( " index\n" ));
2322 
2323                     idx  = cf2_stack_popInt( opStack );
2324                     size = cf2_stack_count( opStack );
2325 
2326                     if ( size > 0 )
2327                     {
2328                       /* for `cf2_stack_getReal',   */
2329                       /* index 0 is bottom of stack */
2330                       CF2_UInt  gr_idx;
2331 
2332 
2333                       if ( idx < 0 )
2334                         gr_idx = size - 1;
2335                       else if ( (CF2_UInt)idx >= size )
2336                         gr_idx = 0;
2337                       else
2338                         gr_idx = size - 1 - (CF2_UInt)idx;
2339 
2340                       cf2_stack_pushFixed( opStack,
2341                                            cf2_stack_getReal( opStack,
2342                                                               gr_idx ) );
2343                     }
2344                   }
2345                   continue; /* do not clear the stack */
2346 
2347                 case cf2_escROLL:
2348                   {
2349                     CF2_Int  idx;
2350                     CF2_Int  count;
2351 
2352 
2353                     FT_TRACE4(( " roll\n" ));
2354 
2355                     idx   = cf2_stack_popInt( opStack );
2356                     count = cf2_stack_popInt( opStack );
2357 
2358                     cf2_stack_roll( opStack, count, idx );
2359                   }
2360                   continue; /* do not clear the stack */
2361 
2362                 case cf2_escSETCURRENTPT:
2363                   if ( !font->isT1 )
2364                     FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
2365                   else
2366                   {
2367                     FT_TRACE4(( " setcurrentpoint" ));
2368 
2369                     if ( !initial_map_ready )
2370                       break;
2371 
2372                     /* From the T1 specification, section 6.4:            */
2373                     /*                                                    */
2374                     /*   The setcurrentpoint command is used only in      */
2375                     /*   conjunction with results from OtherSubrs         */
2376                     /*   procedures.                                      */
2377 
2378                     /* known_othersubr_result_cnt != 0 is already handled */
2379                     /* above.                                             */
2380 
2381                     /* Note, however, that both Ghostscript and Adobe     */
2382                     /* Distiller handle this situation by silently        */
2383                     /* ignoring the inappropriate `setcurrentpoint'       */
2384                     /* instruction.  So we do the same.                   */
2385 #if 0
2386 
2387                     if ( decoder->flex_state != 1 )
2388                     {
2389                       FT_ERROR(( "cf2_interpT2CharString:"
2390                                  " unexpected `setcurrentpoint'\n" ));
2391                       goto Syntax_Error;
2392                     }
2393                     else
2394                       ...
2395 #endif
2396 
2397                     curY = cf2_stack_popFixed( opStack );
2398                     curX = cf2_stack_popFixed( opStack );
2399 
2400                     decoder->flex_state = 0;
2401                   }
2402                   break;
2403 
2404                 } /* end of 2nd switch checking op2 */
2405               }
2406             }
2407           } /* end of 1st switch checking op2 */
2408         } /* case cf2_cmdESC */
2409 
2410         break;
2411 
2412       case cf2_cmdHSBW:
2413         if ( !font->isT1 )
2414           FT_TRACE4(( " unknown op (%d)\n", op1 ));
2415         else
2416         {
2417           CF2_Fixed    lsb_x;
2418           PS_Builder*  builder;
2419 
2420 
2421           FT_TRACE4(( " hsbw" ));
2422 
2423           builder = &decoder->builder;
2424 
2425           builder->advance->x = cf2_stack_popFixed( opStack );
2426           builder->advance->y = 0;
2427 
2428           lsb_x = cf2_stack_popFixed( opStack );
2429 
2430           builder->left_bearing->x = ADD_INT32( builder->left_bearing->x,
2431                                                 lsb_x );
2432 
2433           haveWidth = TRUE;
2434 
2435           /* the `metrics_only' indicates that we only want to compute */
2436           /* the glyph's metrics (lsb + advance width), not load the   */
2437           /* rest of it; so exit immediately                           */
2438           if ( builder->metrics_only )
2439             goto exit;
2440 
2441           if ( initial_map_ready )
2442             curX = ADD_INT32( curX, lsb_x );
2443         }
2444         break;
2445 
2446       case cf2_cmdENDCHAR:
2447         FT_TRACE4(( " endchar\n" ));
2448 
2449         if ( font->isT1 && !initial_map_ready )
2450         {
2451           FT_TRACE5(( "cf2_interpT2CharString (Type 1 mode): "
2452                       "Build initial hintmap, rewinding...\n" ));
2453 
2454           /* trigger initial hintmap build */
2455           cf2_glyphpath_moveTo( &glyphPath, curX, curY );
2456 
2457           initial_map_ready = TRUE;
2458 
2459           /* change hints routine - clear for rewind */
2460           cf2_arrstack_clear( &vStemHintArray );
2461           cf2_arrstack_clear( &hStemHintArray );
2462 
2463           cf2_hintmask_init( &hintMask, error );
2464           hintMask.isValid = FALSE;
2465           hintMask.isNew   = TRUE;
2466 
2467           /* rewind charstring */
2468           /* some charstrings use endchar from a final subroutine call */
2469           /* without returning, detect these and exit to the top level */
2470           /* charstring                                                */
2471           while ( charstringIndex > 0 )
2472           {
2473             FT_TRACE4(( " return (leaving level %d)\n", charstringIndex ));
2474 
2475             /* restore position in previous charstring */
2476             charstring = (CF2_Buffer)
2477                            cf2_arrstack_getPointer(
2478                              &subrStack,
2479                              (CF2_UInt)--charstringIndex );
2480           }
2481           charstring->ptr = charstring->start;
2482 
2483           break;
2484         }
2485 
2486         if ( cf2_stack_count( opStack ) == 1 ||
2487              cf2_stack_count( opStack ) == 5 )
2488         {
2489           if ( !haveWidth )
2490             *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
2491                                 nominalWidthX );
2492         }
2493 
2494         /* width is defined or default after this */
2495         haveWidth = TRUE;
2496 
2497         if ( decoder->width_only )
2498           goto exit;
2499 
2500         /* close path if still open */
2501         cf2_glyphpath_closeOpenPath( &glyphPath );
2502 
2503         /* disable seac for CFF2 and Type1        */
2504         /* (charstring ending with args on stack) */
2505         if ( !font->isCFF2 && !font->isT1 && cf2_stack_count( opStack ) > 1 )
2506         {
2507           /* must be either 4 or 5 --                       */
2508           /* this is a (deprecated) implied `seac' operator */
2509 
2510           CF2_Int        achar;
2511           CF2_Int        bchar;
2512           CF2_BufferRec  component;
2513           CF2_Fixed      dummyWidth;   /* ignore component width */
2514           FT_Error       error2;
2515 
2516 
2517           if ( doingSeac )
2518           {
2519             lastError = FT_THROW( Invalid_Glyph_Format );
2520             goto exit;      /* nested seac */
2521           }
2522 
2523           achar = cf2_stack_popInt( opStack );
2524           bchar = cf2_stack_popInt( opStack );
2525 
2526           curY = cf2_stack_popFixed( opStack );
2527           curX = cf2_stack_popFixed( opStack );
2528 
2529           error2 = cf2_getSeacComponent( decoder, achar, &component );
2530           if ( error2 )
2531           {
2532             lastError = error2;      /* pass FreeType error through */
2533             goto exit;
2534           }
2535           cf2_interpT2CharString( font,
2536                                   &component,
2537                                   callbacks,
2538                                   translation,
2539                                   TRUE,
2540                                   curX,
2541                                   curY,
2542                                   &dummyWidth );
2543           cf2_freeSeacComponent( decoder, &component );
2544 
2545           error2 = cf2_getSeacComponent( decoder, bchar, &component );
2546           if ( error2 )
2547           {
2548             lastError = error2;      /* pass FreeType error through */
2549             goto exit;
2550           }
2551           cf2_interpT2CharString( font,
2552                                   &component,
2553                                   callbacks,
2554                                   translation,
2555                                   TRUE,
2556                                   0,
2557                                   0,
2558                                   &dummyWidth );
2559           cf2_freeSeacComponent( decoder, &component );
2560         }
2561         goto exit;
2562 
2563       case cf2_cmdCNTRMASK:
2564       case cf2_cmdHINTMASK:
2565         /* the final \n in the tracing message gets added in      */
2566         /* `cf2_hintmask_read' (which also traces the mask bytes) */
2567         FT_TRACE4(( op1 == cf2_cmdCNTRMASK ? " cntrmask" : " hintmask" ));
2568 
2569         /* never add hints after the mask is computed */
2570         if ( cf2_stack_count( opStack ) > 1    &&
2571              cf2_hintmask_isValid( &hintMask ) )
2572         {
2573           FT_TRACE4(( "cf2_interpT2CharString: invalid hint mask\n" ));
2574           break;
2575         }
2576 
2577         /* if there are arguments on the stack, there this is an */
2578         /* implied cf2_cmdVSTEMHM                                */
2579         cf2_doStems( font,
2580                      opStack,
2581                      &vStemHintArray,
2582                      width,
2583                      &haveWidth,
2584                      0 );
2585 
2586         if ( decoder->width_only )
2587           goto exit;
2588 
2589         if ( op1 == cf2_cmdHINTMASK )
2590         {
2591           /* consume the hint mask bytes which follow the operator */
2592           cf2_hintmask_read( &hintMask,
2593                              charstring,
2594                              cf2_arrstack_size( &hStemHintArray ) +
2595                                cf2_arrstack_size( &vStemHintArray ) );
2596         }
2597         else
2598         {
2599           /*
2600            * Consume the counter mask bytes which follow the operator:
2601            * Build a temporary hint map, just to place and lock those
2602            * stems participating in the counter mask.  These are most
2603            * likely the dominant hstems, and are grouped together in a
2604            * few counter groups, not necessarily in correspondence
2605            * with the hint groups.  This reduces the chances of
2606            * conflicts between hstems that are initially placed in
2607            * separate hint groups and then brought together.  The
2608            * positions are copied back to `hStemHintArray', so we can
2609            * discard `counterMask' and `counterHintMap'.
2610            *
2611            */
2612           CF2_HintMapRec   counterHintMap;
2613           CF2_HintMaskRec  counterMask;
2614 
2615 
2616           cf2_hintmap_init( &counterHintMap,
2617                             font,
2618                             &glyphPath.initialHintMap,
2619                             &glyphPath.hintMoves,
2620                             scaleY );
2621           cf2_hintmask_init( &counterMask, error );
2622 
2623           cf2_hintmask_read( &counterMask,
2624                              charstring,
2625                              cf2_arrstack_size( &hStemHintArray ) +
2626                                cf2_arrstack_size( &vStemHintArray ) );
2627           cf2_hintmap_build( &counterHintMap,
2628                              &hStemHintArray,
2629                              &vStemHintArray,
2630                              &counterMask,
2631                              0,
2632                              FALSE );
2633         }
2634         break;
2635 
2636       case cf2_cmdRMOVETO:
2637         FT_TRACE4(( " rmoveto\n" ));
2638 
2639         if ( font->isT1 && !decoder->flex_state && !haveWidth )
2640           FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
2641                      " No width. Use hsbw/sbw as first op\n" ));
2642 
2643         if ( cf2_stack_count( opStack ) > 2 && !haveWidth )
2644           *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
2645                               nominalWidthX );
2646 
2647         /* width is defined or default after this */
2648         haveWidth = TRUE;
2649 
2650         if ( decoder->width_only )
2651           goto exit;
2652 
2653         curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) );
2654         curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) );
2655 
2656         if ( !decoder->flex_state )
2657           cf2_glyphpath_moveTo( &glyphPath, curX, curY );
2658 
2659         break;
2660 
2661       case cf2_cmdHMOVETO:
2662         FT_TRACE4(( " hmoveto\n" ));
2663 
2664         if ( font->isT1 && !decoder->flex_state && !haveWidth )
2665           FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
2666                      " No width. Use hsbw/sbw as first op\n" ));
2667 
2668         if ( cf2_stack_count( opStack ) > 1 && !haveWidth )
2669           *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
2670                               nominalWidthX );
2671 
2672         /* width is defined or default after this */
2673         haveWidth = TRUE;
2674 
2675         if ( decoder->width_only )
2676           goto exit;
2677 
2678         curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) );
2679 
2680         if ( !decoder->flex_state )
2681           cf2_glyphpath_moveTo( &glyphPath, curX, curY );
2682 
2683         break;
2684 
2685       case cf2_cmdRLINECURVE:
2686         {
2687           CF2_UInt  count = cf2_stack_count( opStack );
2688           CF2_UInt  idx   = 0;
2689 
2690 
2691           FT_TRACE4(( " rlinecurve\n" ));
2692 
2693           while ( idx + 6 < count )
2694           {
2695             curX = ADD_INT32( curX, cf2_stack_getReal( opStack,
2696                                                        idx + 0 ) );
2697             curY = ADD_INT32( curY, cf2_stack_getReal( opStack,
2698                                                        idx + 1 ) );
2699 
2700             cf2_glyphpath_lineTo( &glyphPath, curX, curY );
2701             idx += 2;
2702           }
2703 
2704           while ( idx < count )
2705           {
2706             CF2_Fixed  x1, y1, x2, y2, x3, y3;
2707 
2708 
2709             x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
2710             y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), curY );
2711             x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), x1 );
2712             y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y1 );
2713             x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 );
2714             y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 5 ), y2 );
2715 
2716             cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
2717 
2718             curX  = x3;
2719             curY  = y3;
2720             idx  += 6;
2721           }
2722 
2723           cf2_stack_clear( opStack );
2724         }
2725         continue; /* no need to clear stack again */
2726 
2727       case cf2_cmdVVCURVETO:
2728         {
2729           CF2_UInt  count, count1 = cf2_stack_count( opStack );
2730           CF2_UInt  idx = 0;
2731 
2732 
2733           /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */
2734           /* we enforce it by clearing the second bit           */
2735           /* (and sorting the stack indexing to suit)           */
2736           count = count1 & ~2U;
2737           idx  += count1 - count;
2738 
2739           FT_TRACE4(( " vvcurveto\n" ));
2740 
2741           while ( idx < count )
2742           {
2743             CF2_Fixed  x1, y1, x2, y2, x3, y3;
2744 
2745 
2746             if ( ( count - idx ) & 1 )
2747             {
2748               x1 = ADD_INT32( cf2_stack_getReal( opStack, idx ), curX );
2749 
2750               idx++;
2751             }
2752             else
2753               x1 = curX;
2754 
2755             y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curY );
2756             x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
2757             y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
2758             x3 = x2;
2759             y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y2 );
2760 
2761             cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
2762 
2763             curX  = x3;
2764             curY  = y3;
2765             idx  += 4;
2766           }
2767 
2768           cf2_stack_clear( opStack );
2769         }
2770         continue; /* no need to clear stack again */
2771 
2772       case cf2_cmdHHCURVETO:
2773         {
2774           CF2_UInt  count, count1 = cf2_stack_count( opStack );
2775           CF2_UInt  idx = 0;
2776 
2777 
2778           /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */
2779           /* we enforce it by clearing the second bit           */
2780           /* (and sorting the stack indexing to suit)           */
2781           count = count1 & ~2U;
2782           idx  += count1 - count;
2783 
2784           FT_TRACE4(( " hhcurveto\n" ));
2785 
2786           while ( idx < count )
2787           {
2788             CF2_Fixed  x1, y1, x2, y2, x3, y3;
2789 
2790 
2791             if ( ( count - idx ) & 1 )
2792             {
2793               y1 = ADD_INT32( cf2_stack_getReal( opStack, idx ), curY );
2794 
2795               idx++;
2796             }
2797             else
2798               y1 = curY;
2799 
2800             x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
2801             x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
2802             y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
2803             x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), x2 );
2804             y3 = y2;
2805 
2806             cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
2807 
2808             curX  = x3;
2809             curY  = y3;
2810             idx  += 4;
2811           }
2812 
2813           cf2_stack_clear( opStack );
2814         }
2815         continue; /* no need to clear stack again */
2816 
2817       case cf2_cmdVHCURVETO:
2818       case cf2_cmdHVCURVETO:
2819         {
2820           CF2_UInt  count, count1 = cf2_stack_count( opStack );
2821           CF2_UInt  idx = 0;
2822 
2823           FT_Bool  alternate = FT_BOOL( op1 == cf2_cmdHVCURVETO );
2824 
2825 
2826           /* if `cf2_stack_count' isn't of the form 8n, 8n+1, */
2827           /* 8n+4, or 8n+5, we enforce it by clearing the     */
2828           /* second bit                                       */
2829           /* (and sorting the stack indexing to suit)         */
2830           count = count1 & ~2U;
2831           idx  += count1 - count;
2832 
2833           FT_TRACE4(( alternate ? " hvcurveto\n" : " vhcurveto\n" ));
2834 
2835           while ( idx < count )
2836           {
2837             CF2_Fixed x1, x2, x3, y1, y2, y3;
2838 
2839 
2840             if ( alternate )
2841             {
2842               x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
2843               y1 = curY;
2844               x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
2845               y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
2846               y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y2 );
2847 
2848               if ( count - idx == 5 )
2849               {
2850                 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 );
2851 
2852                 idx++;
2853               }
2854               else
2855                 x3 = x2;
2856 
2857               alternate = FALSE;
2858             }
2859             else
2860             {
2861               x1 = curX;
2862               y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curY );
2863               x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
2864               y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
2865               x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), x2 );
2866 
2867               if ( count - idx == 5 )
2868               {
2869                 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), y2 );
2870 
2871                 idx++;
2872               }
2873               else
2874                 y3 = y2;
2875 
2876               alternate = TRUE;
2877             }
2878 
2879             cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
2880 
2881             curX  = x3;
2882             curY  = y3;
2883             idx  += 4;
2884           }
2885 
2886           cf2_stack_clear( opStack );
2887         }
2888         continue;     /* no need to clear stack again */
2889 
2890       case cf2_cmdEXTENDEDNMBR:
2891         {
2892           CF2_Int  v;
2893 
2894           CF2_Int  byte1 = cf2_buf_readByte( charstring );
2895           CF2_Int  byte2 = cf2_buf_readByte( charstring );
2896 
2897 
2898           v = (FT_Short)( ( byte1 << 8 ) |
2899                             byte2        );
2900 
2901           FT_TRACE4(( " %d", v ));
2902 
2903           cf2_stack_pushInt( opStack, v );
2904         }
2905         continue;
2906 
2907       default:
2908         /* numbers */
2909         {
2910           if ( /* op1 >= 32 && */ op1 <= 246 )
2911           {
2912             CF2_Int  v;
2913 
2914 
2915             v = op1 - 139;
2916 
2917             FT_TRACE4(( " %d", v ));
2918 
2919             /* -107 .. 107 */
2920             cf2_stack_pushInt( opStack, v );
2921           }
2922 
2923           else if ( /* op1 >= 247 && */ op1 <= 250 )
2924           {
2925             CF2_Int  v;
2926 
2927 
2928             v  = op1;
2929             v -= 247;
2930             v *= 256;
2931             v += cf2_buf_readByte( charstring );
2932             v += 108;
2933 
2934             FT_TRACE4(( " %d", v ));
2935 
2936             /* 108 .. 1131 */
2937             cf2_stack_pushInt( opStack, v );
2938           }
2939 
2940           else if ( /* op1 >= 251 && */ op1 <= 254 )
2941           {
2942             CF2_Int  v;
2943 
2944 
2945             v  = op1;
2946             v -= 251;
2947             v *= 256;
2948             v += cf2_buf_readByte( charstring );
2949             v  = -v - 108;
2950 
2951             FT_TRACE4(( " %d", v ));
2952 
2953             /* -1131 .. -108 */
2954             cf2_stack_pushInt( opStack, v );
2955           }
2956 
2957           else /* op1 == 255 */
2958           {
2959             CF2_Fixed  v;
2960 
2961             FT_UInt32  byte1 = (FT_UInt32)cf2_buf_readByte( charstring );
2962             FT_UInt32  byte2 = (FT_UInt32)cf2_buf_readByte( charstring );
2963             FT_UInt32  byte3 = (FT_UInt32)cf2_buf_readByte( charstring );
2964             FT_UInt32  byte4 = (FT_UInt32)cf2_buf_readByte( charstring );
2965 
2966 
2967             v = (CF2_Fixed)( ( byte1 << 24 ) |
2968                              ( byte2 << 16 ) |
2969                              ( byte3 <<  8 ) |
2970                                byte4         );
2971 
2972             /*
2973              * For Type 1:
2974              *
2975              * According to the specification, values > 32000 or < -32000
2976              * must be followed by a `div' operator to make the result be
2977              * in the range [-32000;32000].  We expect that the second
2978              * argument of `div' is not a large number.  Additionally, we
2979              * don't handle stuff like `<large1> <large2> <num> div <num>
2980              * div' or <large1> <large2> <num> div div'.  This is probably
2981              * not allowed anyway.
2982              *
2983              * <large> <num> <num>+ div is not checked but should not be
2984              * allowed as the large value remains untouched.
2985              *
2986              */
2987             if ( font->isT1 )
2988             {
2989               if ( v > 32000 || v < -32000 )
2990               {
2991                 if ( large_int )
2992                   FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
2993                              " no `div' after large integer\n" ));
2994                 else
2995                   large_int = TRUE;
2996               }
2997 
2998               FT_TRACE4(( " %d", v ));
2999 
3000               cf2_stack_pushInt( opStack, (CF2_Int)v );
3001             }
3002             else
3003             {
3004               FT_TRACE4(( " %.5fF", v / 65536.0 ));
3005 
3006               cf2_stack_pushFixed( opStack, v );
3007             }
3008           }
3009         }
3010         continue;   /* don't clear stack */
3011 
3012       } /* end of switch statement checking `op1' */
3013 
3014       cf2_stack_clear( opStack );
3015 
3016     } /* end of main interpreter loop */
3017 
3018     /* we get here if the charstring ends without cf2_cmdENDCHAR */
3019     FT_TRACE4(( "cf2_interpT2CharString:"
3020                 "  charstring ends without ENDCHAR\n" ));
3021 
3022   exit:
3023     /* check whether last error seen is also the first one */
3024     cf2_setError( error, lastError );
3025 
3026     if ( *error )
3027       FT_TRACE4(( "charstring error %d\n", *error ));
3028 
3029     /* free resources from objects we've used */
3030     cf2_glyphpath_finalize( &glyphPath );
3031     cf2_arrstack_finalize( &vStemHintArray );
3032     cf2_arrstack_finalize( &hStemHintArray );
3033     cf2_arrstack_finalize( &subrStack );
3034     cf2_stack_free( opStack );
3035 
3036     FT_TRACE4(( "\n" ));
3037 
3038     return;
3039   }
3040 
3041 
3042 /* END */
3043