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 trace_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 *charstring = *buf; /* structure copy */ 616 617 charstringIndex = 0; /* entry is valid now */ 618 619 /* catch errors so far */ 620 if ( *error ) 621 goto exit; 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(( op1 == cf2_cmdHSTEMHM ? " hstemhm\n" : " hstem\n" )); 780 781 if ( !font->isT1 ) 782 { 783 /* never add hints after the mask is computed */ 784 /* except if in Type 1 mode (no hintmask op) */ 785 if ( cf2_hintmask_isValid( &hintMask ) ) 786 { 787 FT_TRACE4(( "cf2_interpT2CharString:" 788 " invalid horizontal hint mask\n" )); 789 break; 790 } 791 } 792 793 /* add left-sidebearing correction in Type 1 mode */ 794 cf2_doStems( font, 795 opStack, 796 &hStemHintArray, 797 width, 798 &haveWidth, 799 font->isT1 ? decoder->builder.left_bearing->y 800 : 0 ); 801 802 if ( decoder->width_only ) 803 goto exit; 804 805 break; 806 807 case cf2_cmdVSTEMHM: 808 case cf2_cmdVSTEM: 809 FT_TRACE4(( op1 == cf2_cmdVSTEMHM ? " vstemhm\n" : " vstem\n" )); 810 811 if ( !font->isT1 ) 812 { 813 /* never add hints after the mask is computed */ 814 /* except if in Type 1 mode (no hintmask op) */ 815 if ( cf2_hintmask_isValid( &hintMask ) ) 816 { 817 FT_TRACE4(( "cf2_interpT2CharString:" 818 " invalid vertical hint mask\n" )); 819 break; 820 } 821 } 822 823 /* add left-sidebearing correction in Type 1 mode */ 824 cf2_doStems( font, 825 opStack, 826 &vStemHintArray, 827 width, 828 &haveWidth, 829 font->isT1 ? decoder->builder.left_bearing->x 830 : 0 ); 831 832 if ( decoder->width_only ) 833 goto exit; 834 835 break; 836 837 case cf2_cmdVMOVETO: 838 FT_TRACE4(( " vmoveto\n" )); 839 840 if ( font->isT1 && !decoder->flex_state && !haveWidth ) 841 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" 842 " No width. Use hsbw/sbw as first op\n" )); 843 844 if ( cf2_stack_count( opStack ) > 1 && !haveWidth ) 845 *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ), 846 nominalWidthX ); 847 848 /* width is defined or default after this */ 849 haveWidth = TRUE; 850 851 if ( decoder->width_only ) 852 goto exit; 853 854 curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) ); 855 856 if ( !decoder->flex_state ) 857 cf2_glyphpath_moveTo( &glyphPath, curX, curY ); 858 859 break; 860 861 case cf2_cmdRLINETO: 862 { 863 CF2_UInt idx; 864 CF2_UInt count = cf2_stack_count( opStack ); 865 866 867 FT_TRACE4(( " rlineto\n" )); 868 869 for ( idx = 0; idx < count; idx += 2 ) 870 { 871 curX = ADD_INT32( curX, cf2_stack_getReal( opStack, 872 idx + 0 ) ); 873 curY = ADD_INT32( curY, cf2_stack_getReal( opStack, 874 idx + 1 ) ); 875 876 cf2_glyphpath_lineTo( &glyphPath, curX, curY ); 877 } 878 879 cf2_stack_clear( opStack ); 880 } 881 continue; /* no need to clear stack again */ 882 883 case cf2_cmdHLINETO: 884 case cf2_cmdVLINETO: 885 { 886 CF2_UInt idx; 887 CF2_UInt count = cf2_stack_count( opStack ); 888 889 FT_Bool isX = FT_BOOL( op1 == cf2_cmdHLINETO ); 890 891 892 FT_TRACE4(( isX ? " hlineto\n" : " vlineto\n" )); 893 894 for ( idx = 0; idx < count; idx++ ) 895 { 896 CF2_Fixed v = cf2_stack_getReal( opStack, idx ); 897 898 899 if ( isX ) 900 curX = ADD_INT32( curX, v ); 901 else 902 curY = ADD_INT32( curY, v ); 903 904 isX = !isX; 905 906 cf2_glyphpath_lineTo( &glyphPath, curX, curY ); 907 } 908 909 cf2_stack_clear( opStack ); 910 } 911 continue; 912 913 case cf2_cmdRCURVELINE: 914 case cf2_cmdRRCURVETO: 915 { 916 CF2_UInt count = cf2_stack_count( opStack ); 917 CF2_UInt idx = 0; 918 919 920 FT_TRACE4(( op1 == cf2_cmdRCURVELINE ? " rcurveline\n" 921 : " rrcurveto\n" )); 922 923 while ( idx + 6 <= count ) 924 { 925 CF2_Fixed x1, y1, x2, y2, x3, y3; 926 927 928 x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX ); 929 y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), curY ); 930 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), x1 ); 931 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y1 ); 932 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 ); 933 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 5 ), y2 ); 934 935 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); 936 937 curX = x3; 938 curY = y3; 939 idx += 6; 940 } 941 942 if ( op1 == cf2_cmdRCURVELINE ) 943 { 944 curX = ADD_INT32( curX, cf2_stack_getReal( opStack, 945 idx + 0 ) ); 946 curY = ADD_INT32( curY, cf2_stack_getReal( opStack, 947 idx + 1 ) ); 948 949 cf2_glyphpath_lineTo( &glyphPath, curX, curY ); 950 } 951 952 cf2_stack_clear( opStack ); 953 } 954 continue; /* no need to clear stack again */ 955 956 case cf2_cmdCLOSEPATH: 957 if ( !font->isT1 ) 958 FT_TRACE4(( " unknown op (%d)\n", op1 )); 959 else 960 { 961 FT_TRACE4(( " closepath" )); 962 963 /* if there is no path, `closepath' is a no-op */ 964 ps_builder_close_contour( &decoder->builder ); 965 966 haveWidth = TRUE; 967 } 968 break; 969 970 case cf2_cmdCALLGSUBR: 971 case cf2_cmdCALLSUBR: 972 { 973 CF2_Int subrNum; 974 975 976 FT_TRACE4(( op1 == cf2_cmdCALLGSUBR ? " callgsubr" 977 : " callsubr" )); 978 979 if ( ( !font->isT1 && charstringIndex > CF2_MAX_SUBR ) || 980 ( font->isT1 && charstringIndex > T1_MAX_SUBRS_CALLS ) ) 981 { 982 /* max subr plus one for charstring */ 983 lastError = FT_THROW( Invalid_Glyph_Format ); 984 goto exit; /* overflow of stack */ 985 } 986 987 /* push our current CFF charstring region on subrStack */ 988 charstring = (CF2_Buffer) 989 cf2_arrstack_getPointer( 990 &subrStack, 991 (size_t)charstringIndex + 1 ); 992 993 /* set up the new CFF region and pointer */ 994 subrNum = cf2_stack_popInt( opStack ); 995 996 if ( font->isT1 && decoder->locals_hash ) 997 { 998 size_t* val = ft_hash_num_lookup( subrNum, 999 decoder->locals_hash ); 1000 1001 1002 if ( val ) 1003 subrNum = *val; 1004 else 1005 subrNum = -1; 1006 } 1007 1008 switch ( op1 ) 1009 { 1010 case cf2_cmdCALLGSUBR: 1011 FT_TRACE4(( " (idx %d, entering level %d)\n", 1012 subrNum + decoder->globals_bias, 1013 charstringIndex + 1 )); 1014 1015 if ( cf2_initGlobalRegionBuffer( decoder, 1016 subrNum, 1017 charstring ) ) 1018 { 1019 lastError = FT_THROW( Invalid_Glyph_Format ); 1020 goto exit; /* subroutine lookup or stream error */ 1021 } 1022 break; 1023 1024 default: 1025 /* cf2_cmdCALLSUBR */ 1026 FT_TRACE4(( " (idx %d, entering level %d)\n", 1027 subrNum + decoder->locals_bias, 1028 charstringIndex + 1 )); 1029 1030 if ( cf2_initLocalRegionBuffer( decoder, 1031 subrNum, 1032 charstring ) ) 1033 { 1034 lastError = FT_THROW( Invalid_Glyph_Format ); 1035 goto exit; /* subroutine lookup or stream error */ 1036 } 1037 } 1038 1039 charstringIndex += 1; /* entry is valid now */ 1040 } 1041 continue; /* do not clear the stack */ 1042 1043 case cf2_cmdRETURN: 1044 FT_TRACE4(( " return (leaving level %d)\n", charstringIndex )); 1045 1046 if ( charstringIndex < 1 ) 1047 { 1048 /* Note: cannot return from top charstring */ 1049 lastError = FT_THROW( Invalid_Glyph_Format ); 1050 goto exit; /* underflow of stack */ 1051 } 1052 1053 /* restore position in previous charstring */ 1054 charstring = (CF2_Buffer) 1055 cf2_arrstack_getPointer( 1056 &subrStack, 1057 (CF2_UInt)--charstringIndex ); 1058 continue; /* do not clear the stack */ 1059 1060 case cf2_cmdESC: 1061 { 1062 FT_Byte op2 = (FT_Byte)cf2_buf_readByte( charstring ); 1063 1064 1065 /* first switch for 2-byte operators handles CFF2 */ 1066 /* and opcodes that are reserved for both CFF and CFF2 */ 1067 switch ( op2 ) 1068 { 1069 case cf2_escHFLEX: 1070 { 1071 static const FT_Bool readFromStack[12] = 1072 { 1073 TRUE /* dx1 */, FALSE /* dy1 */, 1074 TRUE /* dx2 */, TRUE /* dy2 */, 1075 TRUE /* dx3 */, FALSE /* dy3 */, 1076 TRUE /* dx4 */, FALSE /* dy4 */, 1077 TRUE /* dx5 */, FALSE /* dy5 */, 1078 TRUE /* dx6 */, FALSE /* dy6 */ 1079 }; 1080 1081 1082 FT_TRACE4(( " hflex\n" )); 1083 1084 cf2_doFlex( opStack, 1085 &curX, 1086 &curY, 1087 &glyphPath, 1088 readFromStack, 1089 FALSE /* doConditionalLastRead */ ); 1090 } 1091 continue; 1092 1093 case cf2_escFLEX: 1094 { 1095 static const FT_Bool readFromStack[12] = 1096 { 1097 TRUE /* dx1 */, TRUE /* dy1 */, 1098 TRUE /* dx2 */, TRUE /* dy2 */, 1099 TRUE /* dx3 */, TRUE /* dy3 */, 1100 TRUE /* dx4 */, TRUE /* dy4 */, 1101 TRUE /* dx5 */, TRUE /* dy5 */, 1102 TRUE /* dx6 */, TRUE /* dy6 */ 1103 }; 1104 1105 1106 FT_TRACE4(( " flex\n" )); 1107 1108 cf2_doFlex( opStack, 1109 &curX, 1110 &curY, 1111 &glyphPath, 1112 readFromStack, 1113 FALSE /* doConditionalLastRead */ ); 1114 } 1115 break; /* TODO: why is this not a continue? */ 1116 1117 case cf2_escHFLEX1: 1118 { 1119 static const FT_Bool readFromStack[12] = 1120 { 1121 TRUE /* dx1 */, TRUE /* dy1 */, 1122 TRUE /* dx2 */, TRUE /* dy2 */, 1123 TRUE /* dx3 */, FALSE /* dy3 */, 1124 TRUE /* dx4 */, FALSE /* dy4 */, 1125 TRUE /* dx5 */, TRUE /* dy5 */, 1126 TRUE /* dx6 */, FALSE /* dy6 */ 1127 }; 1128 1129 1130 FT_TRACE4(( " hflex1\n" )); 1131 1132 cf2_doFlex( opStack, 1133 &curX, 1134 &curY, 1135 &glyphPath, 1136 readFromStack, 1137 FALSE /* doConditionalLastRead */ ); 1138 } 1139 continue; 1140 1141 case cf2_escFLEX1: 1142 { 1143 static const FT_Bool readFromStack[12] = 1144 { 1145 TRUE /* dx1 */, TRUE /* dy1 */, 1146 TRUE /* dx2 */, TRUE /* dy2 */, 1147 TRUE /* dx3 */, TRUE /* dy3 */, 1148 TRUE /* dx4 */, TRUE /* dy4 */, 1149 TRUE /* dx5 */, TRUE /* dy5 */, 1150 FALSE /* dx6 */, FALSE /* dy6 */ 1151 }; 1152 1153 1154 FT_TRACE4(( " flex1\n" )); 1155 1156 cf2_doFlex( opStack, 1157 &curX, 1158 &curY, 1159 &glyphPath, 1160 readFromStack, 1161 TRUE /* doConditionalLastRead */ ); 1162 } 1163 continue; 1164 1165 /* these opcodes are always reserved */ 1166 case cf2_escRESERVED_8: 1167 case cf2_escRESERVED_13: 1168 case cf2_escRESERVED_19: 1169 case cf2_escRESERVED_25: 1170 case cf2_escRESERVED_31: 1171 case cf2_escRESERVED_32: 1172 FT_TRACE4(( " unknown op (12, %d)\n", op2 )); 1173 break; 1174 1175 default: 1176 { 1177 if ( font->isCFF2 || op2 >= cf2_escRESERVED_38 ) 1178 FT_TRACE4(( " unknown op (12, %d)\n", op2 )); 1179 else if ( font->isT1 && result_cnt > 0 && op2 != cf2_escPOP ) 1180 { 1181 /* all operands have been transferred by previous pops */ 1182 result_cnt = 0; 1183 } 1184 else 1185 { 1186 /* second switch for 2-byte operators handles */ 1187 /* CFF and Type 1 */ 1188 switch ( op2 ) 1189 { 1190 1191 case cf2_escDOTSECTION: 1192 /* something about `flip type of locking' -- ignore it */ 1193 FT_TRACE4(( " dotsection\n" )); 1194 1195 break; 1196 1197 case cf2_escVSTEM3: 1198 case cf2_escHSTEM3: 1199 /* 1200 * Type 1: Type 2: 1201 * x0 dx0 x1 dx1 x2 dx2 vstem3 x dx {dxa dxb}* vstem 1202 * y0 dy0 y1 dy1 y2 dy2 hstem3 y dy {dya dyb}* hstem 1203 * relative to lsb point relative to zero 1204 * 1205 */ 1206 { 1207 if ( !font->isT1 ) 1208 FT_TRACE4(( " unknown op (12, %d)\n", op2 )); 1209 else 1210 { 1211 CF2_F16Dot16 v0, v1, v2; 1212 1213 FT_Bool isV = FT_BOOL( op2 == cf2_escVSTEM3 ); 1214 1215 1216 FT_TRACE4(( isV ? " vstem3\n" 1217 : " hstem3\n" )); 1218 1219 FT_ASSERT( cf2_stack_count( opStack ) == 6 ); 1220 1221 v0 = cf2_stack_getReal( opStack, 0 ); 1222 v1 = cf2_stack_getReal( opStack, 2 ); 1223 v2 = cf2_stack_getReal( opStack, 4 ); 1224 1225 cf2_stack_setReal( 1226 opStack, 2, 1227 SUB_INT32( SUB_INT32( v1, v0 ), 1228 cf2_stack_getReal( opStack, 1 ) ) ); 1229 cf2_stack_setReal( 1230 opStack, 4, 1231 SUB_INT32( SUB_INT32( v2, v1 ), 1232 cf2_stack_getReal( opStack, 3 ) ) ); 1233 1234 /* add left-sidebearing correction */ 1235 cf2_doStems( font, 1236 opStack, 1237 isV ? &vStemHintArray : &hStemHintArray, 1238 width, 1239 &haveWidth, 1240 isV ? decoder->builder.left_bearing->x 1241 : decoder->builder.left_bearing->y ); 1242 1243 if ( decoder->width_only ) 1244 goto exit; 1245 } 1246 } 1247 break; 1248 1249 case cf2_escAND: 1250 { 1251 CF2_F16Dot16 arg1; 1252 CF2_F16Dot16 arg2; 1253 1254 1255 FT_TRACE4(( " and\n" )); 1256 1257 arg2 = cf2_stack_popFixed( opStack ); 1258 arg1 = cf2_stack_popFixed( opStack ); 1259 1260 cf2_stack_pushInt( opStack, arg1 && arg2 ); 1261 } 1262 continue; /* do not clear the stack */ 1263 1264 case cf2_escOR: 1265 { 1266 CF2_F16Dot16 arg1; 1267 CF2_F16Dot16 arg2; 1268 1269 1270 FT_TRACE4(( " or\n" )); 1271 1272 arg2 = cf2_stack_popFixed( opStack ); 1273 arg1 = cf2_stack_popFixed( opStack ); 1274 1275 cf2_stack_pushInt( opStack, arg1 || arg2 ); 1276 } 1277 continue; /* do not clear the stack */ 1278 1279 case cf2_escNOT: 1280 { 1281 CF2_F16Dot16 arg; 1282 1283 1284 FT_TRACE4(( " not\n" )); 1285 1286 arg = cf2_stack_popFixed( opStack ); 1287 1288 cf2_stack_pushInt( opStack, !arg ); 1289 } 1290 continue; /* do not clear the stack */ 1291 1292 case cf2_escSEAC: 1293 if ( !font->isT1 ) 1294 FT_TRACE4(( " unknown op (12, %d)\n", op2 )); 1295 else 1296 { 1297 FT_Error error2; 1298 CF2_Int bchar_index, achar_index; 1299 FT_Vector left_bearing, advance; 1300 1301 #ifdef FT_CONFIG_OPTION_INCREMENTAL 1302 T1_Face face = (T1_Face)decoder->builder.face; 1303 #endif 1304 CF2_BufferRec component; 1305 CF2_Fixed dummyWidth; 1306 1307 CF2_Int achar = cf2_stack_popInt( opStack ); 1308 CF2_Int bchar = cf2_stack_popInt( opStack ); 1309 1310 FT_Pos ady = cf2_stack_popFixed ( opStack ); 1311 FT_Pos adx = cf2_stack_popFixed ( opStack ); 1312 FT_Pos asb = cf2_stack_popFixed ( opStack ); 1313 1314 1315 FT_TRACE4(( " seac\n" )); 1316 1317 if ( doingSeac ) 1318 { 1319 FT_ERROR(( " nested seac\n" )); 1320 lastError = FT_THROW( Invalid_Glyph_Format ); 1321 goto exit; /* nested seac */ 1322 } 1323 1324 if ( decoder->builder.metrics_only ) 1325 { 1326 FT_ERROR(( " unexpected seac\n" )); 1327 lastError = FT_THROW( Invalid_Glyph_Format ); 1328 goto exit; /* unexpected seac */ 1329 } 1330 1331 /* `glyph_names' is set to 0 for CID fonts which do */ 1332 /* not include an encoding. How can we deal with */ 1333 /* these? */ 1334 #ifdef FT_CONFIG_OPTION_INCREMENTAL 1335 if ( decoder->glyph_names == 0 && 1336 !face->root.internal->incremental_interface ) 1337 #else 1338 if ( decoder->glyph_names == 0 ) 1339 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 1340 { 1341 FT_ERROR(( 1342 "cf2_interpT2CharString: (Type 1 seac)" 1343 " glyph names table not available in this font\n" )); 1344 lastError = FT_THROW( Invalid_Glyph_Format ); 1345 goto exit; 1346 } 1347 1348 /* seac weirdness */ 1349 adx += decoder->builder.left_bearing->x; 1350 1351 #ifdef FT_CONFIG_OPTION_INCREMENTAL 1352 if ( face->root.internal->incremental_interface ) 1353 { 1354 /* the caller must handle the font encoding also */ 1355 bchar_index = bchar; 1356 achar_index = achar; 1357 } 1358 else 1359 #endif 1360 { 1361 bchar_index = t1_lookup_glyph_by_stdcharcode_ps( 1362 decoder, bchar ); 1363 achar_index = t1_lookup_glyph_by_stdcharcode_ps( 1364 decoder, achar ); 1365 } 1366 1367 if ( bchar_index < 0 || achar_index < 0 ) 1368 { 1369 FT_ERROR(( 1370 "cf2_interpT2CharString: (Type 1 seac)" 1371 " invalid seac character code arguments\n" )); 1372 lastError = FT_THROW( Invalid_Glyph_Format ); 1373 goto exit; 1374 } 1375 1376 /* if we are trying to load a composite glyph, */ 1377 /* do not load the accent character and return */ 1378 /* the array of subglyphs. */ 1379 if ( decoder->builder.no_recurse ) 1380 { 1381 FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph; 1382 FT_GlyphLoader loader = glyph->internal->loader; 1383 FT_SubGlyph subg; 1384 1385 1386 /* reallocate subglyph array if necessary */ 1387 error2 = FT_GlyphLoader_CheckSubGlyphs( loader, 2 ); 1388 if ( error2 ) 1389 { 1390 lastError = error2; /* pass FreeType error through */ 1391 goto exit; 1392 } 1393 1394 subg = loader->current.subglyphs; 1395 1396 /* subglyph 0 = base character */ 1397 subg->index = bchar_index; 1398 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES | 1399 FT_SUBGLYPH_FLAG_USE_MY_METRICS; 1400 subg->arg1 = 0; 1401 subg->arg2 = 0; 1402 subg++; 1403 1404 /* subglyph 1 = accent character */ 1405 subg->index = achar_index; 1406 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; 1407 subg->arg1 = (FT_Int)FIXED_TO_INT( adx - asb ); 1408 subg->arg2 = (FT_Int)FIXED_TO_INT( ady ); 1409 1410 /* set up remaining glyph fields */ 1411 glyph->num_subglyphs = 2; 1412 glyph->subglyphs = loader->base.subglyphs; 1413 glyph->format = FT_GLYPH_FORMAT_COMPOSITE; 1414 1415 loader->current.num_subglyphs = 2; 1416 1417 goto exit; 1418 } 1419 1420 /* First load `bchar' in builder */ 1421 /* now load the unscaled outline */ 1422 1423 /* prepare loader */ 1424 FT_GlyphLoader_Prepare( decoder->builder.loader ); 1425 1426 error2 = cf2_getT1SeacComponent( decoder, 1427 (FT_UInt)bchar_index, 1428 &component ); 1429 if ( error2 ) 1430 { 1431 lastError = error2; /* pass FreeType error through */ 1432 goto exit; 1433 } 1434 cf2_interpT2CharString( font, 1435 &component, 1436 callbacks, 1437 translation, 1438 TRUE, 1439 0, 1440 0, 1441 &dummyWidth ); 1442 cf2_freeT1SeacComponent( decoder, &component ); 1443 1444 /* save the left bearing and width of the base */ 1445 /* character as they will be erased by the next load */ 1446 1447 left_bearing = *decoder->builder.left_bearing; 1448 advance = *decoder->builder.advance; 1449 1450 decoder->builder.left_bearing->x = 0; 1451 decoder->builder.left_bearing->y = 0; 1452 1453 /* Now load `achar' on top of */ 1454 /* the base outline */ 1455 1456 error2 = cf2_getT1SeacComponent( decoder, 1457 (FT_UInt)achar_index, 1458 &component ); 1459 if ( error2 ) 1460 { 1461 lastError = error2; /* pass FreeType error through */ 1462 goto exit; 1463 } 1464 cf2_interpT2CharString( font, 1465 &component, 1466 callbacks, 1467 translation, 1468 TRUE, 1469 adx - asb, 1470 ady, 1471 &dummyWidth ); 1472 cf2_freeT1SeacComponent( decoder, &component ); 1473 1474 /* restore the left side bearing and */ 1475 /* advance width of the base character */ 1476 1477 *decoder->builder.left_bearing = left_bearing; 1478 *decoder->builder.advance = advance; 1479 1480 goto exit; 1481 } 1482 break; 1483 1484 case cf2_escSBW: 1485 if ( !font->isT1 ) 1486 FT_TRACE4(( " unknown op (12, %d)\n", op2 )); 1487 else 1488 { 1489 CF2_Fixed lsb_x, lsb_y; 1490 PS_Builder* builder; 1491 1492 1493 FT_TRACE4(( " sbw" )); 1494 1495 builder = &decoder->builder; 1496 1497 builder->advance->y = cf2_stack_popFixed( opStack ); 1498 builder->advance->x = cf2_stack_popFixed( opStack ); 1499 1500 lsb_y = cf2_stack_popFixed( opStack ); 1501 lsb_x = cf2_stack_popFixed( opStack ); 1502 1503 builder->left_bearing->x = 1504 ADD_INT32( builder->left_bearing->x, lsb_x ); 1505 builder->left_bearing->y = 1506 ADD_INT32( builder->left_bearing->y, lsb_y ); 1507 1508 haveWidth = TRUE; 1509 1510 /* the `metrics_only' indicates that we only want */ 1511 /* to compute the glyph's metrics (lsb + advance */ 1512 /* width), not load the rest of it; so exit */ 1513 /* immediately */ 1514 if ( builder->metrics_only ) 1515 goto exit; 1516 1517 if ( initial_map_ready ) 1518 { 1519 curX = ADD_INT32( curX, lsb_x ); 1520 curY = ADD_INT32( curY, lsb_y ); 1521 } 1522 } 1523 break; 1524 1525 case cf2_escABS: 1526 { 1527 CF2_F16Dot16 arg; 1528 1529 1530 FT_TRACE4(( " abs\n" )); 1531 1532 arg = cf2_stack_popFixed( opStack ); 1533 1534 if ( arg < -CF2_FIXED_MAX ) 1535 cf2_stack_pushFixed( opStack, CF2_FIXED_MAX ); 1536 else 1537 cf2_stack_pushFixed( opStack, FT_ABS( arg ) ); 1538 } 1539 continue; /* do not clear the stack */ 1540 1541 case cf2_escADD: 1542 { 1543 CF2_F16Dot16 summand1; 1544 CF2_F16Dot16 summand2; 1545 1546 1547 FT_TRACE4(( " add\n" )); 1548 1549 summand2 = cf2_stack_popFixed( opStack ); 1550 summand1 = cf2_stack_popFixed( opStack ); 1551 1552 cf2_stack_pushFixed( opStack, 1553 ADD_INT32( summand1, 1554 summand2 ) ); 1555 } 1556 continue; /* do not clear the stack */ 1557 1558 case cf2_escSUB: 1559 { 1560 CF2_F16Dot16 minuend; 1561 CF2_F16Dot16 subtrahend; 1562 1563 1564 FT_TRACE4(( " sub\n" )); 1565 1566 subtrahend = cf2_stack_popFixed( opStack ); 1567 minuend = cf2_stack_popFixed( opStack ); 1568 1569 cf2_stack_pushFixed( opStack, 1570 SUB_INT32( minuend, subtrahend ) ); 1571 } 1572 continue; /* do not clear the stack */ 1573 1574 case cf2_escDIV: 1575 { 1576 CF2_F16Dot16 dividend; 1577 CF2_F16Dot16 divisor; 1578 1579 1580 FT_TRACE4(( " div\n" )); 1581 1582 if ( font->isT1 && large_int ) 1583 { 1584 divisor = (CF2_F16Dot16)cf2_stack_popInt( opStack ); 1585 dividend = (CF2_F16Dot16)cf2_stack_popInt( opStack ); 1586 1587 large_int = FALSE; 1588 } 1589 else 1590 { 1591 divisor = cf2_stack_popFixed( opStack ); 1592 dividend = cf2_stack_popFixed( opStack ); 1593 } 1594 1595 cf2_stack_pushFixed( opStack, 1596 FT_DivFix( dividend, divisor ) ); 1597 1598 } 1599 continue; /* do not clear the stack */ 1600 1601 case cf2_escNEG: 1602 { 1603 CF2_F16Dot16 arg; 1604 1605 1606 FT_TRACE4(( " neg\n" )); 1607 1608 arg = cf2_stack_popFixed( opStack ); 1609 1610 if ( arg < -CF2_FIXED_MAX ) 1611 cf2_stack_pushFixed( opStack, CF2_FIXED_MAX ); 1612 else 1613 cf2_stack_pushFixed( opStack, -arg ); 1614 } 1615 continue; /* do not clear the stack */ 1616 1617 case cf2_escEQ: 1618 { 1619 CF2_F16Dot16 arg1; 1620 CF2_F16Dot16 arg2; 1621 1622 1623 FT_TRACE4(( " eq\n" )); 1624 1625 arg2 = cf2_stack_popFixed( opStack ); 1626 arg1 = cf2_stack_popFixed( opStack ); 1627 1628 cf2_stack_pushInt( opStack, arg1 == arg2 ); 1629 } 1630 continue; /* do not clear the stack */ 1631 1632 case cf2_escCALLOTHERSUBR: 1633 if ( !font->isT1 ) 1634 FT_TRACE4(( " unknown op (12, %d)\n", op2 )); 1635 else 1636 { 1637 CF2_Int subr_no; 1638 CF2_Int arg_cnt; 1639 CF2_UInt count; 1640 CF2_UInt opIdx = 0; 1641 1642 1643 FT_TRACE4(( " callothersubr\n" )); 1644 1645 subr_no = cf2_stack_popInt( opStack ); 1646 arg_cnt = cf2_stack_popInt( opStack ); 1647 1648 /******************************************************** 1649 * 1650 * remove all operands to callothersubr from the stack 1651 * 1652 * for handled othersubrs, where we know the number of 1653 * arguments, we increase the stack by the value of 1654 * known_othersubr_result_cnt 1655 * 1656 * for unhandled othersubrs the following pops adjust 1657 * the stack pointer as necessary 1658 */ 1659 1660 count = cf2_stack_count( opStack ); 1661 FT_ASSERT( (CF2_UInt)arg_cnt <= count ); 1662 1663 opIdx += count - (CF2_UInt)arg_cnt; 1664 1665 known_othersubr_result_cnt = 0; 1666 result_cnt = 0; 1667 1668 /* XXX TODO: The checks to `arg_count == <whatever>' */ 1669 /* might not be correct; an othersubr expects a */ 1670 /* certain number of operands on the PostScript stack */ 1671 /* (as opposed to the T1 stack) but it doesn't have to */ 1672 /* put them there by itself; previous othersubrs might */ 1673 /* have left the operands there if they were not */ 1674 /* followed by an appropriate number of pops */ 1675 /* */ 1676 /* On the other hand, Adobe Reader 7.0.8 for Linux */ 1677 /* doesn't accept a font that contains charstrings */ 1678 /* like */ 1679 /* */ 1680 /* 100 200 2 20 callothersubr */ 1681 /* 300 1 20 callothersubr pop */ 1682 /* */ 1683 /* Perhaps this is the reason why BuildCharArray */ 1684 /* exists. */ 1685 1686 switch ( subr_no ) 1687 { 1688 case 0: /* end flex feature */ 1689 if ( arg_cnt != 3 ) 1690 goto Unexpected_OtherSubr; 1691 1692 if ( initial_map_ready && 1693 ( !decoder->flex_state || 1694 decoder->num_flex_vectors != 7 ) ) 1695 { 1696 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" 1697 " unexpected flex end\n" )); 1698 lastError = FT_THROW( Invalid_Glyph_Format ); 1699 goto exit; 1700 } 1701 1702 /* the two `results' are popped */ 1703 /* by the following setcurrentpoint */ 1704 cf2_stack_pushFixed( opStack, curX ); 1705 cf2_stack_pushFixed( opStack, curY ); 1706 known_othersubr_result_cnt = 2; 1707 break; 1708 1709 case 1: /* start flex feature */ 1710 if ( arg_cnt != 0 ) 1711 goto Unexpected_OtherSubr; 1712 1713 if ( !initial_map_ready ) 1714 break; 1715 1716 if ( ps_builder_check_points( &decoder->builder, 6 ) ) 1717 goto exit; 1718 1719 decoder->flex_state = 1; 1720 decoder->num_flex_vectors = 0; 1721 break; 1722 1723 case 2: /* add flex vectors */ 1724 { 1725 FT_Int idx; 1726 FT_Int idx2; 1727 1728 1729 if ( arg_cnt != 0 ) 1730 goto Unexpected_OtherSubr; 1731 1732 if ( !initial_map_ready ) 1733 break; 1734 1735 if ( !decoder->flex_state ) 1736 { 1737 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" 1738 " missing flex start\n" )); 1739 lastError = FT_THROW( Invalid_Glyph_Format ); 1740 goto exit; 1741 } 1742 1743 /* note that we should not add a point for */ 1744 /* index 0; this will move our current position */ 1745 /* to the flex point without adding any point */ 1746 /* to the outline */ 1747 idx = decoder->num_flex_vectors++; 1748 if ( idx > 0 && idx < 7 ) 1749 { 1750 /* in malformed fonts it is possible to have */ 1751 /* other opcodes in the middle of a flex (which */ 1752 /* don't increase `num_flex_vectors'); we thus */ 1753 /* have to check whether we can add a point */ 1754 1755 if ( ps_builder_check_points( &decoder->builder, 1756 1 ) ) 1757 { 1758 lastError = FT_THROW( Invalid_Glyph_Format ); 1759 goto exit; 1760 } 1761 1762 /* map: 1->2 2->4 3->6 4->2 5->4 6->6 */ 1763 idx2 = ( idx > 3 ? idx - 3 : idx ) * 2; 1764 1765 flexStore[idx2 - 2] = curX; 1766 flexStore[idx2 - 1] = curY; 1767 1768 if ( idx == 3 || idx == 6 ) 1769 cf2_glyphpath_curveTo( &glyphPath, 1770 flexStore[0], 1771 flexStore[1], 1772 flexStore[2], 1773 flexStore[3], 1774 flexStore[4], 1775 flexStore[5] ); 1776 } 1777 } 1778 break; 1779 1780 case 3: /* change hints */ 1781 if ( arg_cnt != 1 ) 1782 goto Unexpected_OtherSubr; 1783 1784 if ( initial_map_ready ) 1785 { 1786 /* do not clear hints if initial hintmap */ 1787 /* is not ready - we need to collate all */ 1788 cf2_arrstack_clear( &vStemHintArray ); 1789 cf2_arrstack_clear( &hStemHintArray ); 1790 1791 cf2_hintmask_init( &hintMask, error ); 1792 hintMask.isValid = FALSE; 1793 hintMask.isNew = TRUE; 1794 } 1795 1796 known_othersubr_result_cnt = 1; 1797 break; 1798 1799 case 12: 1800 case 13: 1801 /* counter control hints, clear stack */ 1802 cf2_stack_clear( opStack ); 1803 break; 1804 1805 case 14: 1806 case 15: 1807 case 16: 1808 case 17: 1809 case 18: /* multiple masters */ 1810 { 1811 PS_Blend blend = decoder->blend; 1812 FT_UInt num_points, nn, mm; 1813 CF2_UInt delta; 1814 CF2_UInt values; 1815 1816 1817 if ( !blend ) 1818 { 1819 FT_ERROR(( 1820 "cf2_interpT2CharString:" 1821 " unexpected multiple masters operator\n" )); 1822 lastError = FT_THROW( Invalid_Glyph_Format ); 1823 goto exit; 1824 } 1825 1826 num_points = (FT_UInt)subr_no - 13 + 1827 ( subr_no == 18 ); 1828 if ( arg_cnt != (FT_Int)( num_points * 1829 blend->num_designs ) ) 1830 { 1831 FT_ERROR(( 1832 "cf2_interpT2CharString:" 1833 " incorrect number of multiple masters arguments\n" )); 1834 lastError = FT_THROW( Invalid_Glyph_Format ); 1835 goto exit; 1836 } 1837 1838 /* We want to compute */ 1839 /* */ 1840 /* a0*w0 + a1*w1 + ... + ak*wk */ 1841 /* */ 1842 /* but we only have a0, a1-a0, a2-a0, ..., ak-a0. */ 1843 /* */ 1844 /* However, given that w0 + w1 + ... + wk == 1, we */ 1845 /* can rewrite it easily as */ 1846 /* */ 1847 /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + ... + (ak-a0)*wk */ 1848 /* */ 1849 /* where k == num_designs-1. */ 1850 /* */ 1851 /* I guess that's why it's written in this `compact' */ 1852 /* form. */ 1853 /* */ 1854 delta = opIdx + num_points; 1855 values = opIdx; 1856 for ( nn = 0; nn < num_points; nn++ ) 1857 { 1858 CF2_Fixed tmp = cf2_stack_getReal( opStack, 1859 values ); 1860 1861 1862 for ( mm = 1; mm < blend->num_designs; mm++ ) 1863 tmp = ADD_INT32( tmp, 1864 FT_MulFix( 1865 cf2_stack_getReal( opStack, 1866 delta++ ), 1867 blend->weight_vector[mm] ) ); 1868 1869 cf2_stack_setReal( opStack, values++, tmp ); 1870 } 1871 cf2_stack_pop( opStack, 1872 (CF2_UInt)arg_cnt - num_points ); 1873 1874 known_othersubr_result_cnt = (FT_Int)num_points; 1875 break; 1876 } 1877 1878 case 19: 1879 /* <idx> 1 19 callothersubr */ 1880 /* ==> replace elements starting from index */ 1881 /* cvi( <idx> ) of BuildCharArray with */ 1882 /* WeightVector */ 1883 { 1884 FT_Int idx; 1885 PS_Blend blend = decoder->blend; 1886 1887 1888 if ( arg_cnt != 1 || !blend ) 1889 goto Unexpected_OtherSubr; 1890 1891 idx = cf2_stack_popInt( opStack ); 1892 1893 if ( idx < 0 || 1894 (FT_UInt)idx + blend->num_designs > 1895 decoder->len_buildchar ) 1896 goto Unexpected_OtherSubr; 1897 1898 ft_memcpy( &decoder->buildchar[idx], 1899 blend->weight_vector, 1900 blend->num_designs * 1901 sizeof ( blend->weight_vector[0] ) ); 1902 } 1903 break; 1904 1905 case 20: 1906 /* <arg1> <arg2> 2 20 callothersubr pop */ 1907 /* ==> push <arg1> + <arg2> onto T1 stack */ 1908 { 1909 CF2_F16Dot16 summand1; 1910 CF2_F16Dot16 summand2; 1911 1912 1913 if ( arg_cnt != 2 ) 1914 goto Unexpected_OtherSubr; 1915 1916 summand2 = cf2_stack_popFixed( opStack ); 1917 summand1 = cf2_stack_popFixed( opStack ); 1918 1919 cf2_stack_pushFixed( opStack, 1920 ADD_INT32( summand1, 1921 summand2 ) ); 1922 known_othersubr_result_cnt = 1; 1923 } 1924 break; 1925 1926 case 21: 1927 /* <arg1> <arg2> 2 21 callothersubr pop */ 1928 /* ==> push <arg1> - <arg2> onto T1 stack */ 1929 { 1930 CF2_F16Dot16 minuend; 1931 CF2_F16Dot16 subtrahend; 1932 1933 1934 if ( arg_cnt != 2 ) 1935 goto Unexpected_OtherSubr; 1936 1937 subtrahend = cf2_stack_popFixed( opStack ); 1938 minuend = cf2_stack_popFixed( opStack ); 1939 1940 cf2_stack_pushFixed( opStack, 1941 SUB_INT32( minuend, 1942 subtrahend ) ); 1943 known_othersubr_result_cnt = 1; 1944 } 1945 break; 1946 1947 case 22: 1948 /* <arg1> <arg2> 2 22 callothersubr pop */ 1949 /* ==> push <arg1> * <arg2> onto T1 stack */ 1950 { 1951 CF2_F16Dot16 factor1; 1952 CF2_F16Dot16 factor2; 1953 1954 1955 if ( arg_cnt != 2 ) 1956 goto Unexpected_OtherSubr; 1957 1958 factor2 = cf2_stack_popFixed( opStack ); 1959 factor1 = cf2_stack_popFixed( opStack ); 1960 1961 cf2_stack_pushFixed( opStack, 1962 FT_MulFix( factor1, factor2 ) ); 1963 known_othersubr_result_cnt = 1; 1964 } 1965 break; 1966 1967 case 23: 1968 /* <arg1> <arg2> 2 23 callothersubr pop */ 1969 /* ==> push <arg1> / <arg2> onto T1 stack */ 1970 { 1971 CF2_F16Dot16 dividend; 1972 CF2_F16Dot16 divisor; 1973 1974 1975 if ( arg_cnt != 2 ) 1976 goto Unexpected_OtherSubr; 1977 1978 divisor = cf2_stack_popFixed( opStack ); 1979 dividend = cf2_stack_popFixed( opStack ); 1980 1981 if ( divisor == 0 ) 1982 goto Unexpected_OtherSubr; 1983 1984 cf2_stack_pushFixed( opStack, 1985 FT_DivFix( dividend, 1986 divisor ) ); 1987 known_othersubr_result_cnt = 1; 1988 } 1989 break; 1990 1991 case 24: 1992 /* <val> <idx> 2 24 callothersubr */ 1993 /* ==> set BuildCharArray[cvi( <idx> )] = <val> */ 1994 { 1995 CF2_Int idx; 1996 PS_Blend blend = decoder->blend; 1997 1998 1999 if ( arg_cnt != 2 || !blend ) 2000 goto Unexpected_OtherSubr; 2001 2002 idx = cf2_stack_popInt( opStack ); 2003 2004 if ( idx < 0 || 2005 (FT_UInt)idx >= decoder->len_buildchar ) 2006 goto Unexpected_OtherSubr; 2007 2008 decoder->buildchar[idx] = 2009 cf2_stack_popFixed( opStack ); 2010 } 2011 break; 2012 2013 case 25: 2014 /* <idx> 1 25 callothersubr pop */ 2015 /* ==> push BuildCharArray[cvi( idx )] */ 2016 /* onto T1 stack */ 2017 { 2018 CF2_Int idx; 2019 PS_Blend blend = decoder->blend; 2020 2021 2022 if ( arg_cnt != 1 || !blend ) 2023 goto Unexpected_OtherSubr; 2024 2025 idx = cf2_stack_popInt( opStack ); 2026 2027 if ( idx < 0 || 2028 (FT_UInt)idx >= decoder->len_buildchar ) 2029 goto Unexpected_OtherSubr; 2030 2031 cf2_stack_pushFixed( opStack, 2032 decoder->buildchar[idx] ); 2033 known_othersubr_result_cnt = 1; 2034 } 2035 break; 2036 2037 #if 0 2038 case 26: 2039 /* <val> mark <idx> */ 2040 /* ==> set BuildCharArray[cvi( <idx> )] = <val>, */ 2041 /* leave mark on T1 stack */ 2042 /* <val> <idx> */ 2043 /* ==> set BuildCharArray[cvi( <idx> )] = <val> */ 2044 XXX which routine has left its mark on the 2045 XXX (PostScript) stack?; 2046 break; 2047 #endif 2048 2049 case 27: 2050 /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */ 2051 /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */ 2052 /* otherwise push <res2> */ 2053 { 2054 CF2_F16Dot16 arg1; 2055 CF2_F16Dot16 arg2; 2056 CF2_F16Dot16 cond1; 2057 CF2_F16Dot16 cond2; 2058 2059 2060 if ( arg_cnt != 4 ) 2061 goto Unexpected_OtherSubr; 2062 2063 cond2 = cf2_stack_popFixed( opStack ); 2064 cond1 = cf2_stack_popFixed( opStack ); 2065 arg2 = cf2_stack_popFixed( opStack ); 2066 arg1 = cf2_stack_popFixed( opStack ); 2067 2068 cf2_stack_pushFixed( opStack, 2069 cond1 <= cond2 ? arg1 : arg2 ); 2070 known_othersubr_result_cnt = 1; 2071 } 2072 break; 2073 2074 case 28: 2075 /* 0 28 callothersubr pop */ 2076 /* ==> push random value from interval [0, 1) */ 2077 /* onto stack */ 2078 { 2079 CF2_F16Dot16 r; 2080 2081 2082 if ( arg_cnt != 0 ) 2083 goto Unexpected_OtherSubr; 2084 2085 /* only use the lower 16 bits of `random' */ 2086 /* to generate a number in the range (0;1] */ 2087 r = (CF2_F16Dot16) 2088 ( ( decoder->current_subfont->random & 0xFFFF ) + 1 ); 2089 2090 decoder->current_subfont->random = 2091 cff_random( decoder->current_subfont->random ); 2092 2093 cf2_stack_pushFixed( opStack, r ); 2094 known_othersubr_result_cnt = 1; 2095 } 2096 break; 2097 2098 default: 2099 if ( arg_cnt >= 0 && subr_no >= 0 ) 2100 { 2101 FT_Int i; 2102 2103 2104 FT_ERROR(( 2105 "cf2_interpT2CharString (Type 1 mode):" 2106 " unknown othersubr [%d %d], wish me luck\n", 2107 arg_cnt, subr_no )); 2108 2109 /* store the unused args */ 2110 /* for this unhandled OtherSubr */ 2111 2112 if ( arg_cnt > PS_STORAGE_SIZE ) 2113 arg_cnt = PS_STORAGE_SIZE; 2114 result_cnt = arg_cnt; 2115 2116 for ( i = 1; i <= arg_cnt; i++ ) 2117 results[result_cnt - i] = 2118 cf2_stack_popFixed( opStack ); 2119 2120 break; 2121 } 2122 /* fall through */ 2123 2124 Unexpected_OtherSubr: 2125 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" 2126 " invalid othersubr [%d %d]\n", 2127 arg_cnt, subr_no )); 2128 lastError = FT_THROW( Invalid_Glyph_Format ); 2129 goto exit; 2130 } 2131 } 2132 continue; /* do not clear the stack */ 2133 2134 case cf2_escPOP: 2135 if ( !font->isT1 ) 2136 FT_TRACE4(( " unknown op (12, %d)\n", op2 )); 2137 else 2138 { 2139 FT_TRACE4(( " pop" )); 2140 2141 if ( known_othersubr_result_cnt > 0 ) 2142 { 2143 known_othersubr_result_cnt--; 2144 /* ignore, we pushed the operands ourselves */ 2145 continue; 2146 } 2147 2148 if ( result_cnt == 0 ) 2149 { 2150 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" 2151 " no more operands for othersubr\n" )); 2152 lastError = FT_THROW( Invalid_Glyph_Format ); 2153 goto exit; 2154 } 2155 2156 result_cnt--; 2157 cf2_stack_pushFixed( opStack, results[result_cnt] ); 2158 } 2159 continue; /* do not clear the stack */ 2160 2161 case cf2_escDROP: 2162 FT_TRACE4(( " drop\n" )); 2163 2164 (void)cf2_stack_popFixed( opStack ); 2165 continue; /* do not clear the stack */ 2166 2167 case cf2_escPUT: 2168 { 2169 CF2_F16Dot16 val; 2170 CF2_Int idx; 2171 2172 2173 FT_TRACE4(( " put\n" )); 2174 2175 idx = cf2_stack_popInt( opStack ); 2176 val = cf2_stack_popFixed( opStack ); 2177 2178 if ( idx >= 0 && idx < CF2_STORAGE_SIZE ) 2179 storage[idx] = val; 2180 } 2181 continue; /* do not clear the stack */ 2182 2183 case cf2_escGET: 2184 { 2185 CF2_Int idx; 2186 2187 2188 FT_TRACE4(( " get\n" )); 2189 2190 idx = cf2_stack_popInt( opStack ); 2191 2192 if ( idx >= 0 && idx < CF2_STORAGE_SIZE ) 2193 cf2_stack_pushFixed( opStack, storage[idx] ); 2194 } 2195 continue; /* do not clear the stack */ 2196 2197 case cf2_escIFELSE: 2198 { 2199 CF2_F16Dot16 arg1; 2200 CF2_F16Dot16 arg2; 2201 CF2_F16Dot16 cond1; 2202 CF2_F16Dot16 cond2; 2203 2204 2205 FT_TRACE4(( " ifelse\n" )); 2206 2207 cond2 = cf2_stack_popFixed( opStack ); 2208 cond1 = cf2_stack_popFixed( opStack ); 2209 arg2 = cf2_stack_popFixed( opStack ); 2210 arg1 = cf2_stack_popFixed( opStack ); 2211 2212 cf2_stack_pushFixed( opStack, 2213 cond1 <= cond2 ? arg1 : arg2 ); 2214 } 2215 continue; /* do not clear the stack */ 2216 2217 case cf2_escRANDOM: /* in spec */ 2218 { 2219 CF2_F16Dot16 r; 2220 2221 2222 FT_TRACE4(( " random\n" )); 2223 2224 /* only use the lower 16 bits of `random' */ 2225 /* to generate a number in the range (0;1] */ 2226 r = (CF2_F16Dot16) 2227 ( ( decoder->current_subfont->random & 0xFFFF ) + 1 ); 2228 2229 decoder->current_subfont->random = 2230 cff_random( decoder->current_subfont->random ); 2231 2232 cf2_stack_pushFixed( opStack, r ); 2233 } 2234 continue; /* do not clear the stack */ 2235 2236 case cf2_escMUL: 2237 { 2238 CF2_F16Dot16 factor1; 2239 CF2_F16Dot16 factor2; 2240 2241 2242 FT_TRACE4(( " mul\n" )); 2243 2244 factor2 = cf2_stack_popFixed( opStack ); 2245 factor1 = cf2_stack_popFixed( opStack ); 2246 2247 cf2_stack_pushFixed( opStack, 2248 FT_MulFix( factor1, factor2 ) ); 2249 } 2250 continue; /* do not clear the stack */ 2251 2252 case cf2_escSQRT: 2253 { 2254 CF2_F16Dot16 arg; 2255 2256 2257 FT_TRACE4(( " sqrt\n" )); 2258 2259 arg = cf2_stack_popFixed( opStack ); 2260 if ( arg > 0 ) 2261 { 2262 /* use a start value that doesn't make */ 2263 /* the algorithm's addition overflow */ 2264 FT_Fixed root = arg < 10 ? arg : arg >> 1; 2265 FT_Fixed new_root; 2266 2267 2268 /* Babylonian method */ 2269 for (;;) 2270 { 2271 new_root = ( root + FT_DivFix( arg, root ) + 1 ) >> 1; 2272 if ( new_root == root ) 2273 break; 2274 root = new_root; 2275 } 2276 arg = new_root; 2277 } 2278 else 2279 arg = 0; 2280 2281 cf2_stack_pushFixed( opStack, arg ); 2282 } 2283 continue; /* do not clear the stack */ 2284 2285 case cf2_escDUP: 2286 { 2287 CF2_F16Dot16 arg; 2288 2289 2290 FT_TRACE4(( " dup\n" )); 2291 2292 arg = cf2_stack_popFixed( opStack ); 2293 2294 cf2_stack_pushFixed( opStack, arg ); 2295 cf2_stack_pushFixed( opStack, arg ); 2296 } 2297 continue; /* do not clear the stack */ 2298 2299 case cf2_escEXCH: 2300 { 2301 CF2_F16Dot16 arg1; 2302 CF2_F16Dot16 arg2; 2303 2304 2305 FT_TRACE4(( " exch\n" )); 2306 2307 arg2 = cf2_stack_popFixed( opStack ); 2308 arg1 = cf2_stack_popFixed( opStack ); 2309 2310 cf2_stack_pushFixed( opStack, arg2 ); 2311 cf2_stack_pushFixed( opStack, arg1 ); 2312 } 2313 continue; /* do not clear the stack */ 2314 2315 case cf2_escINDEX: 2316 { 2317 CF2_Int idx; 2318 CF2_UInt size; 2319 2320 2321 FT_TRACE4(( " index\n" )); 2322 2323 idx = cf2_stack_popInt( opStack ); 2324 size = cf2_stack_count( opStack ); 2325 2326 if ( size > 0 ) 2327 { 2328 /* for `cf2_stack_getReal', */ 2329 /* index 0 is bottom of stack */ 2330 CF2_UInt gr_idx; 2331 2332 2333 if ( idx < 0 ) 2334 gr_idx = size - 1; 2335 else if ( (CF2_UInt)idx >= size ) 2336 gr_idx = 0; 2337 else 2338 gr_idx = size - 1 - (CF2_UInt)idx; 2339 2340 cf2_stack_pushFixed( opStack, 2341 cf2_stack_getReal( opStack, 2342 gr_idx ) ); 2343 } 2344 } 2345 continue; /* do not clear the stack */ 2346 2347 case cf2_escROLL: 2348 { 2349 CF2_Int idx; 2350 CF2_Int count; 2351 2352 2353 FT_TRACE4(( " roll\n" )); 2354 2355 idx = cf2_stack_popInt( opStack ); 2356 count = cf2_stack_popInt( opStack ); 2357 2358 cf2_stack_roll( opStack, count, idx ); 2359 } 2360 continue; /* do not clear the stack */ 2361 2362 case cf2_escSETCURRENTPT: 2363 if ( !font->isT1 ) 2364 FT_TRACE4(( " unknown op (12, %d)\n", op2 )); 2365 else 2366 { 2367 FT_TRACE4(( " setcurrentpoint" )); 2368 2369 if ( !initial_map_ready ) 2370 break; 2371 2372 /* From the T1 specification, section 6.4: */ 2373 /* */ 2374 /* The setcurrentpoint command is used only in */ 2375 /* conjunction with results from OtherSubrs */ 2376 /* procedures. */ 2377 2378 /* known_othersubr_result_cnt != 0 is already handled */ 2379 /* above. */ 2380 2381 /* Note, however, that both Ghostscript and Adobe */ 2382 /* Distiller handle this situation by silently */ 2383 /* ignoring the inappropriate `setcurrentpoint' */ 2384 /* instruction. So we do the same. */ 2385 #if 0 2386 2387 if ( decoder->flex_state != 1 ) 2388 { 2389 FT_ERROR(( "cf2_interpT2CharString:" 2390 " unexpected `setcurrentpoint'\n" )); 2391 goto Syntax_Error; 2392 } 2393 else 2394 ... 2395 #endif 2396 2397 curY = cf2_stack_popFixed( opStack ); 2398 curX = cf2_stack_popFixed( opStack ); 2399 2400 decoder->flex_state = 0; 2401 } 2402 break; 2403 2404 } /* end of 2nd switch checking op2 */ 2405 } 2406 } 2407 } /* end of 1st switch checking op2 */ 2408 } /* case cf2_cmdESC */ 2409 2410 break; 2411 2412 case cf2_cmdHSBW: 2413 if ( !font->isT1 ) 2414 FT_TRACE4(( " unknown op (%d)\n", op1 )); 2415 else 2416 { 2417 CF2_Fixed lsb_x; 2418 PS_Builder* builder; 2419 2420 2421 FT_TRACE4(( " hsbw" )); 2422 2423 builder = &decoder->builder; 2424 2425 builder->advance->x = cf2_stack_popFixed( opStack ); 2426 builder->advance->y = 0; 2427 2428 lsb_x = cf2_stack_popFixed( opStack ); 2429 2430 builder->left_bearing->x = ADD_INT32( builder->left_bearing->x, 2431 lsb_x ); 2432 2433 haveWidth = TRUE; 2434 2435 /* the `metrics_only' indicates that we only want to compute */ 2436 /* the glyph's metrics (lsb + advance width), not load the */ 2437 /* rest of it; so exit immediately */ 2438 if ( builder->metrics_only ) 2439 goto exit; 2440 2441 if ( initial_map_ready ) 2442 curX = ADD_INT32( curX, lsb_x ); 2443 } 2444 break; 2445 2446 case cf2_cmdENDCHAR: 2447 FT_TRACE4(( " endchar\n" )); 2448 2449 if ( font->isT1 && !initial_map_ready ) 2450 { 2451 FT_TRACE5(( "cf2_interpT2CharString (Type 1 mode): " 2452 "Build initial hintmap, rewinding...\n" )); 2453 2454 /* trigger initial hintmap build */ 2455 cf2_glyphpath_moveTo( &glyphPath, curX, curY ); 2456 2457 initial_map_ready = TRUE; 2458 2459 /* change hints routine - clear for rewind */ 2460 cf2_arrstack_clear( &vStemHintArray ); 2461 cf2_arrstack_clear( &hStemHintArray ); 2462 2463 cf2_hintmask_init( &hintMask, error ); 2464 hintMask.isValid = FALSE; 2465 hintMask.isNew = TRUE; 2466 2467 /* rewind charstring */ 2468 /* some charstrings use endchar from a final subroutine call */ 2469 /* without returning, detect these and exit to the top level */ 2470 /* charstring */ 2471 while ( charstringIndex > 0 ) 2472 { 2473 FT_TRACE4(( " return (leaving level %d)\n", charstringIndex )); 2474 2475 /* restore position in previous charstring */ 2476 charstring = (CF2_Buffer) 2477 cf2_arrstack_getPointer( 2478 &subrStack, 2479 (CF2_UInt)--charstringIndex ); 2480 } 2481 charstring->ptr = charstring->start; 2482 2483 break; 2484 } 2485 2486 if ( cf2_stack_count( opStack ) == 1 || 2487 cf2_stack_count( opStack ) == 5 ) 2488 { 2489 if ( !haveWidth ) 2490 *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ), 2491 nominalWidthX ); 2492 } 2493 2494 /* width is defined or default after this */ 2495 haveWidth = TRUE; 2496 2497 if ( decoder->width_only ) 2498 goto exit; 2499 2500 /* close path if still open */ 2501 cf2_glyphpath_closeOpenPath( &glyphPath ); 2502 2503 /* disable seac for CFF2 and Type1 */ 2504 /* (charstring ending with args on stack) */ 2505 if ( !font->isCFF2 && !font->isT1 && cf2_stack_count( opStack ) > 1 ) 2506 { 2507 /* must be either 4 or 5 -- */ 2508 /* this is a (deprecated) implied `seac' operator */ 2509 2510 CF2_Int achar; 2511 CF2_Int bchar; 2512 CF2_BufferRec component; 2513 CF2_Fixed dummyWidth; /* ignore component width */ 2514 FT_Error error2; 2515 2516 2517 if ( doingSeac ) 2518 { 2519 lastError = FT_THROW( Invalid_Glyph_Format ); 2520 goto exit; /* nested seac */ 2521 } 2522 2523 achar = cf2_stack_popInt( opStack ); 2524 bchar = cf2_stack_popInt( opStack ); 2525 2526 curY = cf2_stack_popFixed( opStack ); 2527 curX = cf2_stack_popFixed( opStack ); 2528 2529 error2 = cf2_getSeacComponent( decoder, achar, &component ); 2530 if ( error2 ) 2531 { 2532 lastError = error2; /* pass FreeType error through */ 2533 goto exit; 2534 } 2535 cf2_interpT2CharString( font, 2536 &component, 2537 callbacks, 2538 translation, 2539 TRUE, 2540 curX, 2541 curY, 2542 &dummyWidth ); 2543 cf2_freeSeacComponent( decoder, &component ); 2544 2545 error2 = cf2_getSeacComponent( decoder, bchar, &component ); 2546 if ( error2 ) 2547 { 2548 lastError = error2; /* pass FreeType error through */ 2549 goto exit; 2550 } 2551 cf2_interpT2CharString( font, 2552 &component, 2553 callbacks, 2554 translation, 2555 TRUE, 2556 0, 2557 0, 2558 &dummyWidth ); 2559 cf2_freeSeacComponent( decoder, &component ); 2560 } 2561 goto exit; 2562 2563 case cf2_cmdCNTRMASK: 2564 case cf2_cmdHINTMASK: 2565 /* the final \n in the tracing message gets added in */ 2566 /* `cf2_hintmask_read' (which also traces the mask bytes) */ 2567 FT_TRACE4(( op1 == cf2_cmdCNTRMASK ? " cntrmask" : " hintmask" )); 2568 2569 /* never add hints after the mask is computed */ 2570 if ( cf2_stack_count( opStack ) > 1 && 2571 cf2_hintmask_isValid( &hintMask ) ) 2572 { 2573 FT_TRACE4(( "cf2_interpT2CharString: invalid hint mask\n" )); 2574 break; 2575 } 2576 2577 /* if there are arguments on the stack, there this is an */ 2578 /* implied cf2_cmdVSTEMHM */ 2579 cf2_doStems( font, 2580 opStack, 2581 &vStemHintArray, 2582 width, 2583 &haveWidth, 2584 0 ); 2585 2586 if ( decoder->width_only ) 2587 goto exit; 2588 2589 if ( op1 == cf2_cmdHINTMASK ) 2590 { 2591 /* consume the hint mask bytes which follow the operator */ 2592 cf2_hintmask_read( &hintMask, 2593 charstring, 2594 cf2_arrstack_size( &hStemHintArray ) + 2595 cf2_arrstack_size( &vStemHintArray ) ); 2596 } 2597 else 2598 { 2599 /* 2600 * Consume the counter mask bytes which follow the operator: 2601 * Build a temporary hint map, just to place and lock those 2602 * stems participating in the counter mask. These are most 2603 * likely the dominant hstems, and are grouped together in a 2604 * few counter groups, not necessarily in correspondence 2605 * with the hint groups. This reduces the chances of 2606 * conflicts between hstems that are initially placed in 2607 * separate hint groups and then brought together. The 2608 * positions are copied back to `hStemHintArray', so we can 2609 * discard `counterMask' and `counterHintMap'. 2610 * 2611 */ 2612 CF2_HintMapRec counterHintMap; 2613 CF2_HintMaskRec counterMask; 2614 2615 2616 cf2_hintmap_init( &counterHintMap, 2617 font, 2618 &glyphPath.initialHintMap, 2619 &glyphPath.hintMoves, 2620 scaleY ); 2621 cf2_hintmask_init( &counterMask, error ); 2622 2623 cf2_hintmask_read( &counterMask, 2624 charstring, 2625 cf2_arrstack_size( &hStemHintArray ) + 2626 cf2_arrstack_size( &vStemHintArray ) ); 2627 cf2_hintmap_build( &counterHintMap, 2628 &hStemHintArray, 2629 &vStemHintArray, 2630 &counterMask, 2631 0, 2632 FALSE ); 2633 } 2634 break; 2635 2636 case cf2_cmdRMOVETO: 2637 FT_TRACE4(( " rmoveto\n" )); 2638 2639 if ( font->isT1 && !decoder->flex_state && !haveWidth ) 2640 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" 2641 " No width. Use hsbw/sbw as first op\n" )); 2642 2643 if ( cf2_stack_count( opStack ) > 2 && !haveWidth ) 2644 *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ), 2645 nominalWidthX ); 2646 2647 /* width is defined or default after this */ 2648 haveWidth = TRUE; 2649 2650 if ( decoder->width_only ) 2651 goto exit; 2652 2653 curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) ); 2654 curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) ); 2655 2656 if ( !decoder->flex_state ) 2657 cf2_glyphpath_moveTo( &glyphPath, curX, curY ); 2658 2659 break; 2660 2661 case cf2_cmdHMOVETO: 2662 FT_TRACE4(( " hmoveto\n" )); 2663 2664 if ( font->isT1 && !decoder->flex_state && !haveWidth ) 2665 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" 2666 " No width. Use hsbw/sbw as first op\n" )); 2667 2668 if ( cf2_stack_count( opStack ) > 1 && !haveWidth ) 2669 *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ), 2670 nominalWidthX ); 2671 2672 /* width is defined or default after this */ 2673 haveWidth = TRUE; 2674 2675 if ( decoder->width_only ) 2676 goto exit; 2677 2678 curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) ); 2679 2680 if ( !decoder->flex_state ) 2681 cf2_glyphpath_moveTo( &glyphPath, curX, curY ); 2682 2683 break; 2684 2685 case cf2_cmdRLINECURVE: 2686 { 2687 CF2_UInt count = cf2_stack_count( opStack ); 2688 CF2_UInt idx = 0; 2689 2690 2691 FT_TRACE4(( " rlinecurve\n" )); 2692 2693 while ( idx + 6 < count ) 2694 { 2695 curX = ADD_INT32( curX, cf2_stack_getReal( opStack, 2696 idx + 0 ) ); 2697 curY = ADD_INT32( curY, cf2_stack_getReal( opStack, 2698 idx + 1 ) ); 2699 2700 cf2_glyphpath_lineTo( &glyphPath, curX, curY ); 2701 idx += 2; 2702 } 2703 2704 while ( idx < count ) 2705 { 2706 CF2_Fixed x1, y1, x2, y2, x3, y3; 2707 2708 2709 x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX ); 2710 y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), curY ); 2711 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), x1 ); 2712 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y1 ); 2713 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 ); 2714 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 5 ), y2 ); 2715 2716 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); 2717 2718 curX = x3; 2719 curY = y3; 2720 idx += 6; 2721 } 2722 2723 cf2_stack_clear( opStack ); 2724 } 2725 continue; /* no need to clear stack again */ 2726 2727 case cf2_cmdVVCURVETO: 2728 { 2729 CF2_UInt count, count1 = cf2_stack_count( opStack ); 2730 CF2_UInt idx = 0; 2731 2732 2733 /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */ 2734 /* we enforce it by clearing the second bit */ 2735 /* (and sorting the stack indexing to suit) */ 2736 count = count1 & ~2U; 2737 idx += count1 - count; 2738 2739 FT_TRACE4(( " vvcurveto\n" )); 2740 2741 while ( idx < count ) 2742 { 2743 CF2_Fixed x1, y1, x2, y2, x3, y3; 2744 2745 2746 if ( ( count - idx ) & 1 ) 2747 { 2748 x1 = ADD_INT32( cf2_stack_getReal( opStack, idx ), curX ); 2749 2750 idx++; 2751 } 2752 else 2753 x1 = curX; 2754 2755 y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curY ); 2756 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 ); 2757 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 ); 2758 x3 = x2; 2759 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y2 ); 2760 2761 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); 2762 2763 curX = x3; 2764 curY = y3; 2765 idx += 4; 2766 } 2767 2768 cf2_stack_clear( opStack ); 2769 } 2770 continue; /* no need to clear stack again */ 2771 2772 case cf2_cmdHHCURVETO: 2773 { 2774 CF2_UInt count, count1 = cf2_stack_count( opStack ); 2775 CF2_UInt idx = 0; 2776 2777 2778 /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */ 2779 /* we enforce it by clearing the second bit */ 2780 /* (and sorting the stack indexing to suit) */ 2781 count = count1 & ~2U; 2782 idx += count1 - count; 2783 2784 FT_TRACE4(( " hhcurveto\n" )); 2785 2786 while ( idx < count ) 2787 { 2788 CF2_Fixed x1, y1, x2, y2, x3, y3; 2789 2790 2791 if ( ( count - idx ) & 1 ) 2792 { 2793 y1 = ADD_INT32( cf2_stack_getReal( opStack, idx ), curY ); 2794 2795 idx++; 2796 } 2797 else 2798 y1 = curY; 2799 2800 x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX ); 2801 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 ); 2802 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 ); 2803 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), x2 ); 2804 y3 = y2; 2805 2806 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); 2807 2808 curX = x3; 2809 curY = y3; 2810 idx += 4; 2811 } 2812 2813 cf2_stack_clear( opStack ); 2814 } 2815 continue; /* no need to clear stack again */ 2816 2817 case cf2_cmdVHCURVETO: 2818 case cf2_cmdHVCURVETO: 2819 { 2820 CF2_UInt count, count1 = cf2_stack_count( opStack ); 2821 CF2_UInt idx = 0; 2822 2823 FT_Bool alternate = FT_BOOL( op1 == cf2_cmdHVCURVETO ); 2824 2825 2826 /* if `cf2_stack_count' isn't of the form 8n, 8n+1, */ 2827 /* 8n+4, or 8n+5, we enforce it by clearing the */ 2828 /* second bit */ 2829 /* (and sorting the stack indexing to suit) */ 2830 count = count1 & ~2U; 2831 idx += count1 - count; 2832 2833 FT_TRACE4(( alternate ? " hvcurveto\n" : " vhcurveto\n" )); 2834 2835 while ( idx < count ) 2836 { 2837 CF2_Fixed x1, x2, x3, y1, y2, y3; 2838 2839 2840 if ( alternate ) 2841 { 2842 x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX ); 2843 y1 = curY; 2844 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 ); 2845 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 ); 2846 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y2 ); 2847 2848 if ( count - idx == 5 ) 2849 { 2850 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 ); 2851 2852 idx++; 2853 } 2854 else 2855 x3 = x2; 2856 2857 alternate = FALSE; 2858 } 2859 else 2860 { 2861 x1 = curX; 2862 y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curY ); 2863 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 ); 2864 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 ); 2865 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), x2 ); 2866 2867 if ( count - idx == 5 ) 2868 { 2869 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), y2 ); 2870 2871 idx++; 2872 } 2873 else 2874 y3 = y2; 2875 2876 alternate = TRUE; 2877 } 2878 2879 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); 2880 2881 curX = x3; 2882 curY = y3; 2883 idx += 4; 2884 } 2885 2886 cf2_stack_clear( opStack ); 2887 } 2888 continue; /* no need to clear stack again */ 2889 2890 case cf2_cmdEXTENDEDNMBR: 2891 { 2892 CF2_Int v; 2893 2894 CF2_Int byte1 = cf2_buf_readByte( charstring ); 2895 CF2_Int byte2 = cf2_buf_readByte( charstring ); 2896 2897 2898 v = (FT_Short)( ( byte1 << 8 ) | 2899 byte2 ); 2900 2901 FT_TRACE4(( " %d", v )); 2902 2903 cf2_stack_pushInt( opStack, v ); 2904 } 2905 continue; 2906 2907 default: 2908 /* numbers */ 2909 { 2910 if ( /* op1 >= 32 && */ op1 <= 246 ) 2911 { 2912 CF2_Int v; 2913 2914 2915 v = op1 - 139; 2916 2917 FT_TRACE4(( " %d", v )); 2918 2919 /* -107 .. 107 */ 2920 cf2_stack_pushInt( opStack, v ); 2921 } 2922 2923 else if ( /* op1 >= 247 && */ op1 <= 250 ) 2924 { 2925 CF2_Int v; 2926 2927 2928 v = op1; 2929 v -= 247; 2930 v *= 256; 2931 v += cf2_buf_readByte( charstring ); 2932 v += 108; 2933 2934 FT_TRACE4(( " %d", v )); 2935 2936 /* 108 .. 1131 */ 2937 cf2_stack_pushInt( opStack, v ); 2938 } 2939 2940 else if ( /* op1 >= 251 && */ op1 <= 254 ) 2941 { 2942 CF2_Int v; 2943 2944 2945 v = op1; 2946 v -= 251; 2947 v *= 256; 2948 v += cf2_buf_readByte( charstring ); 2949 v = -v - 108; 2950 2951 FT_TRACE4(( " %d", v )); 2952 2953 /* -1131 .. -108 */ 2954 cf2_stack_pushInt( opStack, v ); 2955 } 2956 2957 else /* op1 == 255 */ 2958 { 2959 CF2_Fixed v; 2960 2961 FT_UInt32 byte1 = (FT_UInt32)cf2_buf_readByte( charstring ); 2962 FT_UInt32 byte2 = (FT_UInt32)cf2_buf_readByte( charstring ); 2963 FT_UInt32 byte3 = (FT_UInt32)cf2_buf_readByte( charstring ); 2964 FT_UInt32 byte4 = (FT_UInt32)cf2_buf_readByte( charstring ); 2965 2966 2967 v = (CF2_Fixed)( ( byte1 << 24 ) | 2968 ( byte2 << 16 ) | 2969 ( byte3 << 8 ) | 2970 byte4 ); 2971 2972 /* 2973 * For Type 1: 2974 * 2975 * According to the specification, values > 32000 or < -32000 2976 * must be followed by a `div' operator to make the result be 2977 * in the range [-32000;32000]. We expect that the second 2978 * argument of `div' is not a large number. Additionally, we 2979 * don't handle stuff like `<large1> <large2> <num> div <num> 2980 * div' or <large1> <large2> <num> div div'. This is probably 2981 * not allowed anyway. 2982 * 2983 * <large> <num> <num>+ div is not checked but should not be 2984 * allowed as the large value remains untouched. 2985 * 2986 */ 2987 if ( font->isT1 ) 2988 { 2989 if ( v > 32000 || v < -32000 ) 2990 { 2991 if ( large_int ) 2992 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" 2993 " no `div' after large integer\n" )); 2994 else 2995 large_int = TRUE; 2996 } 2997 2998 FT_TRACE4(( " %d", v )); 2999 3000 cf2_stack_pushInt( opStack, (CF2_Int)v ); 3001 } 3002 else 3003 { 3004 FT_TRACE4(( " %.5fF", v / 65536.0 )); 3005 3006 cf2_stack_pushFixed( opStack, v ); 3007 } 3008 } 3009 } 3010 continue; /* don't clear stack */ 3011 3012 } /* end of switch statement checking `op1' */ 3013 3014 cf2_stack_clear( opStack ); 3015 3016 } /* end of main interpreter loop */ 3017 3018 /* we get here if the charstring ends without cf2_cmdENDCHAR */ 3019 FT_TRACE4(( "cf2_interpT2CharString:" 3020 " charstring ends without ENDCHAR\n" )); 3021 3022 exit: 3023 /* check whether last error seen is also the first one */ 3024 cf2_setError( error, lastError ); 3025 3026 if ( *error ) 3027 FT_TRACE4(( "charstring error %d\n", *error )); 3028 3029 /* free resources from objects we've used */ 3030 cf2_glyphpath_finalize( &glyphPath ); 3031 cf2_arrstack_finalize( &vStemHintArray ); 3032 cf2_arrstack_finalize( &hStemHintArray ); 3033 cf2_arrstack_finalize( &subrStack ); 3034 cf2_stack_free( opStack ); 3035 3036 FT_TRACE4(( "\n" )); 3037 3038 return; 3039 } 3040 3041 3042 /* END */ 3043