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