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
;
529 CF2_GlyphPathRec
*glyphPath
= malloc(sizeof(CF2_GlyphPathRec
));
530 /* Ugly but it allows us to reduce the diff */
531 #define glyphPath (*glyphPath)
533 CF2_GlyphPathRec glyphPath
;
538 FT_ZERO( &flexStore
);
540 /* initialize the remaining objects */
541 cf2_arrstack_init( &subrStack
,
544 sizeof ( CF2_BufferRec
) );
545 cf2_arrstack_init( &hStemHintArray
,
548 sizeof ( CF2_StemHintRec
) );
549 cf2_arrstack_init( &vStemHintArray
,
552 sizeof ( CF2_StemHintRec
) );
554 /* initialize CF2_StemHint arrays */
555 cf2_hintmask_init( &hintMask
, error
);
557 /* initialize path map to manage drawing operations */
559 /* Note: last 4 params are used to handle `MoveToPermissive', which */
560 /* may need to call `hintMap.Build' */
561 /* TODO: MoveToPermissive is gone; are these still needed? */
562 cf2_glyphpath_init( &glyphPath
,
575 * Initialize state for width parsing. From the CFF Spec:
577 * The first stack-clearing operator, which must be one of hstem,
578 * hstemhm, vstem, vstemhm, cntrmask, hintmask, hmoveto, vmoveto,
579 * rmoveto, or endchar, takes an additional argument - the width (as
580 * described earlier), which may be expressed as zero or one numeric
583 * What we implement here uses the first validly specified width, but
584 * does not detect errors for specifying more than one width.
586 * If one of the above operators occurs without explicitly specifying
587 * a width, we assume the default width.
589 * CFF2 charstrings always return the default width (0).
592 haveWidth
= font
->isCFF2
? TRUE
: FALSE
;
593 *width
= cf2_getDefaultWidthX( decoder
);
596 * Note: At this point, all pointers to resources must be NULL
597 * and all local objects must be initialized.
598 * There must be no branches to `exit:' above this point.
602 /* allocate an operand stack */
603 stackSize
= font
->isCFF2
? cf2_getMaxstack( decoder
)
604 : CF2_OPERAND_STACK_SIZE
;
605 opStack
= cf2_stack_init( memory
, error
, stackSize
);
609 lastError
= FT_THROW( Out_Of_Memory
);
613 /* initialize subroutine stack by placing top level charstring as */
614 /* first element (max depth plus one for the charstring) */
615 /* Note: Caller owns and must finalize the first charstring. */
616 /* Our copy of it does not change that requirement. */
617 cf2_arrstack_setCount( &subrStack
, CF2_MAX_SUBR
+ 1 );
619 charstring
= (CF2_Buffer
)cf2_arrstack_getBuffer( &subrStack
);
620 *charstring
= *buf
; /* structure copy */
622 charstringIndex
= 0; /* entry is valid now */
624 /* catch errors so far */
628 /* main interpreter loop */
632 FT_ASSERT( known_othersubr_result_cnt
== 0 ||
635 if ( cf2_buf_isEnd( charstring
) )
637 /* If we've reached the end of the charstring, simulate a */
638 /* cf2_cmdRETURN or cf2_cmdENDCHAR. */
639 /* We do this for both CFF and CFF2. */
640 if ( charstringIndex
)
641 op1
= cf2_cmdRETURN
; /* end of buffer for subroutine */
643 op1
= cf2_cmdENDCHAR
; /* end of buffer for top level charstring */
647 op1
= (FT_Byte
)cf2_buf_readByte( charstring
);
649 /* Explicit RETURN and ENDCHAR in CFF2 should be ignored. */
650 /* Note: Trace message will report 0 instead of 11 or 14. */
651 if ( ( op1
== cf2_cmdRETURN
|| op1
== cf2_cmdENDCHAR
) &&
653 op1
= cf2_cmdRESERVED_0
;
658 if ( !initial_map_ready
&&
659 !( op1
== cf2_cmdHSTEM
||
660 op1
== cf2_cmdVSTEM
||
661 op1
== cf2_cmdHSBW
||
662 op1
== cf2_cmdCALLSUBR
||
663 op1
== cf2_cmdRETURN
||
665 op1
== cf2_cmdENDCHAR
||
666 op1
>= 32 /* Numbers */ ) )
668 /* Skip outline commands first time round. */
669 /* `endchar' will trigger initial hintmap build */
670 /* and rewind the charstring. */
671 cf2_stack_clear( opStack
);
675 if ( result_cnt
> 0 &&
676 !( op1
== cf2_cmdCALLSUBR
||
677 op1
== cf2_cmdRETURN
||
679 op1
>= 32 /* Numbers */ ) )
681 /* all operands have been transferred by previous pops */
685 if ( large_int
&& !( op1
>= 32 || op1
== cf2_escDIV
) )
687 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
688 " no `div' after large integer\n" ));
694 /* check for errors once per loop */
699 if ( instructionLimit
== 0 )
701 lastError
= FT_THROW( Invalid_Glyph_Format
);
707 case cf2_cmdRESERVED_0
:
708 case cf2_cmdRESERVED_2
:
709 case cf2_cmdRESERVED_17
:
710 /* we may get here if we have a prior error */
711 FT_TRACE4(( " unknown op (%d)\n", op1
));
715 FT_TRACE4(( " vsindex\n" ));
718 break; /* clear stack & ignore */
720 if ( font
->blend
.usedBV
)
722 /* vsindex not allowed after blend */
723 lastError
= FT_THROW( Invalid_Glyph_Format
);
728 FT_Int temp
= cf2_stack_popInt( opStack
);
732 font
->vsindex
= (FT_UInt
)temp
;
741 FT_TRACE4(( " blend\n" ));
744 break; /* clear stack & ignore */
746 /* do we have a `blend' op in a non-variant font? */
747 if ( !font
->blend
.font
)
749 lastError
= FT_THROW( Invalid_Glyph_Format
);
753 /* check cached blend vector */
754 if ( font
->cffload
->blend_check_vector( &font
->blend
,
759 lastError
= font
->cffload
->blend_build_vector( &font
->blend
,
768 numBlends
= (FT_UInt
)cf2_stack_popInt( opStack
);
769 if ( numBlends
> stackSize
)
771 lastError
= FT_THROW( Invalid_Glyph_Format
);
775 cf2_doBlend( &font
->blend
, opStack
, numBlends
);
777 font
->blend
.usedBV
= TRUE
;
779 continue; /* do not clear the stack */
783 FT_TRACE4(( op1
== cf2_cmdHSTEMHM
? " hstemhm\n" : " hstem\n" ));
787 /* never add hints after the mask is computed */
788 /* except if in Type 1 mode (no hintmask op) */
789 if ( cf2_hintmask_isValid( &hintMask
) )
791 FT_TRACE4(( "cf2_interpT2CharString:"
792 " invalid horizontal hint mask\n" ));
797 /* add left-sidebearing correction in Type 1 mode */
803 font
->isT1
? decoder
->builder
.left_bearing
->y
806 if ( decoder
->width_only
)
813 FT_TRACE4(( op1
== cf2_cmdVSTEMHM
? " vstemhm\n" : " vstem\n" ));
817 /* never add hints after the mask is computed */
818 /* except if in Type 1 mode (no hintmask op) */
819 if ( cf2_hintmask_isValid( &hintMask
) )
821 FT_TRACE4(( "cf2_interpT2CharString:"
822 " invalid vertical hint mask\n" ));
827 /* add left-sidebearing correction in Type 1 mode */
833 font
->isT1
? decoder
->builder
.left_bearing
->x
836 if ( decoder
->width_only
)
842 FT_TRACE4(( " vmoveto\n" ));
844 if ( font
->isT1
&& !decoder
->flex_state
&& !haveWidth
)
845 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
846 " No width. Use hsbw/sbw as first op\n" ));
848 if ( cf2_stack_count( opStack
) > 1 && !haveWidth
)
849 *width
= ADD_INT32( cf2_stack_getReal( opStack
, 0 ),
852 /* width is defined or default after this */
855 if ( decoder
->width_only
)
858 curY
= ADD_INT32( curY
, cf2_stack_popFixed( opStack
) );
860 cf2_glyphpath_moveTo( &glyphPath
, curX
, curY
);
867 CF2_UInt count
= cf2_stack_count( opStack
);
870 FT_TRACE4(( " rlineto\n" ));
872 for ( idx
= 0; idx
< count
; idx
+= 2 )
874 curX
= ADD_INT32( curX
, cf2_stack_getReal( opStack
,
876 curY
= ADD_INT32( curY
, cf2_stack_getReal( opStack
,
879 cf2_glyphpath_lineTo( &glyphPath
, curX
, curY
);
882 cf2_stack_clear( opStack
);
884 continue; /* no need to clear stack again */
890 CF2_UInt count
= cf2_stack_count( opStack
);
892 FT_Bool isX
= FT_BOOL( op1
== cf2_cmdHLINETO
);
895 FT_TRACE4(( isX
? " hlineto\n" : " vlineto\n" ));
897 for ( idx
= 0; idx
< count
; idx
++ )
899 CF2_Fixed v
= cf2_stack_getReal( opStack
, idx
);
903 curX
= ADD_INT32( curX
, v
);
905 curY
= ADD_INT32( curY
, v
);
909 cf2_glyphpath_lineTo( &glyphPath
, curX
, curY
);
912 cf2_stack_clear( opStack
);
916 case cf2_cmdRCURVELINE
:
917 case cf2_cmdRRCURVETO
:
919 CF2_UInt count
= cf2_stack_count( opStack
);
923 FT_TRACE4(( op1
== cf2_cmdRCURVELINE
? " rcurveline\n"
926 while ( idx
+ 6 <= count
)
928 CF2_Fixed x1
, y1
, x2
, y2
, x3
, y3
;
931 x1
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 0 ), curX
);
932 y1
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 1 ), curY
);
933 x2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 2 ), x1
);
934 y2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 3 ), y1
);
935 x3
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 4 ), x2
);
936 y3
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 5 ), y2
);
938 cf2_glyphpath_curveTo( &glyphPath
, x1
, y1
, x2
, y2
, x3
, y3
);
945 if ( op1
== cf2_cmdRCURVELINE
)
947 curX
= ADD_INT32( curX
, cf2_stack_getReal( opStack
,
949 curY
= ADD_INT32( curY
, cf2_stack_getReal( opStack
,
952 cf2_glyphpath_lineTo( &glyphPath
, curX
, curY
);
955 cf2_stack_clear( opStack
);
957 continue; /* no need to clear stack again */
959 case cf2_cmdCLOSEPATH
:
961 FT_TRACE4(( " unknown op (%d)\n", op1
));
964 FT_TRACE4(( " closepath" ));
966 /* if there is no path, `closepath' is a no-op */
967 ps_builder_close_contour( &decoder
->builder
);
973 case cf2_cmdCALLGSUBR
:
974 case cf2_cmdCALLSUBR
:
979 FT_TRACE4(( op1
== cf2_cmdCALLGSUBR
? " callgsubr"
982 if ( ( !font
->isT1
&& charstringIndex
> CF2_MAX_SUBR
) ||
983 ( font
->isT1
&& charstringIndex
> T1_MAX_SUBRS_CALLS
) )
985 /* max subr plus one for charstring */
986 lastError
= FT_THROW( Invalid_Glyph_Format
);
987 goto exit
; /* overflow of stack */
990 /* push our current CFF charstring region on subrStack */
991 charstring
= (CF2_Buffer
)
992 cf2_arrstack_getPointer(
994 (size_t)charstringIndex
+ 1 );
996 /* set up the new CFF region and pointer */
997 subrNum
= cf2_stack_popInt( opStack
);
999 if ( font
->isT1
&& decoder
->locals_hash
)
1001 size_t* val
= ft_hash_num_lookup( subrNum
,
1002 decoder
->locals_hash
);
1013 case cf2_cmdCALLGSUBR
:
1014 FT_TRACE4(( " (idx %d, entering level %d)\n",
1015 subrNum
+ decoder
->globals_bias
,
1016 charstringIndex
+ 1 ));
1018 if ( cf2_initGlobalRegionBuffer( decoder
,
1022 lastError
= FT_THROW( Invalid_Glyph_Format
);
1023 goto exit
; /* subroutine lookup or stream error */
1028 /* cf2_cmdCALLSUBR */
1029 FT_TRACE4(( " (idx %d, entering level %d)\n",
1030 subrNum
+ decoder
->locals_bias
,
1031 charstringIndex
+ 1 ));
1033 if ( cf2_initLocalRegionBuffer( decoder
,
1037 lastError
= FT_THROW( Invalid_Glyph_Format
);
1038 goto exit
; /* subroutine lookup or stream error */
1042 charstringIndex
+= 1; /* entry is valid now */
1044 continue; /* do not clear the stack */
1047 FT_TRACE4(( " return (leaving level %d)\n", charstringIndex
));
1049 if ( charstringIndex
< 1 )
1051 /* Note: cannot return from top charstring */
1052 lastError
= FT_THROW( Invalid_Glyph_Format
);
1053 goto exit
; /* underflow of stack */
1056 /* restore position in previous charstring */
1057 charstring
= (CF2_Buffer
)
1058 cf2_arrstack_getPointer(
1060 (CF2_UInt
)--charstringIndex
);
1061 continue; /* do not clear the stack */
1065 FT_Byte op2
= (FT_Byte
)cf2_buf_readByte( charstring
);
1068 /* first switch for 2-byte operators handles CFF2 */
1069 /* and opcodes that are reserved for both CFF and CFF2 */
1074 static const FT_Bool readFromStack
[12] =
1076 TRUE
/* dx1 */, FALSE
/* dy1 */,
1077 TRUE
/* dx2 */, TRUE
/* dy2 */,
1078 TRUE
/* dx3 */, FALSE
/* dy3 */,
1079 TRUE
/* dx4 */, FALSE
/* dy4 */,
1080 TRUE
/* dx5 */, FALSE
/* dy5 */,
1081 TRUE
/* dx6 */, FALSE
/* dy6 */
1085 FT_TRACE4(( " hflex\n" ));
1087 cf2_doFlex( opStack
,
1092 FALSE
/* doConditionalLastRead */ );
1098 static const FT_Bool readFromStack
[12] =
1100 TRUE
/* dx1 */, TRUE
/* dy1 */,
1101 TRUE
/* dx2 */, TRUE
/* dy2 */,
1102 TRUE
/* dx3 */, TRUE
/* dy3 */,
1103 TRUE
/* dx4 */, TRUE
/* dy4 */,
1104 TRUE
/* dx5 */, TRUE
/* dy5 */,
1105 TRUE
/* dx6 */, TRUE
/* dy6 */
1109 FT_TRACE4(( " flex\n" ));
1111 cf2_doFlex( opStack
,
1116 FALSE
/* doConditionalLastRead */ );
1118 break; /* TODO: why is this not a continue? */
1122 static const FT_Bool readFromStack
[12] =
1124 TRUE
/* dx1 */, TRUE
/* dy1 */,
1125 TRUE
/* dx2 */, TRUE
/* dy2 */,
1126 TRUE
/* dx3 */, FALSE
/* dy3 */,
1127 TRUE
/* dx4 */, FALSE
/* dy4 */,
1128 TRUE
/* dx5 */, TRUE
/* dy5 */,
1129 TRUE
/* dx6 */, FALSE
/* dy6 */
1133 FT_TRACE4(( " hflex1\n" ));
1135 cf2_doFlex( opStack
,
1140 FALSE
/* doConditionalLastRead */ );
1146 static const FT_Bool readFromStack
[12] =
1148 TRUE
/* dx1 */, TRUE
/* dy1 */,
1149 TRUE
/* dx2 */, TRUE
/* dy2 */,
1150 TRUE
/* dx3 */, TRUE
/* dy3 */,
1151 TRUE
/* dx4 */, TRUE
/* dy4 */,
1152 TRUE
/* dx5 */, TRUE
/* dy5 */,
1153 FALSE
/* dx6 */, FALSE
/* dy6 */
1157 FT_TRACE4(( " flex1\n" ));
1159 cf2_doFlex( opStack
,
1164 TRUE
/* doConditionalLastRead */ );
1168 /* these opcodes are always reserved */
1169 case cf2_escRESERVED_8
:
1170 case cf2_escRESERVED_13
:
1171 case cf2_escRESERVED_19
:
1172 case cf2_escRESERVED_25
:
1173 case cf2_escRESERVED_31
:
1174 case cf2_escRESERVED_32
:
1175 FT_TRACE4(( " unknown op (12, %d)\n", op2
));
1180 if ( font
->isCFF2
|| op2
>= cf2_escRESERVED_38
)
1181 FT_TRACE4(( " unknown op (12, %d)\n", op2
));
1182 else if ( font
->isT1
&& result_cnt
> 0 && op2
!= cf2_escPOP
)
1184 /* all operands have been transferred by previous pops */
1189 /* second switch for 2-byte operators handles */
1190 /* CFF and Type 1 */
1194 case cf2_escDOTSECTION
:
1195 /* something about `flip type of locking' -- ignore it */
1196 FT_TRACE4(( " dotsection\n" ));
1204 * x0 dx0 x1 dx1 x2 dx2 vstem3 x dx {dxa dxb}* vstem
1205 * y0 dy0 y1 dy1 y2 dy2 hstem3 y dy {dya dyb}* hstem
1206 * relative to lsb point relative to zero
1211 FT_TRACE4(( " unknown op (12, %d)\n", op2
));
1214 CF2_F16Dot16 v0
, v1
, v2
;
1216 FT_Bool isV
= FT_BOOL( op2
== cf2_escVSTEM3
);
1219 FT_TRACE4(( isV
? " vstem3\n"
1222 FT_ASSERT( cf2_stack_count( opStack
) == 6 );
1224 v0
= cf2_stack_getReal( opStack
, 0 );
1225 v1
= cf2_stack_getReal( opStack
, 2 );
1226 v2
= cf2_stack_getReal( opStack
, 4 );
1230 SUB_INT32( SUB_INT32( v1
, v0
),
1231 cf2_stack_getReal( opStack
, 1 ) ) );
1234 SUB_INT32( SUB_INT32( v2
, v1
),
1235 cf2_stack_getReal( opStack
, 3 ) ) );
1237 /* add left-sidebearing correction */
1240 isV
? &vStemHintArray
: &hStemHintArray
,
1243 isV
? decoder
->builder
.left_bearing
->x
1244 : decoder
->builder
.left_bearing
->y
);
1246 if ( decoder
->width_only
)
1258 FT_TRACE4(( " and\n" ));
1260 arg2
= cf2_stack_popFixed( opStack
);
1261 arg1
= cf2_stack_popFixed( opStack
);
1263 cf2_stack_pushInt( opStack
, arg1
&& arg2
);
1265 continue; /* do not clear the stack */
1273 FT_TRACE4(( " or\n" ));
1275 arg2
= cf2_stack_popFixed( opStack
);
1276 arg1
= cf2_stack_popFixed( opStack
);
1278 cf2_stack_pushInt( opStack
, arg1
|| arg2
);
1280 continue; /* do not clear the stack */
1287 FT_TRACE4(( " not\n" ));
1289 arg
= cf2_stack_popFixed( opStack
);
1291 cf2_stack_pushInt( opStack
, !arg
);
1293 continue; /* do not clear the stack */
1297 FT_TRACE4(( " unknown op (12, %d)\n", op2
));
1301 CF2_Int bchar_index
, achar_index
;
1302 FT_Vector left_bearing
, advance
;
1304 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1305 T1_Face face
= (T1_Face
)decoder
->builder
.face
;
1307 CF2_BufferRec component
;
1308 CF2_Fixed dummyWidth
;
1310 CF2_Int achar
= cf2_stack_popInt( opStack
);
1311 CF2_Int bchar
= cf2_stack_popInt( opStack
);
1313 FT_Pos ady
= cf2_stack_popFixed ( opStack
);
1314 FT_Pos adx
= cf2_stack_popFixed ( opStack
);
1315 FT_Pos asb
= cf2_stack_popFixed ( opStack
);
1318 FT_TRACE4(( " seac\n" ));
1322 FT_ERROR(( " nested seac\n" ));
1323 lastError
= FT_THROW( Invalid_Glyph_Format
);
1324 goto exit
; /* nested seac */
1327 if ( decoder
->builder
.metrics_only
)
1329 FT_ERROR(( " unexpected seac\n" ));
1330 lastError
= FT_THROW( Invalid_Glyph_Format
);
1331 goto exit
; /* unexpected seac */
1334 /* `glyph_names' is set to 0 for CID fonts which do */
1335 /* not include an encoding. How can we deal with */
1337 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1338 if ( decoder
->glyph_names
== 0 &&
1339 !face
->root
.internal
->incremental_interface
)
1341 if ( decoder
->glyph_names
== 0 )
1342 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
1345 "cf2_interpT2CharString: (Type 1 seac)"
1346 " glyph names table not available in this font\n" ));
1347 lastError
= FT_THROW( Invalid_Glyph_Format
);
1351 /* seac weirdness */
1352 adx
+= decoder
->builder
.left_bearing
->x
;
1354 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1355 if ( face
->root
.internal
->incremental_interface
)
1357 /* the caller must handle the font encoding also */
1358 bchar_index
= bchar
;
1359 achar_index
= achar
;
1364 bchar_index
= t1_lookup_glyph_by_stdcharcode_ps(
1366 achar_index
= t1_lookup_glyph_by_stdcharcode_ps(
1370 if ( bchar_index
< 0 || achar_index
< 0 )
1373 "cf2_interpT2CharString: (Type 1 seac)"
1374 " invalid seac character code arguments\n" ));
1375 lastError
= FT_THROW( Invalid_Glyph_Format
);
1379 /* if we are trying to load a composite glyph, */
1380 /* do not load the accent character and return */
1381 /* the array of subglyphs. */
1382 if ( decoder
->builder
.no_recurse
)
1384 FT_GlyphSlot glyph
= (FT_GlyphSlot
)decoder
->builder
.glyph
;
1385 FT_GlyphLoader loader
= glyph
->internal
->loader
;
1389 /* reallocate subglyph array if necessary */
1390 error2
= FT_GlyphLoader_CheckSubGlyphs( loader
, 2 );
1393 lastError
= error2
; /* pass FreeType error through */
1397 subg
= loader
->current
.subglyphs
;
1399 /* subglyph 0 = base character */
1400 subg
->index
= bchar_index
;
1401 subg
->flags
= FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES
|
1402 FT_SUBGLYPH_FLAG_USE_MY_METRICS
;
1407 /* subglyph 1 = accent character */
1408 subg
->index
= achar_index
;
1409 subg
->flags
= FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES
;
1410 subg
->arg1
= (FT_Int
)FIXED_TO_INT( adx
- asb
);
1411 subg
->arg2
= (FT_Int
)FIXED_TO_INT( ady
);
1413 /* set up remaining glyph fields */
1414 glyph
->num_subglyphs
= 2;
1415 glyph
->subglyphs
= loader
->base
.subglyphs
;
1416 glyph
->format
= FT_GLYPH_FORMAT_COMPOSITE
;
1418 loader
->current
.num_subglyphs
= 2;
1423 /* First load `bchar' in builder */
1424 /* now load the unscaled outline */
1426 /* prepare loader */
1427 FT_GlyphLoader_Prepare( decoder
->builder
.loader
);
1429 error2
= cf2_getT1SeacComponent( decoder
,
1430 (FT_UInt
)bchar_index
,
1434 lastError
= error2
; /* pass FreeType error through */
1437 cf2_interpT2CharString( font
,
1445 cf2_freeT1SeacComponent( decoder
, &component
);
1447 /* save the left bearing and width of the base */
1448 /* character as they will be erased by the next load */
1450 left_bearing
= *decoder
->builder
.left_bearing
;
1451 advance
= *decoder
->builder
.advance
;
1453 decoder
->builder
.left_bearing
->x
= 0;
1454 decoder
->builder
.left_bearing
->y
= 0;
1456 /* Now load `achar' on top of */
1457 /* the base outline */
1459 error2
= cf2_getT1SeacComponent( decoder
,
1460 (FT_UInt
)achar_index
,
1464 lastError
= error2
; /* pass FreeType error through */
1467 cf2_interpT2CharString( font
,
1475 cf2_freeT1SeacComponent( decoder
, &component
);
1477 /* restore the left side bearing and */
1478 /* advance width of the base character */
1480 *decoder
->builder
.left_bearing
= left_bearing
;
1481 *decoder
->builder
.advance
= advance
;
1489 FT_TRACE4(( " unknown op (12, %d)\n", op2
));
1492 CF2_Fixed lsb_x
, lsb_y
;
1493 PS_Builder
* builder
;
1496 FT_TRACE4(( " sbw" ));
1498 builder
= &decoder
->builder
;
1500 builder
->advance
->y
= cf2_stack_popFixed( opStack
);
1501 builder
->advance
->x
= cf2_stack_popFixed( opStack
);
1503 lsb_y
= cf2_stack_popFixed( opStack
);
1504 lsb_x
= cf2_stack_popFixed( opStack
);
1506 builder
->left_bearing
->x
=
1507 ADD_INT32( builder
->left_bearing
->x
, lsb_x
);
1508 builder
->left_bearing
->y
=
1509 ADD_INT32( builder
->left_bearing
->y
, lsb_y
);
1513 /* the `metrics_only' indicates that we only want */
1514 /* to compute the glyph's metrics (lsb + advance */
1515 /* width), not load the rest of it; so exit */
1517 if ( builder
->metrics_only
)
1520 if ( initial_map_ready
)
1522 curX
= ADD_INT32( curX
, lsb_x
);
1523 curY
= ADD_INT32( curY
, lsb_y
);
1533 FT_TRACE4(( " abs\n" ));
1535 arg
= cf2_stack_popFixed( opStack
);
1537 if ( arg
< -CF2_FIXED_MAX
)
1538 cf2_stack_pushFixed( opStack
, CF2_FIXED_MAX
);
1540 cf2_stack_pushFixed( opStack
, FT_ABS( arg
) );
1542 continue; /* do not clear the stack */
1546 CF2_F16Dot16 summand1
;
1547 CF2_F16Dot16 summand2
;
1550 FT_TRACE4(( " add\n" ));
1552 summand2
= cf2_stack_popFixed( opStack
);
1553 summand1
= cf2_stack_popFixed( opStack
);
1555 cf2_stack_pushFixed( opStack
,
1556 ADD_INT32( summand1
,
1559 continue; /* do not clear the stack */
1563 CF2_F16Dot16 minuend
;
1564 CF2_F16Dot16 subtrahend
;
1567 FT_TRACE4(( " sub\n" ));
1569 subtrahend
= cf2_stack_popFixed( opStack
);
1570 minuend
= cf2_stack_popFixed( opStack
);
1572 cf2_stack_pushFixed( opStack
,
1573 SUB_INT32( minuend
, subtrahend
) );
1575 continue; /* do not clear the stack */
1579 CF2_F16Dot16 dividend
;
1580 CF2_F16Dot16 divisor
;
1583 FT_TRACE4(( " div\n" ));
1585 if ( font
->isT1
&& large_int
)
1587 divisor
= (CF2_F16Dot16
)cf2_stack_popInt( opStack
);
1588 dividend
= (CF2_F16Dot16
)cf2_stack_popInt( opStack
);
1594 divisor
= cf2_stack_popFixed( opStack
);
1595 dividend
= cf2_stack_popFixed( opStack
);
1598 cf2_stack_pushFixed( opStack
,
1599 FT_DivFix( dividend
, divisor
) );
1602 continue; /* do not clear the stack */
1609 FT_TRACE4(( " neg\n" ));
1611 arg
= cf2_stack_popFixed( opStack
);
1613 if ( arg
< -CF2_FIXED_MAX
)
1614 cf2_stack_pushFixed( opStack
, CF2_FIXED_MAX
);
1616 cf2_stack_pushFixed( opStack
, -arg
);
1618 continue; /* do not clear the stack */
1626 FT_TRACE4(( " eq\n" ));
1628 arg2
= cf2_stack_popFixed( opStack
);
1629 arg1
= cf2_stack_popFixed( opStack
);
1631 cf2_stack_pushInt( opStack
, arg1
== arg2
);
1633 continue; /* do not clear the stack */
1635 case cf2_escCALLOTHERSUBR
:
1637 FT_TRACE4(( " unknown op (12, %d)\n", op2
));
1646 FT_TRACE4(( " callothersubr\n" ));
1648 subr_no
= cf2_stack_popInt( opStack
);
1649 arg_cnt
= cf2_stack_popInt( opStack
);
1651 /*******************************************************/
1653 /* remove all operands to callothersubr from the stack */
1655 /* for handled othersubrs, where we know the number of */
1656 /* arguments, we increase the stack by the value of */
1657 /* known_othersubr_result_cnt */
1659 /* for unhandled othersubrs the following pops adjust */
1660 /* the stack pointer as necessary */
1662 count
= cf2_stack_count( opStack
);
1663 FT_ASSERT( (CF2_UInt
)arg_cnt
<= count
);
1665 opIdx
+= count
- (CF2_UInt
)arg_cnt
;
1667 known_othersubr_result_cnt
= 0;
1670 /* XXX TODO: The checks to `arg_count == <whatever>' */
1671 /* might not be correct; an othersubr expects a */
1672 /* certain number of operands on the PostScript stack */
1673 /* (as opposed to the T1 stack) but it doesn't have to */
1674 /* put them there by itself; previous othersubrs might */
1675 /* have left the operands there if they were not */
1676 /* followed by an appropriate number of pops */
1678 /* On the other hand, Adobe Reader 7.0.8 for Linux */
1679 /* doesn't accept a font that contains charstrings */
1682 /* 100 200 2 20 callothersubr */
1683 /* 300 1 20 callothersubr pop */
1685 /* Perhaps this is the reason why BuildCharArray */
1690 case 0: /* end flex feature */
1692 goto Unexpected_OtherSubr
;
1694 if ( initial_map_ready
&&
1695 ( !decoder
->flex_state
||
1696 decoder
->num_flex_vectors
!= 7 ) )
1698 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
1699 " unexpected flex end\n" ));
1700 lastError
= FT_THROW( Invalid_Glyph_Format
);
1704 /* the two `results' are popped */
1705 /* by the following setcurrentpoint */
1706 cf2_stack_pushFixed( opStack
, curX
);
1707 cf2_stack_pushFixed( opStack
, curY
);
1708 known_othersubr_result_cnt
= 2;
1711 case 1: /* start flex feature */
1713 goto Unexpected_OtherSubr
;
1715 if ( !initial_map_ready
)
1718 if ( ps_builder_check_points( &decoder
->builder
, 6 ) )
1721 decoder
->flex_state
= 1;
1722 decoder
->num_flex_vectors
= 0;
1725 case 2: /* add flex vectors */
1732 goto Unexpected_OtherSubr
;
1734 if ( !initial_map_ready
)
1737 if ( !decoder
->flex_state
)
1739 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
1740 " missing flex start\n" ));
1741 lastError
= FT_THROW( Invalid_Glyph_Format
);
1745 /* note that we should not add a point for */
1746 /* index 0; this will move our current position */
1747 /* to the flex point without adding any point */
1748 /* to the outline */
1749 idx
= decoder
->num_flex_vectors
++;
1750 if ( idx
> 0 && idx
< 7 )
1752 /* in malformed fonts it is possible to have */
1753 /* other opcodes in the middle of a flex (which */
1754 /* don't increase `num_flex_vectors'); we thus */
1755 /* have to check whether we can add a point */
1757 if ( ps_builder_check_points( &decoder
->builder
,
1760 lastError
= FT_THROW( Invalid_Glyph_Format
);
1764 /* map: 1->2 2->4 3->6 4->2 5->4 6->6 */
1765 idx2
= ( idx
> 3 ? idx
- 3 : idx
) * 2;
1767 flexStore
[idx2
- 2] = curX
;
1768 flexStore
[idx2
- 1] = curY
;
1770 if ( idx
== 3 || idx
== 6 )
1771 cf2_glyphpath_curveTo( &glyphPath
,
1782 case 3: /* change hints */
1784 goto Unexpected_OtherSubr
;
1786 if ( initial_map_ready
)
1788 /* do not clear hints if initial hintmap */
1789 /* is not ready - we need to collate all */
1790 cf2_arrstack_clear( &vStemHintArray
);
1791 cf2_arrstack_clear( &hStemHintArray
);
1793 cf2_hintmask_init( &hintMask
, error
);
1794 hintMask
.isValid
= FALSE
;
1795 hintMask
.isNew
= TRUE
;
1798 known_othersubr_result_cnt
= 1;
1803 /* counter control hints, clear stack */
1804 cf2_stack_clear( opStack
);
1811 case 18: /* multiple masters */
1813 PS_Blend blend
= decoder
->blend
;
1814 FT_UInt num_points
, nn
, mm
;
1822 "cf2_interpT2CharString:"
1823 " unexpected multiple masters operator\n" ));
1824 lastError
= FT_THROW( Invalid_Glyph_Format
);
1828 num_points
= (FT_UInt
)subr_no
- 13 +
1830 if ( arg_cnt
!= (FT_Int
)( num_points
*
1831 blend
->num_designs
) )
1834 "cf2_interpT2CharString:"
1835 " incorrect number of multiple masters arguments\n" ));
1836 lastError
= FT_THROW( Invalid_Glyph_Format
);
1840 /* We want to compute */
1842 /* a0*w0 + a1*w1 + ... + ak*wk */
1844 /* but we only have a0, a1-a0, a2-a0, ..., ak-a0. */
1846 /* However, given that w0 + w1 + ... + wk == 1, we */
1847 /* can rewrite it easily as */
1849 /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + ... + (ak-a0)*wk */
1851 /* where k == num_designs-1. */
1853 /* I guess that's why it's written in this `compact' */
1856 delta
= opIdx
+ num_points
;
1858 for ( nn
= 0; nn
< num_points
; nn
++ )
1860 CF2_Fixed tmp
= cf2_stack_getReal( opStack
,
1864 for ( mm
= 1; mm
< blend
->num_designs
; mm
++ )
1865 tmp
= ADD_INT32( tmp
,
1867 cf2_stack_getReal( opStack
,
1869 blend
->weight_vector
[mm
] ) );
1871 cf2_stack_setReal( opStack
, values
++, tmp
);
1873 cf2_stack_pop( opStack
,
1874 (CF2_UInt
)arg_cnt
- num_points
);
1876 known_othersubr_result_cnt
= (FT_Int
)num_points
;
1881 /* <idx> 1 19 callothersubr */
1882 /* ==> replace elements starting from index */
1883 /* cvi( <idx> ) of BuildCharArray with */
1887 PS_Blend blend
= decoder
->blend
;
1890 if ( arg_cnt
!= 1 || !blend
)
1891 goto Unexpected_OtherSubr
;
1893 idx
= cf2_stack_popInt( opStack
);
1896 (FT_UInt
)idx
+ blend
->num_designs
>
1897 decoder
->len_buildchar
)
1898 goto Unexpected_OtherSubr
;
1900 ft_memcpy( &decoder
->buildchar
[idx
],
1901 blend
->weight_vector
,
1902 blend
->num_designs
*
1903 sizeof ( blend
->weight_vector
[0] ) );
1908 /* <arg1> <arg2> 2 20 callothersubr pop */
1909 /* ==> push <arg1> + <arg2> onto T1 stack */
1911 CF2_F16Dot16 summand1
;
1912 CF2_F16Dot16 summand2
;
1916 goto Unexpected_OtherSubr
;
1918 summand2
= cf2_stack_popFixed( opStack
);
1919 summand1
= cf2_stack_popFixed( opStack
);
1921 cf2_stack_pushFixed( opStack
,
1922 ADD_INT32( summand1
,
1924 known_othersubr_result_cnt
= 1;
1929 /* <arg1> <arg2> 2 21 callothersubr pop */
1930 /* ==> push <arg1> - <arg2> onto T1 stack */
1932 CF2_F16Dot16 minuend
;
1933 CF2_F16Dot16 subtrahend
;
1937 goto Unexpected_OtherSubr
;
1939 subtrahend
= cf2_stack_popFixed( opStack
);
1940 minuend
= cf2_stack_popFixed( opStack
);
1942 cf2_stack_pushFixed( opStack
,
1945 known_othersubr_result_cnt
= 1;
1950 /* <arg1> <arg2> 2 22 callothersubr pop */
1951 /* ==> push <arg1> * <arg2> onto T1 stack */
1953 CF2_F16Dot16 factor1
;
1954 CF2_F16Dot16 factor2
;
1958 goto Unexpected_OtherSubr
;
1960 factor2
= cf2_stack_popFixed( opStack
);
1961 factor1
= cf2_stack_popFixed( opStack
);
1963 cf2_stack_pushFixed( opStack
,
1964 FT_MulFix( factor1
, factor2
) );
1965 known_othersubr_result_cnt
= 1;
1970 /* <arg1> <arg2> 2 23 callothersubr pop */
1971 /* ==> push <arg1> / <arg2> onto T1 stack */
1973 CF2_F16Dot16 dividend
;
1974 CF2_F16Dot16 divisor
;
1978 goto Unexpected_OtherSubr
;
1980 divisor
= cf2_stack_popFixed( opStack
);
1981 dividend
= cf2_stack_popFixed( opStack
);
1984 goto Unexpected_OtherSubr
;
1986 cf2_stack_pushFixed( opStack
,
1987 FT_DivFix( dividend
,
1989 known_othersubr_result_cnt
= 1;
1994 /* <val> <idx> 2 24 callothersubr */
1995 /* ==> set BuildCharArray[cvi( <idx> )] = <val> */
1998 PS_Blend blend
= decoder
->blend
;
2001 if ( arg_cnt
!= 2 || !blend
)
2002 goto Unexpected_OtherSubr
;
2004 idx
= cf2_stack_popInt( opStack
);
2007 (FT_UInt
)idx
>= decoder
->len_buildchar
)
2008 goto Unexpected_OtherSubr
;
2010 decoder
->buildchar
[idx
] =
2011 cf2_stack_popFixed( opStack
);
2016 /* <idx> 1 25 callothersubr pop */
2017 /* ==> push BuildCharArray[cvi( idx )] */
2021 PS_Blend blend
= decoder
->blend
;
2024 if ( arg_cnt
!= 1 || !blend
)
2025 goto Unexpected_OtherSubr
;
2027 idx
= cf2_stack_popInt( opStack
);
2030 (FT_UInt
)idx
>= decoder
->len_buildchar
)
2031 goto Unexpected_OtherSubr
;
2033 cf2_stack_pushFixed( opStack
,
2034 decoder
->buildchar
[idx
] );
2035 known_othersubr_result_cnt
= 1;
2041 /* <val> mark <idx> */
2042 /* ==> set BuildCharArray[cvi( <idx> )] = <val>, */
2043 /* leave mark on T1 stack */
2045 /* ==> set BuildCharArray[cvi( <idx> )] = <val> */
2046 XXX which routine has left its mark on the
2047 XXX (PostScript
) stack
?;
2052 /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */
2053 /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */
2054 /* otherwise push <res2> */
2063 goto Unexpected_OtherSubr
;
2065 cond2
= cf2_stack_popFixed( opStack
);
2066 cond1
= cf2_stack_popFixed( opStack
);
2067 arg2
= cf2_stack_popFixed( opStack
);
2068 arg1
= cf2_stack_popFixed( opStack
);
2070 cf2_stack_pushFixed( opStack
,
2071 cond1
<= cond2
? arg1
: arg2
);
2072 known_othersubr_result_cnt
= 1;
2077 /* 0 28 callothersubr pop */
2078 /* ==> push random value from interval [0, 1) */
2085 goto Unexpected_OtherSubr
;
2087 /* only use the lower 16 bits of `random' */
2088 /* to generate a number in the range (0;1] */
2090 ( ( decoder
->current_subfont
->random
& 0xFFFF ) + 1 );
2092 decoder
->current_subfont
->random
=
2093 cff_random( decoder
->current_subfont
->random
);
2095 cf2_stack_pushFixed( opStack
, r
);
2096 known_othersubr_result_cnt
= 1;
2101 if ( arg_cnt
>= 0 && subr_no
>= 0 )
2107 "cf2_interpT2CharString (Type 1 mode):"
2108 " unknown othersubr [%d %d], wish me luck\n",
2109 arg_cnt
, subr_no
));
2111 /* store the unused args */
2112 /* for this unhandled OtherSubr */
2114 if ( arg_cnt
> PS_STORAGE_SIZE
)
2115 arg_cnt
= PS_STORAGE_SIZE
;
2116 result_cnt
= arg_cnt
;
2118 for ( i
= 1; i
<= arg_cnt
; i
++ )
2119 results
[result_cnt
- i
] =
2120 cf2_stack_popFixed( opStack
);
2126 Unexpected_OtherSubr
:
2127 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
2128 " invalid othersubr [%d %d]\n",
2129 arg_cnt
, subr_no
));
2130 lastError
= FT_THROW( Invalid_Glyph_Format
);
2134 continue; /* do not clear the stack */
2138 FT_TRACE4(( " unknown op (12, %d)\n", op2
));
2141 FT_TRACE4(( " pop" ));
2143 if ( known_othersubr_result_cnt
> 0 )
2145 known_othersubr_result_cnt
--;
2146 /* ignore, we pushed the operands ourselves */
2150 if ( result_cnt
== 0 )
2152 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
2153 " no more operands for othersubr\n" ));
2154 lastError
= FT_THROW( Invalid_Glyph_Format
);
2159 cf2_stack_pushFixed( opStack
, results
[result_cnt
] );
2161 continue; /* do not clear the stack */
2164 FT_TRACE4(( " drop\n" ));
2166 (void)cf2_stack_popFixed( opStack
);
2167 continue; /* do not clear the stack */
2175 FT_TRACE4(( " put\n" ));
2177 idx
= cf2_stack_popInt( opStack
);
2178 val
= cf2_stack_popFixed( opStack
);
2180 if ( idx
>= 0 && idx
< CF2_STORAGE_SIZE
)
2183 continue; /* do not clear the stack */
2190 FT_TRACE4(( " get\n" ));
2192 idx
= cf2_stack_popInt( opStack
);
2194 if ( idx
>= 0 && idx
< CF2_STORAGE_SIZE
)
2195 cf2_stack_pushFixed( opStack
, storage
[idx
] );
2197 continue; /* do not clear the stack */
2207 FT_TRACE4(( " ifelse\n" ));
2209 cond2
= cf2_stack_popFixed( opStack
);
2210 cond1
= cf2_stack_popFixed( opStack
);
2211 arg2
= cf2_stack_popFixed( opStack
);
2212 arg1
= cf2_stack_popFixed( opStack
);
2214 cf2_stack_pushFixed( opStack
,
2215 cond1
<= cond2
? arg1
: arg2
);
2217 continue; /* do not clear the stack */
2219 case cf2_escRANDOM
: /* in spec */
2224 FT_TRACE4(( " random\n" ));
2226 /* only use the lower 16 bits of `random' */
2227 /* to generate a number in the range (0;1] */
2229 ( ( decoder
->current_subfont
->random
& 0xFFFF ) + 1 );
2231 decoder
->current_subfont
->random
=
2232 cff_random( decoder
->current_subfont
->random
);
2234 cf2_stack_pushFixed( opStack
, r
);
2236 continue; /* do not clear the stack */
2240 CF2_F16Dot16 factor1
;
2241 CF2_F16Dot16 factor2
;
2244 FT_TRACE4(( " mul\n" ));
2246 factor2
= cf2_stack_popFixed( opStack
);
2247 factor1
= cf2_stack_popFixed( opStack
);
2249 cf2_stack_pushFixed( opStack
,
2250 FT_MulFix( factor1
, factor2
) );
2252 continue; /* do not clear the stack */
2259 FT_TRACE4(( " sqrt\n" ));
2261 arg
= cf2_stack_popFixed( opStack
);
2264 /* use a start value that doesn't make */
2265 /* the algorithm's addition overflow */
2266 FT_Fixed root
= arg
< 10 ? arg
: arg
>> 1;
2270 /* Babylonian method */
2273 new_root
= ( root
+ FT_DivFix( arg
, root
) + 1 ) >> 1;
2274 if ( new_root
== root
)
2283 cf2_stack_pushFixed( opStack
, arg
);
2285 continue; /* do not clear the stack */
2292 FT_TRACE4(( " dup\n" ));
2294 arg
= cf2_stack_popFixed( opStack
);
2296 cf2_stack_pushFixed( opStack
, arg
);
2297 cf2_stack_pushFixed( opStack
, arg
);
2299 continue; /* do not clear the stack */
2307 FT_TRACE4(( " exch\n" ));
2309 arg2
= cf2_stack_popFixed( opStack
);
2310 arg1
= cf2_stack_popFixed( opStack
);
2312 cf2_stack_pushFixed( opStack
, arg2
);
2313 cf2_stack_pushFixed( opStack
, arg1
);
2315 continue; /* do not clear the stack */
2323 FT_TRACE4(( " index\n" ));
2325 idx
= cf2_stack_popInt( opStack
);
2326 size
= cf2_stack_count( opStack
);
2330 /* for `cf2_stack_getReal', */
2331 /* index 0 is bottom of stack */
2337 else if ( (CF2_UInt
)idx
>= size
)
2340 gr_idx
= size
- 1 - (CF2_UInt
)idx
;
2342 cf2_stack_pushFixed( opStack
,
2343 cf2_stack_getReal( opStack
,
2347 continue; /* do not clear the stack */
2355 FT_TRACE4(( " roll\n" ));
2357 idx
= cf2_stack_popInt( opStack
);
2358 count
= cf2_stack_popInt( opStack
);
2360 cf2_stack_roll( opStack
, count
, idx
);
2362 continue; /* do not clear the stack */
2364 case cf2_escSETCURRENTPT
:
2366 FT_TRACE4(( " unknown op (12, %d)\n", op2
));
2369 FT_TRACE4(( " setcurrentpoint" ));
2371 if ( !initial_map_ready
)
2374 /* From the T1 specification, section 6.4: */
2376 /* The setcurrentpoint command is used only in */
2377 /* conjunction with results from OtherSubrs */
2380 /* known_othersubr_result_cnt != 0 is already handled */
2383 /* Note, however, that both Ghostscript and Adobe */
2384 /* Distiller handle this situation by silently */
2385 /* ignoring the inappropriate `setcurrentpoint' */
2386 /* instruction. So we do the same. */
2389 if ( decoder
->flex_state
!= 1 )
2391 FT_ERROR(( "cf2_interpT2CharString:"
2392 " unexpected `setcurrentpoint'\n" ));
2399 curY
= cf2_stack_popFixed( opStack
);
2400 curX
= cf2_stack_popFixed( opStack
);
2402 decoder
->flex_state
= 0;
2406 } /* end of 2nd switch checking op2 */
2409 } /* end of 1st switch checking op2 */
2410 } /* case cf2_cmdESC */
2416 FT_TRACE4(( " unknown op (%d)\n", op1
));
2420 PS_Builder
* builder
;
2423 FT_TRACE4(( " hsbw" ));
2425 builder
= &decoder
->builder
;
2427 builder
->advance
->x
= cf2_stack_popFixed( opStack
);
2428 builder
->advance
->y
= 0;
2430 lsb_x
= cf2_stack_popFixed( opStack
);
2432 builder
->left_bearing
->x
= ADD_INT32( builder
->left_bearing
->x
,
2437 /* the `metrics_only' indicates that we only want to compute */
2438 /* the glyph's metrics (lsb + advance width), not load the */
2439 /* rest of it; so exit immediately */
2440 if ( builder
->metrics_only
)
2443 if ( initial_map_ready
)
2444 curX
= ADD_INT32( curX
, lsb_x
);
2448 case cf2_cmdENDCHAR
:
2449 FT_TRACE4(( " endchar\n" ));
2451 if ( font
->isT1
&& !initial_map_ready
)
2453 FT_TRACE5(( "cf2_interpT2CharString (Type 1 mode): "
2454 "Build initial hintmap, rewinding...\n" ));
2456 /* trigger initial hintmap build */
2457 cf2_glyphpath_moveTo( &glyphPath
, curX
, curY
);
2459 initial_map_ready
= TRUE
;
2461 /* change hints routine - clear for rewind */
2462 cf2_arrstack_clear( &vStemHintArray
);
2463 cf2_arrstack_clear( &hStemHintArray
);
2465 cf2_hintmask_init( &hintMask
, error
);
2466 hintMask
.isValid
= FALSE
;
2467 hintMask
.isNew
= TRUE
;
2469 /* rewind charstring */
2470 /* some charstrings use endchar from a final subroutine call */
2471 /* without returning, detect these and exit to the top level */
2473 while ( charstringIndex
> 0 )
2475 FT_TRACE4(( " return (leaving level %d)\n", charstringIndex
));
2477 /* restore position in previous charstring */
2478 charstring
= (CF2_Buffer
)
2479 cf2_arrstack_getPointer(
2481 (CF2_UInt
)--charstringIndex
);
2483 charstring
->ptr
= charstring
->start
;
2488 if ( cf2_stack_count( opStack
) == 1 ||
2489 cf2_stack_count( opStack
) == 5 )
2492 *width
= ADD_INT32( cf2_stack_getReal( opStack
, 0 ),
2496 /* width is defined or default after this */
2499 if ( decoder
->width_only
)
2502 /* close path if still open */
2503 cf2_glyphpath_closeOpenPath( &glyphPath
);
2505 /* disable seac for CFF2 and Type1 */
2506 /* (charstring ending with args on stack) */
2507 if ( !font
->isCFF2
&& !font
->isT1
&& cf2_stack_count( opStack
) > 1 )
2509 /* must be either 4 or 5 -- */
2510 /* this is a (deprecated) implied `seac' operator */
2514 CF2_BufferRec component
;
2515 CF2_Fixed dummyWidth
; /* ignore component width */
2521 lastError
= FT_THROW( Invalid_Glyph_Format
);
2522 goto exit
; /* nested seac */
2525 achar
= cf2_stack_popInt( opStack
);
2526 bchar
= cf2_stack_popInt( opStack
);
2528 curY
= cf2_stack_popFixed( opStack
);
2529 curX
= cf2_stack_popFixed( opStack
);
2531 error2
= cf2_getSeacComponent( decoder
, achar
, &component
);
2534 lastError
= error2
; /* pass FreeType error through */
2537 cf2_interpT2CharString( font
,
2545 cf2_freeSeacComponent( decoder
, &component
);
2547 error2
= cf2_getSeacComponent( decoder
, bchar
, &component
);
2550 lastError
= error2
; /* pass FreeType error through */
2553 cf2_interpT2CharString( font
,
2561 cf2_freeSeacComponent( decoder
, &component
);
2565 case cf2_cmdCNTRMASK
:
2566 case cf2_cmdHINTMASK
:
2567 /* the final \n in the tracing message gets added in */
2568 /* `cf2_hintmask_read' (which also traces the mask bytes) */
2569 FT_TRACE4(( op1
== cf2_cmdCNTRMASK
? " cntrmask" : " hintmask" ));
2571 /* never add hints after the mask is computed */
2572 if ( cf2_stack_count( opStack
) > 1 &&
2573 cf2_hintmask_isValid( &hintMask
) )
2575 FT_TRACE4(( "cf2_interpT2CharString: invalid hint mask\n" ));
2579 /* if there are arguments on the stack, there this is an */
2580 /* implied cf2_cmdVSTEMHM */
2588 if ( decoder
->width_only
)
2591 if ( op1
== cf2_cmdHINTMASK
)
2593 /* consume the hint mask bytes which follow the operator */
2594 cf2_hintmask_read( &hintMask
,
2596 cf2_arrstack_size( &hStemHintArray
) +
2597 cf2_arrstack_size( &vStemHintArray
) );
2602 * Consume the counter mask bytes which follow the operator:
2603 * Build a temporary hint map, just to place and lock those
2604 * stems participating in the counter mask. These are most
2605 * likely the dominant hstems, and are grouped together in a
2606 * few counter groups, not necessarily in correspondence
2607 * with the hint groups. This reduces the chances of
2608 * conflicts between hstems that are initially placed in
2609 * separate hint groups and then brought together. The
2610 * positions are copied back to `hStemHintArray', so we can
2611 * discard `counterMask' and `counterHintMap'.
2615 CF2_HintMapRec
*counterHintMap
= malloc(sizeof(CF2_HintMapRec
));
2616 /* Ugly but it allows us to reduce the diff */
2617 #define counterHintMap (*counterHintMap)
2619 CF2_HintMapRec counterHintMap
;
2621 CF2_HintMaskRec counterMask
;
2624 cf2_hintmap_init( &counterHintMap
,
2626 &glyphPath
.initialHintMap
,
2627 &glyphPath
.hintMoves
,
2629 cf2_hintmask_init( &counterMask
, error
);
2631 cf2_hintmask_read( &counterMask
,
2633 cf2_arrstack_size( &hStemHintArray
) +
2634 cf2_arrstack_size( &vStemHintArray
) );
2635 cf2_hintmap_build( &counterHintMap
,
2642 free(&counterHintMap
);
2647 case cf2_cmdRMOVETO
:
2648 FT_TRACE4(( " rmoveto\n" ));
2650 if ( font
->isT1
&& !decoder
->flex_state
&& !haveWidth
)
2651 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
2652 " No width. Use hsbw/sbw as first op\n" ));
2654 if ( cf2_stack_count( opStack
) > 2 && !haveWidth
)
2655 *width
= ADD_INT32( cf2_stack_getReal( opStack
, 0 ),
2658 /* width is defined or default after this */
2661 if ( decoder
->width_only
)
2664 curY
= ADD_INT32( curY
, cf2_stack_popFixed( opStack
) );
2665 curX
= ADD_INT32( curX
, cf2_stack_popFixed( opStack
) );
2667 if ( !decoder
->flex_state
)
2668 cf2_glyphpath_moveTo( &glyphPath
, curX
, curY
);
2672 case cf2_cmdHMOVETO
:
2673 FT_TRACE4(( " hmoveto\n" ));
2675 if ( font
->isT1
&& !decoder
->flex_state
&& !haveWidth
)
2676 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
2677 " No width. Use hsbw/sbw as first op\n" ));
2679 if ( cf2_stack_count( opStack
) > 1 && !haveWidth
)
2680 *width
= ADD_INT32( cf2_stack_getReal( opStack
, 0 ),
2683 /* width is defined or default after this */
2686 if ( decoder
->width_only
)
2689 curX
= ADD_INT32( curX
, cf2_stack_popFixed( opStack
) );
2691 cf2_glyphpath_moveTo( &glyphPath
, curX
, curY
);
2695 case cf2_cmdRLINECURVE
:
2697 CF2_UInt count
= cf2_stack_count( opStack
);
2701 FT_TRACE4(( " rlinecurve\n" ));
2703 while ( idx
+ 6 < count
)
2705 curX
= ADD_INT32( curX
, cf2_stack_getReal( opStack
,
2707 curY
= ADD_INT32( curY
, cf2_stack_getReal( opStack
,
2710 cf2_glyphpath_lineTo( &glyphPath
, curX
, curY
);
2714 while ( idx
< count
)
2716 CF2_Fixed x1
, y1
, x2
, y2
, x3
, y3
;
2719 x1
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 0 ), curX
);
2720 y1
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 1 ), curY
);
2721 x2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 2 ), x1
);
2722 y2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 3 ), y1
);
2723 x3
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 4 ), x2
);
2724 y3
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 5 ), y2
);
2726 cf2_glyphpath_curveTo( &glyphPath
, x1
, y1
, x2
, y2
, x3
, y3
);
2733 cf2_stack_clear( opStack
);
2735 continue; /* no need to clear stack again */
2737 case cf2_cmdVVCURVETO
:
2739 CF2_UInt count
, count1
= cf2_stack_count( opStack
);
2743 /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */
2744 /* we enforce it by clearing the second bit */
2745 /* (and sorting the stack indexing to suit) */
2746 count
= count1
& ~2U;
2747 idx
+= count1
- count
;
2749 FT_TRACE4(( " vvcurveto\n" ));
2751 while ( idx
< count
)
2753 CF2_Fixed x1
, y1
, x2
, y2
, x3
, y3
;
2756 if ( ( count
- idx
) & 1 )
2758 x1
= ADD_INT32( cf2_stack_getReal( opStack
, idx
), curX
);
2765 y1
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 0 ), curY
);
2766 x2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 1 ), x1
);
2767 y2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 2 ), y1
);
2769 y3
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 3 ), y2
);
2771 cf2_glyphpath_curveTo( &glyphPath
, x1
, y1
, x2
, y2
, x3
, y3
);
2778 cf2_stack_clear( opStack
);
2780 continue; /* no need to clear stack again */
2782 case cf2_cmdHHCURVETO
:
2784 CF2_UInt count
, count1
= cf2_stack_count( opStack
);
2788 /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */
2789 /* we enforce it by clearing the second bit */
2790 /* (and sorting the stack indexing to suit) */
2791 count
= count1
& ~2U;
2792 idx
+= count1
- count
;
2794 FT_TRACE4(( " hhcurveto\n" ));
2796 while ( idx
< count
)
2798 CF2_Fixed x1
, y1
, x2
, y2
, x3
, y3
;
2801 if ( ( count
- idx
) & 1 )
2803 y1
= ADD_INT32( cf2_stack_getReal( opStack
, idx
), curY
);
2810 x1
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 0 ), curX
);
2811 x2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 1 ), x1
);
2812 y2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 2 ), y1
);
2813 x3
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 3 ), x2
);
2816 cf2_glyphpath_curveTo( &glyphPath
, x1
, y1
, x2
, y2
, x3
, y3
);
2823 cf2_stack_clear( opStack
);
2825 continue; /* no need to clear stack again */
2827 case cf2_cmdVHCURVETO
:
2828 case cf2_cmdHVCURVETO
:
2830 CF2_UInt count
, count1
= cf2_stack_count( opStack
);
2833 FT_Bool alternate
= FT_BOOL( op1
== cf2_cmdHVCURVETO
);
2836 /* if `cf2_stack_count' isn't of the form 8n, 8n+1, */
2837 /* 8n+4, or 8n+5, we enforce it by clearing the */
2839 /* (and sorting the stack indexing to suit) */
2840 count
= count1
& ~2U;
2841 idx
+= count1
- count
;
2843 FT_TRACE4(( alternate
? " hvcurveto\n" : " vhcurveto\n" ));
2845 while ( idx
< count
)
2847 CF2_Fixed x1
, x2
, x3
, y1
, y2
, y3
;
2852 x1
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 0 ), curX
);
2854 x2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 1 ), x1
);
2855 y2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 2 ), y1
);
2856 y3
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 3 ), y2
);
2858 if ( count
- idx
== 5 )
2860 x3
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 4 ), x2
);
2872 y1
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 0 ), curY
);
2873 x2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 1 ), x1
);
2874 y2
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 2 ), y1
);
2875 x3
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 3 ), x2
);
2877 if ( count
- idx
== 5 )
2879 y3
= ADD_INT32( cf2_stack_getReal( opStack
, idx
+ 4 ), y2
);
2889 cf2_glyphpath_curveTo( &glyphPath
, x1
, y1
, x2
, y2
, x3
, y3
);
2896 cf2_stack_clear( opStack
);
2898 continue; /* no need to clear stack again */
2900 case cf2_cmdEXTENDEDNMBR
:
2904 CF2_Int byte1
= cf2_buf_readByte( charstring
);
2905 CF2_Int byte2
= cf2_buf_readByte( charstring
);
2908 v
= (FT_Short
)( ( byte1
<< 8 ) |
2911 FT_TRACE4(( " %d", v
));
2913 cf2_stack_pushInt( opStack
, v
);
2920 if ( /* op1 >= 32 && */ op1
<= 246 )
2927 FT_TRACE4(( " %d", v
));
2930 cf2_stack_pushInt( opStack
, v
);
2933 else if ( /* op1 >= 247 && */ op1
<= 250 )
2941 v
+= cf2_buf_readByte( charstring
);
2944 FT_TRACE4(( " %d", v
));
2947 cf2_stack_pushInt( opStack
, v
);
2950 else if ( /* op1 >= 251 && */ op1
<= 254 )
2958 v
+= cf2_buf_readByte( charstring
);
2961 FT_TRACE4(( " %d", v
));
2964 cf2_stack_pushInt( opStack
, v
);
2967 else /* op1 == 255 */
2971 FT_UInt32 byte1
= (FT_UInt32
)cf2_buf_readByte( charstring
);
2972 FT_UInt32 byte2
= (FT_UInt32
)cf2_buf_readByte( charstring
);
2973 FT_UInt32 byte3
= (FT_UInt32
)cf2_buf_readByte( charstring
);
2974 FT_UInt32 byte4
= (FT_UInt32
)cf2_buf_readByte( charstring
);
2977 v
= (CF2_Fixed
)( ( byte1
<< 24 ) |
2985 * According to the specification, values > 32000 or < -32000
2986 * must be followed by a `div' operator to make the result be
2987 * in the range [-32000;32000]. We expect that the second
2988 * argument of `div' is not a large number. Additionally, we
2989 * don't handle stuff like `<large1> <large2> <num> div <num>
2990 * div' or <large1> <large2> <num> div div'. This is probably
2991 * not allowed anyway.
2993 * <large> <num> <num>+ div is not checked but should not be
2994 * allowed as the large value remains untouched.
2999 if ( v
> 32000 || v
< -32000 )
3002 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
3003 " no `div' after large integer\n" ));
3008 FT_TRACE4(( " %d", v
));
3010 cf2_stack_pushInt( opStack
, (CF2_Int
)v
);
3014 FT_TRACE4(( " %.5fF", v
/ 65536.0 ));
3016 cf2_stack_pushFixed( opStack
, v
);
3020 continue; /* don't clear stack */
3022 } /* end of switch statement checking `op1' */
3024 cf2_stack_clear( opStack
);
3026 } /* end of main interpreter loop */
3028 /* we get here if the charstring ends without cf2_cmdENDCHAR */
3029 FT_TRACE4(( "cf2_interpT2CharString:"
3030 " charstring ends without ENDCHAR\n" ));
3033 /* check whether last error seen is also the first one */
3034 cf2_setError( error
, lastError
);
3037 FT_TRACE4(( "charstring error %d\n", *error
));
3039 /* free resources from objects we've used */
3040 cf2_glyphpath_finalize( &glyphPath
);
3041 cf2_arrstack_finalize( &vStemHintArray
);
3042 cf2_arrstack_finalize( &hStemHintArray
);
3043 cf2_arrstack_finalize( &subrStack
);
3044 cf2_stack_free( opStack
);
3046 FT_TRACE4(( "\n" ));
3050 #undef counterHintMap