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 <freetype/internal/ftdebug.h>
41#include <freetype/internal/services/svcfftl.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 const 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(( "cf2_interpT2CharString:\n" ));
1344 FT_ERROR(( " (Type 1 seac) glyph names table"
1345 " 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(( "cf2_interpT2CharString:\n" ));
1372 FT_ERROR(( " (Type 1 seac) invalid"
1373 " 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
1437 /* save the left bearing and width of the SEAC */
1438 /* glyph as they will be erased by the next load */
1439
1440 left_bearing = *decoder->builder.left_bearing;
1441 advance = *decoder->builder.advance;
1442
1443 cf2_interpT2CharString( font,
1444 &component,
1445 callbacks,
1446 translation,
1447 TRUE,
1448 0,
1449 0,
1450 &dummyWidth );
1451 cf2_freeT1SeacComponent( decoder, &component );
1452
1453 /* If the SEAC glyph doesn't have a (H)SBW of its */
1454 /* own use the values from the base glyph. */
1455
1456 if ( !haveWidth )
1457 {
1458 left_bearing = *decoder->builder.left_bearing;
1459 advance = *decoder->builder.advance;
1460 }
1461
1462 decoder->builder.left_bearing->x = 0;
1463 decoder->builder.left_bearing->y = 0;
1464
1465 /* Now load `achar' on top of */
1466 /* the base outline */
1467
1468 error2 = cf2_getT1SeacComponent( decoder,
1469 (FT_UInt)achar_index,
1470 &component );
1471 if ( error2 )
1472 {
1473 lastError = error2; /* pass FreeType error through */
1474 goto exit;
1475 }
1476 cf2_interpT2CharString( font,
1477 &component,
1478 callbacks,
1479 translation,
1480 TRUE,
1481 adx - asb,
1482 ady,
1483 &dummyWidth );
1484 cf2_freeT1SeacComponent( decoder, &component );
1485
1486 /* restore the left side bearing and advance width */
1487 /* of the SEAC glyph or base character (saved above) */
1488
1489 *decoder->builder.left_bearing = left_bearing;
1490 *decoder->builder.advance = advance;
1491
1492 goto exit;
1493 }
1494 break;
1495
1496 case cf2_escSBW:
1497 if ( !font->isT1 )
1498 FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
1499 else
1500 {
1501 CF2_Fixed lsb_x, lsb_y;
1502 PS_Builder* builder;
1503
1504
1505 FT_TRACE4(( " sbw" ));
1506
1507 builder = &decoder->builder;
1508
1509 builder->advance->y = cf2_stack_popFixed( opStack );
1510 builder->advance->x = cf2_stack_popFixed( opStack );
1511
1512 lsb_y = cf2_stack_popFixed( opStack );
1513 lsb_x = cf2_stack_popFixed( opStack );
1514
1515 builder->left_bearing->x =
1516 ADD_INT32( builder->left_bearing->x, lsb_x );
1517 builder->left_bearing->y =
1518 ADD_INT32( builder->left_bearing->y, lsb_y );
1519
1520 haveWidth = TRUE;
1521
1522 /* the `metrics_only' indicates that we only want */
1523 /* to compute the glyph's metrics (lsb + advance */
1524 /* width), not load the rest of it; so exit */
1525 /* immediately */
1526 if ( builder->metrics_only )
1527 goto exit;
1528
1529 if ( initial_map_ready )
1530 {
1531 curX = ADD_INT32( curX, lsb_x );
1532 curY = ADD_INT32( curY, lsb_y );
1533 }
1534 }
1535 break;
1536
1537 case cf2_escABS:
1538 {
1539 CF2_F16Dot16 arg;
1540
1541
1542 FT_TRACE4(( " abs\n" ));
1543
1544 arg = cf2_stack_popFixed( opStack );
1545
1546 if ( arg < -CF2_FIXED_MAX )
1547 cf2_stack_pushFixed( opStack, CF2_FIXED_MAX );
1548 else
1549 cf2_stack_pushFixed( opStack, FT_ABS( arg ) );
1550 }
1551 continue; /* do not clear the stack */
1552
1553 case cf2_escADD:
1554 {
1555 CF2_F16Dot16 summand1;
1556 CF2_F16Dot16 summand2;
1557
1558
1559 FT_TRACE4(( " add\n" ));
1560
1561 summand2 = cf2_stack_popFixed( opStack );
1562 summand1 = cf2_stack_popFixed( opStack );
1563
1564 cf2_stack_pushFixed( opStack,
1565 ADD_INT32( summand1,
1566 summand2 ) );
1567 }
1568 continue; /* do not clear the stack */
1569
1570 case cf2_escSUB:
1571 {
1572 CF2_F16Dot16 minuend;
1573 CF2_F16Dot16 subtrahend;
1574
1575
1576 FT_TRACE4(( " sub\n" ));
1577
1578 subtrahend = cf2_stack_popFixed( opStack );
1579 minuend = cf2_stack_popFixed( opStack );
1580
1581 cf2_stack_pushFixed( opStack,
1582 SUB_INT32( minuend, subtrahend ) );
1583 }
1584 continue; /* do not clear the stack */
1585
1586 case cf2_escDIV:
1587 {
1588 CF2_F16Dot16 dividend;
1589 CF2_F16Dot16 divisor;
1590
1591
1592 FT_TRACE4(( " div\n" ));
1593
1594 if ( font->isT1 && large_int )
1595 {
1596 divisor = (CF2_F16Dot16)cf2_stack_popInt( opStack );
1597 dividend = (CF2_F16Dot16)cf2_stack_popInt( opStack );
1598
1599 large_int = FALSE;
1600 }
1601 else
1602 {
1603 divisor = cf2_stack_popFixed( opStack );
1604 dividend = cf2_stack_popFixed( opStack );
1605 }
1606
1607 cf2_stack_pushFixed( opStack,
1608 FT_DivFix( dividend, divisor ) );
1609
1610 }
1611 continue; /* do not clear the stack */
1612
1613 case cf2_escNEG:
1614 {
1615 CF2_F16Dot16 arg;
1616
1617
1618 FT_TRACE4(( " neg\n" ));
1619
1620 arg = cf2_stack_popFixed( opStack );
1621
1622 if ( arg < -CF2_FIXED_MAX )
1623 cf2_stack_pushFixed( opStack, CF2_FIXED_MAX );
1624 else
1625 cf2_stack_pushFixed( opStack, -arg );
1626 }
1627 continue; /* do not clear the stack */
1628
1629 case cf2_escEQ:
1630 {
1631 CF2_F16Dot16 arg1;
1632 CF2_F16Dot16 arg2;
1633
1634
1635 FT_TRACE4(( " eq\n" ));
1636
1637 arg2 = cf2_stack_popFixed( opStack );
1638 arg1 = cf2_stack_popFixed( opStack );
1639
1640 cf2_stack_pushInt( opStack, arg1 == arg2 );
1641 }
1642 continue; /* do not clear the stack */
1643
1644 case cf2_escCALLOTHERSUBR:
1645 if ( !font->isT1 )
1646 FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
1647 else
1648 {
1649 CF2_Int subr_no;
1650 CF2_Int arg_cnt;
1651 CF2_UInt count;
1652 CF2_UInt opIdx = 0;
1653
1654
1655 FT_TRACE4(( " callothersubr\n" ));
1656
1657 subr_no = cf2_stack_popInt( opStack );
1658 arg_cnt = cf2_stack_popInt( opStack );
1659
1660 /********************************************************
1661 *
1662 * remove all operands to callothersubr from the stack
1663 *
1664 * for handled othersubrs, where we know the number of
1665 * arguments, we increase the stack by the value of
1666 * known_othersubr_result_cnt
1667 *
1668 * for unhandled othersubrs the following pops adjust
1669 * the stack pointer as necessary
1670 */
1671
1672 count = cf2_stack_count( opStack );
1673 if ( (CF2_UInt)arg_cnt > count )
1674 {
1675 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
1676 " stack underflow\n" ));
1677 lastError = FT_THROW( Invalid_Glyph_Format );
1678 goto exit;
1679 }
1680
1681 opIdx += count - (CF2_UInt)arg_cnt;
1682
1683 known_othersubr_result_cnt = 0;
1684 result_cnt = 0;
1685
1686 /* XXX TODO: The checks to `arg_count == <whatever>' */
1687 /* might not be correct; an othersubr expects a */
1688 /* certain number of operands on the PostScript stack */
1689 /* (as opposed to the T1 stack) but it doesn't have to */
1690 /* put them there by itself; previous othersubrs might */
1691 /* have left the operands there if they were not */
1692 /* followed by an appropriate number of pops */
1693 /* */
1694 /* On the other hand, Adobe Reader 7.0.8 for Linux */
1695 /* doesn't accept a font that contains charstrings */
1696 /* like */
1697 /* */
1698 /* 100 200 2 20 callothersubr */
1699 /* 300 1 20 callothersubr pop */
1700 /* */
1701 /* Perhaps this is the reason why BuildCharArray */
1702 /* exists. */
1703
1704 switch ( subr_no )
1705 {
1706 case 0: /* end flex feature */
1707 if ( arg_cnt != 3 )
1708 goto Unexpected_OtherSubr;
1709
1710 if ( initial_map_ready &&
1711 ( !decoder->flex_state ||
1712 decoder->num_flex_vectors != 7 ) )
1713 {
1714 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
1715 " unexpected flex end\n" ));
1716 lastError = FT_THROW( Invalid_Glyph_Format );
1717 goto exit;
1718 }
1719
1720 /* the two `results' are popped */
1721 /* by the following setcurrentpoint */
1722 cf2_stack_pushFixed( opStack, curX );
1723 cf2_stack_pushFixed( opStack, curY );
1724 known_othersubr_result_cnt = 2;
1725 break;
1726
1727 case 1: /* start flex feature */
1728 if ( arg_cnt != 0 )
1729 goto Unexpected_OtherSubr;
1730
1731 if ( !initial_map_ready )
1732 break;
1733
1734 if ( ps_builder_check_points( &decoder->builder, 6 ) )
1735 goto exit;
1736
1737 decoder->flex_state = 1;
1738 decoder->num_flex_vectors = 0;
1739 break;
1740
1741 case 2: /* add flex vectors */
1742 {
1743 FT_Int idx;
1744 FT_Int idx2;
1745
1746
1747 if ( arg_cnt != 0 )
1748 goto Unexpected_OtherSubr;
1749
1750 if ( !initial_map_ready )
1751 break;
1752
1753 if ( !decoder->flex_state )
1754 {
1755 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
1756 " missing flex start\n" ));
1757 lastError = FT_THROW( Invalid_Glyph_Format );
1758 goto exit;
1759 }
1760
1761 /* note that we should not add a point for */
1762 /* index 0; this will move our current position */
1763 /* to the flex point without adding any point */
1764 /* to the outline */
1765 idx = decoder->num_flex_vectors++;
1766 if ( idx > 0 && idx < 7 )
1767 {
1768 /* in malformed fonts it is possible to have */
1769 /* other opcodes in the middle of a flex (which */
1770 /* don't increase `num_flex_vectors'); we thus */
1771 /* have to check whether we can add a point */
1772
1773 if ( ps_builder_check_points( &decoder->builder,
1774 1 ) )
1775 {
1776 lastError = FT_THROW( Invalid_Glyph_Format );
1777 goto exit;
1778 }
1779
1780 /* map: 1->2 2->4 3->6 4->2 5->4 6->6 */
1781 idx2 = ( idx > 3 ? idx - 3 : idx ) * 2;
1782
1783 flexStore[idx2 - 2] = curX;
1784 flexStore[idx2 - 1] = curY;
1785
1786 if ( idx == 3 || idx == 6 )
1787 cf2_glyphpath_curveTo( &glyphPath,
1788 flexStore[0],
1789 flexStore[1],
1790 flexStore[2],
1791 flexStore[3],
1792 flexStore[4],
1793 flexStore[5] );
1794 }
1795 }
1796 break;
1797
1798 case 3: /* change hints */
1799 if ( arg_cnt != 1 )
1800 goto Unexpected_OtherSubr;
1801
1802 if ( initial_map_ready )
1803 {
1804 /* do not clear hints if initial hintmap */
1805 /* is not ready - we need to collate all */
1806 cf2_arrstack_clear( &vStemHintArray );
1807 cf2_arrstack_clear( &hStemHintArray );
1808
1809 cf2_hintmask_init( &hintMask, error );
1810 hintMask.isValid = FALSE;
1811 hintMask.isNew = TRUE;
1812 }
1813
1814 known_othersubr_result_cnt = 1;
1815 break;
1816
1817 case 12:
1818 case 13:
1819 /* counter control hints, clear stack */
1820 cf2_stack_clear( opStack );
1821 break;
1822
1823 case 14:
1824 case 15:
1825 case 16:
1826 case 17:
1827 case 18: /* multiple masters */
1828 {
1829 PS_Blend blend = decoder->blend;
1830 FT_UInt num_points, nn, mm;
1831 CF2_UInt delta;
1832 CF2_UInt values;
1833
1834
1835 if ( !blend )
1836 {
1837 FT_ERROR((
1838 "cf2_interpT2CharString:"
1839 " unexpected multiple masters operator\n" ));
1840 lastError = FT_THROW( Invalid_Glyph_Format );
1841 goto exit;
1842 }
1843
1844 num_points = (FT_UInt)subr_no - 13 +
1845 ( subr_no == 18 );
1846 if ( arg_cnt != (FT_Int)( num_points *
1847 blend->num_designs ) )
1848 {
1849 FT_ERROR((
1850 "cf2_interpT2CharString:"
1851 " incorrect number of multiple masters arguments\n" ));
1852 lastError = FT_THROW( Invalid_Glyph_Format );
1853 goto exit;
1854 }
1855
1856 /* We want to compute */
1857 /* */
1858 /* a0*w0 + a1*w1 + ... + ak*wk */
1859 /* */
1860 /* but we only have a0, a1-a0, a2-a0, ..., ak-a0. */
1861 /* */
1862 /* However, given that w0 + w1 + ... + wk == 1, we */
1863 /* can rewrite it easily as */
1864 /* */
1865 /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + ... + (ak-a0)*wk */
1866 /* */
1867 /* where k == num_designs-1. */
1868 /* */
1869 /* I guess that's why it's written in this `compact' */
1870 /* form. */
1871 /* */
1872 delta = opIdx + num_points;
1873 values = opIdx;
1874 for ( nn = 0; nn < num_points; nn++ )
1875 {
1876 CF2_Fixed tmp = cf2_stack_getReal( opStack,
1877 values );
1878
1879
1880 for ( mm = 1; mm < blend->num_designs; mm++ )
1881 tmp = ADD_INT32( tmp,
1882 FT_MulFix(
1883 cf2_stack_getReal( opStack,
1884 delta++ ),
1885 blend->weight_vector[mm] ) );
1886
1887 cf2_stack_setReal( opStack, values++, tmp );
1888 }
1889 cf2_stack_pop( opStack,
1890 (CF2_UInt)arg_cnt - num_points );
1891
1892 known_othersubr_result_cnt = (FT_Int)num_points;
1893 break;
1894 }
1895
1896 case 19:
1897 /* <idx> 1 19 callothersubr */
1898 /* ==> replace elements starting from index */
1899 /* cvi( <idx> ) of BuildCharArray with */
1900 /* WeightVector */
1901 {
1902 FT_UInt idx;
1903 PS_Blend blend = decoder->blend;
1904 FT_UInt len_buildchar = decoder->len_buildchar;
1905
1906
1907 if ( arg_cnt != 1 || !blend )
1908 goto Unexpected_OtherSubr;
1909
1910 idx = (FT_UInt)cf2_stack_popInt( opStack );
1911
1912 if ( len_buildchar < blend->num_designs ||
1913 len_buildchar - blend->num_designs < idx )
1914 goto Unexpected_OtherSubr;
1915
1916 if ( decoder->buildchar && blend->weight_vector )
1917 ft_memcpy( &decoder->buildchar[idx],
1918 blend->weight_vector,
1919 blend->num_designs *
1920 sizeof ( blend->weight_vector[0] ) );
1921 }
1922 break;
1923
1924 case 20:
1925 /* <arg1> <arg2> 2 20 callothersubr pop */
1926 /* ==> push <arg1> + <arg2> onto T1 stack */
1927 {
1928 CF2_F16Dot16 summand1;
1929 CF2_F16Dot16 summand2;
1930
1931
1932 if ( arg_cnt != 2 )
1933 goto Unexpected_OtherSubr;
1934
1935 summand2 = cf2_stack_popFixed( opStack );
1936 summand1 = cf2_stack_popFixed( opStack );
1937
1938 cf2_stack_pushFixed( opStack,
1939 ADD_INT32( summand1,
1940 summand2 ) );
1941 known_othersubr_result_cnt = 1;
1942 }
1943 break;
1944
1945 case 21:
1946 /* <arg1> <arg2> 2 21 callothersubr pop */
1947 /* ==> push <arg1> - <arg2> onto T1 stack */
1948 {
1949 CF2_F16Dot16 minuend;
1950 CF2_F16Dot16 subtrahend;
1951
1952
1953 if ( arg_cnt != 2 )
1954 goto Unexpected_OtherSubr;
1955
1956 subtrahend = cf2_stack_popFixed( opStack );
1957 minuend = cf2_stack_popFixed( opStack );
1958
1959 cf2_stack_pushFixed( opStack,
1960 SUB_INT32( minuend,
1961 subtrahend ) );
1962 known_othersubr_result_cnt = 1;
1963 }
1964 break;
1965
1966 case 22:
1967 /* <arg1> <arg2> 2 22 callothersubr pop */
1968 /* ==> push <arg1> * <arg2> onto T1 stack */
1969 {
1970 CF2_F16Dot16 factor1;
1971 CF2_F16Dot16 factor2;
1972
1973
1974 if ( arg_cnt != 2 )
1975 goto Unexpected_OtherSubr;
1976
1977 factor2 = cf2_stack_popFixed( opStack );
1978 factor1 = cf2_stack_popFixed( opStack );
1979
1980 cf2_stack_pushFixed( opStack,
1981 FT_MulFix( factor1, factor2 ) );
1982 known_othersubr_result_cnt = 1;
1983 }
1984 break;
1985
1986 case 23:
1987 /* <arg1> <arg2> 2 23 callothersubr pop */
1988 /* ==> push <arg1> / <arg2> onto T1 stack */
1989 {
1990 CF2_F16Dot16 dividend;
1991 CF2_F16Dot16 divisor;
1992
1993
1994 if ( arg_cnt != 2 )
1995 goto Unexpected_OtherSubr;
1996
1997 divisor = cf2_stack_popFixed( opStack );
1998 dividend = cf2_stack_popFixed( opStack );
1999
2000 if ( divisor == 0 )
2001 goto Unexpected_OtherSubr;
2002
2003 cf2_stack_pushFixed( opStack,
2004 FT_DivFix( dividend,
2005 divisor ) );
2006 known_othersubr_result_cnt = 1;
2007 }
2008 break;
2009
2010 case 24:
2011 /* <val> <idx> 2 24 callothersubr */
2012 /* ==> set BuildCharArray[cvi( <idx> )] = <val> */
2013 {
2014 CF2_UInt idx;
2015 PS_Blend blend = decoder->blend;
2016
2017
2018 if ( arg_cnt != 2 || !blend )
2019 goto Unexpected_OtherSubr;
2020
2021 idx = (CF2_UInt)cf2_stack_popInt( opStack );
2022
2023 if ( idx >= decoder->len_buildchar )
2024 goto Unexpected_OtherSubr;
2025
2026 decoder->buildchar[idx] =
2027 cf2_stack_popFixed( opStack );
2028 }
2029 break;
2030
2031 case 25:
2032 /* <idx> 1 25 callothersubr pop */
2033 /* ==> push BuildCharArray[cvi( idx )] */
2034 /* onto T1 stack */
2035 {
2036 CF2_UInt idx;
2037 PS_Blend blend = decoder->blend;
2038
2039
2040 if ( arg_cnt != 1 || !blend )
2041 goto Unexpected_OtherSubr;
2042
2043 idx = (CF2_UInt)cf2_stack_popInt( opStack );
2044
2045 if ( idx >= decoder->len_buildchar )
2046 goto Unexpected_OtherSubr;
2047
2048 cf2_stack_pushFixed( opStack,
2049 decoder->buildchar[idx] );
2050 known_othersubr_result_cnt = 1;
2051 }
2052 break;
2053
2054#if 0
2055 case 26:
2056 /* <val> mark <idx> */
2057 /* ==> set BuildCharArray[cvi( <idx> )] = <val>, */
2058 /* leave mark on T1 stack */
2059 /* <val> <idx> */
2060 /* ==> set BuildCharArray[cvi( <idx> )] = <val> */
2061 XXX which routine has left its mark on the
2062 XXX (PostScript) stack?;
2063 break;
2064#endif
2065
2066 case 27:
2067 /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */
2068 /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */
2069 /* otherwise push <res2> */
2070 {
2071 CF2_F16Dot16 arg1;
2072 CF2_F16Dot16 arg2;
2073 CF2_F16Dot16 cond1;
2074 CF2_F16Dot16 cond2;
2075
2076
2077 if ( arg_cnt != 4 )
2078 goto Unexpected_OtherSubr;
2079
2080 cond2 = cf2_stack_popFixed( opStack );
2081 cond1 = cf2_stack_popFixed( opStack );
2082 arg2 = cf2_stack_popFixed( opStack );
2083 arg1 = cf2_stack_popFixed( opStack );
2084
2085 cf2_stack_pushFixed( opStack,
2086 cond1 <= cond2 ? arg1 : arg2 );
2087 known_othersubr_result_cnt = 1;
2088 }
2089 break;
2090
2091 case 28:
2092 /* 0 28 callothersubr pop */
2093 /* ==> push random value from interval [0, 1) */
2094 /* onto stack */
2095 {
2096 CF2_F16Dot16 r;
2097
2098
2099 if ( arg_cnt != 0 )
2100 goto Unexpected_OtherSubr;
2101
2102 /* only use the lower 16 bits of `random' */
2103 /* to generate a number in the range (0;1] */
2104 r = (CF2_F16Dot16)
2105 ( ( decoder->current_subfont->random & 0xFFFF ) + 1 );
2106
2107 decoder->current_subfont->random =
2108 cff_random( decoder->current_subfont->random );
2109
2110 cf2_stack_pushFixed( opStack, r );
2111 known_othersubr_result_cnt = 1;
2112 }
2113 break;
2114
2115 default:
2116 if ( arg_cnt >= 0 && subr_no >= 0 )
2117 {
2118 FT_Int i;
2119
2120
2121 FT_ERROR((
2122 "cf2_interpT2CharString (Type 1 mode):"
2123 " unknown othersubr [%d %d], wish me luck\n",
2124 arg_cnt, subr_no ));
2125
2126 /* store the unused args */
2127 /* for this unhandled OtherSubr */
2128
2129 if ( arg_cnt > PS_STORAGE_SIZE )
2130 arg_cnt = PS_STORAGE_SIZE;
2131 result_cnt = arg_cnt;
2132
2133 for ( i = 1; i <= arg_cnt; i++ )
2134 results[result_cnt - i] =
2135 cf2_stack_popFixed( opStack );
2136
2137 break;
2138 }
2139 /* fall through */
2140
2141 Unexpected_OtherSubr:
2142 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
2143 " invalid othersubr [%d %d]\n",
2144 arg_cnt, subr_no ));
2145 lastError = FT_THROW( Invalid_Glyph_Format );
2146 goto exit;
2147 }
2148 }
2149 continue; /* do not clear the stack */
2150
2151 case cf2_escPOP:
2152 if ( !font->isT1 )
2153 FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
2154 else
2155 {
2156 FT_TRACE4(( " pop" ));
2157
2158 if ( known_othersubr_result_cnt > 0 )
2159 {
2160 known_othersubr_result_cnt--;
2161 /* ignore, we pushed the operands ourselves */
2162 continue;
2163 }
2164
2165 if ( result_cnt == 0 )
2166 {
2167 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
2168 " no more operands for othersubr\n" ));
2169 lastError = FT_THROW( Invalid_Glyph_Format );
2170 goto exit;
2171 }
2172
2173 result_cnt--;
2174 cf2_stack_pushFixed( opStack, results[result_cnt] );
2175 }
2176 continue; /* do not clear the stack */
2177
2178 case cf2_escDROP:
2179 FT_TRACE4(( " drop\n" ));
2180
2181 (void)cf2_stack_popFixed( opStack );
2182 continue; /* do not clear the stack */
2183
2184 case cf2_escPUT:
2185 {
2186 CF2_F16Dot16 val;
2187 CF2_UInt idx;
2188
2189
2190 FT_TRACE4(( " put\n" ));
2191
2192 idx = (CF2_UInt)cf2_stack_popInt( opStack );
2193 val = cf2_stack_popFixed( opStack );
2194
2195 if ( idx < CF2_STORAGE_SIZE )
2196 storage[idx] = val;
2197 }
2198 continue; /* do not clear the stack */
2199
2200 case cf2_escGET:
2201 {
2202 CF2_UInt idx;
2203
2204
2205 FT_TRACE4(( " get\n" ));
2206
2207 idx = (CF2_UInt)cf2_stack_popInt( opStack );
2208
2209 if ( idx < CF2_STORAGE_SIZE )
2210 cf2_stack_pushFixed( opStack, storage[idx] );
2211 }
2212 continue; /* do not clear the stack */
2213
2214 case cf2_escIFELSE:
2215 {
2216 CF2_F16Dot16 arg1;
2217 CF2_F16Dot16 arg2;
2218 CF2_F16Dot16 cond1;
2219 CF2_F16Dot16 cond2;
2220
2221
2222 FT_TRACE4(( " ifelse\n" ));
2223
2224 cond2 = cf2_stack_popFixed( opStack );
2225 cond1 = cf2_stack_popFixed( opStack );
2226 arg2 = cf2_stack_popFixed( opStack );
2227 arg1 = cf2_stack_popFixed( opStack );
2228
2229 cf2_stack_pushFixed( opStack,
2230 cond1 <= cond2 ? arg1 : arg2 );
2231 }
2232 continue; /* do not clear the stack */
2233
2234 case cf2_escRANDOM: /* in spec */
2235 {
2236 CF2_F16Dot16 r;
2237
2238
2239 FT_TRACE4(( " random\n" ));
2240
2241 /* only use the lower 16 bits of `random' */
2242 /* to generate a number in the range (0;1] */
2243 r = (CF2_F16Dot16)
2244 ( ( decoder->current_subfont->random & 0xFFFF ) + 1 );
2245
2246 decoder->current_subfont->random =
2247 cff_random( decoder->current_subfont->random );
2248
2249 cf2_stack_pushFixed( opStack, r );
2250 }
2251 continue; /* do not clear the stack */
2252
2253 case cf2_escMUL:
2254 {
2255 CF2_F16Dot16 factor1;
2256 CF2_F16Dot16 factor2;
2257
2258
2259 FT_TRACE4(( " mul\n" ));
2260
2261 factor2 = cf2_stack_popFixed( opStack );
2262 factor1 = cf2_stack_popFixed( opStack );
2263
2264 cf2_stack_pushFixed( opStack,
2265 FT_MulFix( factor1, factor2 ) );
2266 }
2267 continue; /* do not clear the stack */
2268
2269 case cf2_escSQRT:
2270 {
2271 CF2_F16Dot16 arg;
2272
2273
2274 FT_TRACE4(( " sqrt\n" ));
2275
2276 arg = cf2_stack_popFixed( opStack );
2277 if ( arg > 0 )
2278 {
2279 /* use a start value that doesn't make */
2280 /* the algorithm's addition overflow */
2281 FT_Fixed root = arg < 10 ? arg : arg >> 1;
2282 FT_Fixed new_root;
2283
2284
2285 /* Babylonian method */
2286 for (;;)
2287 {
2288 new_root = ( root + FT_DivFix( arg, root ) + 1 ) >> 1;
2289 if ( new_root == root )
2290 break;
2291 root = new_root;
2292 }
2293 arg = new_root;
2294 }
2295 else
2296 arg = 0;
2297
2298 cf2_stack_pushFixed( opStack, arg );
2299 }
2300 continue; /* do not clear the stack */
2301
2302 case cf2_escDUP:
2303 {
2304 CF2_F16Dot16 arg;
2305
2306
2307 FT_TRACE4(( " dup\n" ));
2308
2309 arg = cf2_stack_popFixed( opStack );
2310
2311 cf2_stack_pushFixed( opStack, arg );
2312 cf2_stack_pushFixed( opStack, arg );
2313 }
2314 continue; /* do not clear the stack */
2315
2316 case cf2_escEXCH:
2317 {
2318 CF2_F16Dot16 arg1;
2319 CF2_F16Dot16 arg2;
2320
2321
2322 FT_TRACE4(( " exch\n" ));
2323
2324 arg2 = cf2_stack_popFixed( opStack );
2325 arg1 = cf2_stack_popFixed( opStack );
2326
2327 cf2_stack_pushFixed( opStack, arg2 );
2328 cf2_stack_pushFixed( opStack, arg1 );
2329 }
2330 continue; /* do not clear the stack */
2331
2332 case cf2_escINDEX:
2333 {
2334 CF2_Int idx;
2335 CF2_UInt size;
2336
2337
2338 FT_TRACE4(( " index\n" ));
2339
2340 idx = cf2_stack_popInt( opStack );
2341 size = cf2_stack_count( opStack );
2342
2343 if ( size > 0 )
2344 {
2345 /* for `cf2_stack_getReal', */
2346 /* index 0 is bottom of stack */
2347 CF2_UInt gr_idx;
2348
2349
2350 if ( idx < 0 )
2351 gr_idx = size - 1;
2352 else if ( (CF2_UInt)idx >= size )
2353 gr_idx = 0;
2354 else
2355 gr_idx = size - 1 - (CF2_UInt)idx;
2356
2357 cf2_stack_pushFixed( opStack,
2358 cf2_stack_getReal( opStack,
2359 gr_idx ) );
2360 }
2361 }
2362 continue; /* do not clear the stack */
2363
2364 case cf2_escROLL:
2365 {
2366 CF2_Int idx;
2367 CF2_Int count;
2368
2369
2370 FT_TRACE4(( " roll\n" ));
2371
2372 idx = cf2_stack_popInt( opStack );
2373 count = cf2_stack_popInt( opStack );
2374
2375 cf2_stack_roll( opStack, count, idx );
2376 }
2377 continue; /* do not clear the stack */
2378
2379 case cf2_escSETCURRENTPT:
2380 if ( !font->isT1 )
2381 FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
2382 else
2383 {
2384 FT_TRACE4(( " setcurrentpoint" ));
2385
2386 if ( !initial_map_ready )
2387 break;
2388
2389 /* From the T1 specification, section 6.4: */
2390 /* */
2391 /* The setcurrentpoint command is used only in */
2392 /* conjunction with results from OtherSubrs */
2393 /* procedures. */
2394
2395 /* known_othersubr_result_cnt != 0 is already handled */
2396 /* above. */
2397
2398 /* Note, however, that both Ghostscript and Adobe */
2399 /* Distiller handle this situation by silently */
2400 /* ignoring the inappropriate `setcurrentpoint' */
2401 /* instruction. So we do the same. */
2402#if 0
2403
2404 if ( decoder->flex_state != 1 )
2405 {
2406 FT_ERROR(( "cf2_interpT2CharString:"
2407 " unexpected `setcurrentpoint'\n" ));
2408 goto Syntax_Error;
2409 }
2410 else
2411 ...
2412#endif
2413
2414 curY = cf2_stack_popFixed( opStack );
2415 curX = cf2_stack_popFixed( opStack );
2416
2417 decoder->flex_state = 0;
2418 }
2419 break;
2420
2421 } /* end of 2nd switch checking op2 */
2422 }
2423 }
2424 } /* end of 1st switch checking op2 */
2425 } /* case cf2_cmdESC */
2426
2427 break;
2428
2429 case cf2_cmdHSBW:
2430 if ( !font->isT1 )
2431 FT_TRACE4(( " unknown op (%d)\n", op1 ));
2432 else
2433 {
2434 CF2_Fixed lsb_x;
2435 PS_Builder* builder;
2436
2437
2438 FT_TRACE4(( " hsbw\n" ));
2439
2440 builder = &decoder->builder;
2441
2442 builder->advance->x = cf2_stack_popFixed( opStack );
2443 builder->advance->y = 0;
2444
2445 lsb_x = cf2_stack_popFixed( opStack );
2446
2447 builder->left_bearing->x = ADD_INT32( builder->left_bearing->x,
2448 lsb_x );
2449
2450 haveWidth = TRUE;
2451
2452 /* the `metrics_only' indicates that we only want to compute */
2453 /* the glyph's metrics (lsb + advance width), not load the */
2454 /* rest of it; so exit immediately */
2455 if ( builder->metrics_only )
2456 goto exit;
2457
2458 if ( initial_map_ready )
2459 curX = ADD_INT32( curX, lsb_x );
2460 }
2461 break;
2462
2463 case cf2_cmdENDCHAR:
2464 FT_TRACE4(( " endchar\n" ));
2465
2466 if ( font->isT1 && !initial_map_ready )
2467 {
2468 FT_TRACE5(( "cf2_interpT2CharString (Type 1 mode): "
2469 "Build initial hintmap, rewinding...\n" ));
2470
2471 /* trigger initial hintmap build */
2472 cf2_glyphpath_moveTo( &glyphPath, curX, curY );
2473
2474 initial_map_ready = TRUE;
2475
2476 /* change hints routine - clear for rewind */
2477 cf2_arrstack_clear( &vStemHintArray );
2478 cf2_arrstack_clear( &hStemHintArray );
2479
2480 cf2_hintmask_init( &hintMask, error );
2481 hintMask.isValid = FALSE;
2482 hintMask.isNew = TRUE;
2483
2484 /* rewind charstring */
2485 /* some charstrings use endchar from a final subroutine call */
2486 /* without returning, detect these and exit to the top level */
2487 /* charstring */
2488 while ( charstringIndex > 0 )
2489 {
2490 FT_TRACE4(( " return (leaving level %d)\n", charstringIndex ));
2491
2492 /* restore position in previous charstring */
2493 charstring = (CF2_Buffer)
2494 cf2_arrstack_getPointer(
2495 &subrStack,
2496 (CF2_UInt)--charstringIndex );
2497 }
2498 charstring->ptr = charstring->start;
2499
2500 break;
2501 }
2502
2503 if ( cf2_stack_count( opStack ) == 1 ||
2504 cf2_stack_count( opStack ) == 5 )
2505 {
2506 if ( !haveWidth )
2507 *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
2508 nominalWidthX );
2509 }
2510
2511 /* width is defined or default after this */
2512 haveWidth = TRUE;
2513
2514 if ( decoder->width_only )
2515 goto exit;
2516
2517 /* close path if still open */
2518 cf2_glyphpath_closeOpenPath( &glyphPath );
2519
2520 /* disable seac for CFF2 and Type1 */
2521 /* (charstring ending with args on stack) */
2522 if ( !font->isCFF2 && !font->isT1 && cf2_stack_count( opStack ) > 1 )
2523 {
2524 /* must be either 4 or 5 -- */
2525 /* this is a (deprecated) implied `seac' operator */
2526
2527 CF2_Int achar;
2528 CF2_Int bchar;
2529 CF2_BufferRec component;
2530 CF2_Fixed dummyWidth; /* ignore component width */
2531 FT_Error error2;
2532
2533
2534 if ( doingSeac )
2535 {
2536 lastError = FT_THROW( Invalid_Glyph_Format );
2537 goto exit; /* nested seac */
2538 }
2539
2540 achar = cf2_stack_popInt( opStack );
2541 bchar = cf2_stack_popInt( opStack );
2542
2543 curY = cf2_stack_popFixed( opStack );
2544 curX = cf2_stack_popFixed( opStack );
2545
2546 error2 = cf2_getSeacComponent( decoder, achar, &component );
2547 if ( error2 )
2548 {
2549 lastError = error2; /* pass FreeType error through */
2550 goto exit;
2551 }
2552 cf2_interpT2CharString( font,
2553 &component,
2554 callbacks,
2555 translation,
2556 TRUE,
2557 curX,
2558 curY,
2559 &dummyWidth );
2560 cf2_freeSeacComponent( decoder, &component );
2561
2562 error2 = cf2_getSeacComponent( decoder, bchar, &component );
2563 if ( error2 )
2564 {
2565 lastError = error2; /* pass FreeType error through */
2566 goto exit;
2567 }
2568 cf2_interpT2CharString( font,
2569 &component,
2570 callbacks,
2571 translation,
2572 TRUE,
2573 0,
2574 0,
2575 &dummyWidth );
2576 cf2_freeSeacComponent( decoder, &component );
2577 }
2578 goto exit;
2579
2580 case cf2_cmdCNTRMASK:
2581 case cf2_cmdHINTMASK:
2582 /* the final \n in the tracing message gets added in */
2583 /* `cf2_hintmask_read' (which also traces the mask bytes) */
2584 FT_TRACE4(( "%s", op1 == cf2_cmdCNTRMASK ? " cntrmask" : " hintmask" ));
2585
2586 /* never add hints after the mask is computed */
2587 if ( cf2_stack_count( opStack ) > 1 &&
2588 cf2_hintmask_isValid( &hintMask ) )
2589 {
2590 FT_TRACE4(( "cf2_interpT2CharString: invalid hint mask\n" ));
2591 break;
2592 }
2593
2594 /* if there are arguments on the stack, there this is an */
2595 /* implied cf2_cmdVSTEMHM */
2596 cf2_doStems( font,
2597 opStack,
2598 &vStemHintArray,
2599 width,
2600 &haveWidth,
2601 0 );
2602
2603 if ( decoder->width_only )
2604 goto exit;
2605
2606 if ( op1 == cf2_cmdHINTMASK )
2607 {
2608 /* consume the hint mask bytes which follow the operator */
2609 cf2_hintmask_read( &hintMask,
2610 charstring,
2611 cf2_arrstack_size( &hStemHintArray ) +
2612 cf2_arrstack_size( &vStemHintArray ) );
2613 }
2614 else
2615 {
2616 /*
2617 * Consume the counter mask bytes which follow the operator:
2618 * Build a temporary hint map, just to place and lock those
2619 * stems participating in the counter mask. These are most
2620 * likely the dominant hstems, and are grouped together in a
2621 * few counter groups, not necessarily in correspondence
2622 * with the hint groups. This reduces the chances of
2623 * conflicts between hstems that are initially placed in
2624 * separate hint groups and then brought together. The
2625 * positions are copied back to `hStemHintArray', so we can
2626 * discard `counterMask' and `counterHintMap'.
2627 *
2628 */
2629 CF2_HintMapRec counterHintMap;
2630 CF2_HintMaskRec counterMask;
2631
2632
2633 cf2_hintmap_init( &counterHintMap,
2634 font,
2635 &glyphPath.initialHintMap,
2636 &glyphPath.hintMoves,
2637 scaleY );
2638 cf2_hintmask_init( &counterMask, error );
2639
2640 cf2_hintmask_read( &counterMask,
2641 charstring,
2642 cf2_arrstack_size( &hStemHintArray ) +
2643 cf2_arrstack_size( &vStemHintArray ) );
2644 cf2_hintmap_build( &counterHintMap,
2645 &hStemHintArray,
2646 &vStemHintArray,
2647 &counterMask,
2648 0,
2649 FALSE );
2650 }
2651 break;
2652
2653 case cf2_cmdRMOVETO:
2654 FT_TRACE4(( " rmoveto\n" ));
2655
2656 if ( font->isT1 && !decoder->flex_state && !haveWidth )
2657 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
2658 " No width. Use hsbw/sbw as first op\n" ));
2659
2660 if ( cf2_stack_count( opStack ) > 2 && !haveWidth )
2661 *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
2662 nominalWidthX );
2663
2664 /* width is defined or default after this */
2665 haveWidth = TRUE;
2666
2667 if ( decoder->width_only )
2668 goto exit;
2669
2670 curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) );
2671 curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) );
2672
2673 if ( !decoder->flex_state )
2674 cf2_glyphpath_moveTo( &glyphPath, curX, curY );
2675
2676 break;
2677
2678 case cf2_cmdHMOVETO:
2679 FT_TRACE4(( " hmoveto\n" ));
2680
2681 if ( font->isT1 && !decoder->flex_state && !haveWidth )
2682 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
2683 " No width. Use hsbw/sbw as first op\n" ));
2684
2685 if ( cf2_stack_count( opStack ) > 1 && !haveWidth )
2686 *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ),
2687 nominalWidthX );
2688
2689 /* width is defined or default after this */
2690 haveWidth = TRUE;
2691
2692 if ( decoder->width_only )
2693 goto exit;
2694
2695 curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) );
2696
2697 if ( !decoder->flex_state )
2698 cf2_glyphpath_moveTo( &glyphPath, curX, curY );
2699
2700 break;
2701
2702 case cf2_cmdRLINECURVE:
2703 {
2704 CF2_UInt count = cf2_stack_count( opStack );
2705 CF2_UInt idx = 0;
2706
2707
2708 FT_TRACE4(( " rlinecurve\n" ));
2709
2710 while ( idx + 6 < count )
2711 {
2712 curX = ADD_INT32( curX, cf2_stack_getReal( opStack,
2713 idx + 0 ) );
2714 curY = ADD_INT32( curY, cf2_stack_getReal( opStack,
2715 idx + 1 ) );
2716
2717 cf2_glyphpath_lineTo( &glyphPath, curX, curY );
2718 idx += 2;
2719 }
2720
2721 while ( idx < count )
2722 {
2723 CF2_Fixed x1, y1, x2, y2, x3, y3;
2724
2725
2726 x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
2727 y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), curY );
2728 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), x1 );
2729 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y1 );
2730 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 );
2731 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 5 ), y2 );
2732
2733 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
2734
2735 curX = x3;
2736 curY = y3;
2737 idx += 6;
2738 }
2739
2740 cf2_stack_clear( opStack );
2741 }
2742 continue; /* no need to clear stack again */
2743
2744 case cf2_cmdVVCURVETO:
2745 {
2746 CF2_UInt count, count1 = cf2_stack_count( opStack );
2747 CF2_UInt idx = 0;
2748
2749
2750 /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */
2751 /* we enforce it by clearing the second bit */
2752 /* (and sorting the stack indexing to suit) */
2753 count = count1 & ~2U;
2754 idx += count1 - count;
2755
2756 FT_TRACE4(( " vvcurveto\n" ));
2757
2758 while ( idx < count )
2759 {
2760 CF2_Fixed x1, y1, x2, y2, x3, y3;
2761
2762
2763 if ( ( count - idx ) & 1 )
2764 {
2765 x1 = ADD_INT32( cf2_stack_getReal( opStack, idx ), curX );
2766
2767 idx++;
2768 }
2769 else
2770 x1 = curX;
2771
2772 y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curY );
2773 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
2774 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
2775 x3 = x2;
2776 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y2 );
2777
2778 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
2779
2780 curX = x3;
2781 curY = y3;
2782 idx += 4;
2783 }
2784
2785 cf2_stack_clear( opStack );
2786 }
2787 continue; /* no need to clear stack again */
2788
2789 case cf2_cmdHHCURVETO:
2790 {
2791 CF2_UInt count, count1 = cf2_stack_count( opStack );
2792 CF2_UInt idx = 0;
2793
2794
2795 /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */
2796 /* we enforce it by clearing the second bit */
2797 /* (and sorting the stack indexing to suit) */
2798 count = count1 & ~2U;
2799 idx += count1 - count;
2800
2801 FT_TRACE4(( " hhcurveto\n" ));
2802
2803 while ( idx < count )
2804 {
2805 CF2_Fixed x1, y1, x2, y2, x3, y3;
2806
2807
2808 if ( ( count - idx ) & 1 )
2809 {
2810 y1 = ADD_INT32( cf2_stack_getReal( opStack, idx ), curY );
2811
2812 idx++;
2813 }
2814 else
2815 y1 = curY;
2816
2817 x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
2818 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
2819 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
2820 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), x2 );
2821 y3 = y2;
2822
2823 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
2824
2825 curX = x3;
2826 curY = y3;
2827 idx += 4;
2828 }
2829
2830 cf2_stack_clear( opStack );
2831 }
2832 continue; /* no need to clear stack again */
2833
2834 case cf2_cmdVHCURVETO:
2835 case cf2_cmdHVCURVETO:
2836 {
2837 CF2_UInt count, count1 = cf2_stack_count( opStack );
2838 CF2_UInt idx = 0;
2839
2840 FT_Bool alternate = FT_BOOL( op1 == cf2_cmdHVCURVETO );
2841
2842
2843 /* if `cf2_stack_count' isn't of the form 8n, 8n+1, */
2844 /* 8n+4, or 8n+5, we enforce it by clearing the */
2845 /* second bit */
2846 /* (and sorting the stack indexing to suit) */
2847 count = count1 & ~2U;
2848 idx += count1 - count;
2849
2850 FT_TRACE4(( "%s\n", alternate ? " hvcurveto" : " vhcurveto" ));
2851
2852 while ( idx < count )
2853 {
2854 CF2_Fixed x1, x2, x3, y1, y2, y3;
2855
2856
2857 if ( alternate )
2858 {
2859 x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX );
2860 y1 = curY;
2861 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
2862 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
2863 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y2 );
2864
2865 if ( count - idx == 5 )
2866 {
2867 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 );
2868
2869 idx++;
2870 }
2871 else
2872 x3 = x2;
2873
2874 alternate = FALSE;
2875 }
2876 else
2877 {
2878 x1 = curX;
2879 y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curY );
2880 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 );
2881 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 );
2882 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), x2 );
2883
2884 if ( count - idx == 5 )
2885 {
2886 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), y2 );
2887
2888 idx++;
2889 }
2890 else
2891 y3 = y2;
2892
2893 alternate = TRUE;
2894 }
2895
2896 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
2897
2898 curX = x3;
2899 curY = y3;
2900 idx += 4;
2901 }
2902
2903 cf2_stack_clear( opStack );
2904 }
2905 continue; /* no need to clear stack again */
2906
2907 case cf2_cmdEXTENDEDNMBR:
2908 {
2909 CF2_Int v;
2910
2911 CF2_Int byte1 = cf2_buf_readByte( charstring );
2912 CF2_Int byte2 = cf2_buf_readByte( charstring );
2913
2914
2915 v = (FT_Short)( ( byte1 << 8 ) |
2916 byte2 );
2917
2918 FT_TRACE4(( " %d", v ));
2919
2920 cf2_stack_pushInt( opStack, v );
2921 }
2922 continue;
2923
2924 default:
2925 /* numbers */
2926 {
2927 if ( /* op1 >= 32 && */ op1 <= 246 )
2928 {
2929 CF2_Int v;
2930
2931
2932 v = op1 - 139;
2933
2934 FT_TRACE4(( " %d", v ));
2935
2936 /* -107 .. 107 */
2937 cf2_stack_pushInt( opStack, v );
2938 }
2939
2940 else if ( /* op1 >= 247 && */ op1 <= 250 )
2941 {
2942 CF2_Int v;
2943
2944
2945 v = op1;
2946 v -= 247;
2947 v *= 256;
2948 v += cf2_buf_readByte( charstring );
2949 v += 108;
2950
2951 FT_TRACE4(( " %d", v ));
2952
2953 /* 108 .. 1131 */
2954 cf2_stack_pushInt( opStack, v );
2955 }
2956
2957 else if ( /* op1 >= 251 && */ op1 <= 254 )
2958 {
2959 CF2_Int v;
2960
2961
2962 v = op1;
2963 v -= 251;
2964 v *= 256;
2965 v += cf2_buf_readByte( charstring );
2966 v = -v - 108;
2967
2968 FT_TRACE4(( " %d", v ));
2969
2970 /* -1131 .. -108 */
2971 cf2_stack_pushInt( opStack, v );
2972 }
2973
2974 else /* op1 == 255 */
2975 {
2976 CF2_Fixed v;
2977
2978 FT_UInt32 byte1 = (FT_UInt32)cf2_buf_readByte( charstring );
2979 FT_UInt32 byte2 = (FT_UInt32)cf2_buf_readByte( charstring );
2980 FT_UInt32 byte3 = (FT_UInt32)cf2_buf_readByte( charstring );
2981 FT_UInt32 byte4 = (FT_UInt32)cf2_buf_readByte( charstring );
2982
2983
2984 v = (CF2_Fixed)( ( byte1 << 24 ) |
2985 ( byte2 << 16 ) |
2986 ( byte3 << 8 ) |
2987 byte4 );
2988
2989 /*
2990 * For Type 1:
2991 *
2992 * According to the specification, values > 32000 or < -32000
2993 * must be followed by a `div' operator to make the result be
2994 * in the range [-32000;32000]. We expect that the second
2995 * argument of `div' is not a large number. Additionally, we
2996 * don't handle stuff like `<large1> <large2> <num> div <num>
2997 * div' or <large1> <large2> <num> div div'. This is probably
2998 * not allowed anyway.
2999 *
3000 * <large> <num> <num>+ div is not checked but should not be
3001 * allowed as the large value remains untouched.
3002 *
3003 */
3004 if ( font->isT1 )
3005 {
3006 if ( v > 32000 || v < -32000 )
3007 {
3008 if ( large_int )
3009 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):"
3010 " no `div' after large integer\n" ));
3011 else
3012 large_int = TRUE;
3013 }
3014
3015 FT_TRACE4(( " %d", v ));
3016
3017 cf2_stack_pushInt( opStack, (CF2_Int)v );
3018 }
3019 else
3020 {
3021 FT_TRACE4(( " %.5fF", v / 65536.0 ));
3022
3023 cf2_stack_pushFixed( opStack, v );
3024 }
3025 }
3026 }
3027 continue; /* don't clear stack */
3028
3029 } /* end of switch statement checking `op1' */
3030
3031 cf2_stack_clear( opStack );
3032
3033 } /* end of main interpreter loop */
3034
3035 /* we get here if the charstring ends without cf2_cmdENDCHAR */
3036 FT_TRACE4(( "cf2_interpT2CharString:"
3037 " charstring ends without ENDCHAR\n" ));
3038
3039 exit:
3040 /* check whether last error seen is also the first one */
3041 cf2_setError( error, lastError );
3042
3043 if ( *error )
3044 FT_TRACE4(( "charstring error %d\n", *error ));
3045
3046 /* free resources from objects we've used */
3047 cf2_glyphpath_finalize( &glyphPath );
3048 cf2_arrstack_finalize( &vStemHintArray );
3049 cf2_arrstack_finalize( &hStemHintArray );
3050 cf2_arrstack_finalize( &subrStack );
3051 cf2_stack_free( opStack );
3052
3053 FT_TRACE4(( "\n" ));
3054
3055 return;
3056 }
3057
3058
3059/* END */
3060