1 /****************************************************************************
5 * Adobe's CFF Interpreter (body).
7 * Copyright 2007-2014 Adobe Systems Incorporated.
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.
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.
40 #include <freetype/internal/ftdebug.h>
41 #include <freetype/internal/services/svcfftl.h>
51 #include "psobjs.h" /* for cff_random */
52 #include "t1decode.h" /* for t1 seac */
55 /**************************************************************************
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.
62 #define FT_COMPONENT cf2interp
66 cf2_hintmask_init( CF2_HintMask hintmask,
71 hintmask->error = error;
75 FT_LOCAL_DEF( FT_Bool )
76 cf2_hintmask_isValid( const CF2_HintMask hintmask )
78 return hintmask->isValid;
82 FT_LOCAL_DEF( FT_Bool )
83 cf2_hintmask_isNew( const CF2_HintMask hintmask )
85 return hintmask->isNew;
90 cf2_hintmask_setNew( CF2_HintMask hintmask,
93 hintmask->isNew = val;
97 /* clients call `getMaskPtr' in order to iterate */
98 /* through hint mask */
100 FT_LOCAL_DEF( FT_Byte* )
101 cf2_hintmask_getMaskPtr( CF2_HintMask hintmask )
103 return hintmask->mask;
108 cf2_hintmask_setCounts( CF2_HintMask hintmask,
111 if ( bitCount > CF2_MAX_HINTS )
113 /* total of h and v stems must be <= 96 */
114 CF2_SET_ERROR( hintmask->error, Invalid_Glyph_Format );
118 hintmask->bitCount = bitCount;
119 hintmask->byteCount = ( hintmask->bitCount + 7 ) / 8;
121 hintmask->isValid = TRUE;
122 hintmask->isNew = TRUE;
128 /* consume the hintmask bytes from the charstring, advancing the src */
131 cf2_hintmask_read( CF2_HintMask hintmask,
132 CF2_Buffer charstring,
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;
145 /* initialize counts and isValid */
146 if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 )
149 FT_ASSERT( hintmask->byteCount > 0 );
151 FT_TRACE4(( " (maskbytes:" ));
153 /* set mask and advance interpreter's charstring pointer */
154 for ( i = 0; i < hintmask->byteCount; i++ )
156 hintmask->mask[i] = (FT_Byte)cf2_buf_readByte( charstring );
157 FT_TRACE4(( " 0x%02X", hintmask->mask[i] ));
160 FT_TRACE4(( ")\n" ));
162 /* assert any unused bits in last byte are zero unless there's a prior */
164 /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1 */
166 FT_ASSERT( ( hintmask->mask[hintmask->byteCount - 1] & mask ) == 0 ||
173 cf2_hintmask_setAll( CF2_HintMask hintmask,
177 CF2_UInt mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1;
180 /* initialize counts and isValid */
181 if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 )
184 FT_ASSERT( hintmask->byteCount > 0 );
185 FT_ASSERT( hintmask->byteCount <=
186 sizeof ( hintmask->mask ) / sizeof ( hintmask->mask[0] ) );
188 /* set mask to all ones */
189 for ( i = 0; i < hintmask->byteCount; i++ )
190 hintmask->mask[i] = 0xFF;
192 /* clear unused bits */
193 /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1 */
194 hintmask->mask[hintmask->byteCount - 1] &= ~mask;
198 /* Type2 charstring opcodes */
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 */
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 */
237 cf2_escDOTSECTION, /* 0 */
238 cf2_escVSTEM3, /* 1 T1 only */
239 cf2_escHSTEM3, /* 2 T1 only */
243 cf2_escSEAC, /* 6 T1 only */
244 cf2_escSBW, /* 7 T1 only */
245 cf2_escRESERVED_8, /* 8 */
247 cf2_escADD, /* 10 like otherADD */
248 cf2_escSUB, /* 11 like otherSUB */
250 cf2_escRESERVED_13, /* 13 */
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 */
279 /* `stemHintArray' does not change once we start drawing the outline. */
281 cf2_doStems( const CF2_Font font,
283 CF2_ArrStack stemHintArray,
286 CF2_Fixed hintOffset )
289 CF2_UInt count = cf2_stack_count( opStack );
290 FT_Bool hasWidthArg = FT_BOOL( count & 1 );
292 /* variable accumulates delta values from operand stack */
293 CF2_Fixed position = hintOffset;
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" ));
299 if ( !font->isT1 && hasWidthArg && !*haveWidth )
300 *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
301 cf2_getNominalWidthX( font->decoder ) );
303 if ( font->decoder->width_only )
306 for ( i = hasWidthArg ? 1 : 0; i < count; i += 2 )
308 /* construct a CF2_StemHint and push it onto the list */
309 CF2_StemHintRec stemhint;
313 position = ADD_INT32( position,
314 cf2_stack_getReal( opStack, i ) );
316 position = ADD_INT32( position,
317 cf2_stack_getReal( opStack, i + 1 ) );
319 stemhint.used = FALSE;
323 cf2_arrstack_push( stemHintArray, &stemhint ); /* defer error check */
326 cf2_stack_clear( opStack );
329 /* cf2_doStems must define a width (may be default) */
335 cf2_doFlex( CF2_Stack opStack,
338 CF2_GlyphPath glyphPath,
339 const FT_Bool* readFromStack,
340 FT_Bool doConditionalLastRead )
351 isHFlex = FT_BOOL( readFromStack[9] == FALSE );
352 top = isHFlex ? 9 : 10;
354 for ( i = 0; i < top; i++ )
356 vals[i + 2] = vals[i];
357 if ( readFromStack[i] )
358 vals[i + 2] = ADD_INT32( vals[i + 2], cf2_stack_getReal( opStack,
365 if ( doConditionalLastRead )
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 );
375 vals[12] = ADD_INT32( vals[10], lastVal );
381 vals[13] = ADD_INT32( vals[11], lastVal );
386 if ( readFromStack[10] )
387 vals[12] = ADD_INT32( vals[10],
388 cf2_stack_getReal( opStack, idx++ ) );
392 if ( readFromStack[11] )
393 vals[13] = ADD_INT32( vals[11],
394 cf2_stack_getReal( opStack, idx ) );
399 for ( j = 0; j < 2; j++ )
400 cf2_glyphpath_curveTo( glyphPath, vals[j * 6 + 2],
407 cf2_stack_clear( opStack );
414 /* Blend numOperands on the stack, */
415 /* store results into the first numBlends values, */
416 /* then pop remaining arguments. */
418 cf2_doBlend( const CFF_Blend blend,
425 CF2_UInt numOperands = (CF2_UInt)( numBlends * blend->lenBV );
428 base = cf2_stack_count( opStack ) - numOperands;
429 delta = base + numBlends;
431 for ( i = 0; i < numBlends; i++ )
433 const CF2_Fixed* weight = &blend->BV[1];
435 /* start with first term */
436 CF2_Fixed sum = cf2_stack_getReal( opStack, i + base );
439 for ( j = 1; j < blend->lenBV; j++ )
440 sum = ADD_INT32( sum,
441 FT_MulFix( *weight++,
442 cf2_stack_getReal( opStack,
445 /* store blended result */
446 cf2_stack_setReal( opStack, i + base, sum );
449 /* leave only `numBlends' results on stack */
450 cf2_stack_pop( opStack, numOperands - numBlends );
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'.
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.
467 * Unimplemented opcodes are ignored.
471 cf2_interpT2CharString( CF2_Font font,
473 CF2_OutlineCallbacks callbacks,
474 const FT_Vector* translation,
480 /* lastError is used for errors that are immediately tested */
481 FT_Error lastError = FT_Err_Ok;
483 /* pointer to parsed font object */
484 PS_Decoder* decoder = font->decoder;
486 FT_Error* error = &font->error;
487 FT_Memory memory = font->memory;
489 CF2_Fixed scaleY = font->innerTransform.d;
490 CF2_Fixed nominalWidthX = cf2_getNominalWidthX( decoder );
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;
497 #define PS_STORAGE_SIZE 3
498 CF2_F16Dot16 results[PS_STORAGE_SIZE]; /* for othersubr results */
499 FT_Int result_cnt = 0;
501 /* save this for hinting seac accents */
502 CF2_Fixed hintOriginY = curY;
504 CF2_Stack opStack = NULL;
506 FT_Byte op1; /* first opcode byte */
508 CF2_F16Dot16 storage[CF2_STORAGE_SIZE]; /* for `put' and `get' */
509 CF2_F16Dot16 flexStore[6]; /* for Type 1 flex */
511 /* instruction limit; 20,000,000 matches Avalon */
512 FT_UInt32 instructionLimit = 20000000UL;
514 CF2_ArrStackRec subrStack;
517 CF2_Buffer charstring = NULL;
519 CF2_Int charstringIndex = -1; /* initialize to empty */
521 /* TODO: placeholders for hint structures */
523 /* objects used for hinting */
524 CF2_ArrStackRec hStemHintArray;
525 CF2_ArrStackRec vStemHintArray;
527 CF2_HintMaskRec hintMask;
528 CF2_GlyphPathRec glyphPath;
533 FT_ZERO( &flexStore );
535 /* initialize the remaining objects */
536 cf2_arrstack_init( &subrStack,
539 sizeof ( CF2_BufferRec ) );
540 cf2_arrstack_init( &hStemHintArray,
543 sizeof ( CF2_StemHintRec ) );
544 cf2_arrstack_init( &vStemHintArray,
547 sizeof ( CF2_StemHintRec ) );
549 /* initialize CF2_StemHint arrays */
550 cf2_hintmask_init( &hintMask, error );
552 /* initialize path map to manage drawing operations */
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,
570 * Initialize state for width parsing. From the CFF Spec:
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
578 * What we implement here uses the first validly specified width, but
579 * does not detect errors for specifying more than one width.
581 * If one of the above operators occurs without explicitly specifying
582 * a width, we assume the default width.
584 * CFF2 charstrings always return the default width (0).
587 haveWidth = font->isCFF2 ? TRUE : FALSE;
588 *width = cf2_getDefaultWidthX( decoder );
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.
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 );
604 lastError = FT_THROW( Out_Of_Memory );
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 );
614 charstring = (CF2_Buffer)cf2_arrstack_getBuffer( &subrStack );
616 /* catch errors so far */
620 *charstring = *buf; /* structure copy */
621 charstringIndex = 0; /* entry is valid now */
623 /* main interpreter loop */
627 FT_ASSERT( known_othersubr_result_cnt == 0 ||
630 if ( cf2_buf_isEnd( charstring ) )
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 */
638 op1 = cf2_cmdENDCHAR; /* end of buffer for top level charstring */
642 op1 = (FT_Byte)cf2_buf_readByte( charstring );
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 ) &&
648 op1 = cf2_cmdRESERVED_0;
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 ||
660 op1 == cf2_cmdENDCHAR ||
661 op1 >= 32 /* Numbers */ ) )
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 );
671 if ( result_cnt > 0 &&
672 !( op1 == cf2_cmdCALLSUBR ||
673 op1 == cf2_cmdRETURN ||
675 op1 >= 32 /* Numbers */ ) )
677 /* all operands have been transferred by previous pops */
681 if ( large_int && !( op1 >= 32 || op1 == cf2_escDIV ) )
683 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
684 " no `div' after large integer\n" ));
690 /* check for errors once per loop */
695 if ( instructionLimit == 0 )
697 lastError = FT_THROW( Invalid_Glyph_Format );
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 ));
711 FT_TRACE4(( " vsindex\n" ));
714 break; /* clear stack & ignore */
716 if ( font->blend.usedBV )
718 /* vsindex not allowed after blend */
719 lastError = FT_THROW( Invalid_Glyph_Format );
724 FT_Int temp = cf2_stack_popInt( opStack );
728 font->vsindex = (FT_UInt)temp;
737 FT_TRACE4(( " blend\n" ));
740 break; /* clear stack & ignore */
742 /* do we have a `blend' op in a non-variant font? */
743 if ( !font->blend.font )
745 lastError = FT_THROW( Invalid_Glyph_Format );
749 /* check cached blend vector */
750 if ( font->cffload->blend_check_vector( &font->blend,
755 lastError = font->cffload->blend_build_vector( &font->blend,
764 numBlends = (FT_UInt)cf2_stack_popInt( opStack );
765 if ( numBlends > stackSize )
767 lastError = FT_THROW( Invalid_Glyph_Format );
771 cf2_doBlend( &font->blend, opStack, numBlends );
773 font->blend.usedBV = TRUE;
775 continue; /* do not clear the stack */
779 FT_TRACE4(( "%s\n", op1 == cf2_cmdHSTEMHM ? " hstemhm"
784 /* never add hints after the mask is computed */
785 /* except if in Type 1 mode (no hintmask op) */
786 if ( cf2_hintmask_isValid( &hintMask ) )
788 FT_TRACE4(( "cf2_interpT2CharString:"
789 " invalid horizontal hint mask\n" ));
794 /* add left-sidebearing correction in Type 1 mode */
800 font->isT1 ? decoder->builder.left_bearing->y
803 if ( decoder->width_only )
810 FT_TRACE4(( "%s\n", op1 == cf2_cmdVSTEMHM ? " vstemhm"
815 /* never add hints after the mask is computed */
816 /* except if in Type 1 mode (no hintmask op) */
817 if ( cf2_hintmask_isValid( &hintMask ) )
819 FT_TRACE4(( "cf2_interpT2CharString:"
820 " invalid vertical hint mask\n" ));
825 /* add left-sidebearing correction in Type 1 mode */
831 font->isT1 ? decoder->builder.left_bearing->x
834 if ( decoder->width_only )
840 FT_TRACE4(( " vmoveto\n" ));
842 if ( font->isT1 && !decoder->flex_state && !haveWidth )
843 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
844 " No width. Use hsbw/sbw as first op\n" ));
846 if ( cf2_stack_count( opStack ) > 1 && !haveWidth )
847 *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
850 /* width is defined or default after this */
853 if ( decoder->width_only )
856 curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) );
858 if ( !decoder->flex_state )
859 cf2_glyphpath_moveTo( &glyphPath, curX, curY );
866 CF2_UInt count = cf2_stack_count( opStack );
869 FT_TRACE4(( " rlineto\n" ));
871 for ( idx = 0; idx < count; idx += 2 )
873 curX = ADD_INT32( curX, cf2_stack_getReal( opStack,
875 curY = ADD_INT32( curY, cf2_stack_getReal( opStack,
878 cf2_glyphpath_lineTo( &glyphPath, curX, curY );
881 cf2_stack_clear( opStack );
883 continue; /* no need to clear stack again */
889 CF2_UInt count = cf2_stack_count( opStack );
891 FT_Bool isX = FT_BOOL( op1 == cf2_cmdHLINETO );
894 FT_TRACE4(( "%s\n", isX ? " hlineto" : " vlineto" ));
896 for ( idx = 0; idx < count; idx++ )
898 CF2_Fixed v = cf2_stack_getReal( opStack, idx );
902 curX = ADD_INT32( curX, v );
904 curY = ADD_INT32( curY, v );
908 cf2_glyphpath_lineTo( &glyphPath, curX, curY );
911 cf2_stack_clear( opStack );
915 case cf2_cmdRCURVELINE:
916 case cf2_cmdRRCURVETO:
918 CF2_UInt count = cf2_stack_count( opStack );
922 FT_TRACE4(( "%s\n", op1 == cf2_cmdRCURVELINE ? " rcurveline"
925 while ( idx + 6 <= count )
927 CF2_Fixed x1, y1, x2, y2, x3, y3;
930 x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
931 y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), curY );
932 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), x1 );
933 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y1 );
934 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 );
935 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 5 ), y2 );
937 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
944 if ( op1 == cf2_cmdRCURVELINE )
946 curX = ADD_INT32( curX, cf2_stack_getReal( opStack,
948 curY = ADD_INT32( curY, cf2_stack_getReal( opStack,
951 cf2_glyphpath_lineTo( &glyphPath, curX, curY );
954 cf2_stack_clear( opStack );
956 continue; /* no need to clear stack again */
958 case cf2_cmdCLOSEPATH:
960 FT_TRACE4(( " unknown op (%d)\n", op1 ));
963 FT_TRACE4(( " closepath\n" ));
965 /* if there is no path, `closepath' is a no-op */
966 cf2_glyphpath_closeOpenPath( &glyphPath );
972 case cf2_cmdCALLGSUBR:
973 case cf2_cmdCALLSUBR:
978 FT_TRACE4(( "%s", op1 == cf2_cmdCALLGSUBR ? " callgsubr"
981 if ( ( !font->isT1 && charstringIndex > CF2_MAX_SUBR ) ||
982 ( font->isT1 && charstringIndex > T1_MAX_SUBRS_CALLS ) )
984 /* max subr plus one for charstring */
985 lastError = FT_THROW( Invalid_Glyph_Format );
986 goto exit; /* overflow of stack */
989 /* push our current CFF charstring region on subrStack */
990 charstring = (CF2_Buffer)
991 cf2_arrstack_getPointer(
993 (size_t)charstringIndex + 1 );
995 /* set up the new CFF region and pointer */
996 subrNum = cf2_stack_popInt( opStack );
998 if ( font->isT1 && decoder->locals_hash )
1000 size_t* val = ft_hash_num_lookup( subrNum,
1001 decoder->locals_hash );
1012 case cf2_cmdCALLGSUBR:
1013 FT_TRACE4(( " (idx %d, entering level %d)\n",
1014 subrNum + decoder->globals_bias,
1015 charstringIndex + 1 ));
1017 if ( cf2_initGlobalRegionBuffer( decoder,
1021 lastError = FT_THROW( Invalid_Glyph_Format );
1022 goto exit; /* subroutine lookup or stream error */
1027 /* cf2_cmdCALLSUBR */
1028 FT_TRACE4(( " (idx %d, entering level %d)\n",
1029 subrNum + decoder->locals_bias,
1030 charstringIndex + 1 ));
1032 if ( cf2_initLocalRegionBuffer( decoder,
1036 lastError = FT_THROW( Invalid_Glyph_Format );
1037 goto exit; /* subroutine lookup or stream error */
1041 charstringIndex += 1; /* entry is valid now */
1043 continue; /* do not clear the stack */
1046 FT_TRACE4(( " return (leaving level %d)\n", charstringIndex ));
1048 if ( charstringIndex < 1 )
1050 /* Note: cannot return from top charstring */
1051 lastError = FT_THROW( Invalid_Glyph_Format );
1052 goto exit; /* underflow of stack */
1055 /* restore position in previous charstring */
1056 charstring = (CF2_Buffer)
1057 cf2_arrstack_getPointer(
1059 (CF2_UInt)--charstringIndex );
1060 continue; /* do not clear the stack */
1064 FT_Byte op2 = (FT_Byte)cf2_buf_readByte( charstring );
1067 /* first switch for 2-byte operators handles CFF2 */
1068 /* and opcodes that are reserved for both CFF and CFF2 */
1073 static const FT_Bool readFromStack[12] =
1075 TRUE /* dx1 */, FALSE /* dy1 */,
1076 TRUE /* dx2 */, TRUE /* dy2 */,
1077 TRUE /* dx3 */, FALSE /* dy3 */,
1078 TRUE /* dx4 */, FALSE /* dy4 */,
1079 TRUE /* dx5 */, FALSE /* dy5 */,
1080 TRUE /* dx6 */, FALSE /* dy6 */
1084 FT_TRACE4(( " hflex\n" ));
1086 cf2_doFlex( opStack,
1091 FALSE /* doConditionalLastRead */ );
1097 static const FT_Bool readFromStack[12] =
1099 TRUE /* dx1 */, TRUE /* dy1 */,
1100 TRUE /* dx2 */, TRUE /* dy2 */,
1101 TRUE /* dx3 */, TRUE /* dy3 */,
1102 TRUE /* dx4 */, TRUE /* dy4 */,
1103 TRUE /* dx5 */, TRUE /* dy5 */,
1104 TRUE /* dx6 */, TRUE /* dy6 */
1108 FT_TRACE4(( " flex\n" ));
1110 cf2_doFlex( opStack,
1115 FALSE /* doConditionalLastRead */ );
1117 break; /* TODO: why is this not a continue? */
1121 static const FT_Bool readFromStack[12] =
1123 TRUE /* dx1 */, TRUE /* dy1 */,
1124 TRUE /* dx2 */, TRUE /* dy2 */,
1125 TRUE /* dx3 */, FALSE /* dy3 */,
1126 TRUE /* dx4 */, FALSE /* dy4 */,
1127 TRUE /* dx5 */, TRUE /* dy5 */,
1128 TRUE /* dx6 */, FALSE /* dy6 */
1132 FT_TRACE4(( " hflex1\n" ));
1134 cf2_doFlex( opStack,
1139 FALSE /* doConditionalLastRead */ );
1145 static const FT_Bool readFromStack[12] =
1147 TRUE /* dx1 */, TRUE /* dy1 */,
1148 TRUE /* dx2 */, TRUE /* dy2 */,
1149 TRUE /* dx3 */, TRUE /* dy3 */,
1150 TRUE /* dx4 */, TRUE /* dy4 */,
1151 TRUE /* dx5 */, TRUE /* dy5 */,
1152 FALSE /* dx6 */, FALSE /* dy6 */
1156 FT_TRACE4(( " flex1\n" ));
1158 cf2_doFlex( opStack,
1163 TRUE /* doConditionalLastRead */ );
1167 /* these opcodes are always reserved */
1168 case cf2_escRESERVED_8:
1169 case cf2_escRESERVED_13:
1170 case cf2_escRESERVED_19:
1171 case cf2_escRESERVED_25:
1172 case cf2_escRESERVED_31:
1173 case cf2_escRESERVED_32:
1174 FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
1179 if ( font->isCFF2 || op2 >= cf2_escRESERVED_38 )
1180 FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
1181 else if ( font->isT1 && result_cnt > 0 && op2 != cf2_escPOP )
1183 /* all operands have been transferred by previous pops */
1188 /* second switch for 2-byte operators handles */
1189 /* CFF and Type 1 */
1193 case cf2_escDOTSECTION:
1194 /* something about `flip type of locking' -- ignore it */
1195 FT_TRACE4(( " dotsection\n" ));
1203 * x0 dx0 x1 dx1 x2 dx2 vstem3 x dx {dxa dxb}* vstem
1204 * y0 dy0 y1 dy1 y2 dy2 hstem3 y dy {dya dyb}* hstem
1205 * relative to lsb point relative to zero
1210 FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
1213 CF2_F16Dot16 v0, v1, v2;
1215 FT_Bool isV = FT_BOOL( op2 == cf2_escVSTEM3 );
1218 FT_TRACE4(( "%s\n", isV ? " vstem3"
1221 FT_ASSERT( cf2_stack_count( opStack ) == 6 );
1223 v0 = cf2_stack_getReal( opStack, 0 );
1224 v1 = cf2_stack_getReal( opStack, 2 );
1225 v2 = cf2_stack_getReal( opStack, 4 );
1229 SUB_INT32( SUB_INT32( v1, v0 ),
1230 cf2_stack_getReal( opStack, 1 ) ) );
1233 SUB_INT32( SUB_INT32( v2, v1 ),
1234 cf2_stack_getReal( opStack, 3 ) ) );
1236 /* add left-sidebearing correction */
1239 isV ? &vStemHintArray : &hStemHintArray,
1242 isV ? decoder->builder.left_bearing->x
1243 : decoder->builder.left_bearing->y );
1245 if ( decoder->width_only )
1257 FT_TRACE4(( " and\n" ));
1259 arg2 = cf2_stack_popFixed( opStack );
1260 arg1 = cf2_stack_popFixed( opStack );
1262 cf2_stack_pushInt( opStack, arg1 && arg2 );
1264 continue; /* do not clear the stack */
1272 FT_TRACE4(( " or\n" ));
1274 arg2 = cf2_stack_popFixed( opStack );
1275 arg1 = cf2_stack_popFixed( opStack );
1277 cf2_stack_pushInt( opStack, arg1 || arg2 );
1279 continue; /* do not clear the stack */
1286 FT_TRACE4(( " not\n" ));
1288 arg = cf2_stack_popFixed( opStack );
1290 cf2_stack_pushInt( opStack, !arg );
1292 continue; /* do not clear the stack */
1296 FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
1300 CF2_Int bchar_index, achar_index;
1301 FT_Vector left_bearing, advance;
1303 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1304 T1_Face face = (T1_Face)decoder->builder.face;
1306 CF2_BufferRec component;
1307 CF2_Fixed dummyWidth;
1309 CF2_Int achar = cf2_stack_popInt( opStack );
1310 CF2_Int bchar = cf2_stack_popInt( opStack );
1312 FT_Pos ady = cf2_stack_popFixed ( opStack );
1313 FT_Pos adx = cf2_stack_popFixed ( opStack );
1314 FT_Pos asb = cf2_stack_popFixed ( opStack );
1317 FT_TRACE4(( " seac\n" ));
1321 FT_ERROR(( " nested seac\n" ));
1322 lastError = FT_THROW( Invalid_Glyph_Format );
1323 goto exit; /* nested seac */
1326 if ( decoder->builder.metrics_only )
1328 FT_ERROR(( " unexpected seac\n" ));
1329 lastError = FT_THROW( Invalid_Glyph_Format );
1330 goto exit; /* unexpected seac */
1333 /* `glyph_names' is set to 0 for CID fonts which do */
1334 /* not include an encoding. How can we deal with */
1336 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1337 if ( decoder->glyph_names == 0 &&
1338 !face->root.internal->incremental_interface )
1340 if ( decoder->glyph_names == 0 )
1341 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
1344 "cf2_interpT2CharString: (Type 1 seac)"
1345 " glyph names table not available in this font\n" ));
1346 lastError = FT_THROW( Invalid_Glyph_Format );
1350 /* seac weirdness */
1351 adx += decoder->builder.left_bearing->x;
1353 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1354 if ( face->root.internal->incremental_interface )
1356 /* the caller must handle the font encoding also */
1357 bchar_index = bchar;
1358 achar_index = achar;
1363 bchar_index = t1_lookup_glyph_by_stdcharcode_ps(
1365 achar_index = t1_lookup_glyph_by_stdcharcode_ps(
1369 if ( bchar_index < 0 || achar_index < 0 )
1372 "cf2_interpT2CharString: (Type 1 seac)"
1373 " invalid seac character code arguments\n" ));
1374 lastError = FT_THROW( Invalid_Glyph_Format );
1378 /* if we are trying to load a composite glyph, */
1379 /* do not load the accent character and return */
1380 /* the array of subglyphs. */
1381 if ( decoder->builder.no_recurse )
1383 FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
1384 FT_GlyphLoader loader = glyph->internal->loader;
1388 /* reallocate subglyph array if necessary */
1389 error2 = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
1392 lastError = error2; /* pass FreeType error through */
1396 subg = loader->current.subglyphs;
1398 /* subglyph 0 = base character */
1399 subg->index = bchar_index;
1400 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
1401 FT_SUBGLYPH_FLAG_USE_MY_METRICS;
1406 /* subglyph 1 = accent character */
1407 subg->index = achar_index;
1408 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
1409 subg->arg1 = (FT_Int)FIXED_TO_INT( adx - asb );
1410 subg->arg2 = (FT_Int)FIXED_TO_INT( ady );
1412 /* set up remaining glyph fields */
1413 glyph->num_subglyphs = 2;
1414 glyph->subglyphs = loader->base.subglyphs;
1415 glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
1417 loader->current.num_subglyphs = 2;
1422 /* First load `bchar' in builder */
1423 /* now load the unscaled outline */
1425 /* prepare loader */
1426 FT_GlyphLoader_Prepare( decoder->builder.loader );
1428 error2 = cf2_getT1SeacComponent( decoder,
1429 (FT_UInt)bchar_index,
1433 lastError = error2; /* pass FreeType error through */
1437 /* save the left bearing and width of the SEAC */
1438 /* glyph as they will be erased by the next load */
1440 left_bearing = *decoder->builder.left_bearing;
1441 advance = *decoder->builder.advance;
1443 cf2_interpT2CharString( font,
1451 cf2_freeT1SeacComponent( decoder, &component );
1453 /* If the SEAC glyph doesn't have a (H)SBW of its */
1454 /* own use the values from the base glyph. */
1458 left_bearing = *decoder->builder.left_bearing;
1459 advance = *decoder->builder.advance;
1462 decoder->builder.left_bearing->x = 0;
1463 decoder->builder.left_bearing->y = 0;
1465 /* Now load `achar' on top of */
1466 /* the base outline */
1468 error2 = cf2_getT1SeacComponent( decoder,
1469 (FT_UInt)achar_index,
1473 lastError = error2; /* pass FreeType error through */
1476 cf2_interpT2CharString( font,
1484 cf2_freeT1SeacComponent( decoder, &component );
1486 /* restore the left side bearing and advance width */
1487 /* of the SEAC glyph or base character (saved above) */
1489 *decoder->builder.left_bearing = left_bearing;
1490 *decoder->builder.advance = advance;
1498 FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
1501 CF2_Fixed lsb_x, lsb_y;
1502 PS_Builder* builder;
1505 FT_TRACE4(( " sbw" ));
1507 builder = &decoder->builder;
1509 builder->advance->y = cf2_stack_popFixed( opStack );
1510 builder->advance->x = cf2_stack_popFixed( opStack );
1512 lsb_y = cf2_stack_popFixed( opStack );
1513 lsb_x = cf2_stack_popFixed( opStack );
1515 builder->left_bearing->x =
1516 ADD_INT32( builder->left_bearing->x, lsb_x );
1517 builder->left_bearing->y =
1518 ADD_INT32( builder->left_bearing->y, lsb_y );
1522 /* the `metrics_only' indicates that we only want */
1523 /* to compute the glyph's metrics (lsb + advance */
1524 /* width), not load the rest of it; so exit */
1526 if ( builder->metrics_only )
1529 if ( initial_map_ready )
1531 curX = ADD_INT32( curX, lsb_x );
1532 curY = ADD_INT32( curY, lsb_y );
1542 FT_TRACE4(( " abs\n" ));
1544 arg = cf2_stack_popFixed( opStack );
1546 if ( arg < -CF2_FIXED_MAX )
1547 cf2_stack_pushFixed( opStack, CF2_FIXED_MAX );
1549 cf2_stack_pushFixed( opStack, FT_ABS( arg ) );
1551 continue; /* do not clear the stack */
1555 CF2_F16Dot16 summand1;
1556 CF2_F16Dot16 summand2;
1559 FT_TRACE4(( " add\n" ));
1561 summand2 = cf2_stack_popFixed( opStack );
1562 summand1 = cf2_stack_popFixed( opStack );
1564 cf2_stack_pushFixed( opStack,
1565 ADD_INT32( summand1,
1568 continue; /* do not clear the stack */
1572 CF2_F16Dot16 minuend;
1573 CF2_F16Dot16 subtrahend;
1576 FT_TRACE4(( " sub\n" ));
1578 subtrahend = cf2_stack_popFixed( opStack );
1579 minuend = cf2_stack_popFixed( opStack );
1581 cf2_stack_pushFixed( opStack,
1582 SUB_INT32( minuend, subtrahend ) );
1584 continue; /* do not clear the stack */
1588 CF2_F16Dot16 dividend;
1589 CF2_F16Dot16 divisor;
1592 FT_TRACE4(( " div\n" ));
1594 if ( font->isT1 && large_int )
1596 divisor = (CF2_F16Dot16)cf2_stack_popInt( opStack );
1597 dividend = (CF2_F16Dot16)cf2_stack_popInt( opStack );
1603 divisor = cf2_stack_popFixed( opStack );
1604 dividend = cf2_stack_popFixed( opStack );
1607 cf2_stack_pushFixed( opStack,
1608 FT_DivFix( dividend, divisor ) );
1611 continue; /* do not clear the stack */
1618 FT_TRACE4(( " neg\n" ));
1620 arg = cf2_stack_popFixed( opStack );
1622 if ( arg < -CF2_FIXED_MAX )
1623 cf2_stack_pushFixed( opStack, CF2_FIXED_MAX );
1625 cf2_stack_pushFixed( opStack, -arg );
1627 continue; /* do not clear the stack */
1635 FT_TRACE4(( " eq\n" ));
1637 arg2 = cf2_stack_popFixed( opStack );
1638 arg1 = cf2_stack_popFixed( opStack );
1640 cf2_stack_pushInt( opStack, arg1 == arg2 );
1642 continue; /* do not clear the stack */
1644 case cf2_escCALLOTHERSUBR:
1646 FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
1655 FT_TRACE4(( " callothersubr\n" ));
1657 subr_no = cf2_stack_popInt( opStack );
1658 arg_cnt = cf2_stack_popInt( opStack );
1660 /********************************************************
1662 * remove all operands to callothersubr from the stack
1664 * for handled othersubrs, where we know the number of
1665 * arguments, we increase the stack by the value of
1666 * known_othersubr_result_cnt
1668 * for unhandled othersubrs the following pops adjust
1669 * the stack pointer as necessary
1672 count = cf2_stack_count( opStack );
1673 FT_ASSERT( (CF2_UInt)arg_cnt <= count );
1675 opIdx += count - (CF2_UInt)arg_cnt;
1677 known_othersubr_result_cnt = 0;
1680 /* XXX TODO: The checks to `arg_count == <whatever>' */
1681 /* might not be correct; an othersubr expects a */
1682 /* certain number of operands on the PostScript stack */
1683 /* (as opposed to the T1 stack) but it doesn't have to */
1684 /* put them there by itself; previous othersubrs might */
1685 /* have left the operands there if they were not */
1686 /* followed by an appropriate number of pops */
1688 /* On the other hand, Adobe Reader 7.0.8 for Linux */
1689 /* doesn't accept a font that contains charstrings */
1692 /* 100 200 2 20 callothersubr */
1693 /* 300 1 20 callothersubr pop */
1695 /* Perhaps this is the reason why BuildCharArray */
1700 case 0: /* end flex feature */
1702 goto Unexpected_OtherSubr;
1704 if ( initial_map_ready &&
1705 ( !decoder->flex_state ||
1706 decoder->num_flex_vectors != 7 ) )
1708 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
1709 " unexpected flex end\n" ));
1710 lastError = FT_THROW( Invalid_Glyph_Format );
1714 /* the two `results' are popped */
1715 /* by the following setcurrentpoint */
1716 cf2_stack_pushFixed( opStack, curX );
1717 cf2_stack_pushFixed( opStack, curY );
1718 known_othersubr_result_cnt = 2;
1721 case 1: /* start flex feature */
1723 goto Unexpected_OtherSubr;
1725 if ( !initial_map_ready )
1728 if ( ps_builder_check_points( &decoder->builder, 6 ) )
1731 decoder->flex_state = 1;
1732 decoder->num_flex_vectors = 0;
1735 case 2: /* add flex vectors */
1742 goto Unexpected_OtherSubr;
1744 if ( !initial_map_ready )
1747 if ( !decoder->flex_state )
1749 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
1750 " missing flex start\n" ));
1751 lastError = FT_THROW( Invalid_Glyph_Format );
1755 /* note that we should not add a point for */
1756 /* index 0; this will move our current position */
1757 /* to the flex point without adding any point */
1758 /* to the outline */
1759 idx = decoder->num_flex_vectors++;
1760 if ( idx > 0 && idx < 7 )
1762 /* in malformed fonts it is possible to have */
1763 /* other opcodes in the middle of a flex (which */
1764 /* don't increase `num_flex_vectors'); we thus */
1765 /* have to check whether we can add a point */
1767 if ( ps_builder_check_points( &decoder->builder,
1770 lastError = FT_THROW( Invalid_Glyph_Format );
1774 /* map: 1->2 2->4 3->6 4->2 5->4 6->6 */
1775 idx2 = ( idx > 3 ? idx - 3 : idx ) * 2;
1777 flexStore[idx2 - 2] = curX;
1778 flexStore[idx2 - 1] = curY;
1780 if ( idx == 3 || idx == 6 )
1781 cf2_glyphpath_curveTo( &glyphPath,
1792 case 3: /* change hints */
1794 goto Unexpected_OtherSubr;
1796 if ( initial_map_ready )
1798 /* do not clear hints if initial hintmap */
1799 /* is not ready - we need to collate all */
1800 cf2_arrstack_clear( &vStemHintArray );
1801 cf2_arrstack_clear( &hStemHintArray );
1803 cf2_hintmask_init( &hintMask, error );
1804 hintMask.isValid = FALSE;
1805 hintMask.isNew = TRUE;
1808 known_othersubr_result_cnt = 1;
1813 /* counter control hints, clear stack */
1814 cf2_stack_clear( opStack );
1821 case 18: /* multiple masters */
1823 PS_Blend blend = decoder->blend;
1824 FT_UInt num_points, nn, mm;
1832 "cf2_interpT2CharString:"
1833 " unexpected multiple masters operator\n" ));
1834 lastError = FT_THROW( Invalid_Glyph_Format );
1838 num_points = (FT_UInt)subr_no - 13 +
1840 if ( arg_cnt != (FT_Int)( num_points *
1841 blend->num_designs ) )
1844 "cf2_interpT2CharString:"
1845 " incorrect number of multiple masters arguments\n" ));
1846 lastError = FT_THROW( Invalid_Glyph_Format );
1850 /* We want to compute */
1852 /* a0*w0 + a1*w1 + ... + ak*wk */
1854 /* but we only have a0, a1-a0, a2-a0, ..., ak-a0. */
1856 /* However, given that w0 + w1 + ... + wk == 1, we */
1857 /* can rewrite it easily as */
1859 /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + ... + (ak-a0)*wk */
1861 /* where k == num_designs-1. */
1863 /* I guess that's why it's written in this `compact' */
1866 delta = opIdx + num_points;
1868 for ( nn = 0; nn < num_points; nn++ )
1870 CF2_Fixed tmp = cf2_stack_getReal( opStack,
1874 for ( mm = 1; mm < blend->num_designs; mm++ )
1875 tmp = ADD_INT32( tmp,
1877 cf2_stack_getReal( opStack,
1879 blend->weight_vector[mm] ) );
1881 cf2_stack_setReal( opStack, values++, tmp );
1883 cf2_stack_pop( opStack,
1884 (CF2_UInt)arg_cnt - num_points );
1886 known_othersubr_result_cnt = (FT_Int)num_points;
1891 /* <idx> 1 19 callothersubr */
1892 /* ==> replace elements starting from index */
1893 /* cvi( <idx> ) of BuildCharArray with */
1897 PS_Blend blend = decoder->blend;
1900 if ( arg_cnt != 1 || !blend )
1901 goto Unexpected_OtherSubr;
1903 idx = cf2_stack_popInt( opStack );
1906 (FT_UInt)idx + blend->num_designs >
1907 decoder->len_buildchar )
1908 goto Unexpected_OtherSubr;
1910 ft_memcpy( &decoder->buildchar[idx],
1911 blend->weight_vector,
1912 blend->num_designs *
1913 sizeof ( blend->weight_vector[0] ) );
1918 /* <arg1> <arg2> 2 20 callothersubr pop */
1919 /* ==> push <arg1> + <arg2> onto T1 stack */
1921 CF2_F16Dot16 summand1;
1922 CF2_F16Dot16 summand2;
1926 goto Unexpected_OtherSubr;
1928 summand2 = cf2_stack_popFixed( opStack );
1929 summand1 = cf2_stack_popFixed( opStack );
1931 cf2_stack_pushFixed( opStack,
1932 ADD_INT32( summand1,
1934 known_othersubr_result_cnt = 1;
1939 /* <arg1> <arg2> 2 21 callothersubr pop */
1940 /* ==> push <arg1> - <arg2> onto T1 stack */
1942 CF2_F16Dot16 minuend;
1943 CF2_F16Dot16 subtrahend;
1947 goto Unexpected_OtherSubr;
1949 subtrahend = cf2_stack_popFixed( opStack );
1950 minuend = cf2_stack_popFixed( opStack );
1952 cf2_stack_pushFixed( opStack,
1955 known_othersubr_result_cnt = 1;
1960 /* <arg1> <arg2> 2 22 callothersubr pop */
1961 /* ==> push <arg1> * <arg2> onto T1 stack */
1963 CF2_F16Dot16 factor1;
1964 CF2_F16Dot16 factor2;
1968 goto Unexpected_OtherSubr;
1970 factor2 = cf2_stack_popFixed( opStack );
1971 factor1 = cf2_stack_popFixed( opStack );
1973 cf2_stack_pushFixed( opStack,
1974 FT_MulFix( factor1, factor2 ) );
1975 known_othersubr_result_cnt = 1;
1980 /* <arg1> <arg2> 2 23 callothersubr pop */
1981 /* ==> push <arg1> / <arg2> onto T1 stack */
1983 CF2_F16Dot16 dividend;
1984 CF2_F16Dot16 divisor;
1988 goto Unexpected_OtherSubr;
1990 divisor = cf2_stack_popFixed( opStack );
1991 dividend = cf2_stack_popFixed( opStack );
1994 goto Unexpected_OtherSubr;
1996 cf2_stack_pushFixed( opStack,
1997 FT_DivFix( dividend,
1999 known_othersubr_result_cnt = 1;
2004 /* <val> <idx> 2 24 callothersubr */
2005 /* ==> set BuildCharArray[cvi( <idx> )] = <val> */
2008 PS_Blend blend = decoder->blend;
2011 if ( arg_cnt != 2 || !blend )
2012 goto Unexpected_OtherSubr;
2014 idx = cf2_stack_popInt( opStack );
2017 (FT_UInt)idx >= decoder->len_buildchar )
2018 goto Unexpected_OtherSubr;
2020 decoder->buildchar[idx] =
2021 cf2_stack_popFixed( opStack );
2026 /* <idx> 1 25 callothersubr pop */
2027 /* ==> push BuildCharArray[cvi( idx )] */
2031 PS_Blend blend = decoder->blend;
2034 if ( arg_cnt != 1 || !blend )
2035 goto Unexpected_OtherSubr;
2037 idx = cf2_stack_popInt( opStack );
2040 (FT_UInt)idx >= decoder->len_buildchar )
2041 goto Unexpected_OtherSubr;
2043 cf2_stack_pushFixed( opStack,
2044 decoder->buildchar[idx] );
2045 known_othersubr_result_cnt = 1;
2051 /* <val> mark <idx> */
2052 /* ==> set BuildCharArray[cvi( <idx> )] = <val>, */
2053 /* leave mark on T1 stack */
2055 /* ==> set BuildCharArray[cvi( <idx> )] = <val> */
2056 XXX which routine has left its mark on the
2057 XXX (PostScript) stack?;
2062 /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */
2063 /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */
2064 /* otherwise push <res2> */
2073 goto Unexpected_OtherSubr;
2075 cond2 = cf2_stack_popFixed( opStack );
2076 cond1 = cf2_stack_popFixed( opStack );
2077 arg2 = cf2_stack_popFixed( opStack );
2078 arg1 = cf2_stack_popFixed( opStack );
2080 cf2_stack_pushFixed( opStack,
2081 cond1 <= cond2 ? arg1 : arg2 );
2082 known_othersubr_result_cnt = 1;
2087 /* 0 28 callothersubr pop */
2088 /* ==> push random value from interval [0, 1) */
2095 goto Unexpected_OtherSubr;
2097 /* only use the lower 16 bits of `random' */
2098 /* to generate a number in the range (0;1] */
2100 ( ( decoder->current_subfont->random & 0xFFFF ) + 1 );
2102 decoder->current_subfont->random =
2103 cff_random( decoder->current_subfont->random );
2105 cf2_stack_pushFixed( opStack, r );
2106 known_othersubr_result_cnt = 1;
2111 if ( arg_cnt >= 0 && subr_no >= 0 )
2117 "cf2_interpT2CharString (Type 1 mode):"
2118 " unknown othersubr [%d %d], wish me luck\n",
2119 arg_cnt, subr_no ));
2121 /* store the unused args */
2122 /* for this unhandled OtherSubr */
2124 if ( arg_cnt > PS_STORAGE_SIZE )
2125 arg_cnt = PS_STORAGE_SIZE;
2126 result_cnt = arg_cnt;
2128 for ( i = 1; i <= arg_cnt; i++ )
2129 results[result_cnt - i] =
2130 cf2_stack_popFixed( opStack );
2136 Unexpected_OtherSubr:
2137 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
2138 " invalid othersubr [%d %d]\n",
2139 arg_cnt, subr_no ));
2140 lastError = FT_THROW( Invalid_Glyph_Format );
2144 continue; /* do not clear the stack */
2148 FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
2151 FT_TRACE4(( " pop" ));
2153 if ( known_othersubr_result_cnt > 0 )
2155 known_othersubr_result_cnt--;
2156 /* ignore, we pushed the operands ourselves */
2160 if ( result_cnt == 0 )
2162 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
2163 " no more operands for othersubr\n" ));
2164 lastError = FT_THROW( Invalid_Glyph_Format );
2169 cf2_stack_pushFixed( opStack, results[result_cnt] );
2171 continue; /* do not clear the stack */
2174 FT_TRACE4(( " drop\n" ));
2176 (void)cf2_stack_popFixed( opStack );
2177 continue; /* do not clear the stack */
2185 FT_TRACE4(( " put\n" ));
2187 idx = cf2_stack_popInt( opStack );
2188 val = cf2_stack_popFixed( opStack );
2190 if ( idx >= 0 && idx < CF2_STORAGE_SIZE )
2193 continue; /* do not clear the stack */
2200 FT_TRACE4(( " get\n" ));
2202 idx = cf2_stack_popInt( opStack );
2204 if ( idx >= 0 && idx < CF2_STORAGE_SIZE )
2205 cf2_stack_pushFixed( opStack, storage[idx] );
2207 continue; /* do not clear the stack */
2217 FT_TRACE4(( " ifelse\n" ));
2219 cond2 = cf2_stack_popFixed( opStack );
2220 cond1 = cf2_stack_popFixed( opStack );
2221 arg2 = cf2_stack_popFixed( opStack );
2222 arg1 = cf2_stack_popFixed( opStack );
2224 cf2_stack_pushFixed( opStack,
2225 cond1 <= cond2 ? arg1 : arg2 );
2227 continue; /* do not clear the stack */
2229 case cf2_escRANDOM: /* in spec */
2234 FT_TRACE4(( " random\n" ));
2236 /* only use the lower 16 bits of `random' */
2237 /* to generate a number in the range (0;1] */
2239 ( ( decoder->current_subfont->random & 0xFFFF ) + 1 );
2241 decoder->current_subfont->random =
2242 cff_random( decoder->current_subfont->random );
2244 cf2_stack_pushFixed( opStack, r );
2246 continue; /* do not clear the stack */
2250 CF2_F16Dot16 factor1;
2251 CF2_F16Dot16 factor2;
2254 FT_TRACE4(( " mul\n" ));
2256 factor2 = cf2_stack_popFixed( opStack );
2257 factor1 = cf2_stack_popFixed( opStack );
2259 cf2_stack_pushFixed( opStack,
2260 FT_MulFix( factor1, factor2 ) );
2262 continue; /* do not clear the stack */
2269 FT_TRACE4(( " sqrt\n" ));
2271 arg = cf2_stack_popFixed( opStack );
2274 /* use a start value that doesn't make */
2275 /* the algorithm's addition overflow */
2276 FT_Fixed root = arg < 10 ? arg : arg >> 1;
2280 /* Babylonian method */
2283 new_root = ( root + FT_DivFix( arg, root ) + 1 ) >> 1;
2284 if ( new_root == root )
2293 cf2_stack_pushFixed( opStack, arg );
2295 continue; /* do not clear the stack */
2302 FT_TRACE4(( " dup\n" ));
2304 arg = cf2_stack_popFixed( opStack );
2306 cf2_stack_pushFixed( opStack, arg );
2307 cf2_stack_pushFixed( opStack, arg );
2309 continue; /* do not clear the stack */
2317 FT_TRACE4(( " exch\n" ));
2319 arg2 = cf2_stack_popFixed( opStack );
2320 arg1 = cf2_stack_popFixed( opStack );
2322 cf2_stack_pushFixed( opStack, arg2 );
2323 cf2_stack_pushFixed( opStack, arg1 );
2325 continue; /* do not clear the stack */
2333 FT_TRACE4(( " index\n" ));
2335 idx = cf2_stack_popInt( opStack );
2336 size = cf2_stack_count( opStack );
2340 /* for `cf2_stack_getReal', */
2341 /* index 0 is bottom of stack */
2347 else if ( (CF2_UInt)idx >= size )
2350 gr_idx = size - 1 - (CF2_UInt)idx;
2352 cf2_stack_pushFixed( opStack,
2353 cf2_stack_getReal( opStack,
2357 continue; /* do not clear the stack */
2365 FT_TRACE4(( " roll\n" ));
2367 idx = cf2_stack_popInt( opStack );
2368 count = cf2_stack_popInt( opStack );
2370 cf2_stack_roll( opStack, count, idx );
2372 continue; /* do not clear the stack */
2374 case cf2_escSETCURRENTPT:
2376 FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
2379 FT_TRACE4(( " setcurrentpoint" ));
2381 if ( !initial_map_ready )
2384 /* From the T1 specification, section 6.4: */
2386 /* The setcurrentpoint command is used only in */
2387 /* conjunction with results from OtherSubrs */
2390 /* known_othersubr_result_cnt != 0 is already handled */
2393 /* Note, however, that both Ghostscript and Adobe */
2394 /* Distiller handle this situation by silently */
2395 /* ignoring the inappropriate `setcurrentpoint' */
2396 /* instruction. So we do the same. */
2399 if ( decoder->flex_state != 1 )
2401 FT_ERROR(( "cf2_interpT2CharString:"
2402 " unexpected `setcurrentpoint'\n" ));
2409 curY = cf2_stack_popFixed( opStack );
2410 curX = cf2_stack_popFixed( opStack );
2412 decoder->flex_state = 0;
2416 } /* end of 2nd switch checking op2 */
2419 } /* end of 1st switch checking op2 */
2420 } /* case cf2_cmdESC */
2426 FT_TRACE4(( " unknown op (%d)\n", op1 ));
2430 PS_Builder* builder;
2433 FT_TRACE4(( " hsbw\n" ));
2435 builder = &decoder->builder;
2437 builder->advance->x = cf2_stack_popFixed( opStack );
2438 builder->advance->y = 0;
2440 lsb_x = cf2_stack_popFixed( opStack );
2442 builder->left_bearing->x = ADD_INT32( builder->left_bearing->x,
2447 /* the `metrics_only' indicates that we only want to compute */
2448 /* the glyph's metrics (lsb + advance width), not load the */
2449 /* rest of it; so exit immediately */
2450 if ( builder->metrics_only )
2453 if ( initial_map_ready )
2454 curX = ADD_INT32( curX, lsb_x );
2458 case cf2_cmdENDCHAR:
2459 FT_TRACE4(( " endchar\n" ));
2461 if ( font->isT1 && !initial_map_ready )
2463 FT_TRACE5(( "cf2_interpT2CharString (Type 1 mode): "
2464 "Build initial hintmap, rewinding...\n" ));
2466 /* trigger initial hintmap build */
2467 cf2_glyphpath_moveTo( &glyphPath, curX, curY );
2469 initial_map_ready = TRUE;
2471 /* change hints routine - clear for rewind */
2472 cf2_arrstack_clear( &vStemHintArray );
2473 cf2_arrstack_clear( &hStemHintArray );
2475 cf2_hintmask_init( &hintMask, error );
2476 hintMask.isValid = FALSE;
2477 hintMask.isNew = TRUE;
2479 /* rewind charstring */
2480 /* some charstrings use endchar from a final subroutine call */
2481 /* without returning, detect these and exit to the top level */
2483 while ( charstringIndex > 0 )
2485 FT_TRACE4(( " return (leaving level %d)\n", charstringIndex ));
2487 /* restore position in previous charstring */
2488 charstring = (CF2_Buffer)
2489 cf2_arrstack_getPointer(
2491 (CF2_UInt)--charstringIndex );
2493 charstring->ptr = charstring->start;
2498 if ( cf2_stack_count( opStack ) == 1 ||
2499 cf2_stack_count( opStack ) == 5 )
2502 *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
2506 /* width is defined or default after this */
2509 if ( decoder->width_only )
2512 /* close path if still open */
2513 cf2_glyphpath_closeOpenPath( &glyphPath );
2515 /* disable seac for CFF2 and Type1 */
2516 /* (charstring ending with args on stack) */
2517 if ( !font->isCFF2 && !font->isT1 && cf2_stack_count( opStack ) > 1 )
2519 /* must be either 4 or 5 -- */
2520 /* this is a (deprecated) implied `seac' operator */
2524 CF2_BufferRec component;
2525 CF2_Fixed dummyWidth; /* ignore component width */
2531 lastError = FT_THROW( Invalid_Glyph_Format );
2532 goto exit; /* nested seac */
2535 achar = cf2_stack_popInt( opStack );
2536 bchar = cf2_stack_popInt( opStack );
2538 curY = cf2_stack_popFixed( opStack );
2539 curX = cf2_stack_popFixed( opStack );
2541 error2 = cf2_getSeacComponent( decoder, achar, &component );
2544 lastError = error2; /* pass FreeType error through */
2547 cf2_interpT2CharString( font,
2555 cf2_freeSeacComponent( decoder, &component );
2557 error2 = cf2_getSeacComponent( decoder, bchar, &component );
2560 lastError = error2; /* pass FreeType error through */
2563 cf2_interpT2CharString( font,
2571 cf2_freeSeacComponent( decoder, &component );
2575 case cf2_cmdCNTRMASK:
2576 case cf2_cmdHINTMASK:
2577 /* the final \n in the tracing message gets added in */
2578 /* `cf2_hintmask_read' (which also traces the mask bytes) */
2579 FT_TRACE4(( "%s", op1 == cf2_cmdCNTRMASK ? " cntrmask" : " hintmask" ));
2581 /* never add hints after the mask is computed */
2582 if ( cf2_stack_count( opStack ) > 1 &&
2583 cf2_hintmask_isValid( &hintMask ) )
2585 FT_TRACE4(( "cf2_interpT2CharString: invalid hint mask\n" ));
2589 /* if there are arguments on the stack, there this is an */
2590 /* implied cf2_cmdVSTEMHM */
2598 if ( decoder->width_only )
2601 if ( op1 == cf2_cmdHINTMASK )
2603 /* consume the hint mask bytes which follow the operator */
2604 cf2_hintmask_read( &hintMask,
2606 cf2_arrstack_size( &hStemHintArray ) +
2607 cf2_arrstack_size( &vStemHintArray ) );
2612 * Consume the counter mask bytes which follow the operator:
2613 * Build a temporary hint map, just to place and lock those
2614 * stems participating in the counter mask. These are most
2615 * likely the dominant hstems, and are grouped together in a
2616 * few counter groups, not necessarily in correspondence
2617 * with the hint groups. This reduces the chances of
2618 * conflicts between hstems that are initially placed in
2619 * separate hint groups and then brought together. The
2620 * positions are copied back to `hStemHintArray', so we can
2621 * discard `counterMask' and `counterHintMap'.
2624 CF2_HintMapRec counterHintMap;
2625 CF2_HintMaskRec counterMask;
2628 cf2_hintmap_init( &counterHintMap,
2630 &glyphPath.initialHintMap,
2631 &glyphPath.hintMoves,
2633 cf2_hintmask_init( &counterMask, error );
2635 cf2_hintmask_read( &counterMask,
2637 cf2_arrstack_size( &hStemHintArray ) +
2638 cf2_arrstack_size( &vStemHintArray ) );
2639 cf2_hintmap_build( &counterHintMap,
2648 case cf2_cmdRMOVETO:
2649 FT_TRACE4(( " rmoveto\n" ));
2651 if ( font->isT1 && !decoder->flex_state && !haveWidth )
2652 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
2653 " No width. Use hsbw/sbw as first op\n" ));
2655 if ( cf2_stack_count( opStack ) > 2 && !haveWidth )
2656 *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
2659 /* width is defined or default after this */
2662 if ( decoder->width_only )
2665 curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) );
2666 curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) );
2668 if ( !decoder->flex_state )
2669 cf2_glyphpath_moveTo( &glyphPath, curX, curY );
2673 case cf2_cmdHMOVETO:
2674 FT_TRACE4(( " hmoveto\n" ));
2676 if ( font->isT1 && !decoder->flex_state && !haveWidth )
2677 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
2678 " No width. Use hsbw/sbw as first op\n" ));
2680 if ( cf2_stack_count( opStack ) > 1 && !haveWidth )
2681 *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
2684 /* width is defined or default after this */
2687 if ( decoder->width_only )
2690 curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) );
2692 if ( !decoder->flex_state )
2693 cf2_glyphpath_moveTo( &glyphPath, curX, curY );
2697 case cf2_cmdRLINECURVE:
2699 CF2_UInt count = cf2_stack_count( opStack );
2703 FT_TRACE4(( " rlinecurve\n" ));
2705 while ( idx + 6 < count )
2707 curX = ADD_INT32( curX, cf2_stack_getReal( opStack,
2709 curY = ADD_INT32( curY, cf2_stack_getReal( opStack,
2712 cf2_glyphpath_lineTo( &glyphPath, curX, curY );
2716 while ( idx < count )
2718 CF2_Fixed x1, y1, x2, y2, x3, y3;
2721 x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
2722 y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), curY );
2723 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), x1 );
2724 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y1 );
2725 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 );
2726 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 5 ), y2 );
2728 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
2735 cf2_stack_clear( opStack );
2737 continue; /* no need to clear stack again */
2739 case cf2_cmdVVCURVETO:
2741 CF2_UInt count, count1 = cf2_stack_count( opStack );
2745 /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */
2746 /* we enforce it by clearing the second bit */
2747 /* (and sorting the stack indexing to suit) */
2748 count = count1 & ~2U;
2749 idx += count1 - count;
2751 FT_TRACE4(( " vvcurveto\n" ));
2753 while ( idx < count )
2755 CF2_Fixed x1, y1, x2, y2, x3, y3;
2758 if ( ( count - idx ) & 1 )
2760 x1 = ADD_INT32( cf2_stack_getReal( opStack, idx ), curX );
2767 y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curY );
2768 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
2769 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
2771 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y2 );
2773 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
2780 cf2_stack_clear( opStack );
2782 continue; /* no need to clear stack again */
2784 case cf2_cmdHHCURVETO:
2786 CF2_UInt count, count1 = cf2_stack_count( opStack );
2790 /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */
2791 /* we enforce it by clearing the second bit */
2792 /* (and sorting the stack indexing to suit) */
2793 count = count1 & ~2U;
2794 idx += count1 - count;
2796 FT_TRACE4(( " hhcurveto\n" ));
2798 while ( idx < count )
2800 CF2_Fixed x1, y1, x2, y2, x3, y3;
2803 if ( ( count - idx ) & 1 )
2805 y1 = ADD_INT32( cf2_stack_getReal( opStack, idx ), curY );
2812 x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
2813 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
2814 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
2815 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), x2 );
2818 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
2825 cf2_stack_clear( opStack );
2827 continue; /* no need to clear stack again */
2829 case cf2_cmdVHCURVETO:
2830 case cf2_cmdHVCURVETO:
2832 CF2_UInt count, count1 = cf2_stack_count( opStack );
2835 FT_Bool alternate = FT_BOOL( op1 == cf2_cmdHVCURVETO );
2838 /* if `cf2_stack_count' isn't of the form 8n, 8n+1, */
2839 /* 8n+4, or 8n+5, we enforce it by clearing the */
2841 /* (and sorting the stack indexing to suit) */
2842 count = count1 & ~2U;
2843 idx += count1 - count;
2845 FT_TRACE4(( "%s\n", alternate ? " hvcurveto" : " vhcurveto" ));
2847 while ( idx < count )
2849 CF2_Fixed x1, x2, x3, y1, y2, y3;
2854 x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
2856 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
2857 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
2858 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y2 );
2860 if ( count - idx == 5 )
2862 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 );
2874 y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curY );
2875 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
2876 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
2877 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), x2 );
2879 if ( count - idx == 5 )
2881 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), y2 );
2891 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
2898 cf2_stack_clear( opStack );
2900 continue; /* no need to clear stack again */
2902 case cf2_cmdEXTENDEDNMBR:
2906 CF2_Int byte1 = cf2_buf_readByte( charstring );
2907 CF2_Int byte2 = cf2_buf_readByte( charstring );
2910 v = (FT_Short)( ( byte1 << 8 ) |
2913 FT_TRACE4(( " %d", v ));
2915 cf2_stack_pushInt( opStack, v );
2922 if ( /* op1 >= 32 && */ op1 <= 246 )
2929 FT_TRACE4(( " %d", v ));
2932 cf2_stack_pushInt( opStack, v );
2935 else if ( /* op1 >= 247 && */ op1 <= 250 )
2943 v += cf2_buf_readByte( charstring );
2946 FT_TRACE4(( " %d", v ));
2949 cf2_stack_pushInt( opStack, v );
2952 else if ( /* op1 >= 251 && */ op1 <= 254 )
2960 v += cf2_buf_readByte( charstring );
2963 FT_TRACE4(( " %d", v ));
2966 cf2_stack_pushInt( opStack, v );
2969 else /* op1 == 255 */
2973 FT_UInt32 byte1 = (FT_UInt32)cf2_buf_readByte( charstring );
2974 FT_UInt32 byte2 = (FT_UInt32)cf2_buf_readByte( charstring );
2975 FT_UInt32 byte3 = (FT_UInt32)cf2_buf_readByte( charstring );
2976 FT_UInt32 byte4 = (FT_UInt32)cf2_buf_readByte( charstring );
2979 v = (CF2_Fixed)( ( byte1 << 24 ) |
2987 * According to the specification, values > 32000 or < -32000
2988 * must be followed by a `div' operator to make the result be
2989 * in the range [-32000;32000]. We expect that the second
2990 * argument of `div' is not a large number. Additionally, we
2991 * don't handle stuff like `<large1> <large2> <num> div <num>
2992 * div' or <large1> <large2> <num> div div'. This is probably
2993 * not allowed anyway.
2995 * <large> <num> <num>+ div is not checked but should not be
2996 * allowed as the large value remains untouched.
3001 if ( v > 32000 || v < -32000 )
3004 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
3005 " no `div' after large integer\n" ));
3010 FT_TRACE4(( " %d", v ));
3012 cf2_stack_pushInt( opStack, (CF2_Int)v );
3016 FT_TRACE4(( " %.5fF", v / 65536.0 ));
3018 cf2_stack_pushFixed( opStack, v );
3022 continue; /* don't clear stack */
3024 } /* end of switch statement checking `op1' */
3026 cf2_stack_clear( opStack );
3028 } /* end of main interpreter loop */
3030 /* we get here if the charstring ends without cf2_cmdENDCHAR */
3031 FT_TRACE4(( "cf2_interpT2CharString:"
3032 " charstring ends without ENDCHAR\n" ));
3035 /* check whether last error seen is also the first one */
3036 cf2_setError( error, lastError );
3039 FT_TRACE4(( "charstring error %d\n", *error ));
3041 /* free resources from objects we've used */
3042 cf2_glyphpath_finalize( &glyphPath );
3043 cf2_arrstack_finalize( &vStemHintArray );
3044 cf2_arrstack_finalize( &hStemHintArray );
3045 cf2_arrstack_finalize( &subrStack );
3046 cf2_stack_free( opStack );
3048 FT_TRACE4(( "\n" ));