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. */
36 /***************************************************************************/
40 #include FT_INTERNAL_DEBUG_H
41 #include FT_SERVICE_CFF_TABLE_LOAD_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 trace_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
);
615 *charstring
= *buf
; /* structure copy */
617 charstringIndex
= 0; /* entry is valid now */
619 /* catch errors so far */
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 cf2_stack_clear( opStack
);
670 if ( result_cnt
> 0 &&
671 !( op1
== cf2_cmdCALLSUBR
||
672 op1
== cf2_cmdRETURN
||
674 op1
>= 32 /* Numbers */ ) )
676 /* all operands have been transferred by previous pops */
680 if ( large_int
&& !( op1
>= 32 || op1
== cf2_escDIV
) )
682 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
683 " no `div' after large integer\n" ));
689 /* check for errors once per loop */
694 if ( instructionLimit
== 0 )
696 lastError
= FT_THROW( Invalid_Glyph_Format
);
702 case cf2_cmdRESERVED_0
:
703 case cf2_cmdRESERVED_2
:
704 case cf2_cmdRESERVED_17
:
705 /* we may get here if we have a prior error */
706 FT_TRACE4(( " unknown op (%d)\n", op1
));
710 FT_TRACE4(( " vsindex\n" ));
713 break; /* clear stack & ignore */
715 if ( font
->blend
.usedBV
)
717 /* vsindex not allowed after blend */
718 lastError
= FT_THROW( Invalid_Glyph_Format
);
723 FT_Int temp
= cf2_stack_popInt( opStack
);
727 font
->vsindex
= (FT_UInt
)temp
;
736 FT_TRACE4(( " blend\n" ));
739 break; /* clear stack & ignore */
741 /* do we have a `blend' op in a non-variant font? */
742 if ( !font
->blend
.font
)
744 lastError
= FT_THROW( Invalid_Glyph_Format
);
748 /* check cached blend vector */
749 if ( font
->cffload
->blend_check_vector( &font
->blend
,
754 lastError
= font
->cffload
->blend_build_vector( &font
->blend
,
763 numBlends
= (FT_UInt
)cf2_stack_popInt( opStack
);
764 if ( numBlends
> stackSize
)
766 lastError
= FT_THROW( Invalid_Glyph_Format
);
770 cf2_doBlend( &font
->blend
, opStack
, numBlends
);
772 font
->blend
.usedBV
= TRUE
;
774 continue; /* do not clear the stack */
778 FT_TRACE4(( op1
== cf2_cmdHSTEMHM
? " hstemhm\n" : " hstem\n" ));
782 /* never add hints after the mask is computed */
783 /* except if in Type 1 mode (no hintmask op) */
784 if ( cf2_hintmask_isValid( &hintMask
) )
786 FT_TRACE4(( "cf2_interpT2CharString:"
787 " invalid horizontal hint mask\n" ));
792 /* add left-sidebearing correction in Type 1 mode */
798 font
->isT1
? decoder
->builder
.left_bearing
->y
801 if ( decoder
->width_only
)
808 FT_TRACE4(( op1
== cf2_cmdVSTEMHM
? " vstemhm\n" : " vstem\n" ));
812 /* never add hints after the mask is computed */
813 /* except if in Type 1 mode (no hintmask op) */
814 if ( cf2_hintmask_isValid( &hintMask
) )
816 FT_TRACE4(( "cf2_interpT2CharString:"
817 " invalid vertical hint mask\n" ));
822 /* add left-sidebearing correction in Type 1 mode */
828 font
->isT1
? decoder
->builder
.left_bearing
->x
831 if ( decoder
->width_only
)
837 FT_TRACE4(( " vmoveto\n" ));
839 if ( font
->isT1
&& !decoder
->flex_state
&& !haveWidth
)
840 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
841 " No width. Use hsbw/sbw as first op\n" ));
843 if ( cf2_stack_count( opStack
) > 1 && !haveWidth
)
844 *width
= ADD_INT32( cf2_stack_getReal( opStack
, 0 ),
847 /* width is defined or default after this */
850 if ( decoder
->width_only
)
853 curY
= ADD_INT32( curY
, cf2_stack_popFixed( opStack
) );
855 cf2_glyphpath_moveTo( &glyphPath
, curX
, curY
);
862 CF2_UInt count
= cf2_stack_count( opStack
);
865 FT_TRACE4(( " rlineto\n" ));
867 for ( idx
= 0; idx
< count
; idx
+= 2 )
869 curX
= ADD_INT32( curX
, cf2_stack_getReal( opStack
,
871 curY
= ADD_INT32( curY
, cf2_stack_getReal( opStack
,
874 cf2_glyphpath_lineTo( &glyphPath
, curX
, curY
);
877 cf2_stack_clear( opStack
);
879 continue; /* no need to clear stack again */
885 CF2_UInt count
= cf2_stack_count( opStack
);
887 FT_Bool isX
= FT_BOOL( op1
== cf2_cmdHLINETO
);
890 FT_TRACE4(( isX
? " hlineto\n" : " vlineto\n" ));
892 for ( idx
= 0; idx
< count
; idx
++ )
894 CF2_Fixed v
= cf2_stack_getReal( opStack
, idx
);
898 curX
= ADD_INT32( curX
, v
);
900 curY
= ADD_INT32( curY
, v
);
904 cf2_glyphpath_lineTo( &glyphPath
, curX
, curY
);
907 cf2_stack_clear( opStack
);
911 case cf2_cmdRCURVELINE
:
912 case cf2_cmdRRCURVETO
:
914 CF2_UInt count
= cf2_stack_count( opStack
);
918 FT_TRACE4(( op1
== cf2_cmdRCURVELINE
? " rcurveline\n"
921 while ( idx
+ 6 <= count
)
923 CF2_Fixed x1
, y1
, x2
, y2
, x3
, y3
;
926 x1
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 0 ), curX
);
927 y1
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 1 ), curY
);
928 x2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 2 ), x1
);
929 y2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 3 ), y1
);
930 x3
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 4 ), x2
);
931 y3
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 5 ), y2
);
933 cf2_glyphpath_curveTo( &glyphPath
, x1
, y1
, x2
, y2
, x3
, y3
);
940 if ( op1
== cf2_cmdRCURVELINE
)
942 curX
= ADD_INT32( curX
, cf2_stack_getReal( opStack
,
944 curY
= ADD_INT32( curY
, cf2_stack_getReal( opStack
,
947 cf2_glyphpath_lineTo( &glyphPath
, curX
, curY
);
950 cf2_stack_clear( opStack
);
952 continue; /* no need to clear stack again */
954 case cf2_cmdCLOSEPATH
:
956 FT_TRACE4(( " unknown op (%d)\n", op1
));
959 FT_TRACE4(( " closepath" ));
961 /* if there is no path, `closepath' is a no-op */
962 ps_builder_close_contour( &decoder
->builder
);
968 case cf2_cmdCALLGSUBR
:
969 case cf2_cmdCALLSUBR
:
974 FT_TRACE4(( op1
== cf2_cmdCALLGSUBR
? " callgsubr"
977 if ( ( !font
->isT1
&& charstringIndex
> CF2_MAX_SUBR
) ||
978 ( font
->isT1
&& charstringIndex
> T1_MAX_SUBRS_CALLS
) )
980 /* max subr plus one for charstring */
981 lastError
= FT_THROW( Invalid_Glyph_Format
);
982 goto exit
; /* overflow of stack */
985 /* push our current CFF charstring region on subrStack */
986 charstring
= (CF2_Buffer
)
987 cf2_arrstack_getPointer(
989 (size_t)charstringIndex
+ 1 );
991 /* set up the new CFF region and pointer */
992 subrNum
= cf2_stack_popInt( opStack
);
994 if ( font
->isT1
&& decoder
->locals_hash
)
996 size_t* val
= ft_hash_num_lookup( subrNum
,
997 decoder
->locals_hash
);
1008 case cf2_cmdCALLGSUBR
:
1009 FT_TRACE4(( " (idx %d, entering level %d)\n",
1010 subrNum
+ decoder
->globals_bias
,
1011 charstringIndex
+ 1 ));
1013 if ( cf2_initGlobalRegionBuffer( decoder
,
1017 lastError
= FT_THROW( Invalid_Glyph_Format
);
1018 goto exit
; /* subroutine lookup or stream error */
1023 /* cf2_cmdCALLSUBR */
1024 FT_TRACE4(( " (idx %d, entering level %d)\n",
1025 subrNum
+ decoder
->locals_bias
,
1026 charstringIndex
+ 1 ));
1028 if ( cf2_initLocalRegionBuffer( decoder
,
1032 lastError
= FT_THROW( Invalid_Glyph_Format
);
1033 goto exit
; /* subroutine lookup or stream error */
1037 charstringIndex
+= 1; /* entry is valid now */
1039 continue; /* do not clear the stack */
1042 FT_TRACE4(( " return (leaving level %d)\n", charstringIndex
));
1044 if ( charstringIndex
< 1 )
1046 /* Note: cannot return from top charstring */
1047 lastError
= FT_THROW( Invalid_Glyph_Format
);
1048 goto exit
; /* underflow of stack */
1051 /* restore position in previous charstring */
1052 charstring
= (CF2_Buffer
)
1053 cf2_arrstack_getPointer(
1055 (CF2_UInt
)--charstringIndex
);
1056 continue; /* do not clear the stack */
1060 FT_Byte op2
= (FT_Byte
)cf2_buf_readByte( charstring
);
1063 /* first switch for 2-byte operators handles CFF2 */
1064 /* and opcodes that are reserved for both CFF and CFF2 */
1069 static const FT_Bool readFromStack
[12] =
1071 TRUE
/* dx1 */, FALSE
/* dy1 */,
1072 TRUE
/* dx2 */, TRUE
/* dy2 */,
1073 TRUE
/* dx3 */, FALSE
/* dy3 */,
1074 TRUE
/* dx4 */, FALSE
/* dy4 */,
1075 TRUE
/* dx5 */, FALSE
/* dy5 */,
1076 TRUE
/* dx6 */, FALSE
/* dy6 */
1080 FT_TRACE4(( " hflex\n" ));
1082 cf2_doFlex( opStack
,
1087 FALSE
/* doConditionalLastRead */ );
1093 static const FT_Bool readFromStack
[12] =
1095 TRUE
/* dx1 */, TRUE
/* dy1 */,
1096 TRUE
/* dx2 */, TRUE
/* dy2 */,
1097 TRUE
/* dx3 */, TRUE
/* dy3 */,
1098 TRUE
/* dx4 */, TRUE
/* dy4 */,
1099 TRUE
/* dx5 */, TRUE
/* dy5 */,
1100 TRUE
/* dx6 */, TRUE
/* dy6 */
1104 FT_TRACE4(( " flex\n" ));
1106 cf2_doFlex( opStack
,
1111 FALSE
/* doConditionalLastRead */ );
1113 break; /* TODO: why is this not a continue? */
1117 static const FT_Bool readFromStack
[12] =
1119 TRUE
/* dx1 */, TRUE
/* dy1 */,
1120 TRUE
/* dx2 */, TRUE
/* dy2 */,
1121 TRUE
/* dx3 */, FALSE
/* dy3 */,
1122 TRUE
/* dx4 */, FALSE
/* dy4 */,
1123 TRUE
/* dx5 */, TRUE
/* dy5 */,
1124 TRUE
/* dx6 */, FALSE
/* dy6 */
1128 FT_TRACE4(( " hflex1\n" ));
1130 cf2_doFlex( opStack
,
1135 FALSE
/* doConditionalLastRead */ );
1141 static const FT_Bool readFromStack
[12] =
1143 TRUE
/* dx1 */, TRUE
/* dy1 */,
1144 TRUE
/* dx2 */, TRUE
/* dy2 */,
1145 TRUE
/* dx3 */, TRUE
/* dy3 */,
1146 TRUE
/* dx4 */, TRUE
/* dy4 */,
1147 TRUE
/* dx5 */, TRUE
/* dy5 */,
1148 FALSE
/* dx6 */, FALSE
/* dy6 */
1152 FT_TRACE4(( " flex1\n" ));
1154 cf2_doFlex( opStack
,
1159 TRUE
/* doConditionalLastRead */ );
1163 /* these opcodes are always reserved */
1164 case cf2_escRESERVED_8
:
1165 case cf2_escRESERVED_13
:
1166 case cf2_escRESERVED_19
:
1167 case cf2_escRESERVED_25
:
1168 case cf2_escRESERVED_31
:
1169 case cf2_escRESERVED_32
:
1170 FT_TRACE4(( " unknown op (12, %d)\n", op2
));
1175 if ( font
->isCFF2
|| op2
>= cf2_escRESERVED_38
)
1176 FT_TRACE4(( " unknown op (12, %d)\n", op2
));
1177 else if ( font
->isT1
&& result_cnt
> 0 && op2
!= cf2_escPOP
)
1179 /* all operands have been transferred by previous pops */
1184 /* second switch for 2-byte operators handles */
1185 /* CFF and Type 1 */
1189 case cf2_escDOTSECTION
:
1190 /* something about `flip type of locking' -- ignore it */
1191 FT_TRACE4(( " dotsection\n" ));
1199 * x0 dx0 x1 dx1 x2 dx2 vstem3 x dx {dxa dxb}* vstem
1200 * y0 dy0 y1 dy1 y2 dy2 hstem3 y dy {dya dyb}* hstem
1201 * relative to lsb point relative to zero
1206 FT_TRACE4(( " unknown op (12, %d)\n", op2
));
1209 CF2_F16Dot16 v0
, v1
, v2
;
1211 FT_Bool isV
= FT_BOOL( op2
== cf2_escVSTEM3
);
1214 FT_TRACE4(( isV
? " vstem3\n"
1217 FT_ASSERT( cf2_stack_count( opStack
) == 6 );
1219 v0
= cf2_stack_getReal( opStack
, 0 );
1220 v1
= cf2_stack_getReal( opStack
, 2 );
1221 v2
= cf2_stack_getReal( opStack
, 4 );
1225 SUB_INT32( SUB_INT32( v1
, v0
),
1226 cf2_stack_getReal( opStack
, 1 ) ) );
1229 SUB_INT32( SUB_INT32( v2
, v1
),
1230 cf2_stack_getReal( opStack
, 3 ) ) );
1232 /* add left-sidebearing correction */
1235 isV
? &vStemHintArray
: &hStemHintArray
,
1238 isV
? decoder
->builder
.left_bearing
->x
1239 : decoder
->builder
.left_bearing
->y
);
1241 if ( decoder
->width_only
)
1253 FT_TRACE4(( " and\n" ));
1255 arg2
= cf2_stack_popFixed( opStack
);
1256 arg1
= cf2_stack_popFixed( opStack
);
1258 cf2_stack_pushInt( opStack
, arg1
&& arg2
);
1260 continue; /* do not clear the stack */
1268 FT_TRACE4(( " or\n" ));
1270 arg2
= cf2_stack_popFixed( opStack
);
1271 arg1
= cf2_stack_popFixed( opStack
);
1273 cf2_stack_pushInt( opStack
, arg1
|| arg2
);
1275 continue; /* do not clear the stack */
1282 FT_TRACE4(( " not\n" ));
1284 arg
= cf2_stack_popFixed( opStack
);
1286 cf2_stack_pushInt( opStack
, !arg
);
1288 continue; /* do not clear the stack */
1292 FT_TRACE4(( " unknown op (12, %d)\n", op2
));
1296 CF2_Int bchar_index
, achar_index
;
1297 FT_Vector left_bearing
, advance
;
1299 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1300 T1_Face face
= (T1_Face
)decoder
->builder
.face
;
1302 CF2_BufferRec component
;
1303 CF2_Fixed dummyWidth
;
1305 CF2_Int achar
= cf2_stack_popInt( opStack
);
1306 CF2_Int bchar
= cf2_stack_popInt( opStack
);
1308 FT_Pos ady
= cf2_stack_popFixed ( opStack
);
1309 FT_Pos adx
= cf2_stack_popFixed ( opStack
);
1310 FT_Pos asb
= cf2_stack_popFixed ( opStack
);
1313 FT_TRACE4(( " seac\n" ));
1317 FT_ERROR(( " nested seac\n" ));
1318 lastError
= FT_THROW( Invalid_Glyph_Format
);
1319 goto exit
; /* nested seac */
1322 if ( decoder
->builder
.metrics_only
)
1324 FT_ERROR(( " unexpected seac\n" ));
1325 lastError
= FT_THROW( Invalid_Glyph_Format
);
1326 goto exit
; /* unexpected seac */
1329 /* `glyph_names' is set to 0 for CID fonts which do */
1330 /* not include an encoding. How can we deal with */
1332 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1333 if ( decoder
->glyph_names
== 0 &&
1334 !face
->root
.internal
->incremental_interface
)
1336 if ( decoder
->glyph_names
== 0 )
1337 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
1340 "cf2_interpT2CharString: (Type 1 seac)"
1341 " glyph names table not available in this font\n" ));
1342 lastError
= FT_THROW( Invalid_Glyph_Format
);
1346 /* seac weirdness */
1347 adx
+= decoder
->builder
.left_bearing
->x
;
1349 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1350 if ( face
->root
.internal
->incremental_interface
)
1352 /* the caller must handle the font encoding also */
1353 bchar_index
= bchar
;
1354 achar_index
= achar
;
1359 bchar_index
= t1_lookup_glyph_by_stdcharcode_ps(
1361 achar_index
= t1_lookup_glyph_by_stdcharcode_ps(
1365 if ( bchar_index
< 0 || achar_index
< 0 )
1368 "cf2_interpT2CharString: (Type 1 seac)"
1369 " invalid seac character code arguments\n" ));
1370 lastError
= FT_THROW( Invalid_Glyph_Format
);
1374 /* if we are trying to load a composite glyph, */
1375 /* do not load the accent character and return */
1376 /* the array of subglyphs. */
1377 if ( decoder
->builder
.no_recurse
)
1379 FT_GlyphSlot glyph
= (FT_GlyphSlot
)decoder
->builder
.glyph
;
1380 FT_GlyphLoader loader
= glyph
->internal
->loader
;
1384 /* reallocate subglyph array if necessary */
1385 error2
= FT_GlyphLoader_CheckSubGlyphs( loader
, 2 );
1388 lastError
= error2
; /* pass FreeType error through */
1392 subg
= loader
->current
.subglyphs
;
1394 /* subglyph 0 = base character */
1395 subg
->index
= bchar_index
;
1396 subg
->flags
= FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES
|
1397 FT_SUBGLYPH_FLAG_USE_MY_METRICS
;
1402 /* subglyph 1 = accent character */
1403 subg
->index
= achar_index
;
1404 subg
->flags
= FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES
;
1405 subg
->arg1
= (FT_Int
)FIXED_TO_INT( adx
- asb
);
1406 subg
->arg2
= (FT_Int
)FIXED_TO_INT( ady
);
1408 /* set up remaining glyph fields */
1409 glyph
->num_subglyphs
= 2;
1410 glyph
->subglyphs
= loader
->base
.subglyphs
;
1411 glyph
->format
= FT_GLYPH_FORMAT_COMPOSITE
;
1413 loader
->current
.num_subglyphs
= 2;
1418 /* First load `bchar' in builder */
1419 /* now load the unscaled outline */
1421 /* prepare loader */
1422 FT_GlyphLoader_Prepare( decoder
->builder
.loader
);
1424 error2
= cf2_getT1SeacComponent( decoder
,
1425 (FT_UInt
)bchar_index
,
1429 lastError
= error2
; /* pass FreeType error through */
1432 cf2_interpT2CharString( font
,
1440 cf2_freeT1SeacComponent( decoder
, &component
);
1442 /* save the left bearing and width of the base */
1443 /* character as they will be erased by the next load */
1445 left_bearing
= *decoder
->builder
.left_bearing
;
1446 advance
= *decoder
->builder
.advance
;
1448 decoder
->builder
.left_bearing
->x
= 0;
1449 decoder
->builder
.left_bearing
->y
= 0;
1451 /* Now load `achar' on top of */
1452 /* the base outline */
1454 error2
= cf2_getT1SeacComponent( decoder
,
1455 (FT_UInt
)achar_index
,
1459 lastError
= error2
; /* pass FreeType error through */
1462 cf2_interpT2CharString( font
,
1470 cf2_freeT1SeacComponent( decoder
, &component
);
1472 /* restore the left side bearing and */
1473 /* advance width of the base character */
1475 *decoder
->builder
.left_bearing
= left_bearing
;
1476 *decoder
->builder
.advance
= advance
;
1484 FT_TRACE4(( " unknown op (12, %d)\n", op2
));
1487 CF2_Fixed lsb_x
, lsb_y
;
1488 PS_Builder
* builder
;
1491 FT_TRACE4(( " sbw" ));
1493 builder
= &decoder
->builder
;
1495 builder
->advance
->y
= cf2_stack_popFixed( opStack
);
1496 builder
->advance
->x
= cf2_stack_popFixed( opStack
);
1498 lsb_y
= cf2_stack_popFixed( opStack
);
1499 lsb_x
= cf2_stack_popFixed( opStack
);
1501 builder
->left_bearing
->x
=
1502 ADD_INT32( builder
->left_bearing
->x
, lsb_x
);
1503 builder
->left_bearing
->y
=
1504 ADD_INT32( builder
->left_bearing
->y
, lsb_y
);
1508 /* the `metrics_only' indicates that we only want */
1509 /* to compute the glyph's metrics (lsb + advance */
1510 /* width), not load the rest of it; so exit */
1512 if ( builder
->metrics_only
)
1515 if ( initial_map_ready
)
1517 curX
= ADD_INT32( curX
, lsb_x
);
1518 curY
= ADD_INT32( curY
, lsb_y
);
1528 FT_TRACE4(( " abs\n" ));
1530 arg
= cf2_stack_popFixed( opStack
);
1532 if ( arg
< -CF2_FIXED_MAX
)
1533 cf2_stack_pushFixed( opStack
, CF2_FIXED_MAX
);
1535 cf2_stack_pushFixed( opStack
, FT_ABS( arg
) );
1537 continue; /* do not clear the stack */
1541 CF2_F16Dot16 summand1
;
1542 CF2_F16Dot16 summand2
;
1545 FT_TRACE4(( " add\n" ));
1547 summand2
= cf2_stack_popFixed( opStack
);
1548 summand1
= cf2_stack_popFixed( opStack
);
1550 cf2_stack_pushFixed( opStack
,
1551 ADD_INT32( summand1
,
1554 continue; /* do not clear the stack */
1558 CF2_F16Dot16 minuend
;
1559 CF2_F16Dot16 subtrahend
;
1562 FT_TRACE4(( " sub\n" ));
1564 subtrahend
= cf2_stack_popFixed( opStack
);
1565 minuend
= cf2_stack_popFixed( opStack
);
1567 cf2_stack_pushFixed( opStack
,
1568 SUB_INT32( minuend
, subtrahend
) );
1570 continue; /* do not clear the stack */
1574 CF2_F16Dot16 dividend
;
1575 CF2_F16Dot16 divisor
;
1578 FT_TRACE4(( " div\n" ));
1580 if ( font
->isT1
&& large_int
)
1582 divisor
= (CF2_F16Dot16
)cf2_stack_popInt( opStack
);
1583 dividend
= (CF2_F16Dot16
)cf2_stack_popInt( opStack
);
1589 divisor
= cf2_stack_popFixed( opStack
);
1590 dividend
= cf2_stack_popFixed( opStack
);
1593 cf2_stack_pushFixed( opStack
,
1594 FT_DivFix( dividend
, divisor
) );
1597 continue; /* do not clear the stack */
1604 FT_TRACE4(( " neg\n" ));
1606 arg
= cf2_stack_popFixed( opStack
);
1608 if ( arg
< -CF2_FIXED_MAX
)
1609 cf2_stack_pushFixed( opStack
, CF2_FIXED_MAX
);
1611 cf2_stack_pushFixed( opStack
, -arg
);
1613 continue; /* do not clear the stack */
1621 FT_TRACE4(( " eq\n" ));
1623 arg2
= cf2_stack_popFixed( opStack
);
1624 arg1
= cf2_stack_popFixed( opStack
);
1626 cf2_stack_pushInt( opStack
, arg1
== arg2
);
1628 continue; /* do not clear the stack */
1630 case cf2_escCALLOTHERSUBR
:
1632 FT_TRACE4(( " unknown op (12, %d)\n", op2
));
1641 FT_TRACE4(( " callothersubr\n" ));
1643 subr_no
= cf2_stack_popInt( opStack
);
1644 arg_cnt
= cf2_stack_popInt( opStack
);
1646 /*******************************************************/
1648 /* remove all operands to callothersubr from the stack */
1650 /* for handled othersubrs, where we know the number of */
1651 /* arguments, we increase the stack by the value of */
1652 /* known_othersubr_result_cnt */
1654 /* for unhandled othersubrs the following pops adjust */
1655 /* the stack pointer as necessary */
1657 count
= cf2_stack_count( opStack
);
1658 FT_ASSERT( (CF2_UInt
)arg_cnt
<= count
);
1660 opIdx
+= count
- (CF2_UInt
)arg_cnt
;
1662 known_othersubr_result_cnt
= 0;
1665 /* XXX TODO: The checks to `arg_count == <whatever>' */
1666 /* might not be correct; an othersubr expects a */
1667 /* certain number of operands on the PostScript stack */
1668 /* (as opposed to the T1 stack) but it doesn't have to */
1669 /* put them there by itself; previous othersubrs might */
1670 /* have left the operands there if they were not */
1671 /* followed by an appropriate number of pops */
1673 /* On the other hand, Adobe Reader 7.0.8 for Linux */
1674 /* doesn't accept a font that contains charstrings */
1677 /* 100 200 2 20 callothersubr */
1678 /* 300 1 20 callothersubr pop */
1680 /* Perhaps this is the reason why BuildCharArray */
1685 case 0: /* end flex feature */
1687 goto Unexpected_OtherSubr
;
1689 if ( initial_map_ready
&&
1690 ( !decoder
->flex_state
||
1691 decoder
->num_flex_vectors
!= 7 ) )
1693 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
1694 " unexpected flex end\n" ));
1695 lastError
= FT_THROW( Invalid_Glyph_Format
);
1699 /* the two `results' are popped */
1700 /* by the following setcurrentpoint */
1701 cf2_stack_pushFixed( opStack
, curX
);
1702 cf2_stack_pushFixed( opStack
, curY
);
1703 known_othersubr_result_cnt
= 2;
1706 case 1: /* start flex feature */
1708 goto Unexpected_OtherSubr
;
1710 if ( !initial_map_ready
)
1713 if ( ps_builder_check_points( &decoder
->builder
, 6 ) )
1716 decoder
->flex_state
= 1;
1717 decoder
->num_flex_vectors
= 0;
1720 case 2: /* add flex vectors */
1727 goto Unexpected_OtherSubr
;
1729 if ( !initial_map_ready
)
1732 if ( !decoder
->flex_state
)
1734 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
1735 " missing flex start\n" ));
1736 lastError
= FT_THROW( Invalid_Glyph_Format
);
1740 /* note that we should not add a point for */
1741 /* index 0; this will move our current position */
1742 /* to the flex point without adding any point */
1743 /* to the outline */
1744 idx
= decoder
->num_flex_vectors
++;
1745 if ( idx
> 0 && idx
< 7 )
1747 /* in malformed fonts it is possible to have */
1748 /* other opcodes in the middle of a flex (which */
1749 /* don't increase `num_flex_vectors'); we thus */
1750 /* have to check whether we can add a point */
1752 if ( ps_builder_check_points( &decoder
->builder
,
1755 lastError
= FT_THROW( Invalid_Glyph_Format
);
1759 /* map: 1->2 2->4 3->6 4->2 5->4 6->6 */
1760 idx2
= ( idx
> 3 ? idx
- 3 : idx
) * 2;
1762 flexStore
[idx2
- 2] = curX
;
1763 flexStore
[idx2
- 1] = curY
;
1765 if ( idx
== 3 || idx
== 6 )
1766 cf2_glyphpath_curveTo( &glyphPath
,
1777 case 3: /* change hints */
1779 goto Unexpected_OtherSubr
;
1781 if ( initial_map_ready
)
1783 /* do not clear hints if initial hintmap */
1784 /* is not ready - we need to collate all */
1785 cf2_arrstack_clear( &vStemHintArray
);
1786 cf2_arrstack_clear( &hStemHintArray
);
1788 cf2_hintmask_init( &hintMask
, error
);
1789 hintMask
.isValid
= FALSE
;
1790 hintMask
.isNew
= TRUE
;
1793 known_othersubr_result_cnt
= 1;
1798 /* counter control hints, clear stack */
1799 cf2_stack_clear( opStack
);
1806 case 18: /* multiple masters */
1808 PS_Blend blend
= decoder
->blend
;
1809 FT_UInt num_points
, nn
, mm
;
1817 "cf2_interpT2CharString:"
1818 " unexpected multiple masters operator\n" ));
1819 lastError
= FT_THROW( Invalid_Glyph_Format
);
1823 num_points
= (FT_UInt
)subr_no
- 13 +
1825 if ( arg_cnt
!= (FT_Int
)( num_points
*
1826 blend
->num_designs
) )
1829 "cf2_interpT2CharString:"
1830 " incorrect number of multiple masters arguments\n" ));
1831 lastError
= FT_THROW( Invalid_Glyph_Format
);
1835 /* We want to compute */
1837 /* a0*w0 + a1*w1 + ... + ak*wk */
1839 /* but we only have a0, a1-a0, a2-a0, ..., ak-a0. */
1841 /* However, given that w0 + w1 + ... + wk == 1, we */
1842 /* can rewrite it easily as */
1844 /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + ... + (ak-a0)*wk */
1846 /* where k == num_designs-1. */
1848 /* I guess that's why it's written in this `compact' */
1851 delta
= opIdx
+ num_points
;
1853 for ( nn
= 0; nn
< num_points
; nn
++ )
1855 CF2_Fixed tmp
= cf2_stack_getReal( opStack
,
1859 for ( mm
= 1; mm
< blend
->num_designs
; mm
++ )
1860 tmp
= ADD_INT32( tmp
,
1862 cf2_stack_getReal( opStack
,
1864 blend
->weight_vector
[mm
] ) );
1866 cf2_stack_setReal( opStack
, values
++, tmp
);
1868 cf2_stack_pop( opStack
,
1869 (CF2_UInt
)arg_cnt
- num_points
);
1871 known_othersubr_result_cnt
= (FT_Int
)num_points
;
1876 /* <idx> 1 19 callothersubr */
1877 /* ==> replace elements starting from index */
1878 /* cvi( <idx> ) of BuildCharArray with */
1882 PS_Blend blend
= decoder
->blend
;
1885 if ( arg_cnt
!= 1 || !blend
)
1886 goto Unexpected_OtherSubr
;
1888 idx
= cf2_stack_popInt( opStack
);
1891 (FT_UInt
)idx
+ blend
->num_designs
>
1892 decoder
->len_buildchar
)
1893 goto Unexpected_OtherSubr
;
1895 ft_memcpy( &decoder
->buildchar
[idx
],
1896 blend
->weight_vector
,
1897 blend
->num_designs
*
1898 sizeof ( blend
->weight_vector
[0] ) );
1903 /* <arg1> <arg2> 2 20 callothersubr pop */
1904 /* ==> push <arg1> + <arg2> onto T1 stack */
1906 CF2_F16Dot16 summand1
;
1907 CF2_F16Dot16 summand2
;
1911 goto Unexpected_OtherSubr
;
1913 summand2
= cf2_stack_popFixed( opStack
);
1914 summand1
= cf2_stack_popFixed( opStack
);
1916 cf2_stack_pushFixed( opStack
,
1917 ADD_INT32( summand1
,
1919 known_othersubr_result_cnt
= 1;
1924 /* <arg1> <arg2> 2 21 callothersubr pop */
1925 /* ==> push <arg1> - <arg2> onto T1 stack */
1927 CF2_F16Dot16 minuend
;
1928 CF2_F16Dot16 subtrahend
;
1932 goto Unexpected_OtherSubr
;
1934 subtrahend
= cf2_stack_popFixed( opStack
);
1935 minuend
= cf2_stack_popFixed( opStack
);
1937 cf2_stack_pushFixed( opStack
,
1940 known_othersubr_result_cnt
= 1;
1945 /* <arg1> <arg2> 2 22 callothersubr pop */
1946 /* ==> push <arg1> * <arg2> onto T1 stack */
1948 CF2_F16Dot16 factor1
;
1949 CF2_F16Dot16 factor2
;
1953 goto Unexpected_OtherSubr
;
1955 factor2
= cf2_stack_popFixed( opStack
);
1956 factor1
= cf2_stack_popFixed( opStack
);
1958 cf2_stack_pushFixed( opStack
,
1959 FT_MulFix( factor1
, factor2
) );
1960 known_othersubr_result_cnt
= 1;
1965 /* <arg1> <arg2> 2 23 callothersubr pop */
1966 /* ==> push <arg1> / <arg2> onto T1 stack */
1968 CF2_F16Dot16 dividend
;
1969 CF2_F16Dot16 divisor
;
1973 goto Unexpected_OtherSubr
;
1975 divisor
= cf2_stack_popFixed( opStack
);
1976 dividend
= cf2_stack_popFixed( opStack
);
1979 goto Unexpected_OtherSubr
;
1981 cf2_stack_pushFixed( opStack
,
1982 FT_DivFix( dividend
,
1984 known_othersubr_result_cnt
= 1;
1989 /* <val> <idx> 2 24 callothersubr */
1990 /* ==> set BuildCharArray[cvi( <idx> )] = <val> */
1993 PS_Blend blend
= decoder
->blend
;
1996 if ( arg_cnt
!= 2 || !blend
)
1997 goto Unexpected_OtherSubr
;
1999 idx
= cf2_stack_popInt( opStack
);
2002 (FT_UInt
)idx
>= decoder
->len_buildchar
)
2003 goto Unexpected_OtherSubr
;
2005 decoder
->buildchar
[idx
] =
2006 cf2_stack_popFixed( opStack
);
2011 /* <idx> 1 25 callothersubr pop */
2012 /* ==> push BuildCharArray[cvi( idx )] */
2016 PS_Blend blend
= decoder
->blend
;
2019 if ( arg_cnt
!= 1 || !blend
)
2020 goto Unexpected_OtherSubr
;
2022 idx
= cf2_stack_popInt( opStack
);
2025 (FT_UInt
)idx
>= decoder
->len_buildchar
)
2026 goto Unexpected_OtherSubr
;
2028 cf2_stack_pushFixed( opStack
,
2029 decoder
->buildchar
[idx
] );
2030 known_othersubr_result_cnt
= 1;
2036 /* <val> mark <idx> */
2037 /* ==> set BuildCharArray[cvi( <idx> )] = <val>, */
2038 /* leave mark on T1 stack */
2040 /* ==> set BuildCharArray[cvi( <idx> )] = <val> */
2041 XXX which routine has left its mark on the
2042 XXX (PostScript
) stack
?;
2047 /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */
2048 /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */
2049 /* otherwise push <res2> */
2058 goto Unexpected_OtherSubr
;
2060 cond2
= cf2_stack_popFixed( opStack
);
2061 cond1
= cf2_stack_popFixed( opStack
);
2062 arg2
= cf2_stack_popFixed( opStack
);
2063 arg1
= cf2_stack_popFixed( opStack
);
2065 cf2_stack_pushFixed( opStack
,
2066 cond1
<= cond2
? arg1
: arg2
);
2067 known_othersubr_result_cnt
= 1;
2072 /* 0 28 callothersubr pop */
2073 /* ==> push random value from interval [0, 1) */
2080 goto Unexpected_OtherSubr
;
2082 /* only use the lower 16 bits of `random' */
2083 /* to generate a number in the range (0;1] */
2085 ( ( decoder
->current_subfont
->random
& 0xFFFF ) + 1 );
2087 decoder
->current_subfont
->random
=
2088 cff_random( decoder
->current_subfont
->random
);
2090 cf2_stack_pushFixed( opStack
, r
);
2091 known_othersubr_result_cnt
= 1;
2096 if ( arg_cnt
>= 0 && subr_no
>= 0 )
2102 "cf2_interpT2CharString (Type 1 mode):"
2103 " unknown othersubr [%d %d], wish me luck\n",
2104 arg_cnt
, subr_no
));
2106 /* store the unused args */
2107 /* for this unhandled OtherSubr */
2109 if ( arg_cnt
> PS_STORAGE_SIZE
)
2110 arg_cnt
= PS_STORAGE_SIZE
;
2111 result_cnt
= arg_cnt
;
2113 for ( i
= 1; i
<= arg_cnt
; i
++ )
2114 results
[result_cnt
- i
] =
2115 cf2_stack_popFixed( opStack
);
2121 Unexpected_OtherSubr
:
2122 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
2123 " invalid othersubr [%d %d]\n",
2124 arg_cnt
, subr_no
));
2125 lastError
= FT_THROW( Invalid_Glyph_Format
);
2129 continue; /* do not clear the stack */
2133 FT_TRACE4(( " unknown op (12, %d)\n", op2
));
2136 FT_TRACE4(( " pop" ));
2138 if ( known_othersubr_result_cnt
> 0 )
2140 known_othersubr_result_cnt
--;
2141 /* ignore, we pushed the operands ourselves */
2145 if ( result_cnt
== 0 )
2147 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
2148 " no more operands for othersubr\n" ));
2149 lastError
= FT_THROW( Invalid_Glyph_Format
);
2154 cf2_stack_pushFixed( opStack
, results
[result_cnt
] );
2156 continue; /* do not clear the stack */
2159 FT_TRACE4(( " drop\n" ));
2161 (void)cf2_stack_popFixed( opStack
);
2162 continue; /* do not clear the stack */
2170 FT_TRACE4(( " put\n" ));
2172 idx
= cf2_stack_popInt( opStack
);
2173 val
= cf2_stack_popFixed( opStack
);
2175 if ( idx
>= 0 && idx
< CF2_STORAGE_SIZE
)
2178 continue; /* do not clear the stack */
2185 FT_TRACE4(( " get\n" ));
2187 idx
= cf2_stack_popInt( opStack
);
2189 if ( idx
>= 0 && idx
< CF2_STORAGE_SIZE
)
2190 cf2_stack_pushFixed( opStack
, storage
[idx
] );
2192 continue; /* do not clear the stack */
2202 FT_TRACE4(( " ifelse\n" ));
2204 cond2
= cf2_stack_popFixed( opStack
);
2205 cond1
= cf2_stack_popFixed( opStack
);
2206 arg2
= cf2_stack_popFixed( opStack
);
2207 arg1
= cf2_stack_popFixed( opStack
);
2209 cf2_stack_pushFixed( opStack
,
2210 cond1
<= cond2
? arg1
: arg2
);
2212 continue; /* do not clear the stack */
2214 case cf2_escRANDOM
: /* in spec */
2219 FT_TRACE4(( " random\n" ));
2221 /* only use the lower 16 bits of `random' */
2222 /* to generate a number in the range (0;1] */
2224 ( ( decoder
->current_subfont
->random
& 0xFFFF ) + 1 );
2226 decoder
->current_subfont
->random
=
2227 cff_random( decoder
->current_subfont
->random
);
2229 cf2_stack_pushFixed( opStack
, r
);
2231 continue; /* do not clear the stack */
2235 CF2_F16Dot16 factor1
;
2236 CF2_F16Dot16 factor2
;
2239 FT_TRACE4(( " mul\n" ));
2241 factor2
= cf2_stack_popFixed( opStack
);
2242 factor1
= cf2_stack_popFixed( opStack
);
2244 cf2_stack_pushFixed( opStack
,
2245 FT_MulFix( factor1
, factor2
) );
2247 continue; /* do not clear the stack */
2254 FT_TRACE4(( " sqrt\n" ));
2256 arg
= cf2_stack_popFixed( opStack
);
2259 /* use a start value that doesn't make */
2260 /* the algorithm's addition overflow */
2261 FT_Fixed root
= arg
< 10 ? arg
: arg
>> 1;
2265 /* Babylonian method */
2268 new_root
= ( root
+ FT_DivFix( arg
, root
) + 1 ) >> 1;
2269 if ( new_root
== root
)
2278 cf2_stack_pushFixed( opStack
, arg
);
2280 continue; /* do not clear the stack */
2287 FT_TRACE4(( " dup\n" ));
2289 arg
= cf2_stack_popFixed( opStack
);
2291 cf2_stack_pushFixed( opStack
, arg
);
2292 cf2_stack_pushFixed( opStack
, arg
);
2294 continue; /* do not clear the stack */
2302 FT_TRACE4(( " exch\n" ));
2304 arg2
= cf2_stack_popFixed( opStack
);
2305 arg1
= cf2_stack_popFixed( opStack
);
2307 cf2_stack_pushFixed( opStack
, arg2
);
2308 cf2_stack_pushFixed( opStack
, arg1
);
2310 continue; /* do not clear the stack */
2318 FT_TRACE4(( " index\n" ));
2320 idx
= cf2_stack_popInt( opStack
);
2321 size
= cf2_stack_count( opStack
);
2325 /* for `cf2_stack_getReal', */
2326 /* index 0 is bottom of stack */
2332 else if ( (CF2_UInt
)idx
>= size
)
2335 gr_idx
= size
- 1 - (CF2_UInt
)idx
;
2337 cf2_stack_pushFixed( opStack
,
2338 cf2_stack_getReal( opStack
,
2342 continue; /* do not clear the stack */
2350 FT_TRACE4(( " roll\n" ));
2352 idx
= cf2_stack_popInt( opStack
);
2353 count
= cf2_stack_popInt( opStack
);
2355 cf2_stack_roll( opStack
, count
, idx
);
2357 continue; /* do not clear the stack */
2359 case cf2_escSETCURRENTPT
:
2361 FT_TRACE4(( " unknown op (12, %d)\n", op2
));
2364 FT_TRACE4(( " setcurrentpoint" ));
2366 if ( !initial_map_ready
)
2369 /* From the T1 specification, section 6.4: */
2371 /* The setcurrentpoint command is used only in */
2372 /* conjunction with results from OtherSubrs */
2375 /* known_othersubr_result_cnt != 0 is already handled */
2378 /* Note, however, that both Ghostscript and Adobe */
2379 /* Distiller handle this situation by silently */
2380 /* ignoring the inappropriate `setcurrentpoint' */
2381 /* instruction. So we do the same. */
2384 if ( decoder
->flex_state
!= 1 )
2386 FT_ERROR(( "cf2_interpT2CharString:"
2387 " unexpected `setcurrentpoint'\n" ));
2394 curY
= cf2_stack_popFixed( opStack
);
2395 curX
= cf2_stack_popFixed( opStack
);
2397 decoder
->flex_state
= 0;
2401 } /* end of 2nd switch checking op2 */
2404 } /* end of 1st switch checking op2 */
2405 } /* case cf2_cmdESC */
2411 FT_TRACE4(( " unknown op (%d)\n", op1
));
2415 PS_Builder
* builder
;
2418 FT_TRACE4(( " hsbw" ));
2420 builder
= &decoder
->builder
;
2422 builder
->advance
->x
= cf2_stack_popFixed( opStack
);
2423 builder
->advance
->y
= 0;
2425 lsb_x
= cf2_stack_popFixed( opStack
);
2427 builder
->left_bearing
->x
= ADD_INT32( builder
->left_bearing
->x
,
2432 /* the `metrics_only' indicates that we only want to compute */
2433 /* the glyph's metrics (lsb + advance width), not load the */
2434 /* rest of it; so exit immediately */
2435 if ( builder
->metrics_only
)
2438 if ( initial_map_ready
)
2439 curX
= ADD_INT32( curX
, lsb_x
);
2443 case cf2_cmdENDCHAR
:
2444 FT_TRACE4(( " endchar\n" ));
2446 if ( font
->isT1
&& !initial_map_ready
)
2448 FT_TRACE5(( "cf2_interpT2CharString (Type 1 mode): "
2449 "Build initial hintmap, rewinding...\n" ));
2451 /* trigger initial hintmap build */
2452 cf2_glyphpath_moveTo( &glyphPath
, curX
, curY
);
2454 initial_map_ready
= TRUE
;
2456 /* change hints routine - clear for rewind */
2457 cf2_arrstack_clear( &vStemHintArray
);
2458 cf2_arrstack_clear( &hStemHintArray
);
2460 cf2_hintmask_init( &hintMask
, error
);
2461 hintMask
.isValid
= FALSE
;
2462 hintMask
.isNew
= TRUE
;
2464 /* rewind charstring */
2465 /* some charstrings use endchar from a final subroutine call */
2466 /* without returning, detect these and exit to the top level */
2468 while ( charstringIndex
> 0 )
2470 FT_TRACE4(( " return (leaving level %d)\n", charstringIndex
));
2472 /* restore position in previous charstring */
2473 charstring
= (CF2_Buffer
)
2474 cf2_arrstack_getPointer(
2476 (CF2_UInt
)--charstringIndex
);
2478 charstring
->ptr
= charstring
->start
;
2483 if ( cf2_stack_count( opStack
) == 1 ||
2484 cf2_stack_count( opStack
) == 5 )
2487 *width
= ADD_INT32( cf2_stack_getReal( opStack
, 0 ),
2491 /* width is defined or default after this */
2494 if ( decoder
->width_only
)
2497 /* close path if still open */
2498 cf2_glyphpath_closeOpenPath( &glyphPath
);
2500 /* disable seac for CFF2 and Type1 */
2501 /* (charstring ending with args on stack) */
2502 if ( !font
->isCFF2
&& !font
->isT1
&& cf2_stack_count( opStack
) > 1 )
2504 /* must be either 4 or 5 -- */
2505 /* this is a (deprecated) implied `seac' operator */
2509 CF2_BufferRec component
;
2510 CF2_Fixed dummyWidth
; /* ignore component width */
2516 lastError
= FT_THROW( Invalid_Glyph_Format
);
2517 goto exit
; /* nested seac */
2520 achar
= cf2_stack_popInt( opStack
);
2521 bchar
= cf2_stack_popInt( opStack
);
2523 curY
= cf2_stack_popFixed( opStack
);
2524 curX
= cf2_stack_popFixed( opStack
);
2526 error2
= cf2_getSeacComponent( decoder
, achar
, &component
);
2529 lastError
= error2
; /* pass FreeType error through */
2532 cf2_interpT2CharString( font
,
2540 cf2_freeSeacComponent( decoder
, &component
);
2542 error2
= cf2_getSeacComponent( decoder
, bchar
, &component
);
2545 lastError
= error2
; /* pass FreeType error through */
2548 cf2_interpT2CharString( font
,
2556 cf2_freeSeacComponent( decoder
, &component
);
2560 case cf2_cmdCNTRMASK
:
2561 case cf2_cmdHINTMASK
:
2562 /* the final \n in the tracing message gets added in */
2563 /* `cf2_hintmask_read' (which also traces the mask bytes) */
2564 FT_TRACE4(( op1
== cf2_cmdCNTRMASK
? " cntrmask" : " hintmask" ));
2566 /* never add hints after the mask is computed */
2567 if ( cf2_stack_count( opStack
) > 1 &&
2568 cf2_hintmask_isValid( &hintMask
) )
2570 FT_TRACE4(( "cf2_interpT2CharString: invalid hint mask\n" ));
2574 /* if there are arguments on the stack, there this is an */
2575 /* implied cf2_cmdVSTEMHM */
2583 if ( decoder
->width_only
)
2586 if ( op1
== cf2_cmdHINTMASK
)
2588 /* consume the hint mask bytes which follow the operator */
2589 cf2_hintmask_read( &hintMask
,
2591 cf2_arrstack_size( &hStemHintArray
) +
2592 cf2_arrstack_size( &vStemHintArray
) );
2597 * Consume the counter mask bytes which follow the operator:
2598 * Build a temporary hint map, just to place and lock those
2599 * stems participating in the counter mask. These are most
2600 * likely the dominant hstems, and are grouped together in a
2601 * few counter groups, not necessarily in correspondence
2602 * with the hint groups. This reduces the chances of
2603 * conflicts between hstems that are initially placed in
2604 * separate hint groups and then brought together. The
2605 * positions are copied back to `hStemHintArray', so we can
2606 * discard `counterMask' and `counterHintMap'.
2609 CF2_HintMapRec counterHintMap
;
2610 CF2_HintMaskRec counterMask
;
2613 cf2_hintmap_init( &counterHintMap
,
2615 &glyphPath
.initialHintMap
,
2616 &glyphPath
.hintMoves
,
2618 cf2_hintmask_init( &counterMask
, error
);
2620 cf2_hintmask_read( &counterMask
,
2622 cf2_arrstack_size( &hStemHintArray
) +
2623 cf2_arrstack_size( &vStemHintArray
) );
2624 cf2_hintmap_build( &counterHintMap
,
2633 case cf2_cmdRMOVETO
:
2634 FT_TRACE4(( " rmoveto\n" ));
2636 if ( font
->isT1
&& !decoder
->flex_state
&& !haveWidth
)
2637 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
2638 " No width. Use hsbw/sbw as first op\n" ));
2640 if ( cf2_stack_count( opStack
) > 2 && !haveWidth
)
2641 *width
= ADD_INT32( cf2_stack_getReal( opStack
, 0 ),
2644 /* width is defined or default after this */
2647 if ( decoder
->width_only
)
2650 curY
= ADD_INT32( curY
, cf2_stack_popFixed( opStack
) );
2651 curX
= ADD_INT32( curX
, cf2_stack_popFixed( opStack
) );
2653 if ( !decoder
->flex_state
)
2654 cf2_glyphpath_moveTo( &glyphPath
, curX
, curY
);
2658 case cf2_cmdHMOVETO
:
2659 FT_TRACE4(( " hmoveto\n" ));
2661 if ( font
->isT1
&& !decoder
->flex_state
&& !haveWidth
)
2662 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
2663 " No width. Use hsbw/sbw as first op\n" ));
2665 if ( cf2_stack_count( opStack
) > 1 && !haveWidth
)
2666 *width
= ADD_INT32( cf2_stack_getReal( opStack
, 0 ),
2669 /* width is defined or default after this */
2672 if ( decoder
->width_only
)
2675 curX
= ADD_INT32( curX
, cf2_stack_popFixed( opStack
) );
2677 cf2_glyphpath_moveTo( &glyphPath
, curX
, curY
);
2681 case cf2_cmdRLINECURVE
:
2683 CF2_UInt count
= cf2_stack_count( opStack
);
2687 FT_TRACE4(( " rlinecurve\n" ));
2689 while ( idx
+ 6 < count
)
2691 curX
= ADD_INT32( curX
, cf2_stack_getReal( opStack
,
2693 curY
= ADD_INT32( curY
, cf2_stack_getReal( opStack
,
2696 cf2_glyphpath_lineTo( &glyphPath
, curX
, curY
);
2700 while ( idx
< count
)
2702 CF2_Fixed x1
, y1
, x2
, y2
, x3
, y3
;
2705 x1
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 0 ), curX
);
2706 y1
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 1 ), curY
);
2707 x2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 2 ), x1
);
2708 y2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 3 ), y1
);
2709 x3
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 4 ), x2
);
2710 y3
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 5 ), y2
);
2712 cf2_glyphpath_curveTo( &glyphPath
, x1
, y1
, x2
, y2
, x3
, y3
);
2719 cf2_stack_clear( opStack
);
2721 continue; /* no need to clear stack again */
2723 case cf2_cmdVVCURVETO
:
2725 CF2_UInt count
, count1
= cf2_stack_count( opStack
);
2729 /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */
2730 /* we enforce it by clearing the second bit */
2731 /* (and sorting the stack indexing to suit) */
2732 count
= count1
& ~2U;
2733 idx
+= count1
- count
;
2735 FT_TRACE4(( " vvcurveto\n" ));
2737 while ( idx
< count
)
2739 CF2_Fixed x1
, y1
, x2
, y2
, x3
, y3
;
2742 if ( ( count
- idx
) & 1 )
2744 x1
= ADD_INT32( cf2_stack_getReal( opStack
, idx
), curX
);
2751 y1
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 0 ), curY
);
2752 x2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 1 ), x1
);
2753 y2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 2 ), y1
);
2755 y3
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 3 ), y2
);
2757 cf2_glyphpath_curveTo( &glyphPath
, x1
, y1
, x2
, y2
, x3
, y3
);
2764 cf2_stack_clear( opStack
);
2766 continue; /* no need to clear stack again */
2768 case cf2_cmdHHCURVETO
:
2770 CF2_UInt count
, count1
= cf2_stack_count( opStack
);
2774 /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */
2775 /* we enforce it by clearing the second bit */
2776 /* (and sorting the stack indexing to suit) */
2777 count
= count1
& ~2U;
2778 idx
+= count1
- count
;
2780 FT_TRACE4(( " hhcurveto\n" ));
2782 while ( idx
< count
)
2784 CF2_Fixed x1
, y1
, x2
, y2
, x3
, y3
;
2787 if ( ( count
- idx
) & 1 )
2789 y1
= ADD_INT32( cf2_stack_getReal( opStack
, idx
), curY
);
2796 x1
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 0 ), curX
);
2797 x2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 1 ), x1
);
2798 y2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 2 ), y1
);
2799 x3
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 3 ), x2
);
2802 cf2_glyphpath_curveTo( &glyphPath
, x1
, y1
, x2
, y2
, x3
, y3
);
2809 cf2_stack_clear( opStack
);
2811 continue; /* no need to clear stack again */
2813 case cf2_cmdVHCURVETO
:
2814 case cf2_cmdHVCURVETO
:
2816 CF2_UInt count
, count1
= cf2_stack_count( opStack
);
2819 FT_Bool alternate
= FT_BOOL( op1
== cf2_cmdHVCURVETO
);
2822 /* if `cf2_stack_count' isn't of the form 8n, 8n+1, */
2823 /* 8n+4, or 8n+5, we enforce it by clearing the */
2825 /* (and sorting the stack indexing to suit) */
2826 count
= count1
& ~2U;
2827 idx
+= count1
- count
;
2829 FT_TRACE4(( alternate
? " hvcurveto\n" : " vhcurveto\n" ));
2831 while ( idx
< count
)
2833 CF2_Fixed x1
, x2
, x3
, y1
, y2
, y3
;
2838 x1
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 0 ), curX
);
2840 x2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 1 ), x1
);
2841 y2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 2 ), y1
);
2842 y3
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 3 ), y2
);
2844 if ( count
- idx
== 5 )
2846 x3
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 4 ), x2
);
2858 y1
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 0 ), curY
);
2859 x2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 1 ), x1
);
2860 y2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 2 ), y1
);
2861 x3
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 3 ), x2
);
2863 if ( count
- idx
== 5 )
2865 y3
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 4 ), y2
);
2875 cf2_glyphpath_curveTo( &glyphPath
, x1
, y1
, x2
, y2
, x3
, y3
);
2882 cf2_stack_clear( opStack
);
2884 continue; /* no need to clear stack again */
2886 case cf2_cmdEXTENDEDNMBR
:
2890 CF2_Int byte1
= cf2_buf_readByte( charstring
);
2891 CF2_Int byte2
= cf2_buf_readByte( charstring
);
2894 v
= (FT_Short
)( ( byte1
<< 8 ) |
2897 FT_TRACE4(( " %d", v
));
2899 cf2_stack_pushInt( opStack
, v
);
2906 if ( /* op1 >= 32 && */ op1
<= 246 )
2913 FT_TRACE4(( " %d", v
));
2916 cf2_stack_pushInt( opStack
, v
);
2919 else if ( /* op1 >= 247 && */ op1
<= 250 )
2927 v
+= cf2_buf_readByte( charstring
);
2930 FT_TRACE4(( " %d", v
));
2933 cf2_stack_pushInt( opStack
, v
);
2936 else if ( /* op1 >= 251 && */ op1
<= 254 )
2944 v
+= cf2_buf_readByte( charstring
);
2947 FT_TRACE4(( " %d", v
));
2950 cf2_stack_pushInt( opStack
, v
);
2953 else /* op1 == 255 */
2957 FT_UInt32 byte1
= (FT_UInt32
)cf2_buf_readByte( charstring
);
2958 FT_UInt32 byte2
= (FT_UInt32
)cf2_buf_readByte( charstring
);
2959 FT_UInt32 byte3
= (FT_UInt32
)cf2_buf_readByte( charstring
);
2960 FT_UInt32 byte4
= (FT_UInt32
)cf2_buf_readByte( charstring
);
2963 v
= (CF2_Fixed
)( ( byte1
<< 24 ) |
2971 * According to the specification, values > 32000 or < -32000
2972 * must be followed by a `div' operator to make the result be
2973 * in the range [-32000;32000]. We expect that the second
2974 * argument of `div' is not a large number. Additionally, we
2975 * don't handle stuff like `<large1> <large2> <num> div <num>
2976 * div' or <large1> <large2> <num> div div'. This is probably
2977 * not allowed anyway.
2979 * <large> <num> <num>+ div is not checked but should not be
2980 * allowed as the large value remains untouched.
2985 if ( v
> 32000 || v
< -32000 )
2988 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
2989 " no `div' after large integer\n" ));
2994 FT_TRACE4(( " %d", v
));
2996 cf2_stack_pushInt( opStack
, (CF2_Int
)v
);
3000 FT_TRACE4(( " %.5fF", v
/ 65536.0 ));
3002 cf2_stack_pushFixed( opStack
, v
);
3006 continue; /* don't clear stack */
3008 } /* end of switch statement checking `op1' */
3010 cf2_stack_clear( opStack
);
3012 } /* end of main interpreter loop */
3014 /* we get here if the charstring ends without cf2_cmdENDCHAR */
3015 FT_TRACE4(( "cf2_interpT2CharString:"
3016 " charstring ends without ENDCHAR\n" ));
3019 /* check whether last error seen is also the first one */
3020 cf2_setError( error
, lastError
);
3023 FT_TRACE4(( "charstring error %d\n", *error
));
3025 /* free resources from objects we've used */
3026 cf2_glyphpath_finalize( &glyphPath
);
3027 cf2_arrstack_finalize( &vStemHintArray
);
3028 cf2_arrstack_finalize( &hStemHintArray
);
3029 cf2_arrstack_finalize( &subrStack
);
3030 cf2_stack_free( opStack
);
3032 FT_TRACE4(( "\n" ));