1 /***************************************************************************/ 2 /* */ 3 /* cf2intrp.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 "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 #include "cf2intrp.h" 47 48 #include "cf2error.h" 49 50 #include "cffload.h" 51 52 53 /*************************************************************************/ 54 /* */ 55 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 56 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 57 /* messages during execution. */ 58 /* */ 59 #undef FT_COMPONENT 60 #define FT_COMPONENT trace_cf2interp 61 62 63 FT_LOCAL_DEF( void ) cf2_hintmask_init(CF2_HintMask hintmask,FT_Error * error)64 cf2_hintmask_init( CF2_HintMask hintmask, 65 FT_Error* error ) 66 { 67 FT_ZERO( hintmask ); 68 69 hintmask->error = error; 70 } 71 72 73 FT_LOCAL_DEF( FT_Bool ) cf2_hintmask_isValid(const CF2_HintMask hintmask)74 cf2_hintmask_isValid( const CF2_HintMask hintmask ) 75 { 76 return hintmask->isValid; 77 } 78 79 80 FT_LOCAL_DEF( FT_Bool ) cf2_hintmask_isNew(const CF2_HintMask hintmask)81 cf2_hintmask_isNew( const CF2_HintMask hintmask ) 82 { 83 return hintmask->isNew; 84 } 85 86 87 FT_LOCAL_DEF( void ) cf2_hintmask_setNew(CF2_HintMask hintmask,FT_Bool val)88 cf2_hintmask_setNew( CF2_HintMask hintmask, 89 FT_Bool val ) 90 { 91 hintmask->isNew = val; 92 } 93 94 95 /* clients call `getMaskPtr' in order to iterate */ 96 /* through hint mask */ 97 98 FT_LOCAL_DEF( FT_Byte* ) cf2_hintmask_getMaskPtr(CF2_HintMask hintmask)99 cf2_hintmask_getMaskPtr( CF2_HintMask hintmask ) 100 { 101 return hintmask->mask; 102 } 103 104 105 static size_t cf2_hintmask_setCounts(CF2_HintMask hintmask,size_t bitCount)106 cf2_hintmask_setCounts( CF2_HintMask hintmask, 107 size_t bitCount ) 108 { 109 if ( bitCount > CF2_MAX_HINTS ) 110 { 111 /* total of h and v stems must be <= 96 */ 112 CF2_SET_ERROR( hintmask->error, Invalid_Glyph_Format ); 113 return 0; 114 } 115 116 hintmask->bitCount = bitCount; 117 hintmask->byteCount = ( hintmask->bitCount + 7 ) / 8; 118 119 hintmask->isValid = TRUE; 120 hintmask->isNew = TRUE; 121 122 return bitCount; 123 } 124 125 126 /* consume the hintmask bytes from the charstring, advancing the src */ 127 /* pointer */ 128 static void cf2_hintmask_read(CF2_HintMask hintmask,CF2_Buffer charstring,size_t bitCount)129 cf2_hintmask_read( CF2_HintMask hintmask, 130 CF2_Buffer charstring, 131 size_t bitCount ) 132 { 133 size_t i; 134 135 #ifndef CF2_NDEBUG 136 /* these are the bits in the final mask byte that should be zero */ 137 /* Note: this variable is only used in an assert expression below */ 138 /* and then only if CF2_NDEBUG is not defined */ 139 CF2_UInt mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1; 140 #endif 141 142 143 /* initialize counts and isValid */ 144 if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 ) 145 return; 146 147 FT_ASSERT( hintmask->byteCount > 0 ); 148 149 FT_TRACE4(( " (maskbytes:" )); 150 151 /* set mask and advance interpreter's charstring pointer */ 152 for ( i = 0; i < hintmask->byteCount; i++ ) 153 { 154 hintmask->mask[i] = (FT_Byte)cf2_buf_readByte( charstring ); 155 FT_TRACE4(( " 0x%02X", hintmask->mask[i] )); 156 } 157 158 FT_TRACE4(( ")\n" )); 159 160 /* assert any unused bits in last byte are zero unless there's a prior */ 161 /* error */ 162 /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1 */ 163 #ifndef CF2_NDEBUG 164 FT_ASSERT( ( hintmask->mask[hintmask->byteCount - 1] & mask ) == 0 || 165 *hintmask->error ); 166 #endif 167 } 168 169 170 FT_LOCAL_DEF( void ) cf2_hintmask_setAll(CF2_HintMask hintmask,size_t bitCount)171 cf2_hintmask_setAll( CF2_HintMask hintmask, 172 size_t bitCount ) 173 { 174 size_t i; 175 CF2_UInt mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1; 176 177 178 /* initialize counts and isValid */ 179 if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 ) 180 return; 181 182 FT_ASSERT( hintmask->byteCount > 0 ); 183 FT_ASSERT( hintmask->byteCount <= 184 sizeof ( hintmask->mask ) / sizeof ( hintmask->mask[0] ) ); 185 186 /* set mask to all ones */ 187 for ( i = 0; i < hintmask->byteCount; i++ ) 188 hintmask->mask[i] = 0xFF; 189 190 /* clear unused bits */ 191 /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1 */ 192 hintmask->mask[hintmask->byteCount - 1] &= ~mask; 193 } 194 195 196 /* Type2 charstring opcodes */ 197 enum 198 { 199 cf2_cmdRESERVED_0, /* 0 */ 200 cf2_cmdHSTEM, /* 1 */ 201 cf2_cmdRESERVED_2, /* 2 */ 202 cf2_cmdVSTEM, /* 3 */ 203 cf2_cmdVMOVETO, /* 4 */ 204 cf2_cmdRLINETO, /* 5 */ 205 cf2_cmdHLINETO, /* 6 */ 206 cf2_cmdVLINETO, /* 7 */ 207 cf2_cmdRRCURVETO, /* 8 */ 208 cf2_cmdRESERVED_9, /* 9 */ 209 cf2_cmdCALLSUBR, /* 10 */ 210 cf2_cmdRETURN, /* 11 */ 211 cf2_cmdESC, /* 12 */ 212 cf2_cmdRESERVED_13, /* 13 */ 213 cf2_cmdENDCHAR, /* 14 */ 214 cf2_cmdVSINDEX, /* 15 */ 215 cf2_cmdBLEND, /* 16 */ 216 cf2_cmdRESERVED_17, /* 17 */ 217 cf2_cmdHSTEMHM, /* 18 */ 218 cf2_cmdHINTMASK, /* 19 */ 219 cf2_cmdCNTRMASK, /* 20 */ 220 cf2_cmdRMOVETO, /* 21 */ 221 cf2_cmdHMOVETO, /* 22 */ 222 cf2_cmdVSTEMHM, /* 23 */ 223 cf2_cmdRCURVELINE, /* 24 */ 224 cf2_cmdRLINECURVE, /* 25 */ 225 cf2_cmdVVCURVETO, /* 26 */ 226 cf2_cmdHHCURVETO, /* 27 */ 227 cf2_cmdEXTENDEDNMBR, /* 28 */ 228 cf2_cmdCALLGSUBR, /* 29 */ 229 cf2_cmdVHCURVETO, /* 30 */ 230 cf2_cmdHVCURVETO /* 31 */ 231 }; 232 233 enum 234 { 235 cf2_escDOTSECTION, /* 0 */ 236 cf2_escRESERVED_1, /* 1 */ 237 cf2_escRESERVED_2, /* 2 */ 238 cf2_escAND, /* 3 */ 239 cf2_escOR, /* 4 */ 240 cf2_escNOT, /* 5 */ 241 cf2_escRESERVED_6, /* 6 */ 242 cf2_escRESERVED_7, /* 7 */ 243 cf2_escRESERVED_8, /* 8 */ 244 cf2_escABS, /* 9 */ 245 cf2_escADD, /* 10 like otherADD */ 246 cf2_escSUB, /* 11 like otherSUB */ 247 cf2_escDIV, /* 12 */ 248 cf2_escRESERVED_13, /* 13 */ 249 cf2_escNEG, /* 14 */ 250 cf2_escEQ, /* 15 */ 251 cf2_escRESERVED_16, /* 16 */ 252 cf2_escRESERVED_17, /* 17 */ 253 cf2_escDROP, /* 18 */ 254 cf2_escRESERVED_19, /* 19 */ 255 cf2_escPUT, /* 20 like otherPUT */ 256 cf2_escGET, /* 21 like otherGET */ 257 cf2_escIFELSE, /* 22 like otherIFELSE */ 258 cf2_escRANDOM, /* 23 like otherRANDOM */ 259 cf2_escMUL, /* 24 like otherMUL */ 260 cf2_escRESERVED_25, /* 25 */ 261 cf2_escSQRT, /* 26 */ 262 cf2_escDUP, /* 27 like otherDUP */ 263 cf2_escEXCH, /* 28 like otherEXCH */ 264 cf2_escINDEX, /* 29 */ 265 cf2_escROLL, /* 30 */ 266 cf2_escRESERVED_31, /* 31 */ 267 cf2_escRESERVED_32, /* 32 */ 268 cf2_escRESERVED_33, /* 33 */ 269 cf2_escHFLEX, /* 34 */ 270 cf2_escFLEX, /* 35 */ 271 cf2_escHFLEX1, /* 36 */ 272 cf2_escFLEX1, /* 37 */ 273 cf2_escRESERVED_38 /* 38 & all higher */ 274 }; 275 276 277 /* `stemHintArray' does not change once we start drawing the outline. */ 278 static void cf2_doStems(const CF2_Font font,CF2_Stack opStack,CF2_ArrStack stemHintArray,CF2_Fixed * width,FT_Bool * haveWidth,CF2_Fixed hintOffset)279 cf2_doStems( const CF2_Font font, 280 CF2_Stack opStack, 281 CF2_ArrStack stemHintArray, 282 CF2_Fixed* width, 283 FT_Bool* haveWidth, 284 CF2_Fixed hintOffset ) 285 { 286 CF2_UInt i; 287 CF2_UInt count = cf2_stack_count( opStack ); 288 FT_Bool hasWidthArg = (FT_Bool)( count & 1 ); 289 290 /* variable accumulates delta values from operand stack */ 291 CF2_Fixed position = hintOffset; 292 293 294 if ( hasWidthArg && !*haveWidth ) 295 *width = cf2_stack_getReal( opStack, 0 ) + 296 cf2_getNominalWidthX( font->decoder ); 297 298 if ( font->decoder->width_only ) 299 goto exit; 300 301 for ( i = hasWidthArg ? 1 : 0; i < count; i += 2 ) 302 { 303 /* construct a CF2_StemHint and push it onto the list */ 304 CF2_StemHintRec stemhint; 305 306 307 stemhint.min = 308 position = ADD_INT32( position, 309 cf2_stack_getReal( opStack, i ) ); 310 stemhint.max = 311 position = ADD_INT32( position, 312 cf2_stack_getReal( opStack, i + 1 ) ); 313 314 stemhint.used = FALSE; 315 stemhint.maxDS = 316 stemhint.minDS = 0; 317 318 cf2_arrstack_push( stemHintArray, &stemhint ); /* defer error check */ 319 } 320 321 cf2_stack_clear( opStack ); 322 323 exit: 324 /* cf2_doStems must define a width (may be default) */ 325 *haveWidth = TRUE; 326 } 327 328 329 static void cf2_doFlex(CF2_Stack opStack,CF2_Fixed * curX,CF2_Fixed * curY,CF2_GlyphPath glyphPath,const FT_Bool * readFromStack,FT_Bool doConditionalLastRead)330 cf2_doFlex( CF2_Stack opStack, 331 CF2_Fixed* curX, 332 CF2_Fixed* curY, 333 CF2_GlyphPath glyphPath, 334 const FT_Bool* readFromStack, 335 FT_Bool doConditionalLastRead ) 336 { 337 CF2_Fixed vals[14]; 338 CF2_UInt idx; 339 FT_Bool isHFlex; 340 CF2_Int top, i, j; 341 342 343 vals[0] = *curX; 344 vals[1] = *curY; 345 idx = 0; 346 isHFlex = FT_BOOL( readFromStack[9] == FALSE ); 347 top = isHFlex ? 9 : 10; 348 349 for ( i = 0; i < top; i++ ) 350 { 351 vals[i + 2] = vals[i]; 352 if ( readFromStack[i] ) 353 vals[i + 2] = ADD_INT32( vals[i + 2], cf2_stack_getReal( opStack, 354 idx++ ) ); 355 } 356 357 if ( isHFlex ) 358 vals[9 + 2] = *curY; 359 360 if ( doConditionalLastRead ) 361 { 362 FT_Bool lastIsX = (FT_Bool)( 363 cf2_fixedAbs( SUB_INT32( vals[10], *curX ) ) > 364 cf2_fixedAbs( SUB_INT32( vals[11], *curY ) ) ); 365 CF2_Fixed lastVal = cf2_stack_getReal( opStack, idx ); 366 367 368 if ( lastIsX ) 369 { 370 vals[12] = ADD_INT32( vals[10], lastVal ); 371 vals[13] = *curY; 372 } 373 else 374 { 375 vals[12] = *curX; 376 vals[13] = ADD_INT32( vals[11], lastVal ); 377 } 378 } 379 else 380 { 381 if ( readFromStack[10] ) 382 vals[12] = ADD_INT32( vals[10], 383 cf2_stack_getReal( opStack, idx++ ) ); 384 else 385 vals[12] = *curX; 386 387 if ( readFromStack[11] ) 388 vals[13] = ADD_INT32( vals[11], 389 cf2_stack_getReal( opStack, idx ) ); 390 else 391 vals[13] = *curY; 392 } 393 394 for ( j = 0; j < 2; j++ ) 395 cf2_glyphpath_curveTo( glyphPath, vals[j * 6 + 2], 396 vals[j * 6 + 3], 397 vals[j * 6 + 4], 398 vals[j * 6 + 5], 399 vals[j * 6 + 6], 400 vals[j * 6 + 7] ); 401 402 cf2_stack_clear( opStack ); 403 404 *curX = vals[12]; 405 *curY = vals[13]; 406 } 407 408 409 /* Blend numOperands on the stack, */ 410 /* store results into the first numBlends values, */ 411 /* then pop remaining arguments. */ 412 static void cf2_doBlend(const CFF_Blend blend,CF2_Stack opStack,CF2_UInt numBlends)413 cf2_doBlend( const CFF_Blend blend, 414 CF2_Stack opStack, 415 CF2_UInt numBlends ) 416 { 417 CF2_UInt delta; 418 CF2_UInt base; 419 CF2_UInt i, j; 420 CF2_UInt numOperands = (CF2_UInt)( numBlends * blend->lenBV ); 421 422 423 base = cf2_stack_count( opStack ) - numOperands; 424 delta = base + numBlends; 425 426 for ( i = 0; i < numBlends; i++ ) 427 { 428 const CF2_Fixed* weight = &blend->BV[1]; 429 430 /* start with first term */ 431 CF2_Fixed sum = cf2_stack_getReal( opStack, i + base ); 432 433 434 for ( j = 1; j < blend->lenBV; j++ ) 435 sum = ADD_INT32( sum, 436 FT_MulFix( *weight++, 437 cf2_stack_getReal( opStack, 438 delta++ ) ) ); 439 440 /* store blended result */ 441 cf2_stack_setReal( opStack, i + base, sum ); 442 } 443 444 /* leave only `numBlends' results on stack */ 445 cf2_stack_pop( opStack, numOperands - numBlends ); 446 } 447 448 449 /* 450 * `error' is a shared error code used by many objects in this 451 * routine. Before the code continues from an error, it must check and 452 * record the error in `*error'. The idea is that this shared 453 * error code will record the first error encountered. If testing 454 * for an error anyway, the cost of `goto exit' is small, so we do it, 455 * even if continuing would be safe. In this case, `lastError' is 456 * set, so the testing and storing can be done in one place, at `exit'. 457 * 458 * Continuing after an error is intended for objects which do their own 459 * testing of `*error', e.g., array stack functions. This allows us to 460 * avoid an extra test after the call. 461 * 462 * Unimplemented opcodes are ignored. 463 * 464 */ 465 FT_LOCAL_DEF( void ) cf2_interpT2CharString(CF2_Font font,CF2_Buffer buf,CF2_OutlineCallbacks callbacks,const FT_Vector * translation,FT_Bool doingSeac,CF2_Fixed curX,CF2_Fixed curY,CF2_Fixed * width)466 cf2_interpT2CharString( CF2_Font font, 467 CF2_Buffer buf, 468 CF2_OutlineCallbacks callbacks, 469 const FT_Vector* translation, 470 FT_Bool doingSeac, 471 CF2_Fixed curX, 472 CF2_Fixed curY, 473 CF2_Fixed* width ) 474 { 475 /* lastError is used for errors that are immediately tested */ 476 FT_Error lastError = FT_Err_Ok; 477 478 /* pointer to parsed font object */ 479 CFF_Decoder* decoder = font->decoder; 480 481 FT_Error* error = &font->error; 482 FT_Memory memory = font->memory; 483 484 CF2_Fixed scaleY = font->innerTransform.d; 485 CF2_Fixed nominalWidthX = cf2_getNominalWidthX( decoder ); 486 487 /* save this for hinting seac accents */ 488 CF2_Fixed hintOriginY = curY; 489 490 CF2_Stack opStack = NULL; 491 FT_UInt stackSize; 492 FT_Byte op1; /* first opcode byte */ 493 494 CF2_F16Dot16 storage[CF2_STORAGE_SIZE]; /* for `put' and `get' */ 495 496 /* instruction limit; 20,000,000 matches Avalon */ 497 FT_UInt32 instructionLimit = 20000000UL; 498 499 CF2_ArrStackRec subrStack; 500 501 FT_Bool haveWidth; 502 CF2_Buffer charstring = NULL; 503 504 CF2_Int charstringIndex = -1; /* initialize to empty */ 505 506 /* TODO: placeholders for hint structures */ 507 508 /* objects used for hinting */ 509 CF2_ArrStackRec hStemHintArray; 510 CF2_ArrStackRec vStemHintArray; 511 512 CF2_HintMaskRec hintMask; 513 CF2_GlyphPathRec glyphPath; 514 515 516 FT_ZERO( &storage ); 517 518 /* initialize the remaining objects */ 519 cf2_arrstack_init( &subrStack, 520 memory, 521 error, 522 sizeof ( CF2_BufferRec ) ); 523 cf2_arrstack_init( &hStemHintArray, 524 memory, 525 error, 526 sizeof ( CF2_StemHintRec ) ); 527 cf2_arrstack_init( &vStemHintArray, 528 memory, 529 error, 530 sizeof ( CF2_StemHintRec ) ); 531 532 /* initialize CF2_StemHint arrays */ 533 cf2_hintmask_init( &hintMask, error ); 534 535 /* initialize path map to manage drawing operations */ 536 537 /* Note: last 4 params are used to handle `MoveToPermissive', which */ 538 /* may need to call `hintMap.Build' */ 539 /* TODO: MoveToPermissive is gone; are these still needed? */ 540 cf2_glyphpath_init( &glyphPath, 541 font, 542 callbacks, 543 scaleY, 544 /* hShift, */ 545 &hStemHintArray, 546 &vStemHintArray, 547 &hintMask, 548 hintOriginY, 549 &font->blues, 550 translation ); 551 552 /* 553 * Initialize state for width parsing. From the CFF Spec: 554 * 555 * The first stack-clearing operator, which must be one of hstem, 556 * hstemhm, vstem, vstemhm, cntrmask, hintmask, hmoveto, vmoveto, 557 * rmoveto, or endchar, takes an additional argument - the width (as 558 * described earlier), which may be expressed as zero or one numeric 559 * argument. 560 * 561 * What we implement here uses the first validly specified width, but 562 * does not detect errors for specifying more than one width. 563 * 564 * If one of the above operators occurs without explicitly specifying 565 * a width, we assume the default width. 566 * 567 * CFF2 charstrings always return the default width (0). 568 * 569 */ 570 haveWidth = font->isCFF2 ? TRUE : FALSE; 571 *width = cf2_getDefaultWidthX( decoder ); 572 573 /* 574 * Note: At this point, all pointers to resources must be NULL 575 * and all local objects must be initialized. 576 * There must be no branches to `exit:' above this point. 577 * 578 */ 579 580 /* allocate an operand stack */ 581 stackSize = font->isCFF2 ? cf2_getMaxstack( decoder ) 582 : CF2_OPERAND_STACK_SIZE; 583 opStack = cf2_stack_init( memory, error, stackSize ); 584 585 if ( !opStack ) 586 { 587 lastError = FT_THROW( Out_Of_Memory ); 588 goto exit; 589 } 590 591 /* initialize subroutine stack by placing top level charstring as */ 592 /* first element (max depth plus one for the charstring) */ 593 /* Note: Caller owns and must finalize the first charstring. */ 594 /* Our copy of it does not change that requirement. */ 595 cf2_arrstack_setCount( &subrStack, CF2_MAX_SUBR + 1 ); 596 597 charstring = (CF2_Buffer)cf2_arrstack_getBuffer( &subrStack ); 598 *charstring = *buf; /* structure copy */ 599 600 charstringIndex = 0; /* entry is valid now */ 601 602 /* catch errors so far */ 603 if ( *error ) 604 goto exit; 605 606 /* main interpreter loop */ 607 while ( 1 ) 608 { 609 if ( cf2_buf_isEnd( charstring ) ) 610 { 611 /* If we've reached the end of the charstring, simulate a */ 612 /* cf2_cmdRETURN or cf2_cmdENDCHAR. */ 613 /* We do this for both CFF and CFF2. */ 614 if ( charstringIndex ) 615 op1 = cf2_cmdRETURN; /* end of buffer for subroutine */ 616 else 617 op1 = cf2_cmdENDCHAR; /* end of buffer for top level charstring */ 618 } 619 else 620 { 621 op1 = (FT_Byte)cf2_buf_readByte( charstring ); 622 623 /* Explicit RETURN and ENDCHAR in CFF2 should be ignored. */ 624 /* Note: Trace message will report 0 instead of 11 or 14. */ 625 if ( ( op1 == cf2_cmdRETURN || op1 == cf2_cmdENDCHAR ) && 626 font->isCFF2 ) 627 op1 = cf2_cmdRESERVED_0; 628 } 629 630 /* check for errors once per loop */ 631 if ( *error ) 632 goto exit; 633 634 instructionLimit--; 635 if ( instructionLimit == 0 ) 636 { 637 lastError = FT_THROW( Invalid_Glyph_Format ); 638 goto exit; 639 } 640 641 switch( op1 ) 642 { 643 case cf2_cmdRESERVED_0: 644 case cf2_cmdRESERVED_2: 645 case cf2_cmdRESERVED_9: 646 case cf2_cmdRESERVED_13: 647 case cf2_cmdRESERVED_17: 648 /* we may get here if we have a prior error */ 649 FT_TRACE4(( " unknown op (%d)\n", op1 )); 650 break; 651 652 case cf2_cmdVSINDEX: 653 FT_TRACE4(( " vsindex\n" )); 654 655 if ( !font->isCFF2 ) 656 break; /* clear stack & ignore */ 657 658 if ( font->blend.usedBV ) 659 { 660 /* vsindex not allowed after blend */ 661 lastError = FT_THROW( Invalid_Glyph_Format ); 662 goto exit; 663 } 664 665 { 666 FT_Int temp = cf2_stack_popInt( opStack ); 667 668 669 if ( temp >= 0 ) 670 font->vsindex = (FT_UInt)temp; 671 } 672 break; 673 674 case cf2_cmdBLEND: 675 { 676 FT_UInt numBlends; 677 678 679 FT_TRACE4(( " blend\n" )); 680 681 if ( !font->isCFF2 ) 682 break; /* clear stack & ignore */ 683 684 /* do we have a `blend' op in a non-variant font? */ 685 if ( !font->blend.font ) 686 { 687 lastError = FT_THROW( Invalid_Glyph_Format ); 688 goto exit; 689 } 690 691 /* check cached blend vector */ 692 if ( cff_blend_check_vector( &font->blend, 693 font->vsindex, 694 font->lenNDV, 695 font->NDV ) ) 696 { 697 lastError = cff_blend_build_vector( &font->blend, 698 font->vsindex, 699 font->lenNDV, 700 font->NDV ); 701 if ( lastError ) 702 goto exit; 703 } 704 705 /* do the blend */ 706 numBlends = (FT_UInt)cf2_stack_popInt( opStack ); 707 if ( numBlends > stackSize ) 708 { 709 lastError = FT_THROW( Invalid_Glyph_Format ); 710 goto exit; 711 } 712 713 cf2_doBlend( &font->blend, opStack, numBlends ); 714 715 font->blend.usedBV = TRUE; 716 } 717 continue; /* do not clear the stack */ 718 719 case cf2_cmdHSTEMHM: 720 case cf2_cmdHSTEM: 721 FT_TRACE4(( op1 == cf2_cmdHSTEMHM ? " hstemhm\n" : " hstem\n" )); 722 723 /* never add hints after the mask is computed */ 724 if ( cf2_hintmask_isValid( &hintMask ) ) 725 { 726 FT_TRACE4(( "cf2_interpT2CharString:" 727 " invalid horizontal hint mask\n" )); 728 break; 729 } 730 731 cf2_doStems( font, 732 opStack, 733 &hStemHintArray, 734 width, 735 &haveWidth, 736 0 ); 737 738 if ( font->decoder->width_only ) 739 goto exit; 740 741 break; 742 743 case cf2_cmdVSTEMHM: 744 case cf2_cmdVSTEM: 745 FT_TRACE4(( op1 == cf2_cmdVSTEMHM ? " vstemhm\n" : " vstem\n" )); 746 747 /* never add hints after the mask is computed */ 748 if ( cf2_hintmask_isValid( &hintMask ) ) 749 { 750 FT_TRACE4(( "cf2_interpT2CharString:" 751 " invalid vertical hint mask\n" )); 752 break; 753 } 754 755 cf2_doStems( font, 756 opStack, 757 &vStemHintArray, 758 width, 759 &haveWidth, 760 0 ); 761 762 if ( font->decoder->width_only ) 763 goto exit; 764 765 break; 766 767 case cf2_cmdVMOVETO: 768 FT_TRACE4(( " vmoveto\n" )); 769 770 if ( cf2_stack_count( opStack ) > 1 && !haveWidth ) 771 *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ), 772 nominalWidthX ); 773 774 /* width is defined or default after this */ 775 haveWidth = TRUE; 776 777 if ( font->decoder->width_only ) 778 goto exit; 779 780 curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) ); 781 782 cf2_glyphpath_moveTo( &glyphPath, curX, curY ); 783 784 break; 785 786 case cf2_cmdRLINETO: 787 { 788 CF2_UInt idx; 789 CF2_UInt count = cf2_stack_count( opStack ); 790 791 792 FT_TRACE4(( " rlineto\n" )); 793 794 for ( idx = 0; idx < count; idx += 2 ) 795 { 796 curX = ADD_INT32( curX, cf2_stack_getReal( opStack, 797 idx + 0 ) ); 798 curY = ADD_INT32( curY, cf2_stack_getReal( opStack, 799 idx + 1 ) ); 800 801 cf2_glyphpath_lineTo( &glyphPath, curX, curY ); 802 } 803 804 cf2_stack_clear( opStack ); 805 } 806 continue; /* no need to clear stack again */ 807 808 case cf2_cmdHLINETO: 809 case cf2_cmdVLINETO: 810 { 811 CF2_UInt idx; 812 CF2_UInt count = cf2_stack_count( opStack ); 813 814 FT_Bool isX = FT_BOOL( op1 == cf2_cmdHLINETO ); 815 816 817 FT_TRACE4(( isX ? " hlineto\n" : " vlineto\n" )); 818 819 for ( idx = 0; idx < count; idx++ ) 820 { 821 CF2_Fixed v = cf2_stack_getReal( opStack, idx ); 822 823 824 if ( isX ) 825 curX = ADD_INT32( curX, v ); 826 else 827 curY = ADD_INT32( curY, v ); 828 829 isX = !isX; 830 831 cf2_glyphpath_lineTo( &glyphPath, curX, curY ); 832 } 833 834 cf2_stack_clear( opStack ); 835 } 836 continue; 837 838 case cf2_cmdRCURVELINE: 839 case cf2_cmdRRCURVETO: 840 { 841 CF2_UInt count = cf2_stack_count( opStack ); 842 CF2_UInt idx = 0; 843 844 845 FT_TRACE4(( op1 == cf2_cmdRCURVELINE ? " rcurveline\n" 846 : " rrcurveto\n" )); 847 848 while ( idx + 6 <= count ) 849 { 850 CF2_Fixed x1, y1, x2, y2, x3, y3; 851 852 853 x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX ); 854 y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), curY ); 855 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), x1 ); 856 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y1 ); 857 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 ); 858 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 5 ), y2 ); 859 860 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); 861 862 curX = x3; 863 curY = y3; 864 idx += 6; 865 } 866 867 if ( op1 == cf2_cmdRCURVELINE ) 868 { 869 curX = ADD_INT32( curX, cf2_stack_getReal( opStack, 870 idx + 0 ) ); 871 curY = ADD_INT32( curY, cf2_stack_getReal( opStack, 872 idx + 1 ) ); 873 874 cf2_glyphpath_lineTo( &glyphPath, curX, curY ); 875 } 876 877 cf2_stack_clear( opStack ); 878 } 879 continue; /* no need to clear stack again */ 880 881 case cf2_cmdCALLGSUBR: 882 case cf2_cmdCALLSUBR: 883 { 884 CF2_Int subrNum; 885 886 887 FT_TRACE4(( op1 == cf2_cmdCALLGSUBR ? " callgsubr" 888 : " callsubr" )); 889 890 if ( charstringIndex > CF2_MAX_SUBR ) 891 { 892 /* max subr plus one for charstring */ 893 lastError = FT_THROW( Invalid_Glyph_Format ); 894 goto exit; /* overflow of stack */ 895 } 896 897 /* push our current CFF charstring region on subrStack */ 898 charstring = (CF2_Buffer) 899 cf2_arrstack_getPointer( 900 &subrStack, 901 (size_t)charstringIndex + 1 ); 902 903 /* set up the new CFF region and pointer */ 904 subrNum = cf2_stack_popInt( opStack ); 905 906 switch ( op1 ) 907 { 908 case cf2_cmdCALLGSUBR: 909 FT_TRACE4(( " (idx %d, entering level %d)\n", 910 subrNum + decoder->globals_bias, 911 charstringIndex + 1 )); 912 913 if ( cf2_initGlobalRegionBuffer( decoder, 914 subrNum, 915 charstring ) ) 916 { 917 lastError = FT_THROW( Invalid_Glyph_Format ); 918 goto exit; /* subroutine lookup or stream error */ 919 } 920 break; 921 922 default: 923 /* cf2_cmdCALLSUBR */ 924 FT_TRACE4(( " (idx %d, entering level %d)\n", 925 subrNum + decoder->locals_bias, 926 charstringIndex + 1 )); 927 928 if ( cf2_initLocalRegionBuffer( decoder, 929 subrNum, 930 charstring ) ) 931 { 932 lastError = FT_THROW( Invalid_Glyph_Format ); 933 goto exit; /* subroutine lookup or stream error */ 934 } 935 } 936 937 charstringIndex += 1; /* entry is valid now */ 938 } 939 continue; /* do not clear the stack */ 940 941 case cf2_cmdRETURN: 942 FT_TRACE4(( " return (leaving level %d)\n", charstringIndex )); 943 944 if ( charstringIndex < 1 ) 945 { 946 /* Note: cannot return from top charstring */ 947 lastError = FT_THROW( Invalid_Glyph_Format ); 948 goto exit; /* underflow of stack */ 949 } 950 951 /* restore position in previous charstring */ 952 charstring = (CF2_Buffer) 953 cf2_arrstack_getPointer( 954 &subrStack, 955 (CF2_UInt)--charstringIndex ); 956 continue; /* do not clear the stack */ 957 958 case cf2_cmdESC: 959 { 960 FT_Byte op2 = (FT_Byte)cf2_buf_readByte( charstring ); 961 962 963 /* first switch for 2-byte operators handles CFF2 */ 964 /* and opcodes that are reserved for both CFF and CFF2 */ 965 switch ( op2 ) 966 { 967 case cf2_escHFLEX: 968 { 969 static const FT_Bool readFromStack[12] = 970 { 971 TRUE /* dx1 */, FALSE /* dy1 */, 972 TRUE /* dx2 */, TRUE /* dy2 */, 973 TRUE /* dx3 */, FALSE /* dy3 */, 974 TRUE /* dx4 */, FALSE /* dy4 */, 975 TRUE /* dx5 */, FALSE /* dy5 */, 976 TRUE /* dx6 */, FALSE /* dy6 */ 977 }; 978 979 980 FT_TRACE4(( " hflex\n" )); 981 982 cf2_doFlex( opStack, 983 &curX, 984 &curY, 985 &glyphPath, 986 readFromStack, 987 FALSE /* doConditionalLastRead */ ); 988 } 989 continue; 990 991 case cf2_escFLEX: 992 { 993 static const FT_Bool readFromStack[12] = 994 { 995 TRUE /* dx1 */, TRUE /* dy1 */, 996 TRUE /* dx2 */, TRUE /* dy2 */, 997 TRUE /* dx3 */, TRUE /* dy3 */, 998 TRUE /* dx4 */, TRUE /* dy4 */, 999 TRUE /* dx5 */, TRUE /* dy5 */, 1000 TRUE /* dx6 */, TRUE /* dy6 */ 1001 }; 1002 1003 1004 FT_TRACE4(( " flex\n" )); 1005 1006 cf2_doFlex( opStack, 1007 &curX, 1008 &curY, 1009 &glyphPath, 1010 readFromStack, 1011 FALSE /* doConditionalLastRead */ ); 1012 } 1013 break; /* TODO: why is this not a continue? */ 1014 1015 case cf2_escHFLEX1: 1016 { 1017 static const FT_Bool readFromStack[12] = 1018 { 1019 TRUE /* dx1 */, TRUE /* dy1 */, 1020 TRUE /* dx2 */, TRUE /* dy2 */, 1021 TRUE /* dx3 */, FALSE /* dy3 */, 1022 TRUE /* dx4 */, FALSE /* dy4 */, 1023 TRUE /* dx5 */, TRUE /* dy5 */, 1024 TRUE /* dx6 */, FALSE /* dy6 */ 1025 }; 1026 1027 1028 FT_TRACE4(( " hflex1\n" )); 1029 1030 cf2_doFlex( opStack, 1031 &curX, 1032 &curY, 1033 &glyphPath, 1034 readFromStack, 1035 FALSE /* doConditionalLastRead */ ); 1036 } 1037 continue; 1038 1039 case cf2_escFLEX1: 1040 { 1041 static const FT_Bool readFromStack[12] = 1042 { 1043 TRUE /* dx1 */, TRUE /* dy1 */, 1044 TRUE /* dx2 */, TRUE /* dy2 */, 1045 TRUE /* dx3 */, TRUE /* dy3 */, 1046 TRUE /* dx4 */, TRUE /* dy4 */, 1047 TRUE /* dx5 */, TRUE /* dy5 */, 1048 FALSE /* dx6 */, FALSE /* dy6 */ 1049 }; 1050 1051 1052 FT_TRACE4(( " flex1\n" )); 1053 1054 cf2_doFlex( opStack, 1055 &curX, 1056 &curY, 1057 &glyphPath, 1058 readFromStack, 1059 TRUE /* doConditionalLastRead */ ); 1060 } 1061 continue; 1062 1063 /* these opcodes are reserved in both CFF & CFF2 */ 1064 case cf2_escRESERVED_1: 1065 case cf2_escRESERVED_2: 1066 case cf2_escRESERVED_6: 1067 case cf2_escRESERVED_7: 1068 case cf2_escRESERVED_8: 1069 case cf2_escRESERVED_13: 1070 case cf2_escRESERVED_16: 1071 case cf2_escRESERVED_17: 1072 case cf2_escRESERVED_19: 1073 case cf2_escRESERVED_25: 1074 case cf2_escRESERVED_31: 1075 case cf2_escRESERVED_32: 1076 case cf2_escRESERVED_33: 1077 FT_TRACE4(( " unknown op (12, %d)\n", op2 )); 1078 break; 1079 1080 default: 1081 { 1082 if ( font->isCFF2 || op2 >= cf2_escRESERVED_38 ) 1083 FT_TRACE4(( " unknown op (12, %d)\n", op2 )); 1084 else 1085 { 1086 /* second switch for 2-byte operators handles just CFF */ 1087 switch ( op2 ) 1088 { 1089 1090 case cf2_escDOTSECTION: 1091 /* something about `flip type of locking' -- ignore it */ 1092 FT_TRACE4(( " dotsection\n" )); 1093 1094 break; 1095 1096 case cf2_escAND: 1097 { 1098 CF2_F16Dot16 arg1; 1099 CF2_F16Dot16 arg2; 1100 1101 1102 FT_TRACE4(( " and\n" )); 1103 1104 arg2 = cf2_stack_popFixed( opStack ); 1105 arg1 = cf2_stack_popFixed( opStack ); 1106 1107 cf2_stack_pushInt( opStack, arg1 && arg2 ); 1108 } 1109 continue; /* do not clear the stack */ 1110 1111 case cf2_escOR: 1112 { 1113 CF2_F16Dot16 arg1; 1114 CF2_F16Dot16 arg2; 1115 1116 1117 FT_TRACE4(( " or\n" )); 1118 1119 arg2 = cf2_stack_popFixed( opStack ); 1120 arg1 = cf2_stack_popFixed( opStack ); 1121 1122 cf2_stack_pushInt( opStack, arg1 || arg2 ); 1123 } 1124 continue; /* do not clear the stack */ 1125 1126 case cf2_escNOT: 1127 { 1128 CF2_F16Dot16 arg; 1129 1130 1131 FT_TRACE4(( " not\n" )); 1132 1133 arg = cf2_stack_popFixed( opStack ); 1134 1135 cf2_stack_pushInt( opStack, !arg ); 1136 } 1137 continue; /* do not clear the stack */ 1138 1139 case cf2_escABS: 1140 { 1141 CF2_F16Dot16 arg; 1142 1143 1144 FT_TRACE4(( " abs\n" )); 1145 1146 arg = cf2_stack_popFixed( opStack ); 1147 1148 if ( arg < -CF2_FIXED_MAX ) 1149 cf2_stack_pushFixed( opStack, CF2_FIXED_MAX ); 1150 else 1151 cf2_stack_pushFixed( opStack, FT_ABS( arg ) ); 1152 } 1153 continue; /* do not clear the stack */ 1154 1155 case cf2_escADD: 1156 { 1157 CF2_F16Dot16 summand1; 1158 CF2_F16Dot16 summand2; 1159 1160 1161 FT_TRACE4(( " add\n" )); 1162 1163 summand2 = cf2_stack_popFixed( opStack ); 1164 summand1 = cf2_stack_popFixed( opStack ); 1165 1166 cf2_stack_pushFixed( opStack, 1167 ADD_INT32( summand1, 1168 summand2 ) ); 1169 } 1170 continue; /* do not clear the stack */ 1171 1172 case cf2_escSUB: 1173 { 1174 CF2_F16Dot16 minuend; 1175 CF2_F16Dot16 subtrahend; 1176 1177 1178 FT_TRACE4(( " sub\n" )); 1179 1180 subtrahend = cf2_stack_popFixed( opStack ); 1181 minuend = cf2_stack_popFixed( opStack ); 1182 1183 cf2_stack_pushFixed( opStack, 1184 SUB_INT32( minuend, subtrahend ) ); 1185 } 1186 continue; /* do not clear the stack */ 1187 1188 case cf2_escDIV: 1189 { 1190 CF2_F16Dot16 dividend; 1191 CF2_F16Dot16 divisor; 1192 1193 1194 FT_TRACE4(( " div\n" )); 1195 1196 divisor = cf2_stack_popFixed( opStack ); 1197 dividend = cf2_stack_popFixed( opStack ); 1198 1199 cf2_stack_pushFixed( opStack, 1200 FT_DivFix( dividend, divisor ) ); 1201 } 1202 continue; /* do not clear the stack */ 1203 1204 case cf2_escNEG: 1205 { 1206 CF2_F16Dot16 arg; 1207 1208 1209 FT_TRACE4(( " neg\n" )); 1210 1211 arg = cf2_stack_popFixed( opStack ); 1212 1213 if ( arg < -CF2_FIXED_MAX ) 1214 cf2_stack_pushFixed( opStack, CF2_FIXED_MAX ); 1215 else 1216 cf2_stack_pushFixed( opStack, -arg ); 1217 } 1218 continue; /* do not clear the stack */ 1219 1220 case cf2_escEQ: 1221 { 1222 CF2_F16Dot16 arg1; 1223 CF2_F16Dot16 arg2; 1224 1225 1226 FT_TRACE4(( " eq\n" )); 1227 1228 arg2 = cf2_stack_popFixed( opStack ); 1229 arg1 = cf2_stack_popFixed( opStack ); 1230 1231 cf2_stack_pushInt( opStack, arg1 == arg2 ); 1232 } 1233 continue; /* do not clear the stack */ 1234 1235 case cf2_escDROP: 1236 FT_TRACE4(( " drop\n" )); 1237 1238 (void)cf2_stack_popFixed( opStack ); 1239 continue; /* do not clear the stack */ 1240 1241 case cf2_escPUT: 1242 { 1243 CF2_F16Dot16 val; 1244 CF2_Int idx; 1245 1246 1247 FT_TRACE4(( " put\n" )); 1248 1249 idx = cf2_stack_popInt( opStack ); 1250 val = cf2_stack_popFixed( opStack ); 1251 1252 if ( idx >= 0 && idx < CF2_STORAGE_SIZE ) 1253 storage[idx] = val; 1254 } 1255 continue; /* do not clear the stack */ 1256 1257 case cf2_escGET: 1258 { 1259 CF2_Int idx; 1260 1261 1262 FT_TRACE4(( " get\n" )); 1263 1264 idx = cf2_stack_popInt( opStack ); 1265 1266 if ( idx >= 0 && idx < CF2_STORAGE_SIZE ) 1267 cf2_stack_pushFixed( opStack, storage[idx] ); 1268 } 1269 continue; /* do not clear the stack */ 1270 1271 case cf2_escIFELSE: 1272 { 1273 CF2_F16Dot16 arg1; 1274 CF2_F16Dot16 arg2; 1275 CF2_F16Dot16 cond1; 1276 CF2_F16Dot16 cond2; 1277 1278 1279 FT_TRACE4(( " ifelse\n" )); 1280 1281 cond2 = cf2_stack_popFixed( opStack ); 1282 cond1 = cf2_stack_popFixed( opStack ); 1283 arg2 = cf2_stack_popFixed( opStack ); 1284 arg1 = cf2_stack_popFixed( opStack ); 1285 1286 cf2_stack_pushFixed( opStack, 1287 cond1 <= cond2 ? arg1 : arg2 ); 1288 } 1289 continue; /* do not clear the stack */ 1290 1291 case cf2_escRANDOM: /* in spec */ 1292 { 1293 CF2_F16Dot16 r; 1294 1295 1296 FT_TRACE4(( " random\n" )); 1297 1298 /* only use the lower 16 bits of `random' */ 1299 /* to generate a number in the range (0;1] */ 1300 r = (CF2_F16Dot16) 1301 ( ( decoder->current_subfont->random & 0xFFFF ) + 1 ); 1302 1303 decoder->current_subfont->random = 1304 cff_random( decoder->current_subfont->random ); 1305 1306 cf2_stack_pushFixed( opStack, r ); 1307 } 1308 continue; /* do not clear the stack */ 1309 1310 case cf2_escMUL: 1311 { 1312 CF2_F16Dot16 factor1; 1313 CF2_F16Dot16 factor2; 1314 1315 1316 FT_TRACE4(( " mul\n" )); 1317 1318 factor2 = cf2_stack_popFixed( opStack ); 1319 factor1 = cf2_stack_popFixed( opStack ); 1320 1321 cf2_stack_pushFixed( opStack, 1322 FT_MulFix( factor1, factor2 ) ); 1323 } 1324 continue; /* do not clear the stack */ 1325 1326 case cf2_escSQRT: 1327 { 1328 CF2_F16Dot16 arg; 1329 1330 1331 FT_TRACE4(( " sqrt\n" )); 1332 1333 arg = cf2_stack_popFixed( opStack ); 1334 if ( arg > 0 ) 1335 { 1336 /* use a start value that doesn't make */ 1337 /* the algorithm's addition overflow */ 1338 FT_Fixed root = arg < 10 ? arg : arg >> 1; 1339 FT_Fixed new_root; 1340 1341 1342 /* Babylonian method */ 1343 for (;;) 1344 { 1345 new_root = ( root + FT_DivFix( arg, root ) + 1 ) >> 1; 1346 if ( new_root == root ) 1347 break; 1348 root = new_root; 1349 } 1350 arg = new_root; 1351 } 1352 else 1353 arg = 0; 1354 1355 cf2_stack_pushFixed( opStack, arg ); 1356 } 1357 continue; /* do not clear the stack */ 1358 1359 case cf2_escDUP: 1360 { 1361 CF2_F16Dot16 arg; 1362 1363 1364 FT_TRACE4(( " dup\n" )); 1365 1366 arg = cf2_stack_popFixed( opStack ); 1367 1368 cf2_stack_pushFixed( opStack, arg ); 1369 cf2_stack_pushFixed( opStack, arg ); 1370 } 1371 continue; /* do not clear the stack */ 1372 1373 case cf2_escEXCH: 1374 { 1375 CF2_F16Dot16 arg1; 1376 CF2_F16Dot16 arg2; 1377 1378 1379 FT_TRACE4(( " exch\n" )); 1380 1381 arg2 = cf2_stack_popFixed( opStack ); 1382 arg1 = cf2_stack_popFixed( opStack ); 1383 1384 cf2_stack_pushFixed( opStack, arg2 ); 1385 cf2_stack_pushFixed( opStack, arg1 ); 1386 } 1387 continue; /* do not clear the stack */ 1388 1389 case cf2_escINDEX: 1390 { 1391 CF2_Int idx; 1392 CF2_UInt size; 1393 1394 1395 FT_TRACE4(( " index\n" )); 1396 1397 idx = cf2_stack_popInt( opStack ); 1398 size = cf2_stack_count( opStack ); 1399 1400 if ( size > 0 ) 1401 { 1402 /* for `cf2_stack_getReal', */ 1403 /* index 0 is bottom of stack */ 1404 CF2_UInt gr_idx; 1405 1406 1407 if ( idx < 0 ) 1408 gr_idx = size - 1; 1409 else if ( (CF2_UInt)idx >= size ) 1410 gr_idx = 0; 1411 else 1412 gr_idx = size - 1 - (CF2_UInt)idx; 1413 1414 cf2_stack_pushFixed( opStack, 1415 cf2_stack_getReal( opStack, 1416 gr_idx ) ); 1417 } 1418 } 1419 continue; /* do not clear the stack */ 1420 1421 case cf2_escROLL: 1422 { 1423 CF2_Int idx; 1424 CF2_Int count; 1425 1426 1427 FT_TRACE4(( " roll\n" )); 1428 1429 idx = cf2_stack_popInt( opStack ); 1430 count = cf2_stack_popInt( opStack ); 1431 1432 cf2_stack_roll( opStack, count, idx ); 1433 } 1434 continue; /* do not clear the stack */ 1435 1436 } /* end of 2nd switch checking op2 */ 1437 } 1438 } 1439 } /* end of 1st switch checking op2 */ 1440 } /* case cf2_cmdESC */ 1441 1442 break; 1443 1444 case cf2_cmdENDCHAR: 1445 FT_TRACE4(( " endchar\n" )); 1446 1447 if ( cf2_stack_count( opStack ) == 1 || 1448 cf2_stack_count( opStack ) == 5 ) 1449 { 1450 if ( !haveWidth ) 1451 *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ), 1452 nominalWidthX ); 1453 } 1454 1455 /* width is defined or default after this */ 1456 haveWidth = TRUE; 1457 1458 if ( font->decoder->width_only ) 1459 goto exit; 1460 1461 /* close path if still open */ 1462 cf2_glyphpath_closeOpenPath( &glyphPath ); 1463 1464 /* disable seac for CFF2 (charstring ending with args on stack) */ 1465 if ( !font->isCFF2 && cf2_stack_count( opStack ) > 1 ) 1466 { 1467 /* must be either 4 or 5 -- */ 1468 /* this is a (deprecated) implied `seac' operator */ 1469 1470 CF2_Int achar; 1471 CF2_Int bchar; 1472 CF2_BufferRec component; 1473 CF2_Fixed dummyWidth; /* ignore component width */ 1474 FT_Error error2; 1475 1476 1477 if ( doingSeac ) 1478 { 1479 lastError = FT_THROW( Invalid_Glyph_Format ); 1480 goto exit; /* nested seac */ 1481 } 1482 1483 achar = cf2_stack_popInt( opStack ); 1484 bchar = cf2_stack_popInt( opStack ); 1485 1486 curY = cf2_stack_popFixed( opStack ); 1487 curX = cf2_stack_popFixed( opStack ); 1488 1489 error2 = cf2_getSeacComponent( decoder, achar, &component ); 1490 if ( error2 ) 1491 { 1492 lastError = error2; /* pass FreeType error through */ 1493 goto exit; 1494 } 1495 cf2_interpT2CharString( font, 1496 &component, 1497 callbacks, 1498 translation, 1499 TRUE, 1500 curX, 1501 curY, 1502 &dummyWidth ); 1503 cf2_freeSeacComponent( decoder, &component ); 1504 1505 error2 = cf2_getSeacComponent( decoder, bchar, &component ); 1506 if ( error2 ) 1507 { 1508 lastError = error2; /* pass FreeType error through */ 1509 goto exit; 1510 } 1511 cf2_interpT2CharString( font, 1512 &component, 1513 callbacks, 1514 translation, 1515 TRUE, 1516 0, 1517 0, 1518 &dummyWidth ); 1519 cf2_freeSeacComponent( decoder, &component ); 1520 } 1521 goto exit; 1522 1523 case cf2_cmdCNTRMASK: 1524 case cf2_cmdHINTMASK: 1525 /* the final \n in the tracing message gets added in */ 1526 /* `cf2_hintmask_read' (which also traces the mask bytes) */ 1527 FT_TRACE4(( op1 == cf2_cmdCNTRMASK ? " cntrmask" : " hintmask" )); 1528 1529 /* never add hints after the mask is computed */ 1530 if ( cf2_stack_count( opStack ) > 1 && 1531 cf2_hintmask_isValid( &hintMask ) ) 1532 { 1533 FT_TRACE4(( "cf2_interpT2CharString: invalid hint mask\n" )); 1534 break; 1535 } 1536 1537 /* if there are arguments on the stack, there this is an */ 1538 /* implied cf2_cmdVSTEMHM */ 1539 cf2_doStems( font, 1540 opStack, 1541 &vStemHintArray, 1542 width, 1543 &haveWidth, 1544 0 ); 1545 1546 if ( font->decoder->width_only ) 1547 goto exit; 1548 1549 if ( op1 == cf2_cmdHINTMASK ) 1550 { 1551 /* consume the hint mask bytes which follow the operator */ 1552 cf2_hintmask_read( &hintMask, 1553 charstring, 1554 cf2_arrstack_size( &hStemHintArray ) + 1555 cf2_arrstack_size( &vStemHintArray ) ); 1556 } 1557 else 1558 { 1559 /* 1560 * Consume the counter mask bytes which follow the operator: 1561 * Build a temporary hint map, just to place and lock those 1562 * stems participating in the counter mask. These are most 1563 * likely the dominant hstems, and are grouped together in a 1564 * few counter groups, not necessarily in correspondence 1565 * with the hint groups. This reduces the chances of 1566 * conflicts between hstems that are initially placed in 1567 * separate hint groups and then brought together. The 1568 * positions are copied back to `hStemHintArray', so we can 1569 * discard `counterMask' and `counterHintMap'. 1570 * 1571 */ 1572 CF2_HintMapRec counterHintMap; 1573 CF2_HintMaskRec counterMask; 1574 1575 1576 cf2_hintmap_init( &counterHintMap, 1577 font, 1578 &glyphPath.initialHintMap, 1579 &glyphPath.hintMoves, 1580 scaleY ); 1581 cf2_hintmask_init( &counterMask, error ); 1582 1583 cf2_hintmask_read( &counterMask, 1584 charstring, 1585 cf2_arrstack_size( &hStemHintArray ) + 1586 cf2_arrstack_size( &vStemHintArray ) ); 1587 cf2_hintmap_build( &counterHintMap, 1588 &hStemHintArray, 1589 &vStemHintArray, 1590 &counterMask, 1591 0, 1592 FALSE ); 1593 } 1594 break; 1595 1596 case cf2_cmdRMOVETO: 1597 FT_TRACE4(( " rmoveto\n" )); 1598 1599 if ( cf2_stack_count( opStack ) > 2 && !haveWidth ) 1600 *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ), 1601 nominalWidthX ); 1602 1603 /* width is defined or default after this */ 1604 haveWidth = TRUE; 1605 1606 if ( font->decoder->width_only ) 1607 goto exit; 1608 1609 curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) ); 1610 curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) ); 1611 1612 cf2_glyphpath_moveTo( &glyphPath, curX, curY ); 1613 1614 break; 1615 1616 case cf2_cmdHMOVETO: 1617 FT_TRACE4(( " hmoveto\n" )); 1618 1619 if ( cf2_stack_count( opStack ) > 1 && !haveWidth ) 1620 *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ), 1621 nominalWidthX ); 1622 1623 /* width is defined or default after this */ 1624 haveWidth = TRUE; 1625 1626 if ( font->decoder->width_only ) 1627 goto exit; 1628 1629 curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) ); 1630 1631 cf2_glyphpath_moveTo( &glyphPath, curX, curY ); 1632 1633 break; 1634 1635 case cf2_cmdRLINECURVE: 1636 { 1637 CF2_UInt count = cf2_stack_count( opStack ); 1638 CF2_UInt idx = 0; 1639 1640 1641 FT_TRACE4(( " rlinecurve\n" )); 1642 1643 while ( idx + 6 < count ) 1644 { 1645 curX = ADD_INT32( curX, cf2_stack_getReal( opStack, 1646 idx + 0 ) ); 1647 curY = ADD_INT32( curY, cf2_stack_getReal( opStack, 1648 idx + 1 ) ); 1649 1650 cf2_glyphpath_lineTo( &glyphPath, curX, curY ); 1651 idx += 2; 1652 } 1653 1654 while ( idx < count ) 1655 { 1656 CF2_Fixed x1, y1, x2, y2, x3, y3; 1657 1658 1659 x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX ); 1660 y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), curY ); 1661 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), x1 ); 1662 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y1 ); 1663 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 ); 1664 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 5 ), y2 ); 1665 1666 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); 1667 1668 curX = x3; 1669 curY = y3; 1670 idx += 6; 1671 } 1672 1673 cf2_stack_clear( opStack ); 1674 } 1675 continue; /* no need to clear stack again */ 1676 1677 case cf2_cmdVVCURVETO: 1678 { 1679 CF2_UInt count, count1 = cf2_stack_count( opStack ); 1680 CF2_UInt idx = 0; 1681 1682 1683 /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */ 1684 /* we enforce it by clearing the second bit */ 1685 /* (and sorting the stack indexing to suit) */ 1686 count = count1 & ~2U; 1687 idx += count1 - count; 1688 1689 FT_TRACE4(( " vvcurveto\n" )); 1690 1691 while ( idx < count ) 1692 { 1693 CF2_Fixed x1, y1, x2, y2, x3, y3; 1694 1695 1696 if ( ( count - idx ) & 1 ) 1697 { 1698 x1 = ADD_INT32( cf2_stack_getReal( opStack, idx ), curX ); 1699 1700 idx++; 1701 } 1702 else 1703 x1 = curX; 1704 1705 y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curY ); 1706 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 ); 1707 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 ); 1708 x3 = x2; 1709 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y2 ); 1710 1711 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); 1712 1713 curX = x3; 1714 curY = y3; 1715 idx += 4; 1716 } 1717 1718 cf2_stack_clear( opStack ); 1719 } 1720 continue; /* no need to clear stack again */ 1721 1722 case cf2_cmdHHCURVETO: 1723 { 1724 CF2_UInt count, count1 = cf2_stack_count( opStack ); 1725 CF2_UInt idx = 0; 1726 1727 1728 /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */ 1729 /* we enforce it by clearing the second bit */ 1730 /* (and sorting the stack indexing to suit) */ 1731 count = count1 & ~2U; 1732 idx += count1 - count; 1733 1734 FT_TRACE4(( " hhcurveto\n" )); 1735 1736 while ( idx < count ) 1737 { 1738 CF2_Fixed x1, y1, x2, y2, x3, y3; 1739 1740 1741 if ( ( count - idx ) & 1 ) 1742 { 1743 y1 = ADD_INT32( cf2_stack_getReal( opStack, idx ), curY ); 1744 1745 idx++; 1746 } 1747 else 1748 y1 = curY; 1749 1750 x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX ); 1751 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 ); 1752 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 ); 1753 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), x2 ); 1754 y3 = y2; 1755 1756 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); 1757 1758 curX = x3; 1759 curY = y3; 1760 idx += 4; 1761 } 1762 1763 cf2_stack_clear( opStack ); 1764 } 1765 continue; /* no need to clear stack again */ 1766 1767 case cf2_cmdVHCURVETO: 1768 case cf2_cmdHVCURVETO: 1769 { 1770 CF2_UInt count, count1 = cf2_stack_count( opStack ); 1771 CF2_UInt idx = 0; 1772 1773 FT_Bool alternate = FT_BOOL( op1 == cf2_cmdHVCURVETO ); 1774 1775 1776 /* if `cf2_stack_count' isn't of the form 8n, 8n+1, */ 1777 /* 8n+4, or 8n+5, we enforce it by clearing the */ 1778 /* second bit */ 1779 /* (and sorting the stack indexing to suit) */ 1780 count = count1 & ~2U; 1781 idx += count1 - count; 1782 1783 FT_TRACE4(( alternate ? " hvcurveto\n" : " vhcurveto\n" )); 1784 1785 while ( idx < count ) 1786 { 1787 CF2_Fixed x1, x2, x3, y1, y2, y3; 1788 1789 1790 if ( alternate ) 1791 { 1792 x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX ); 1793 y1 = curY; 1794 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 ); 1795 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 ); 1796 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y2 ); 1797 1798 if ( count - idx == 5 ) 1799 { 1800 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 ); 1801 1802 idx++; 1803 } 1804 else 1805 x3 = x2; 1806 1807 alternate = FALSE; 1808 } 1809 else 1810 { 1811 x1 = curX; 1812 y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curY ); 1813 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 ); 1814 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 ); 1815 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), x2 ); 1816 1817 if ( count - idx == 5 ) 1818 { 1819 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), y2 ); 1820 1821 idx++; 1822 } 1823 else 1824 y3 = y2; 1825 1826 alternate = TRUE; 1827 } 1828 1829 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); 1830 1831 curX = x3; 1832 curY = y3; 1833 idx += 4; 1834 } 1835 1836 cf2_stack_clear( opStack ); 1837 } 1838 continue; /* no need to clear stack again */ 1839 1840 case cf2_cmdEXTENDEDNMBR: 1841 { 1842 CF2_Int v; 1843 1844 CF2_Int byte1 = cf2_buf_readByte( charstring ); 1845 CF2_Int byte2 = cf2_buf_readByte( charstring ); 1846 1847 1848 v = (FT_Short)( ( byte1 << 8 ) | 1849 byte2 ); 1850 1851 FT_TRACE4(( " %d", v )); 1852 1853 cf2_stack_pushInt( opStack, v ); 1854 } 1855 continue; 1856 1857 default: 1858 /* numbers */ 1859 { 1860 if ( /* op1 >= 32 && */ op1 <= 246 ) 1861 { 1862 CF2_Int v; 1863 1864 1865 v = op1 - 139; 1866 1867 FT_TRACE4(( " %d", v )); 1868 1869 /* -107 .. 107 */ 1870 cf2_stack_pushInt( opStack, v ); 1871 } 1872 1873 else if ( /* op1 >= 247 && */ op1 <= 250 ) 1874 { 1875 CF2_Int v; 1876 1877 1878 v = op1; 1879 v -= 247; 1880 v *= 256; 1881 v += cf2_buf_readByte( charstring ); 1882 v += 108; 1883 1884 FT_TRACE4(( " %d", v )); 1885 1886 /* 108 .. 1131 */ 1887 cf2_stack_pushInt( opStack, v ); 1888 } 1889 1890 else if ( /* op1 >= 251 && */ op1 <= 254 ) 1891 { 1892 CF2_Int v; 1893 1894 1895 v = op1; 1896 v -= 251; 1897 v *= 256; 1898 v += cf2_buf_readByte( charstring ); 1899 v = -v - 108; 1900 1901 FT_TRACE4(( " %d", v )); 1902 1903 /* -1131 .. -108 */ 1904 cf2_stack_pushInt( opStack, v ); 1905 } 1906 1907 else /* op1 == 255 */ 1908 { 1909 CF2_Fixed v; 1910 1911 FT_UInt32 byte1 = (FT_UInt32)cf2_buf_readByte( charstring ); 1912 FT_UInt32 byte2 = (FT_UInt32)cf2_buf_readByte( charstring ); 1913 FT_UInt32 byte3 = (FT_UInt32)cf2_buf_readByte( charstring ); 1914 FT_UInt32 byte4 = (FT_UInt32)cf2_buf_readByte( charstring ); 1915 1916 1917 v = (CF2_Fixed)( ( byte1 << 24 ) | 1918 ( byte2 << 16 ) | 1919 ( byte3 << 8 ) | 1920 byte4 ); 1921 1922 FT_TRACE4(( " %.5f", v / 65536.0 )); 1923 1924 cf2_stack_pushFixed( opStack, v ); 1925 } 1926 } 1927 continue; /* don't clear stack */ 1928 1929 } /* end of switch statement checking `op1' */ 1930 1931 cf2_stack_clear( opStack ); 1932 1933 } /* end of main interpreter loop */ 1934 1935 /* we get here if the charstring ends without cf2_cmdENDCHAR */ 1936 FT_TRACE4(( "cf2_interpT2CharString:" 1937 " charstring ends without ENDCHAR\n" )); 1938 1939 exit: 1940 /* check whether last error seen is also the first one */ 1941 cf2_setError( error, lastError ); 1942 1943 if ( *error ) 1944 FT_TRACE4(( "charstring error %d\n", *error )); 1945 1946 /* free resources from objects we've used */ 1947 cf2_glyphpath_finalize( &glyphPath ); 1948 cf2_arrstack_finalize( &vStemHintArray ); 1949 cf2_arrstack_finalize( &hStemHintArray ); 1950 cf2_arrstack_finalize( &subrStack ); 1951 cf2_stack_free( opStack ); 1952 1953 FT_TRACE4(( "\n" )); 1954 1955 return; 1956 } 1957 1958 1959 /* END */ 1960