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