psintrp.c (105457B)
1 /**************************************************************************** 2 * 3 * psintrp.c 4 * 5 * Adobe's CFF Interpreter (body). 6 * 7 * Copyright 2007-2014 Adobe Systems Incorporated. 8 * 9 * This software, and all works of authorship, whether in source or 10 * object code form as indicated by the copyright notice(s) included 11 * herein (collectively, the "Work") is made available, and may only be 12 * used, modified, and distributed under the FreeType Project License, 13 * LICENSE.TXT. Additionally, subject to the terms and conditions of the 14 * FreeType Project License, each contributor to the Work hereby grants 15 * to any individual or legal entity exercising permissions granted by 16 * the FreeType Project License and this section (hereafter, "You" or 17 * "Your") a perpetual, worldwide, non-exclusive, no-charge, 18 * royalty-free, irrevocable (except as stated in this section) patent 19 * license to make, have made, use, offer to sell, sell, import, and 20 * otherwise transfer the Work, where such license applies only to those 21 * patent claims licensable by such contributor that are necessarily 22 * infringed by their contribution(s) alone or by combination of their 23 * contribution(s) with the Work to which such contribution(s) was 24 * submitted. If You institute patent litigation against any entity 25 * (including a cross-claim or counterclaim in a lawsuit) alleging that 26 * the Work or a contribution incorporated within the Work constitutes 27 * direct or contributory patent infringement, then any patent licenses 28 * granted to You under this License for that Work shall terminate as of 29 * the date such litigation is filed. 30 * 31 * By using, modifying, or distributing the Work you indicate that you 32 * have read and understood the terms and conditions of the 33 * FreeType Project License as well as those provided in this section, 34 * and you accept them fully. 35 * 36 */ 37 38 39 #include "psft.h" 40 #include <freetype/internal/ftcalc.h> 41 #include <freetype/internal/ftdebug.h> 42 #include <freetype/internal/services/svcfftl.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 */