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