Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: src/cff/cf2intrp.c

Issue 89753003: Update freetype to latest version of ASOP. (Closed) Base URL: https://chromium.googlesource.com/chromium/src/third_party/freetype.git@master
Patch Set: Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/cff/cf2intrp.h ('k') | src/cff/cf2read.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /***************************************************************************/
2 /* */
3 /* cf2intrp.c */
4 /* */
5 /* Adobe's CFF Interpreter (body). */
6 /* */
7 /* Copyright 2007-2013 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 "cf2ft.h"
40 #include FT_INTERNAL_DEBUG_H
41
42 #include "cf2glue.h"
43 #include "cf2font.h"
44 #include "cf2stack.h"
45 #include "cf2hints.h"
46
47 #include "cf2error.h"
48
49
50 /*************************************************************************/
51 /* */
52 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
53 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
54 /* messages during execution. */
55 /* */
56 #undef FT_COMPONENT
57 #define FT_COMPONENT trace_cf2interp
58
59
60 /* some operators are not implemented yet */
61 #define CF2_FIXME FT_TRACE4(( "cf2_interpT2CharString:" \
62 " operator not implemented yet\n" ))
63
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_cmdRESERVED_9, /* 9 */
212 cf2_cmdCALLSUBR, /* 10 */
213 cf2_cmdRETURN, /* 11 */
214 cf2_cmdESC, /* 12 */
215 cf2_cmdRESERVED_13, /* 13 */
216 cf2_cmdENDCHAR, /* 14 */
217 cf2_cmdRESERVED_15, /* 15 */
218 cf2_cmdRESERVED_16, /* 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_escRESERVED_1, /* 1 */
240 cf2_escRESERVED_2, /* 2 */
241 cf2_escAND, /* 3 */
242 cf2_escOR, /* 4 */
243 cf2_escNOT, /* 5 */
244 cf2_escRESERVED_6, /* 6 */
245 cf2_escRESERVED_7, /* 7 */
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_escRESERVED_16, /* 16 */
255 cf2_escRESERVED_17, /* 17 */
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_escRESERVED_33, /* 33 */
272 cf2_escHFLEX, /* 34 */
273 cf2_escFLEX, /* 35 */
274 cf2_escHFLEX1, /* 36 */
275 cf2_escFLEX1 /* 37 */
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 = count & 1;
291
292 /* variable accumulates delta values from operand stack */
293 CF2_Fixed position = hintOffset;
294
295 if ( hasWidthArg && ! *haveWidth )
296 *width = cf2_stack_getReal( opStack, 0 ) +
297 cf2_getNominalWidthX( font->decoder );
298
299 if ( font->decoder->width_only )
300 goto exit;
301
302 for ( i = hasWidthArg ? 1 : 0; i < count; i += 2 )
303 {
304 /* construct a CF2_StemHint and push it onto the list */
305 CF2_StemHintRec stemhint;
306
307
308 stemhint.min =
309 position += cf2_stack_getReal( opStack, i );
310 stemhint.max =
311 position += cf2_stack_getReal( opStack, i + 1 );
312
313 stemhint.used = FALSE;
314 stemhint.maxDS =
315 stemhint.minDS = 0;
316
317 cf2_arrstack_push( stemHintArray, &stemhint ); /* defer error check */
318 }
319
320 cf2_stack_clear( opStack );
321
322 exit:
323 /* cf2_doStems must define a width (may be default) */
324 *haveWidth = TRUE;
325 }
326
327
328 static void
329 cf2_doFlex( CF2_Stack opStack,
330 CF2_Fixed* curX,
331 CF2_Fixed* curY,
332 CF2_GlyphPath glyphPath,
333 const FT_Bool* readFromStack,
334 FT_Bool doConditionalLastRead )
335 {
336 CF2_Fixed vals[14];
337 CF2_UInt index;
338 FT_Bool isHFlex;
339 CF2_Int top, i, j;
340
341
342 vals[0] = *curX;
343 vals[1] = *curY;
344 index = 0;
345 isHFlex = readFromStack[9] == FALSE;
346 top = isHFlex ? 9 : 10;
347
348 for ( i = 0; i < top; i++ )
349 {
350 vals[i + 2] = vals[i];
351 if ( readFromStack[i] )
352 vals[i + 2] += cf2_stack_getReal( opStack, index++ );
353 }
354
355 if ( isHFlex )
356 vals[9 + 2] = *curY;
357
358 if ( doConditionalLastRead )
359 {
360 FT_Bool lastIsX = cf2_fixedAbs( vals[10] - *curX ) >
361 cf2_fixedAbs( vals[11] - *curY );
362 CF2_Fixed lastVal = cf2_stack_getReal( opStack, index );
363
364
365 if ( lastIsX )
366 {
367 vals[12] = vals[10] + lastVal;
368 vals[13] = *curY;
369 }
370 else
371 {
372 vals[12] = *curX;
373 vals[13] = vals[11] + lastVal;
374 }
375 }
376 else
377 {
378 if ( readFromStack[10] )
379 vals[12] = vals[10] + cf2_stack_getReal( opStack, index++ );
380 else
381 vals[12] = *curX;
382
383 if ( readFromStack[11] )
384 vals[13] = vals[11] + cf2_stack_getReal( opStack, index );
385 else
386 vals[13] = *curY;
387 }
388
389 for ( j = 0; j < 2; j++ )
390 cf2_glyphpath_curveTo( glyphPath, vals[j * 6 + 2],
391 vals[j * 6 + 3],
392 vals[j * 6 + 4],
393 vals[j * 6 + 5],
394 vals[j * 6 + 6],
395 vals[j * 6 + 7] );
396
397 cf2_stack_clear( opStack );
398
399 *curX = vals[12];
400 *curY = vals[13];
401 }
402
403
404 /*
405 * `error' is a shared error code used by many objects in this
406 * routine. Before the code continues from an error, it must check and
407 * record the error in `*error'. The idea is that this shared
408 * error code will record the first error encountered. If testing
409 * for an error anyway, the cost of `goto exit' is small, so we do it,
410 * even if continuing would be safe. In this case, `lastError' is
411 * set, so the testing and storing can be done in one place, at `exit'.
412 *
413 * Continuing after an error is intended for objects which do their own
414 * testing of `*error', e.g., array stack functions. This allows us to
415 * avoid an extra test after the call.
416 *
417 * Unimplemented opcodes are ignored.
418 *
419 */
420 FT_LOCAL_DEF( void )
421 cf2_interpT2CharString( CF2_Font font,
422 CF2_Buffer buf,
423 CF2_OutlineCallbacks callbacks,
424 const FT_Vector* translation,
425 FT_Bool doingSeac,
426 CF2_Fixed curX,
427 CF2_Fixed curY,
428 CF2_Fixed* width )
429 {
430 /* lastError is used for errors that are immediately tested */
431 FT_Error lastError = FT_Err_Ok;
432
433 /* pointer to parsed font object */
434 CFF_Decoder* decoder = font->decoder;
435
436 FT_Error* error = &font->error;
437 FT_Memory memory = font->memory;
438
439 CF2_Fixed scaleY = font->innerTransform.d;
440 CF2_Fixed nominalWidthX = cf2_getNominalWidthX( decoder );
441
442 /* save this for hinting seac accents */
443 CF2_Fixed hintOriginY = curY;
444
445 CF2_Stack opStack = NULL;
446 FT_Byte op1; /* first opcode byte */
447
448 /* instruction limit; 20,000,000 matches Avalon */
449 FT_UInt32 instructionLimit = 20000000UL;
450
451 CF2_ArrStackRec subrStack;
452
453 FT_Bool haveWidth;
454 CF2_Buffer charstring = NULL;
455
456 CF2_Int charstringIndex = -1; /* initialize to empty */
457
458 /* TODO: placeholders for hint structures */
459
460 /* objects used for hinting */
461 CF2_ArrStackRec hStemHintArray;
462 CF2_ArrStackRec vStemHintArray;
463
464 CF2_HintMaskRec hintMask;
465 CF2_GlyphPathRec glyphPath;
466
467
468 /* initialize the remaining objects */
469 cf2_arrstack_init( &subrStack,
470 memory,
471 error,
472 sizeof ( CF2_BufferRec ) );
473 cf2_arrstack_init( &hStemHintArray,
474 memory,
475 error,
476 sizeof ( CF2_StemHintRec ) );
477 cf2_arrstack_init( &vStemHintArray,
478 memory,
479 error,
480 sizeof ( CF2_StemHintRec ) );
481
482 /* initialize CF2_StemHint arrays */
483 cf2_hintmask_init( &hintMask, error );
484
485 /* initialize path map to manage drawing operations */
486
487 /* Note: last 4 params are used to handle `MoveToPermissive', which */
488 /* may need to call `hintMap.Build' */
489 /* TODO: MoveToPermissive is gone; are these still needed? */
490 cf2_glyphpath_init( &glyphPath,
491 font,
492 callbacks,
493 scaleY,
494 /* hShift, */
495 &hStemHintArray,
496 &vStemHintArray,
497 &hintMask,
498 hintOriginY,
499 &font->blues,
500 translation );
501
502 /*
503 * Initialize state for width parsing. From the CFF Spec:
504 *
505 * The first stack-clearing operator, which must be one of hstem,
506 * hstemhm, vstem, vstemhm, cntrmask, hintmask, hmoveto, vmoveto,
507 * rmoveto, or endchar, takes an additional argument - the width (as
508 * described earlier), which may be expressed as zero or one numeric
509 * argument.
510 *
511 * What we implement here uses the first validly specified width, but
512 * does not detect errors for specifying more than one width.
513 *
514 * If one of the above operators occurs without explicitly specifying
515 * a width, we assume the default width.
516 *
517 */
518 haveWidth = FALSE;
519 *width = cf2_getDefaultWidthX( decoder );
520
521 /*
522 * Note: at this point, all pointers to resources must be NULL
523 * and all local objects must be initialized.
524 * There must be no branches to exit: above this point.
525 *
526 */
527
528 /* allocate an operand stack */
529 opStack = cf2_stack_init( memory, error );
530 if ( !opStack )
531 {
532 lastError = FT_THROW( Out_Of_Memory );
533 goto exit;
534 }
535
536 /* initialize subroutine stack by placing top level charstring as */
537 /* first element (max depth plus one for the charstring) */
538 /* Note: Caller owns and must finalize the first charstring. */
539 /* Our copy of it does not change that requirement. */
540 cf2_arrstack_setCount( &subrStack, CF2_MAX_SUBR + 1 );
541
542 charstring = (CF2_Buffer)cf2_arrstack_getBuffer( &subrStack );
543 *charstring = *buf; /* structure copy */
544
545 charstringIndex = 0; /* entry is valid now */
546
547 /* catch errors so far */
548 if ( *error )
549 goto exit;
550
551 /* main interpreter loop */
552 while ( 1 )
553 {
554 if ( cf2_buf_isEnd( charstring ) )
555 {
556 /* If we've reached the end of the charstring, simulate a */
557 /* cf2_cmdRETURN or cf2_cmdENDCHAR. */
558 if ( charstringIndex )
559 op1 = cf2_cmdRETURN; /* end of buffer for subroutine */
560 else
561 op1 = cf2_cmdENDCHAR; /* end of buffer for top level charstring */
562 }
563 else
564 op1 = (FT_Byte)cf2_buf_readByte( charstring );
565
566 /* check for errors once per loop */
567 if ( *error )
568 goto exit;
569
570 instructionLimit--;
571 if ( instructionLimit == 0 )
572 {
573 lastError = FT_THROW( Invalid_Glyph_Format );
574 goto exit;
575 }
576
577 switch( op1 )
578 {
579 case cf2_cmdRESERVED_0:
580 case cf2_cmdRESERVED_2:
581 case cf2_cmdRESERVED_9:
582 case cf2_cmdRESERVED_13:
583 case cf2_cmdRESERVED_15:
584 case cf2_cmdRESERVED_16:
585 case cf2_cmdRESERVED_17:
586 /* we may get here if we have a prior error */
587 FT_TRACE4(( " unknown op (%d)\n", op1 ));
588 break;
589
590 case cf2_cmdHSTEMHM:
591 case cf2_cmdHSTEM:
592 FT_TRACE4(( op1 == cf2_cmdHSTEMHM ? " hstemhm\n" : " hstem\n" ));
593
594 /* never add hints after the mask is computed */
595 if ( cf2_hintmask_isValid( &hintMask ) )
596 FT_TRACE4(( "cf2_interpT2CharString:"
597 " invalid horizontal hint mask\n" ));
598
599 cf2_doStems( font,
600 opStack,
601 &hStemHintArray,
602 width,
603 &haveWidth,
604 0 );
605
606 if ( font->decoder->width_only )
607 goto exit;
608
609 break;
610
611 case cf2_cmdVSTEMHM:
612 case cf2_cmdVSTEM:
613 FT_TRACE4(( op1 == cf2_cmdVSTEMHM ? " vstemhm\n" : " vstem\n" ));
614
615 /* never add hints after the mask is computed */
616 if ( cf2_hintmask_isValid( &hintMask ) )
617 FT_TRACE4(( "cf2_interpT2CharString:"
618 " invalid vertical hint mask\n" ));
619
620 cf2_doStems( font,
621 opStack,
622 &vStemHintArray,
623 width,
624 &haveWidth,
625 0 );
626
627 if ( font->decoder->width_only )
628 goto exit;
629
630 break;
631
632 case cf2_cmdVMOVETO:
633 FT_TRACE4(( " vmoveto\n" ));
634
635 if ( cf2_stack_count( opStack ) > 1 && !haveWidth )
636 *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
637
638 /* width is defined or default after this */
639 haveWidth = TRUE;
640
641 if ( font->decoder->width_only )
642 goto exit;
643
644 curY += cf2_stack_popFixed( opStack );
645
646 cf2_glyphpath_moveTo( &glyphPath, curX, curY );
647
648 break;
649
650 case cf2_cmdRLINETO:
651 {
652 CF2_UInt index;
653 CF2_UInt count = cf2_stack_count( opStack );
654
655
656 FT_TRACE4(( " rlineto\n" ));
657
658 for ( index = 0; index < count; index += 2 )
659 {
660 curX += cf2_stack_getReal( opStack, index + 0 );
661 curY += cf2_stack_getReal( opStack, index + 1 );
662
663 cf2_glyphpath_lineTo( &glyphPath, curX, curY );
664 }
665
666 cf2_stack_clear( opStack );
667 }
668 continue; /* no need to clear stack again */
669
670 case cf2_cmdHLINETO:
671 case cf2_cmdVLINETO:
672 {
673 CF2_UInt index;
674 CF2_UInt count = cf2_stack_count( opStack );
675
676 FT_Bool isX = op1 == cf2_cmdHLINETO;
677
678
679 FT_TRACE4(( isX ? " hlineto\n" : " vlineto\n" ));
680
681 for ( index = 0; index < count; index++ )
682 {
683 CF2_Fixed v = cf2_stack_getReal( opStack, index );
684
685
686 if ( isX )
687 curX += v;
688 else
689 curY += v;
690
691 isX = !isX;
692
693 cf2_glyphpath_lineTo( &glyphPath, curX, curY );
694 }
695
696 cf2_stack_clear( opStack );
697 }
698 continue;
699
700 case cf2_cmdRCURVELINE:
701 case cf2_cmdRRCURVETO:
702 {
703 CF2_UInt count = cf2_stack_count( opStack );
704 CF2_UInt index = 0;
705
706
707 FT_TRACE4(( op1 == cf2_cmdRCURVELINE ? " rcurveline\n"
708 : " rrcurveto\n" ));
709
710 while ( index + 6 <= count )
711 {
712 CF2_Fixed x1 = cf2_stack_getReal( opStack, index + 0 ) + curX;
713 CF2_Fixed y1 = cf2_stack_getReal( opStack, index + 1 ) + curY;
714 CF2_Fixed x2 = cf2_stack_getReal( opStack, index + 2 ) + x1;
715 CF2_Fixed y2 = cf2_stack_getReal( opStack, index + 3 ) + y1;
716 CF2_Fixed x3 = cf2_stack_getReal( opStack, index + 4 ) + x2;
717 CF2_Fixed y3 = cf2_stack_getReal( opStack, index + 5 ) + y2;
718
719
720 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
721
722 curX = x3;
723 curY = y3;
724 index += 6;
725 }
726
727 if ( op1 == cf2_cmdRCURVELINE )
728 {
729 curX += cf2_stack_getReal( opStack, index + 0 );
730 curY += cf2_stack_getReal( opStack, index + 1 );
731
732 cf2_glyphpath_lineTo( &glyphPath, curX, curY );
733 }
734
735 cf2_stack_clear( opStack );
736 }
737 continue; /* no need to clear stack again */
738
739 case cf2_cmdCALLGSUBR:
740 case cf2_cmdCALLSUBR:
741 {
742 CF2_UInt subrIndex;
743
744
745 FT_TRACE4(( op1 == cf2_cmdCALLGSUBR ? " callgsubr"
746 : " callsubr" ));
747
748 if ( charstringIndex > CF2_MAX_SUBR )
749 {
750 /* max subr plus one for charstring */
751 lastError = FT_THROW( Invalid_Glyph_Format );
752 goto exit; /* overflow of stack */
753 }
754
755 /* push our current CFF charstring region on subrStack */
756 charstring = (CF2_Buffer)
757 cf2_arrstack_getPointer( &subrStack,
758 charstringIndex + 1 );
759
760 /* set up the new CFF region and pointer */
761 subrIndex = cf2_stack_popInt( opStack );
762
763 switch ( op1 )
764 {
765 case cf2_cmdCALLGSUBR:
766 FT_TRACE4(( "(%d)\n", subrIndex + decoder->globals_bias ));
767
768 if ( cf2_initGlobalRegionBuffer( decoder,
769 subrIndex,
770 charstring ) )
771 {
772 lastError = FT_THROW( Invalid_Glyph_Format );
773 goto exit; /* subroutine lookup or stream error */
774 }
775 break;
776
777 default:
778 /* cf2_cmdCALLSUBR */
779 FT_TRACE4(( "(%d)\n", subrIndex + decoder->locals_bias ));
780
781 if ( cf2_initLocalRegionBuffer( decoder,
782 subrIndex,
783 charstring ) )
784 {
785 lastError = FT_THROW( Invalid_Glyph_Format );
786 goto exit; /* subroutine lookup or stream error */
787 }
788 }
789
790 charstringIndex += 1; /* entry is valid now */
791 }
792 continue; /* do not clear the stack */
793
794 case cf2_cmdRETURN:
795 FT_TRACE4(( " return\n" ));
796
797 if ( charstringIndex < 1 )
798 {
799 /* Note: cannot return from top charstring */
800 lastError = FT_THROW( Invalid_Glyph_Format );
801 goto exit; /* underflow of stack */
802 }
803
804 /* restore position in previous charstring */
805 charstring = (CF2_Buffer)
806 cf2_arrstack_getPointer( &subrStack,
807 --charstringIndex );
808 continue; /* do not clear the stack */
809
810 case cf2_cmdESC:
811 {
812 FT_Byte op2 = (FT_Byte)cf2_buf_readByte( charstring );
813
814
815 switch ( op2 )
816 {
817 case cf2_escDOTSECTION:
818 /* something about `flip type of locking' -- ignore it */
819 FT_TRACE4(( " dotsection\n" ));
820
821 break;
822
823 /* TODO: should these operators be supported? */
824 case cf2_escAND: /* in spec */
825 FT_TRACE4(( " and\n" ));
826
827 CF2_FIXME;
828 break;
829
830 case cf2_escOR: /* in spec */
831 FT_TRACE4(( " or\n" ));
832
833 CF2_FIXME;
834 break;
835
836 case cf2_escNOT: /* in spec */
837 FT_TRACE4(( " not\n" ));
838
839 CF2_FIXME;
840 break;
841
842 case cf2_escABS: /* in spec */
843 FT_TRACE4(( " abs\n" ));
844
845 CF2_FIXME;
846 break;
847
848 case cf2_escADD: /* in spec */
849 FT_TRACE4(( " add\n" ));
850
851 CF2_FIXME;
852 break;
853
854 case cf2_escSUB: /* in spec */
855 FT_TRACE4(( " sub\n" ));
856
857 CF2_FIXME;
858 break;
859
860 case cf2_escDIV: /* in spec */
861 FT_TRACE4(( " div\n" ));
862
863 CF2_FIXME;
864 break;
865
866 case cf2_escNEG: /* in spec */
867 FT_TRACE4(( " neg\n" ));
868
869 CF2_FIXME;
870 break;
871
872 case cf2_escEQ: /* in spec */
873 FT_TRACE4(( " eq\n" ));
874
875 CF2_FIXME;
876 break;
877
878 case cf2_escDROP: /* in spec */
879 FT_TRACE4(( " drop\n" ));
880
881 CF2_FIXME;
882 break;
883
884 case cf2_escPUT: /* in spec */
885 FT_TRACE4(( " put\n" ));
886
887 CF2_FIXME;
888 break;
889
890 case cf2_escGET: /* in spec */
891 FT_TRACE4(( " get\n" ));
892
893 CF2_FIXME;
894 break;
895
896 case cf2_escIFELSE: /* in spec */
897 FT_TRACE4(( " ifelse\n" ));
898
899 CF2_FIXME;
900 break;
901
902 case cf2_escRANDOM: /* in spec */
903 FT_TRACE4(( " random\n" ));
904
905 CF2_FIXME;
906 break;
907
908 case cf2_escMUL: /* in spec */
909 FT_TRACE4(( " mul\n" ));
910
911 CF2_FIXME;
912 break;
913
914 case cf2_escSQRT: /* in spec */
915 FT_TRACE4(( " sqrt\n" ));
916
917 CF2_FIXME;
918 break;
919
920 case cf2_escDUP: /* in spec */
921 FT_TRACE4(( " dup\n" ));
922
923 CF2_FIXME;
924 break;
925
926 case cf2_escEXCH: /* in spec */
927 FT_TRACE4(( " exch\n" ));
928
929 CF2_FIXME;
930 break;
931
932 case cf2_escINDEX: /* in spec */
933 FT_TRACE4(( " index\n" ));
934
935 CF2_FIXME;
936 break;
937
938 case cf2_escROLL: /* in spec */
939 FT_TRACE4(( " roll\n" ));
940
941 CF2_FIXME;
942 break;
943
944 case cf2_escHFLEX:
945 {
946 static const FT_Bool readFromStack[12] =
947 {
948 TRUE /* dx1 */, FALSE /* dy1 */,
949 TRUE /* dx2 */, TRUE /* dy2 */,
950 TRUE /* dx3 */, FALSE /* dy3 */,
951 TRUE /* dx4 */, FALSE /* dy4 */,
952 TRUE /* dx5 */, FALSE /* dy5 */,
953 TRUE /* dx6 */, FALSE /* dy6 */
954 };
955
956
957 FT_TRACE4(( " hflex\n" ));
958
959 cf2_doFlex( opStack,
960 &curX,
961 &curY,
962 &glyphPath,
963 readFromStack,
964 FALSE /* doConditionalLastRead */ );
965 }
966 continue;
967
968 case cf2_escFLEX:
969 {
970 static const FT_Bool readFromStack[12] =
971 {
972 TRUE /* dx1 */, TRUE /* dy1 */,
973 TRUE /* dx2 */, TRUE /* dy2 */,
974 TRUE /* dx3 */, TRUE /* dy3 */,
975 TRUE /* dx4 */, TRUE /* dy4 */,
976 TRUE /* dx5 */, TRUE /* dy5 */,
977 TRUE /* dx6 */, TRUE /* dy6 */
978 };
979
980
981 FT_TRACE4(( " flex\n" ));
982
983 cf2_doFlex( opStack,
984 &curX,
985 &curY,
986 &glyphPath,
987 readFromStack,
988 FALSE /* doConditionalLastRead */ );
989 }
990 break; /* TODO: why is this not a continue? */
991
992 case cf2_escHFLEX1:
993 {
994 static const FT_Bool readFromStack[12] =
995 {
996 TRUE /* dx1 */, TRUE /* dy1 */,
997 TRUE /* dx2 */, TRUE /* dy2 */,
998 TRUE /* dx3 */, FALSE /* dy3 */,
999 TRUE /* dx4 */, FALSE /* dy4 */,
1000 TRUE /* dx5 */, TRUE /* dy5 */,
1001 TRUE /* dx6 */, FALSE /* dy6 */
1002 };
1003
1004
1005 FT_TRACE4(( " hflex1\n" ));
1006
1007 cf2_doFlex( opStack,
1008 &curX,
1009 &curY,
1010 &glyphPath,
1011 readFromStack,
1012 FALSE /* doConditionalLastRead */ );
1013 }
1014 continue;
1015
1016 case cf2_escFLEX1:
1017 {
1018 static const FT_Bool readFromStack[12] =
1019 {
1020 TRUE /* dx1 */, TRUE /* dy1 */,
1021 TRUE /* dx2 */, TRUE /* dy2 */,
1022 TRUE /* dx3 */, TRUE /* dy3 */,
1023 TRUE /* dx4 */, TRUE /* dy4 */,
1024 TRUE /* dx5 */, TRUE /* dy5 */,
1025 FALSE /* dx6 */, FALSE /* dy6 */
1026 };
1027
1028
1029 FT_TRACE4(( " flex1\n" ));
1030
1031 cf2_doFlex( opStack,
1032 &curX,
1033 &curY,
1034 &glyphPath,
1035 readFromStack,
1036 TRUE /* doConditionalLastRead */ );
1037 }
1038 continue;
1039
1040 case cf2_escRESERVED_1:
1041 case cf2_escRESERVED_2:
1042 case cf2_escRESERVED_6:
1043 case cf2_escRESERVED_7:
1044 case cf2_escRESERVED_8:
1045 case cf2_escRESERVED_13:
1046 case cf2_escRESERVED_16:
1047 case cf2_escRESERVED_17:
1048 case cf2_escRESERVED_19:
1049 case cf2_escRESERVED_25:
1050 case cf2_escRESERVED_31:
1051 case cf2_escRESERVED_32:
1052 case cf2_escRESERVED_33:
1053 default:
1054 FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
1055
1056 }; /* end of switch statement checking `op2' */
1057
1058 } /* case cf2_cmdESC */
1059 break;
1060
1061 case cf2_cmdENDCHAR:
1062 FT_TRACE4(( " endchar\n" ));
1063
1064 if ( cf2_stack_count( opStack ) == 1 ||
1065 cf2_stack_count( opStack ) == 5 )
1066 {
1067 if ( !haveWidth )
1068 *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
1069 }
1070
1071 /* width is defined or default after this */
1072 haveWidth = TRUE;
1073
1074 if ( font->decoder->width_only )
1075 goto exit;
1076
1077 /* close path if still open */
1078 cf2_glyphpath_closeOpenPath( &glyphPath );
1079
1080 if ( cf2_stack_count( opStack ) > 1 )
1081 {
1082 /* must be either 4 or 5 -- */
1083 /* this is a (deprecated) implied `seac' operator */
1084
1085 CF2_UInt achar;
1086 CF2_UInt bchar;
1087 CF2_BufferRec component;
1088 CF2_Fixed dummyWidth; /* ignore component width */
1089 FT_Error error2;
1090
1091
1092 if ( doingSeac )
1093 {
1094 lastError = FT_THROW( Invalid_Glyph_Format );
1095 goto exit; /* nested seac */
1096 }
1097
1098 achar = cf2_stack_popInt( opStack );
1099 bchar = cf2_stack_popInt( opStack );
1100
1101 curY = cf2_stack_popFixed( opStack );
1102 curX = cf2_stack_popFixed( opStack );
1103
1104 error2 = cf2_getSeacComponent( decoder, achar, &component );
1105 if ( error2 )
1106 {
1107 lastError = error2; /* pass FreeType error through */
1108 goto exit;
1109 }
1110 cf2_interpT2CharString( font,
1111 &component,
1112 callbacks,
1113 translation,
1114 TRUE,
1115 curX,
1116 curY,
1117 &dummyWidth );
1118 cf2_freeSeacComponent( decoder, &component );
1119
1120 error2 = cf2_getSeacComponent( decoder, bchar, &component );
1121 if ( error2 )
1122 {
1123 lastError = error2; /* pass FreeType error through */
1124 goto exit;
1125 }
1126 cf2_interpT2CharString( font,
1127 &component,
1128 callbacks,
1129 translation,
1130 TRUE,
1131 0,
1132 0,
1133 &dummyWidth );
1134 cf2_freeSeacComponent( decoder, &component );
1135 }
1136 goto exit;
1137
1138 case cf2_cmdCNTRMASK:
1139 case cf2_cmdHINTMASK:
1140 /* the final \n in the tracing message gets added in */
1141 /* `cf2_hintmask_read' (which also traces the mask bytes) */
1142 FT_TRACE4(( op1 == cf2_cmdCNTRMASK ? " cntrmask" : " hintmask" ));
1143
1144 /* if there are arguments on the stack, there this is an */
1145 /* implied cf2_cmdVSTEMHM */
1146 if ( cf2_stack_count( opStack ) != 0 )
1147 {
1148 /* never add hints after the mask is computed */
1149 if ( cf2_hintmask_isValid( &hintMask ) )
1150 FT_TRACE4(( "cf2_interpT2CharString: invalid hint mask\n" ));
1151 }
1152
1153 cf2_doStems( font,
1154 opStack,
1155 &vStemHintArray,
1156 width,
1157 &haveWidth,
1158 0 );
1159
1160 if ( font->decoder->width_only )
1161 goto exit;
1162
1163 if ( op1 == cf2_cmdHINTMASK )
1164 {
1165 /* consume the hint mask bytes which follow the operator */
1166 cf2_hintmask_read( &hintMask,
1167 charstring,
1168 cf2_arrstack_size( &hStemHintArray ) +
1169 cf2_arrstack_size( &vStemHintArray ) );
1170 }
1171 else
1172 {
1173 /*
1174 * Consume the counter mask bytes which follow the operator:
1175 * Build a temporary hint map, just to place and lock those
1176 * stems participating in the counter mask. These are most
1177 * likely the dominant hstems, and are grouped together in a
1178 * few counter groups, not necessarily in correspondence
1179 * with the hint groups. This reduces the chances of
1180 * conflicts between hstems that are initially placed in
1181 * separate hint groups and then brought together. The
1182 * positions are copied back to `hStemHintArray', so we can
1183 * discard `counterMask' and `counterHintMap'.
1184 *
1185 */
1186 CF2_HintMapRec counterHintMap;
1187 CF2_HintMaskRec counterMask;
1188
1189
1190 cf2_hintmap_init( &counterHintMap,
1191 font,
1192 &glyphPath.initialHintMap,
1193 &glyphPath.hintMoves,
1194 scaleY );
1195 cf2_hintmask_init( &counterMask, error );
1196
1197 cf2_hintmask_read( &counterMask,
1198 charstring,
1199 cf2_arrstack_size( &hStemHintArray ) +
1200 cf2_arrstack_size( &vStemHintArray ) );
1201 cf2_hintmap_build( &counterHintMap,
1202 &hStemHintArray,
1203 &vStemHintArray,
1204 &counterMask,
1205 0,
1206 FALSE );
1207 }
1208 break;
1209
1210 case cf2_cmdRMOVETO:
1211 FT_TRACE4(( " rmoveto\n" ));
1212
1213 if ( cf2_stack_count( opStack ) > 2 && !haveWidth )
1214 *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
1215
1216 /* width is defined or default after this */
1217 haveWidth = TRUE;
1218
1219 if ( font->decoder->width_only )
1220 goto exit;
1221
1222 curY += cf2_stack_popFixed( opStack );
1223 curX += cf2_stack_popFixed( opStack );
1224
1225 cf2_glyphpath_moveTo( &glyphPath, curX, curY );
1226
1227 break;
1228
1229 case cf2_cmdHMOVETO:
1230 FT_TRACE4(( " hmoveto\n" ));
1231
1232 if ( cf2_stack_count( opStack ) > 1 && !haveWidth )
1233 *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
1234
1235 /* width is defined or default after this */
1236 haveWidth = TRUE;
1237
1238 if ( font->decoder->width_only )
1239 goto exit;
1240
1241 curX += cf2_stack_popFixed( opStack );
1242
1243 cf2_glyphpath_moveTo( &glyphPath, curX, curY );
1244
1245 break;
1246
1247 case cf2_cmdRLINECURVE:
1248 {
1249 CF2_UInt count = cf2_stack_count( opStack );
1250 CF2_UInt index = 0;
1251
1252
1253 FT_TRACE4(( " rlinecurve\n" ));
1254
1255 while ( index + 6 < count )
1256 {
1257 curX += cf2_stack_getReal( opStack, index + 0 );
1258 curY += cf2_stack_getReal( opStack, index + 1 );
1259
1260 cf2_glyphpath_lineTo( &glyphPath, curX, curY );
1261 index += 2;
1262 }
1263
1264 while ( index < count )
1265 {
1266 CF2_Fixed x1 = cf2_stack_getReal( opStack, index + 0 ) + curX;
1267 CF2_Fixed y1 = cf2_stack_getReal( opStack, index + 1 ) + curY;
1268 CF2_Fixed x2 = cf2_stack_getReal( opStack, index + 2 ) + x1;
1269 CF2_Fixed y2 = cf2_stack_getReal( opStack, index + 3 ) + y1;
1270 CF2_Fixed x3 = cf2_stack_getReal( opStack, index + 4 ) + x2;
1271 CF2_Fixed y3 = cf2_stack_getReal( opStack, index + 5 ) + y2;
1272
1273
1274 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
1275
1276 curX = x3;
1277 curY = y3;
1278 index += 6;
1279 }
1280
1281 cf2_stack_clear( opStack );
1282 }
1283 continue; /* no need to clear stack again */
1284
1285 case cf2_cmdVVCURVETO:
1286 {
1287 CF2_UInt count = cf2_stack_count( opStack );
1288 CF2_UInt index = 0;
1289
1290
1291 FT_TRACE4(( " vvcurveto\n" ));
1292
1293 while ( index < count )
1294 {
1295 CF2_Fixed x1, y1, x2, y2, x3, y3;
1296
1297
1298 if ( ( count - index ) & 1 )
1299 {
1300 x1 = cf2_stack_getReal( opStack, index ) + curX;
1301
1302 ++index;
1303 }
1304 else
1305 x1 = curX;
1306
1307 y1 = cf2_stack_getReal( opStack, index + 0 ) + curY;
1308 x2 = cf2_stack_getReal( opStack, index + 1 ) + x1;
1309 y2 = cf2_stack_getReal( opStack, index + 2 ) + y1;
1310 x3 = x2;
1311 y3 = cf2_stack_getReal( opStack, index + 3 ) + y2;
1312
1313 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
1314
1315 curX = x3;
1316 curY = y3;
1317 index += 4;
1318 }
1319
1320 cf2_stack_clear( opStack );
1321 }
1322 continue; /* no need to clear stack again */
1323
1324 case cf2_cmdHHCURVETO:
1325 {
1326 CF2_UInt count = cf2_stack_count( opStack );
1327 CF2_UInt index = 0;
1328
1329
1330 FT_TRACE4(( " hhcurveto\n" ));
1331
1332 while ( index < count )
1333 {
1334 CF2_Fixed x1, y1, x2, y2, x3, y3;
1335
1336
1337 if ( ( count - index ) & 1 )
1338 {
1339 y1 = cf2_stack_getReal( opStack, index ) + curY;
1340
1341 ++index;
1342 }
1343 else
1344 y1 = curY;
1345
1346 x1 = cf2_stack_getReal( opStack, index + 0 ) + curX;
1347 x2 = cf2_stack_getReal( opStack, index + 1 ) + x1;
1348 y2 = cf2_stack_getReal( opStack, index + 2 ) + y1;
1349 x3 = cf2_stack_getReal( opStack, index + 3 ) + x2;
1350 y3 = y2;
1351
1352 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
1353
1354 curX = x3;
1355 curY = y3;
1356 index += 4;
1357 }
1358
1359 cf2_stack_clear( opStack );
1360 }
1361 continue; /* no need to clear stack again */
1362
1363 case cf2_cmdVHCURVETO:
1364 case cf2_cmdHVCURVETO:
1365 {
1366 CF2_UInt count = cf2_stack_count( opStack );
1367 CF2_UInt index = 0;
1368
1369 FT_Bool alternate = op1 == cf2_cmdHVCURVETO;
1370
1371
1372 FT_TRACE4(( alternate ? " hvcurveto\n" : " vhcurveto\n" ));
1373
1374 while ( index < count )
1375 {
1376 CF2_Fixed x1, x2, x3, y1, y2, y3;
1377
1378
1379 if ( alternate )
1380 {
1381 x1 = cf2_stack_getReal( opStack, index + 0 ) + curX;
1382 y1 = curY;
1383 x2 = cf2_stack_getReal( opStack, index + 1 ) + x1;
1384 y2 = cf2_stack_getReal( opStack, index + 2 ) + y1;
1385 y3 = cf2_stack_getReal( opStack, index + 3 ) + y2;
1386
1387 if ( count - index == 5 )
1388 {
1389 x3 = cf2_stack_getReal( opStack, index + 4 ) + x2;
1390
1391 ++index;
1392 }
1393 else
1394 x3 = x2;
1395
1396 alternate = FALSE;
1397 }
1398 else
1399 {
1400 x1 = curX;
1401 y1 = cf2_stack_getReal( opStack, index + 0 ) + curY;
1402 x2 = cf2_stack_getReal( opStack, index + 1 ) + x1;
1403 y2 = cf2_stack_getReal( opStack, index + 2 ) + y1;
1404 x3 = cf2_stack_getReal( opStack, index + 3 ) + x2;
1405
1406 if ( count - index == 5 )
1407 {
1408 y3 = cf2_stack_getReal( opStack, index + 4 ) + y2;
1409
1410 ++index;
1411 }
1412 else
1413 y3 = y2;
1414
1415 alternate = TRUE;
1416 }
1417
1418 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
1419
1420 curX = x3;
1421 curY = y3;
1422 index += 4;
1423 }
1424
1425 cf2_stack_clear( opStack );
1426 }
1427 continue; /* no need to clear stack again */
1428
1429 case cf2_cmdEXTENDEDNMBR:
1430 {
1431 CF2_Int v;
1432
1433
1434 v = (FT_Short)( ( cf2_buf_readByte( charstring ) << 8 ) |
1435 cf2_buf_readByte( charstring ) );
1436
1437 FT_TRACE4(( " %d", v ));
1438
1439 cf2_stack_pushInt( opStack, v );
1440 }
1441 continue;
1442
1443 default:
1444 /* numbers */
1445 {
1446 if ( /* op1 >= 32 && */ op1 <= 246 )
1447 {
1448 CF2_Int v;
1449
1450
1451 v = op1 - 139;
1452
1453 FT_TRACE4(( " %d", v ));
1454
1455 /* -107 .. 107 */
1456 cf2_stack_pushInt( opStack, v );
1457 }
1458
1459 else if ( /* op1 >= 247 && */ op1 <= 250 )
1460 {
1461 CF2_Int v;
1462
1463
1464 v = op1;
1465 v -= 247;
1466 v *= 256;
1467 v += cf2_buf_readByte( charstring );
1468 v += 108;
1469
1470 FT_TRACE4(( " %d", v ));
1471
1472 /* 108 .. 1131 */
1473 cf2_stack_pushInt( opStack, v );
1474 }
1475
1476 else if ( /* op1 >= 251 && */ op1 <= 254 )
1477 {
1478 CF2_Int v;
1479
1480
1481 v = op1;
1482 v -= 251;
1483 v *= 256;
1484 v += cf2_buf_readByte( charstring );
1485 v = -v - 108;
1486
1487 FT_TRACE4(( " %d", v ));
1488
1489 /* -1131 .. -108 */
1490 cf2_stack_pushInt( opStack, v );
1491 }
1492
1493 else /* op1 == 255 */
1494 {
1495 CF2_Fixed v;
1496
1497
1498 v = (CF2_Fixed)
1499 ( ( (FT_UInt32)cf2_buf_readByte( charstring ) << 24 ) |
1500 ( (FT_UInt32)cf2_buf_readByte( charstring ) << 16 ) |
1501 ( (FT_UInt32)cf2_buf_readByte( charstring ) << 8 ) |
1502 (FT_UInt32)cf2_buf_readByte( charstring ) );
1503
1504 FT_TRACE4(( " %.2f", v / 65536.0 ));
1505
1506 cf2_stack_pushFixed( opStack, v );
1507 }
1508 }
1509 continue; /* don't clear stack */
1510
1511 } /* end of switch statement checking `op1' */
1512
1513 cf2_stack_clear( opStack );
1514
1515 } /* end of main interpreter loop */
1516
1517 /* we get here if the charstring ends without cf2_cmdENDCHAR */
1518 FT_TRACE4(( "cf2_interpT2CharString:"
1519 " charstring ends without ENDCHAR\n" ));
1520
1521 exit:
1522 /* check whether last error seen is also the first one */
1523 cf2_setError( error, lastError );
1524
1525 /* free resources from objects we've used */
1526 cf2_glyphpath_finalize( &glyphPath );
1527 cf2_arrstack_finalize( &vStemHintArray );
1528 cf2_arrstack_finalize( &hStemHintArray );
1529 cf2_arrstack_finalize( &subrStack );
1530 cf2_stack_free( opStack );
1531
1532 FT_TRACE4(( "\n" ));
1533
1534 return;
1535 }
1536
1537
1538 /* END */
OLDNEW
« no previous file with comments | « src/cff/cf2intrp.h ('k') | src/cff/cf2read.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698