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