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