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