1 /**************************************************************************** 2 * 3 * psintrp.c 4 * 5 * Adobe's CFF Interpreter (body). 6 * 7 * Copyright 2007-2014 Adobe Systems Incorporated. 8 * 9 * This software, and all works of authorship, whether in source or 10 * object code form as indicated by the copyright notice(s) included 11 * herein (collectively, the "Work") is made available, and may only be 12 * used, modified, and distributed under the FreeType Project License, 13 * LICENSE.TXT. Additionally, subject to the terms and conditions of the 14 * FreeType Project License, each contributor to the Work hereby grants 15 * to any individual or legal entity exercising permissions granted by 16 * the FreeType Project License and this section (hereafter, "You" or 17 * "Your") a perpetual, worldwide, non-exclusive, no-charge, 18 * royalty-free, irrevocable (except as stated in this section) patent 19 * license to make, have made, use, offer to sell, sell, import, and 20 * otherwise transfer the Work, where such license applies only to those 21 * patent claims licensable by such contributor that are necessarily 22 * infringed by their contribution(s) alone or by combination of their 23 * contribution(s) with the Work to which such contribution(s) was 24 * submitted. If You institute patent litigation against any entity 25 * (including a cross-claim or counterclaim in a lawsuit) alleging that 26 * the Work or a contribution incorporated within the Work constitutes 27 * direct or contributory patent infringement, then any patent licenses 28 * granted to You under this License for that Work shall terminate as of 29 * the date such litigation is filed. 30 * 31 * By using, modifying, or distributing the Work you indicate that you 32 * have read and understood the terms and conditions of the 33 * FreeType Project License as well as those provided in this section, 34 * and you accept them fully. 35 * 36 */ 37 38 39 #include "psft.h" 40 #include <freetype/internal/ftdebug.h> 41 #include <freetype/internal/services/svcfftl.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 1437 /* save the left bearing and width of the SEAC */ 1438 /* glyph as they will be erased by the next load */ 1439 1440 left_bearing = *decoder->builder.left_bearing; 1441 advance = *decoder->builder.advance; 1442 1443 cf2_interpT2CharString( font, 1444 &component, 1445 callbacks, 1446 translation, 1447 TRUE, 1448 0, 1449 0, 1450 &dummyWidth ); 1451 cf2_freeT1SeacComponent( decoder, &component ); 1452 1453 /* If the SEAC glyph doesn't have a (H)SBW of its */ 1454 /* own use the values from the base glyph. */ 1455 1456 if ( !haveWidth ) 1457 { 1458 left_bearing = *decoder->builder.left_bearing; 1459 advance = *decoder->builder.advance; 1460 } 1461 1462 decoder->builder.left_bearing->x = 0; 1463 decoder->builder.left_bearing->y = 0; 1464 1465 /* Now load `achar' on top of */ 1466 /* the base outline */ 1467 1468 error2 = cf2_getT1SeacComponent( decoder, 1469 (FT_UInt)achar_index, 1470 &component ); 1471 if ( error2 ) 1472 { 1473 lastError = error2; /* pass FreeType error through */ 1474 goto exit; 1475 } 1476 cf2_interpT2CharString( font, 1477 &component, 1478 callbacks, 1479 translation, 1480 TRUE, 1481 adx - asb, 1482 ady, 1483 &dummyWidth ); 1484 cf2_freeT1SeacComponent( decoder, &component ); 1485 1486 /* restore the left side bearing and advance width */ 1487 /* of the SEAC glyph or base character (saved above) */ 1488 1489 *decoder->builder.left_bearing = left_bearing; 1490 *decoder->builder.advance = advance; 1491 1492 goto exit; 1493 } 1494 break; 1495 1496 case cf2_escSBW: 1497 if ( !font->isT1 ) 1498 FT_TRACE4(( " unknown op (12, %d)\n", op2 )); 1499 else 1500 { 1501 CF2_Fixed lsb_x, lsb_y; 1502 PS_Builder* builder; 1503 1504 1505 FT_TRACE4(( " sbw" )); 1506 1507 builder = &decoder->builder; 1508 1509 builder->advance->y = cf2_stack_popFixed( opStack ); 1510 builder->advance->x = cf2_stack_popFixed( opStack ); 1511 1512 lsb_y = cf2_stack_popFixed( opStack ); 1513 lsb_x = cf2_stack_popFixed( opStack ); 1514 1515 builder->left_bearing->x = 1516 ADD_INT32( builder->left_bearing->x, lsb_x ); 1517 builder->left_bearing->y = 1518 ADD_INT32( builder->left_bearing->y, lsb_y ); 1519 1520 haveWidth = TRUE; 1521 1522 /* the `metrics_only' indicates that we only want */ 1523 /* to compute the glyph's metrics (lsb + advance */ 1524 /* width), not load the rest of it; so exit */ 1525 /* immediately */ 1526 if ( builder->metrics_only ) 1527 goto exit; 1528 1529 if ( initial_map_ready ) 1530 { 1531 curX = ADD_INT32( curX, lsb_x ); 1532 curY = ADD_INT32( curY, lsb_y ); 1533 } 1534 } 1535 break; 1536 1537 case cf2_escABS: 1538 { 1539 CF2_F16Dot16 arg; 1540 1541 1542 FT_TRACE4(( " abs\n" )); 1543 1544 arg = cf2_stack_popFixed( opStack ); 1545 1546 if ( arg < -CF2_FIXED_MAX ) 1547 cf2_stack_pushFixed( opStack, CF2_FIXED_MAX ); 1548 else 1549 cf2_stack_pushFixed( opStack, FT_ABS( arg ) ); 1550 } 1551 continue; /* do not clear the stack */ 1552 1553 case cf2_escADD: 1554 { 1555 CF2_F16Dot16 summand1; 1556 CF2_F16Dot16 summand2; 1557 1558 1559 FT_TRACE4(( " add\n" )); 1560 1561 summand2 = cf2_stack_popFixed( opStack ); 1562 summand1 = cf2_stack_popFixed( opStack ); 1563 1564 cf2_stack_pushFixed( opStack, 1565 ADD_INT32( summand1, 1566 summand2 ) ); 1567 } 1568 continue; /* do not clear the stack */ 1569 1570 case cf2_escSUB: 1571 { 1572 CF2_F16Dot16 minuend; 1573 CF2_F16Dot16 subtrahend; 1574 1575 1576 FT_TRACE4(( " sub\n" )); 1577 1578 subtrahend = cf2_stack_popFixed( opStack ); 1579 minuend = cf2_stack_popFixed( opStack ); 1580 1581 cf2_stack_pushFixed( opStack, 1582 SUB_INT32( minuend, subtrahend ) ); 1583 } 1584 continue; /* do not clear the stack */ 1585 1586 case cf2_escDIV: 1587 { 1588 CF2_F16Dot16 dividend; 1589 CF2_F16Dot16 divisor; 1590 1591 1592 FT_TRACE4(( " div\n" )); 1593 1594 if ( font->isT1 && large_int ) 1595 { 1596 divisor = (CF2_F16Dot16)cf2_stack_popInt( opStack ); 1597 dividend = (CF2_F16Dot16)cf2_stack_popInt( opStack ); 1598 1599 large_int = FALSE; 1600 } 1601 else 1602 { 1603 divisor = cf2_stack_popFixed( opStack ); 1604 dividend = cf2_stack_popFixed( opStack ); 1605 } 1606 1607 cf2_stack_pushFixed( opStack, 1608 FT_DivFix( dividend, divisor ) ); 1609 1610 } 1611 continue; /* do not clear the stack */ 1612 1613 case cf2_escNEG: 1614 { 1615 CF2_F16Dot16 arg; 1616 1617 1618 FT_TRACE4(( " neg\n" )); 1619 1620 arg = cf2_stack_popFixed( opStack ); 1621 1622 if ( arg < -CF2_FIXED_MAX ) 1623 cf2_stack_pushFixed( opStack, CF2_FIXED_MAX ); 1624 else 1625 cf2_stack_pushFixed( opStack, -arg ); 1626 } 1627 continue; /* do not clear the stack */ 1628 1629 case cf2_escEQ: 1630 { 1631 CF2_F16Dot16 arg1; 1632 CF2_F16Dot16 arg2; 1633 1634 1635 FT_TRACE4(( " eq\n" )); 1636 1637 arg2 = cf2_stack_popFixed( opStack ); 1638 arg1 = cf2_stack_popFixed( opStack ); 1639 1640 cf2_stack_pushInt( opStack, arg1 == arg2 ); 1641 } 1642 continue; /* do not clear the stack */ 1643 1644 case cf2_escCALLOTHERSUBR: 1645 if ( !font->isT1 ) 1646 FT_TRACE4(( " unknown op (12, %d)\n", op2 )); 1647 else 1648 { 1649 CF2_Int subr_no; 1650 CF2_Int arg_cnt; 1651 CF2_UInt count; 1652 CF2_UInt opIdx = 0; 1653 1654 1655 FT_TRACE4(( " callothersubr\n" )); 1656 1657 subr_no = cf2_stack_popInt( opStack ); 1658 arg_cnt = cf2_stack_popInt( opStack ); 1659 1660 /******************************************************** 1661 * 1662 * remove all operands to callothersubr from the stack 1663 * 1664 * for handled othersubrs, where we know the number of 1665 * arguments, we increase the stack by the value of 1666 * known_othersubr_result_cnt 1667 * 1668 * for unhandled othersubrs the following pops adjust 1669 * the stack pointer as necessary 1670 */ 1671 1672 count = cf2_stack_count( opStack ); 1673 FT_ASSERT( (CF2_UInt)arg_cnt <= count ); 1674 1675 opIdx += count - (CF2_UInt)arg_cnt; 1676 1677 known_othersubr_result_cnt = 0; 1678 result_cnt = 0; 1679 1680 /* XXX TODO: The checks to `arg_count == <whatever>' */ 1681 /* might not be correct; an othersubr expects a */ 1682 /* certain number of operands on the PostScript stack */ 1683 /* (as opposed to the T1 stack) but it doesn't have to */ 1684 /* put them there by itself; previous othersubrs might */ 1685 /* have left the operands there if they were not */ 1686 /* followed by an appropriate number of pops */ 1687 /* */ 1688 /* On the other hand, Adobe Reader 7.0.8 for Linux */ 1689 /* doesn't accept a font that contains charstrings */ 1690 /* like */ 1691 /* */ 1692 /* 100 200 2 20 callothersubr */ 1693 /* 300 1 20 callothersubr pop */ 1694 /* */ 1695 /* Perhaps this is the reason why BuildCharArray */ 1696 /* exists. */ 1697 1698 switch ( subr_no ) 1699 { 1700 case 0: /* end flex feature */ 1701 if ( arg_cnt != 3 ) 1702 goto Unexpected_OtherSubr; 1703 1704 if ( initial_map_ready && 1705 ( !decoder->flex_state || 1706 decoder->num_flex_vectors != 7 ) ) 1707 { 1708 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" 1709 " unexpected flex end\n" )); 1710 lastError = FT_THROW( Invalid_Glyph_Format ); 1711 goto exit; 1712 } 1713 1714 /* the two `results' are popped */ 1715 /* by the following setcurrentpoint */ 1716 cf2_stack_pushFixed( opStack, curX ); 1717 cf2_stack_pushFixed( opStack, curY ); 1718 known_othersubr_result_cnt = 2; 1719 break; 1720 1721 case 1: /* start flex feature */ 1722 if ( arg_cnt != 0 ) 1723 goto Unexpected_OtherSubr; 1724 1725 if ( !initial_map_ready ) 1726 break; 1727 1728 if ( ps_builder_check_points( &decoder->builder, 6 ) ) 1729 goto exit; 1730 1731 decoder->flex_state = 1; 1732 decoder->num_flex_vectors = 0; 1733 break; 1734 1735 case 2: /* add flex vectors */ 1736 { 1737 FT_Int idx; 1738 FT_Int idx2; 1739 1740 1741 if ( arg_cnt != 0 ) 1742 goto Unexpected_OtherSubr; 1743 1744 if ( !initial_map_ready ) 1745 break; 1746 1747 if ( !decoder->flex_state ) 1748 { 1749 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" 1750 " missing flex start\n" )); 1751 lastError = FT_THROW( Invalid_Glyph_Format ); 1752 goto exit; 1753 } 1754 1755 /* note that we should not add a point for */ 1756 /* index 0; this will move our current position */ 1757 /* to the flex point without adding any point */ 1758 /* to the outline */ 1759 idx = decoder->num_flex_vectors++; 1760 if ( idx > 0 && idx < 7 ) 1761 { 1762 /* in malformed fonts it is possible to have */ 1763 /* other opcodes in the middle of a flex (which */ 1764 /* don't increase `num_flex_vectors'); we thus */ 1765 /* have to check whether we can add a point */ 1766 1767 if ( ps_builder_check_points( &decoder->builder, 1768 1 ) ) 1769 { 1770 lastError = FT_THROW( Invalid_Glyph_Format ); 1771 goto exit; 1772 } 1773 1774 /* map: 1->2 2->4 3->6 4->2 5->4 6->6 */ 1775 idx2 = ( idx > 3 ? idx - 3 : idx ) * 2; 1776 1777 flexStore[idx2 - 2] = curX; 1778 flexStore[idx2 - 1] = curY; 1779 1780 if ( idx == 3 || idx == 6 ) 1781 cf2_glyphpath_curveTo( &glyphPath, 1782 flexStore[0], 1783 flexStore[1], 1784 flexStore[2], 1785 flexStore[3], 1786 flexStore[4], 1787 flexStore[5] ); 1788 } 1789 } 1790 break; 1791 1792 case 3: /* change hints */ 1793 if ( arg_cnt != 1 ) 1794 goto Unexpected_OtherSubr; 1795 1796 if ( initial_map_ready ) 1797 { 1798 /* do not clear hints if initial hintmap */ 1799 /* is not ready - we need to collate all */ 1800 cf2_arrstack_clear( &vStemHintArray ); 1801 cf2_arrstack_clear( &hStemHintArray ); 1802 1803 cf2_hintmask_init( &hintMask, error ); 1804 hintMask.isValid = FALSE; 1805 hintMask.isNew = TRUE; 1806 } 1807 1808 known_othersubr_result_cnt = 1; 1809 break; 1810 1811 case 12: 1812 case 13: 1813 /* counter control hints, clear stack */ 1814 cf2_stack_clear( opStack ); 1815 break; 1816 1817 case 14: 1818 case 15: 1819 case 16: 1820 case 17: 1821 case 18: /* multiple masters */ 1822 { 1823 PS_Blend blend = decoder->blend; 1824 FT_UInt num_points, nn, mm; 1825 CF2_UInt delta; 1826 CF2_UInt values; 1827 1828 1829 if ( !blend ) 1830 { 1831 FT_ERROR(( 1832 "cf2_interpT2CharString:" 1833 " unexpected multiple masters operator\n" )); 1834 lastError = FT_THROW( Invalid_Glyph_Format ); 1835 goto exit; 1836 } 1837 1838 num_points = (FT_UInt)subr_no - 13 + 1839 ( subr_no == 18 ); 1840 if ( arg_cnt != (FT_Int)( num_points * 1841 blend->num_designs ) ) 1842 { 1843 FT_ERROR(( 1844 "cf2_interpT2CharString:" 1845 " incorrect number of multiple masters arguments\n" )); 1846 lastError = FT_THROW( Invalid_Glyph_Format ); 1847 goto exit; 1848 } 1849 1850 /* We want to compute */ 1851 /* */ 1852 /* a0*w0 + a1*w1 + ... + ak*wk */ 1853 /* */ 1854 /* but we only have a0, a1-a0, a2-a0, ..., ak-a0. */ 1855 /* */ 1856 /* However, given that w0 + w1 + ... + wk == 1, we */ 1857 /* can rewrite it easily as */ 1858 /* */ 1859 /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + ... + (ak-a0)*wk */ 1860 /* */ 1861 /* where k == num_designs-1. */ 1862 /* */ 1863 /* I guess that's why it's written in this `compact' */ 1864 /* form. */ 1865 /* */ 1866 delta = opIdx + num_points; 1867 values = opIdx; 1868 for ( nn = 0; nn < num_points; nn++ ) 1869 { 1870 CF2_Fixed tmp = cf2_stack_getReal( opStack, 1871 values ); 1872 1873 1874 for ( mm = 1; mm < blend->num_designs; mm++ ) 1875 tmp = ADD_INT32( tmp, 1876 FT_MulFix( 1877 cf2_stack_getReal( opStack, 1878 delta++ ), 1879 blend->weight_vector[mm] ) ); 1880 1881 cf2_stack_setReal( opStack, values++, tmp ); 1882 } 1883 cf2_stack_pop( opStack, 1884 (CF2_UInt)arg_cnt - num_points ); 1885 1886 known_othersubr_result_cnt = (FT_Int)num_points; 1887 break; 1888 } 1889 1890 case 19: 1891 /* <idx> 1 19 callothersubr */ 1892 /* ==> replace elements starting from index */ 1893 /* cvi( <idx> ) of BuildCharArray with */ 1894 /* WeightVector */ 1895 { 1896 FT_Int idx; 1897 PS_Blend blend = decoder->blend; 1898 1899 1900 if ( arg_cnt != 1 || !blend ) 1901 goto Unexpected_OtherSubr; 1902 1903 idx = cf2_stack_popInt( opStack ); 1904 1905 if ( idx < 0 || 1906 (FT_UInt)idx + blend->num_designs > 1907 decoder->len_buildchar ) 1908 goto Unexpected_OtherSubr; 1909 1910 ft_memcpy( &decoder->buildchar[idx], 1911 blend->weight_vector, 1912 blend->num_designs * 1913 sizeof ( blend->weight_vector[0] ) ); 1914 } 1915 break; 1916 1917 case 20: 1918 /* <arg1> <arg2> 2 20 callothersubr pop */ 1919 /* ==> push <arg1> + <arg2> onto T1 stack */ 1920 { 1921 CF2_F16Dot16 summand1; 1922 CF2_F16Dot16 summand2; 1923 1924 1925 if ( arg_cnt != 2 ) 1926 goto Unexpected_OtherSubr; 1927 1928 summand2 = cf2_stack_popFixed( opStack ); 1929 summand1 = cf2_stack_popFixed( opStack ); 1930 1931 cf2_stack_pushFixed( opStack, 1932 ADD_INT32( summand1, 1933 summand2 ) ); 1934 known_othersubr_result_cnt = 1; 1935 } 1936 break; 1937 1938 case 21: 1939 /* <arg1> <arg2> 2 21 callothersubr pop */ 1940 /* ==> push <arg1> - <arg2> onto T1 stack */ 1941 { 1942 CF2_F16Dot16 minuend; 1943 CF2_F16Dot16 subtrahend; 1944 1945 1946 if ( arg_cnt != 2 ) 1947 goto Unexpected_OtherSubr; 1948 1949 subtrahend = cf2_stack_popFixed( opStack ); 1950 minuend = cf2_stack_popFixed( opStack ); 1951 1952 cf2_stack_pushFixed( opStack, 1953 SUB_INT32( minuend, 1954 subtrahend ) ); 1955 known_othersubr_result_cnt = 1; 1956 } 1957 break; 1958 1959 case 22: 1960 /* <arg1> <arg2> 2 22 callothersubr pop */ 1961 /* ==> push <arg1> * <arg2> onto T1 stack */ 1962 { 1963 CF2_F16Dot16 factor1; 1964 CF2_F16Dot16 factor2; 1965 1966 1967 if ( arg_cnt != 2 ) 1968 goto Unexpected_OtherSubr; 1969 1970 factor2 = cf2_stack_popFixed( opStack ); 1971 factor1 = cf2_stack_popFixed( opStack ); 1972 1973 cf2_stack_pushFixed( opStack, 1974 FT_MulFix( factor1, factor2 ) ); 1975 known_othersubr_result_cnt = 1; 1976 } 1977 break; 1978 1979 case 23: 1980 /* <arg1> <arg2> 2 23 callothersubr pop */ 1981 /* ==> push <arg1> / <arg2> onto T1 stack */ 1982 { 1983 CF2_F16Dot16 dividend; 1984 CF2_F16Dot16 divisor; 1985 1986 1987 if ( arg_cnt != 2 ) 1988 goto Unexpected_OtherSubr; 1989 1990 divisor = cf2_stack_popFixed( opStack ); 1991 dividend = cf2_stack_popFixed( opStack ); 1992 1993 if ( divisor == 0 ) 1994 goto Unexpected_OtherSubr; 1995 1996 cf2_stack_pushFixed( opStack, 1997 FT_DivFix( dividend, 1998 divisor ) ); 1999 known_othersubr_result_cnt = 1; 2000 } 2001 break; 2002 2003 case 24: 2004 /* <val> <idx> 2 24 callothersubr */ 2005 /* ==> set BuildCharArray[cvi( <idx> )] = <val> */ 2006 { 2007 CF2_Int idx; 2008 PS_Blend blend = decoder->blend; 2009 2010 2011 if ( arg_cnt != 2 || !blend ) 2012 goto Unexpected_OtherSubr; 2013 2014 idx = cf2_stack_popInt( opStack ); 2015 2016 if ( idx < 0 || 2017 (FT_UInt)idx >= decoder->len_buildchar ) 2018 goto Unexpected_OtherSubr; 2019 2020 decoder->buildchar[idx] = 2021 cf2_stack_popFixed( opStack ); 2022 } 2023 break; 2024 2025 case 25: 2026 /* <idx> 1 25 callothersubr pop */ 2027 /* ==> push BuildCharArray[cvi( idx )] */ 2028 /* onto T1 stack */ 2029 { 2030 CF2_Int idx; 2031 PS_Blend blend = decoder->blend; 2032 2033 2034 if ( arg_cnt != 1 || !blend ) 2035 goto Unexpected_OtherSubr; 2036 2037 idx = cf2_stack_popInt( opStack ); 2038 2039 if ( idx < 0 || 2040 (FT_UInt)idx >= decoder->len_buildchar ) 2041 goto Unexpected_OtherSubr; 2042 2043 cf2_stack_pushFixed( opStack, 2044 decoder->buildchar[idx] ); 2045 known_othersubr_result_cnt = 1; 2046 } 2047 break; 2048 2049 #if 0 2050 case 26: 2051 /* <val> mark <idx> */ 2052 /* ==> set BuildCharArray[cvi( <idx> )] = <val>, */ 2053 /* leave mark on T1 stack */ 2054 /* <val> <idx> */ 2055 /* ==> set BuildCharArray[cvi( <idx> )] = <val> */ 2056 XXX which routine has left its mark on the 2057 XXX (PostScript) stack?; 2058 break; 2059 #endif 2060 2061 case 27: 2062 /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */ 2063 /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */ 2064 /* otherwise push <res2> */ 2065 { 2066 CF2_F16Dot16 arg1; 2067 CF2_F16Dot16 arg2; 2068 CF2_F16Dot16 cond1; 2069 CF2_F16Dot16 cond2; 2070 2071 2072 if ( arg_cnt != 4 ) 2073 goto Unexpected_OtherSubr; 2074 2075 cond2 = cf2_stack_popFixed( opStack ); 2076 cond1 = cf2_stack_popFixed( opStack ); 2077 arg2 = cf2_stack_popFixed( opStack ); 2078 arg1 = cf2_stack_popFixed( opStack ); 2079 2080 cf2_stack_pushFixed( opStack, 2081 cond1 <= cond2 ? arg1 : arg2 ); 2082 known_othersubr_result_cnt = 1; 2083 } 2084 break; 2085 2086 case 28: 2087 /* 0 28 callothersubr pop */ 2088 /* ==> push random value from interval [0, 1) */ 2089 /* onto stack */ 2090 { 2091 CF2_F16Dot16 r; 2092 2093 2094 if ( arg_cnt != 0 ) 2095 goto Unexpected_OtherSubr; 2096 2097 /* only use the lower 16 bits of `random' */ 2098 /* to generate a number in the range (0;1] */ 2099 r = (CF2_F16Dot16) 2100 ( ( decoder->current_subfont->random & 0xFFFF ) + 1 ); 2101 2102 decoder->current_subfont->random = 2103 cff_random( decoder->current_subfont->random ); 2104 2105 cf2_stack_pushFixed( opStack, r ); 2106 known_othersubr_result_cnt = 1; 2107 } 2108 break; 2109 2110 default: 2111 if ( arg_cnt >= 0 && subr_no >= 0 ) 2112 { 2113 FT_Int i; 2114 2115 2116 FT_ERROR(( 2117 "cf2_interpT2CharString (Type 1 mode):" 2118 " unknown othersubr [%d %d], wish me luck\n", 2119 arg_cnt, subr_no )); 2120 2121 /* store the unused args */ 2122 /* for this unhandled OtherSubr */ 2123 2124 if ( arg_cnt > PS_STORAGE_SIZE ) 2125 arg_cnt = PS_STORAGE_SIZE; 2126 result_cnt = arg_cnt; 2127 2128 for ( i = 1; i <= arg_cnt; i++ ) 2129 results[result_cnt - i] = 2130 cf2_stack_popFixed( opStack ); 2131 2132 break; 2133 } 2134 /* fall through */ 2135 2136 Unexpected_OtherSubr: 2137 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" 2138 " invalid othersubr [%d %d]\n", 2139 arg_cnt, subr_no )); 2140 lastError = FT_THROW( Invalid_Glyph_Format ); 2141 goto exit; 2142 } 2143 } 2144 continue; /* do not clear the stack */ 2145 2146 case cf2_escPOP: 2147 if ( !font->isT1 ) 2148 FT_TRACE4(( " unknown op (12, %d)\n", op2 )); 2149 else 2150 { 2151 FT_TRACE4(( " pop" )); 2152 2153 if ( known_othersubr_result_cnt > 0 ) 2154 { 2155 known_othersubr_result_cnt--; 2156 /* ignore, we pushed the operands ourselves */ 2157 continue; 2158 } 2159 2160 if ( result_cnt == 0 ) 2161 { 2162 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" 2163 " no more operands for othersubr\n" )); 2164 lastError = FT_THROW( Invalid_Glyph_Format ); 2165 goto exit; 2166 } 2167 2168 result_cnt--; 2169 cf2_stack_pushFixed( opStack, results[result_cnt] ); 2170 } 2171 continue; /* do not clear the stack */ 2172 2173 case cf2_escDROP: 2174 FT_TRACE4(( " drop\n" )); 2175 2176 (void)cf2_stack_popFixed( opStack ); 2177 continue; /* do not clear the stack */ 2178 2179 case cf2_escPUT: 2180 { 2181 CF2_F16Dot16 val; 2182 CF2_Int idx; 2183 2184 2185 FT_TRACE4(( " put\n" )); 2186 2187 idx = cf2_stack_popInt( opStack ); 2188 val = cf2_stack_popFixed( opStack ); 2189 2190 if ( idx >= 0 && idx < CF2_STORAGE_SIZE ) 2191 storage[idx] = val; 2192 } 2193 continue; /* do not clear the stack */ 2194 2195 case cf2_escGET: 2196 { 2197 CF2_Int idx; 2198 2199 2200 FT_TRACE4(( " get\n" )); 2201 2202 idx = cf2_stack_popInt( opStack ); 2203 2204 if ( idx >= 0 && idx < CF2_STORAGE_SIZE ) 2205 cf2_stack_pushFixed( opStack, storage[idx] ); 2206 } 2207 continue; /* do not clear the stack */ 2208 2209 case cf2_escIFELSE: 2210 { 2211 CF2_F16Dot16 arg1; 2212 CF2_F16Dot16 arg2; 2213 CF2_F16Dot16 cond1; 2214 CF2_F16Dot16 cond2; 2215 2216 2217 FT_TRACE4(( " ifelse\n" )); 2218 2219 cond2 = cf2_stack_popFixed( opStack ); 2220 cond1 = cf2_stack_popFixed( opStack ); 2221 arg2 = cf2_stack_popFixed( opStack ); 2222 arg1 = cf2_stack_popFixed( opStack ); 2223 2224 cf2_stack_pushFixed( opStack, 2225 cond1 <= cond2 ? arg1 : arg2 ); 2226 } 2227 continue; /* do not clear the stack */ 2228 2229 case cf2_escRANDOM: /* in spec */ 2230 { 2231 CF2_F16Dot16 r; 2232 2233 2234 FT_TRACE4(( " random\n" )); 2235 2236 /* only use the lower 16 bits of `random' */ 2237 /* to generate a number in the range (0;1] */ 2238 r = (CF2_F16Dot16) 2239 ( ( decoder->current_subfont->random & 0xFFFF ) + 1 ); 2240 2241 decoder->current_subfont->random = 2242 cff_random( decoder->current_subfont->random ); 2243 2244 cf2_stack_pushFixed( opStack, r ); 2245 } 2246 continue; /* do not clear the stack */ 2247 2248 case cf2_escMUL: 2249 { 2250 CF2_F16Dot16 factor1; 2251 CF2_F16Dot16 factor2; 2252 2253 2254 FT_TRACE4(( " mul\n" )); 2255 2256 factor2 = cf2_stack_popFixed( opStack ); 2257 factor1 = cf2_stack_popFixed( opStack ); 2258 2259 cf2_stack_pushFixed( opStack, 2260 FT_MulFix( factor1, factor2 ) ); 2261 } 2262 continue; /* do not clear the stack */ 2263 2264 case cf2_escSQRT: 2265 { 2266 CF2_F16Dot16 arg; 2267 2268 2269 FT_TRACE4(( " sqrt\n" )); 2270 2271 arg = cf2_stack_popFixed( opStack ); 2272 if ( arg > 0 ) 2273 { 2274 /* use a start value that doesn't make */ 2275 /* the algorithm's addition overflow */ 2276 FT_Fixed root = arg < 10 ? arg : arg >> 1; 2277 FT_Fixed new_root; 2278 2279 2280 /* Babylonian method */ 2281 for (;;) 2282 { 2283 new_root = ( root + FT_DivFix( arg, root ) + 1 ) >> 1; 2284 if ( new_root == root ) 2285 break; 2286 root = new_root; 2287 } 2288 arg = new_root; 2289 } 2290 else 2291 arg = 0; 2292 2293 cf2_stack_pushFixed( opStack, arg ); 2294 } 2295 continue; /* do not clear the stack */ 2296 2297 case cf2_escDUP: 2298 { 2299 CF2_F16Dot16 arg; 2300 2301 2302 FT_TRACE4(( " dup\n" )); 2303 2304 arg = cf2_stack_popFixed( opStack ); 2305 2306 cf2_stack_pushFixed( opStack, arg ); 2307 cf2_stack_pushFixed( opStack, arg ); 2308 } 2309 continue; /* do not clear the stack */ 2310 2311 case cf2_escEXCH: 2312 { 2313 CF2_F16Dot16 arg1; 2314 CF2_F16Dot16 arg2; 2315 2316 2317 FT_TRACE4(( " exch\n" )); 2318 2319 arg2 = cf2_stack_popFixed( opStack ); 2320 arg1 = cf2_stack_popFixed( opStack ); 2321 2322 cf2_stack_pushFixed( opStack, arg2 ); 2323 cf2_stack_pushFixed( opStack, arg1 ); 2324 } 2325 continue; /* do not clear the stack */ 2326 2327 case cf2_escINDEX: 2328 { 2329 CF2_Int idx; 2330 CF2_UInt size; 2331 2332 2333 FT_TRACE4(( " index\n" )); 2334 2335 idx = cf2_stack_popInt( opStack ); 2336 size = cf2_stack_count( opStack ); 2337 2338 if ( size > 0 ) 2339 { 2340 /* for `cf2_stack_getReal', */ 2341 /* index 0 is bottom of stack */ 2342 CF2_UInt gr_idx; 2343 2344 2345 if ( idx < 0 ) 2346 gr_idx = size - 1; 2347 else if ( (CF2_UInt)idx >= size ) 2348 gr_idx = 0; 2349 else 2350 gr_idx = size - 1 - (CF2_UInt)idx; 2351 2352 cf2_stack_pushFixed( opStack, 2353 cf2_stack_getReal( opStack, 2354 gr_idx ) ); 2355 } 2356 } 2357 continue; /* do not clear the stack */ 2358 2359 case cf2_escROLL: 2360 { 2361 CF2_Int idx; 2362 CF2_Int count; 2363 2364 2365 FT_TRACE4(( " roll\n" )); 2366 2367 idx = cf2_stack_popInt( opStack ); 2368 count = cf2_stack_popInt( opStack ); 2369 2370 cf2_stack_roll( opStack, count, idx ); 2371 } 2372 continue; /* do not clear the stack */ 2373 2374 case cf2_escSETCURRENTPT: 2375 if ( !font->isT1 ) 2376 FT_TRACE4(( " unknown op (12, %d)\n", op2 )); 2377 else 2378 { 2379 FT_TRACE4(( " setcurrentpoint" )); 2380 2381 if ( !initial_map_ready ) 2382 break; 2383 2384 /* From the T1 specification, section 6.4: */ 2385 /* */ 2386 /* The setcurrentpoint command is used only in */ 2387 /* conjunction with results from OtherSubrs */ 2388 /* procedures. */ 2389 2390 /* known_othersubr_result_cnt != 0 is already handled */ 2391 /* above. */ 2392 2393 /* Note, however, that both Ghostscript and Adobe */ 2394 /* Distiller handle this situation by silently */ 2395 /* ignoring the inappropriate `setcurrentpoint' */ 2396 /* instruction. So we do the same. */ 2397 #if 0 2398 2399 if ( decoder->flex_state != 1 ) 2400 { 2401 FT_ERROR(( "cf2_interpT2CharString:" 2402 " unexpected `setcurrentpoint'\n" )); 2403 goto Syntax_Error; 2404 } 2405 else 2406 ... 2407 #endif 2408 2409 curY = cf2_stack_popFixed( opStack ); 2410 curX = cf2_stack_popFixed( opStack ); 2411 2412 decoder->flex_state = 0; 2413 } 2414 break; 2415 2416 } /* end of 2nd switch checking op2 */ 2417 } 2418 } 2419 } /* end of 1st switch checking op2 */ 2420 } /* case cf2_cmdESC */ 2421 2422 break; 2423 2424 case cf2_cmdHSBW: 2425 if ( !font->isT1 ) 2426 FT_TRACE4(( " unknown op (%d)\n", op1 )); 2427 else 2428 { 2429 CF2_Fixed lsb_x; 2430 PS_Builder* builder; 2431 2432 2433 FT_TRACE4(( " hsbw\n" )); 2434 2435 builder = &decoder->builder; 2436 2437 builder->advance->x = cf2_stack_popFixed( opStack ); 2438 builder->advance->y = 0; 2439 2440 lsb_x = cf2_stack_popFixed( opStack ); 2441 2442 builder->left_bearing->x = ADD_INT32( builder->left_bearing->x, 2443 lsb_x ); 2444 2445 haveWidth = TRUE; 2446 2447 /* the `metrics_only' indicates that we only want to compute */ 2448 /* the glyph's metrics (lsb + advance width), not load the */ 2449 /* rest of it; so exit immediately */ 2450 if ( builder->metrics_only ) 2451 goto exit; 2452 2453 if ( initial_map_ready ) 2454 curX = ADD_INT32( curX, lsb_x ); 2455 } 2456 break; 2457 2458 case cf2_cmdENDCHAR: 2459 FT_TRACE4(( " endchar\n" )); 2460 2461 if ( font->isT1 && !initial_map_ready ) 2462 { 2463 FT_TRACE5(( "cf2_interpT2CharString (Type 1 mode): " 2464 "Build initial hintmap, rewinding...\n" )); 2465 2466 /* trigger initial hintmap build */ 2467 cf2_glyphpath_moveTo( &glyphPath, curX, curY ); 2468 2469 initial_map_ready = TRUE; 2470 2471 /* change hints routine - clear for rewind */ 2472 cf2_arrstack_clear( &vStemHintArray ); 2473 cf2_arrstack_clear( &hStemHintArray ); 2474 2475 cf2_hintmask_init( &hintMask, error ); 2476 hintMask.isValid = FALSE; 2477 hintMask.isNew = TRUE; 2478 2479 /* rewind charstring */ 2480 /* some charstrings use endchar from a final subroutine call */ 2481 /* without returning, detect these and exit to the top level */ 2482 /* charstring */ 2483 while ( charstringIndex > 0 ) 2484 { 2485 FT_TRACE4(( " return (leaving level %d)\n", charstringIndex )); 2486 2487 /* restore position in previous charstring */ 2488 charstring = (CF2_Buffer) 2489 cf2_arrstack_getPointer( 2490 &subrStack, 2491 (CF2_UInt)--charstringIndex ); 2492 } 2493 charstring->ptr = charstring->start; 2494 2495 break; 2496 } 2497 2498 if ( cf2_stack_count( opStack ) == 1 || 2499 cf2_stack_count( opStack ) == 5 ) 2500 { 2501 if ( !haveWidth ) 2502 *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ), 2503 nominalWidthX ); 2504 } 2505 2506 /* width is defined or default after this */ 2507 haveWidth = TRUE; 2508 2509 if ( decoder->width_only ) 2510 goto exit; 2511 2512 /* close path if still open */ 2513 cf2_glyphpath_closeOpenPath( &glyphPath ); 2514 2515 /* disable seac for CFF2 and Type1 */ 2516 /* (charstring ending with args on stack) */ 2517 if ( !font->isCFF2 && !font->isT1 && cf2_stack_count( opStack ) > 1 ) 2518 { 2519 /* must be either 4 or 5 -- */ 2520 /* this is a (deprecated) implied `seac' operator */ 2521 2522 CF2_Int achar; 2523 CF2_Int bchar; 2524 CF2_BufferRec component; 2525 CF2_Fixed dummyWidth; /* ignore component width */ 2526 FT_Error error2; 2527 2528 2529 if ( doingSeac ) 2530 { 2531 lastError = FT_THROW( Invalid_Glyph_Format ); 2532 goto exit; /* nested seac */ 2533 } 2534 2535 achar = cf2_stack_popInt( opStack ); 2536 bchar = cf2_stack_popInt( opStack ); 2537 2538 curY = cf2_stack_popFixed( opStack ); 2539 curX = cf2_stack_popFixed( opStack ); 2540 2541 error2 = cf2_getSeacComponent( decoder, achar, &component ); 2542 if ( error2 ) 2543 { 2544 lastError = error2; /* pass FreeType error through */ 2545 goto exit; 2546 } 2547 cf2_interpT2CharString( font, 2548 &component, 2549 callbacks, 2550 translation, 2551 TRUE, 2552 curX, 2553 curY, 2554 &dummyWidth ); 2555 cf2_freeSeacComponent( decoder, &component ); 2556 2557 error2 = cf2_getSeacComponent( decoder, bchar, &component ); 2558 if ( error2 ) 2559 { 2560 lastError = error2; /* pass FreeType error through */ 2561 goto exit; 2562 } 2563 cf2_interpT2CharString( font, 2564 &component, 2565 callbacks, 2566 translation, 2567 TRUE, 2568 0, 2569 0, 2570 &dummyWidth ); 2571 cf2_freeSeacComponent( decoder, &component ); 2572 } 2573 goto exit; 2574 2575 case cf2_cmdCNTRMASK: 2576 case cf2_cmdHINTMASK: 2577 /* the final \n in the tracing message gets added in */ 2578 /* `cf2_hintmask_read' (which also traces the mask bytes) */ 2579 FT_TRACE4(( "%s", op1 == cf2_cmdCNTRMASK ? " cntrmask" : " hintmask" )); 2580 2581 /* never add hints after the mask is computed */ 2582 if ( cf2_stack_count( opStack ) > 1 && 2583 cf2_hintmask_isValid( &hintMask ) ) 2584 { 2585 FT_TRACE4(( "cf2_interpT2CharString: invalid hint mask\n" )); 2586 break; 2587 } 2588 2589 /* if there are arguments on the stack, there this is an */ 2590 /* implied cf2_cmdVSTEMHM */ 2591 cf2_doStems( font, 2592 opStack, 2593 &vStemHintArray, 2594 width, 2595 &haveWidth, 2596 0 ); 2597 2598 if ( decoder->width_only ) 2599 goto exit; 2600 2601 if ( op1 == cf2_cmdHINTMASK ) 2602 { 2603 /* consume the hint mask bytes which follow the operator */ 2604 cf2_hintmask_read( &hintMask, 2605 charstring, 2606 cf2_arrstack_size( &hStemHintArray ) + 2607 cf2_arrstack_size( &vStemHintArray ) ); 2608 } 2609 else 2610 { 2611 /* 2612 * Consume the counter mask bytes which follow the operator: 2613 * Build a temporary hint map, just to place and lock those 2614 * stems participating in the counter mask. These are most 2615 * likely the dominant hstems, and are grouped together in a 2616 * few counter groups, not necessarily in correspondence 2617 * with the hint groups. This reduces the chances of 2618 * conflicts between hstems that are initially placed in 2619 * separate hint groups and then brought together. The 2620 * positions are copied back to `hStemHintArray', so we can 2621 * discard `counterMask' and `counterHintMap'. 2622 * 2623 */ 2624 CF2_HintMapRec counterHintMap; 2625 CF2_HintMaskRec counterMask; 2626 2627 2628 cf2_hintmap_init( &counterHintMap, 2629 font, 2630 &glyphPath.initialHintMap, 2631 &glyphPath.hintMoves, 2632 scaleY ); 2633 cf2_hintmask_init( &counterMask, error ); 2634 2635 cf2_hintmask_read( &counterMask, 2636 charstring, 2637 cf2_arrstack_size( &hStemHintArray ) + 2638 cf2_arrstack_size( &vStemHintArray ) ); 2639 cf2_hintmap_build( &counterHintMap, 2640 &hStemHintArray, 2641 &vStemHintArray, 2642 &counterMask, 2643 0, 2644 FALSE ); 2645 } 2646 break; 2647 2648 case cf2_cmdRMOVETO: 2649 FT_TRACE4(( " rmoveto\n" )); 2650 2651 if ( font->isT1 && !decoder->flex_state && !haveWidth ) 2652 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" 2653 " No width. Use hsbw/sbw as first op\n" )); 2654 2655 if ( cf2_stack_count( opStack ) > 2 && !haveWidth ) 2656 *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ), 2657 nominalWidthX ); 2658 2659 /* width is defined or default after this */ 2660 haveWidth = TRUE; 2661 2662 if ( decoder->width_only ) 2663 goto exit; 2664 2665 curY = ADD_INT32( curY, cf2_stack_popFixed( opStack ) ); 2666 curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) ); 2667 2668 if ( !decoder->flex_state ) 2669 cf2_glyphpath_moveTo( &glyphPath, curX, curY ); 2670 2671 break; 2672 2673 case cf2_cmdHMOVETO: 2674 FT_TRACE4(( " hmoveto\n" )); 2675 2676 if ( font->isT1 && !decoder->flex_state && !haveWidth ) 2677 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" 2678 " No width. Use hsbw/sbw as first op\n" )); 2679 2680 if ( cf2_stack_count( opStack ) > 1 && !haveWidth ) 2681 *width = ADD_INT32( cf2_stack_getReal( opStack, 0 ), 2682 nominalWidthX ); 2683 2684 /* width is defined or default after this */ 2685 haveWidth = TRUE; 2686 2687 if ( decoder->width_only ) 2688 goto exit; 2689 2690 curX = ADD_INT32( curX, cf2_stack_popFixed( opStack ) ); 2691 2692 if ( !decoder->flex_state ) 2693 cf2_glyphpath_moveTo( &glyphPath, curX, curY ); 2694 2695 break; 2696 2697 case cf2_cmdRLINECURVE: 2698 { 2699 CF2_UInt count = cf2_stack_count( opStack ); 2700 CF2_UInt idx = 0; 2701 2702 2703 FT_TRACE4(( " rlinecurve\n" )); 2704 2705 while ( idx + 6 < count ) 2706 { 2707 curX = ADD_INT32( curX, cf2_stack_getReal( opStack, 2708 idx + 0 ) ); 2709 curY = ADD_INT32( curY, cf2_stack_getReal( opStack, 2710 idx + 1 ) ); 2711 2712 cf2_glyphpath_lineTo( &glyphPath, curX, curY ); 2713 idx += 2; 2714 } 2715 2716 while ( idx < count ) 2717 { 2718 CF2_Fixed x1, y1, x2, y2, x3, y3; 2719 2720 2721 x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX ); 2722 y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), curY ); 2723 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), x1 ); 2724 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y1 ); 2725 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 ); 2726 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 5 ), y2 ); 2727 2728 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); 2729 2730 curX = x3; 2731 curY = y3; 2732 idx += 6; 2733 } 2734 2735 cf2_stack_clear( opStack ); 2736 } 2737 continue; /* no need to clear stack again */ 2738 2739 case cf2_cmdVVCURVETO: 2740 { 2741 CF2_UInt count, count1 = cf2_stack_count( opStack ); 2742 CF2_UInt idx = 0; 2743 2744 2745 /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */ 2746 /* we enforce it by clearing the second bit */ 2747 /* (and sorting the stack indexing to suit) */ 2748 count = count1 & ~2U; 2749 idx += count1 - count; 2750 2751 FT_TRACE4(( " vvcurveto\n" )); 2752 2753 while ( idx < count ) 2754 { 2755 CF2_Fixed x1, y1, x2, y2, x3, y3; 2756 2757 2758 if ( ( count - idx ) & 1 ) 2759 { 2760 x1 = ADD_INT32( cf2_stack_getReal( opStack, idx ), curX ); 2761 2762 idx++; 2763 } 2764 else 2765 x1 = curX; 2766 2767 y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curY ); 2768 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 ); 2769 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 ); 2770 x3 = x2; 2771 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y2 ); 2772 2773 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); 2774 2775 curX = x3; 2776 curY = y3; 2777 idx += 4; 2778 } 2779 2780 cf2_stack_clear( opStack ); 2781 } 2782 continue; /* no need to clear stack again */ 2783 2784 case cf2_cmdHHCURVETO: 2785 { 2786 CF2_UInt count, count1 = cf2_stack_count( opStack ); 2787 CF2_UInt idx = 0; 2788 2789 2790 /* if `cf2_stack_count' isn't of the form 4n or 4n+1, */ 2791 /* we enforce it by clearing the second bit */ 2792 /* (and sorting the stack indexing to suit) */ 2793 count = count1 & ~2U; 2794 idx += count1 - count; 2795 2796 FT_TRACE4(( " hhcurveto\n" )); 2797 2798 while ( idx < count ) 2799 { 2800 CF2_Fixed x1, y1, x2, y2, x3, y3; 2801 2802 2803 if ( ( count - idx ) & 1 ) 2804 { 2805 y1 = ADD_INT32( cf2_stack_getReal( opStack, idx ), curY ); 2806 2807 idx++; 2808 } 2809 else 2810 y1 = curY; 2811 2812 x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX ); 2813 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 ); 2814 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 ); 2815 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), x2 ); 2816 y3 = y2; 2817 2818 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); 2819 2820 curX = x3; 2821 curY = y3; 2822 idx += 4; 2823 } 2824 2825 cf2_stack_clear( opStack ); 2826 } 2827 continue; /* no need to clear stack again */ 2828 2829 case cf2_cmdVHCURVETO: 2830 case cf2_cmdHVCURVETO: 2831 { 2832 CF2_UInt count, count1 = cf2_stack_count( opStack ); 2833 CF2_UInt idx = 0; 2834 2835 FT_Bool alternate = FT_BOOL( op1 == cf2_cmdHVCURVETO ); 2836 2837 2838 /* if `cf2_stack_count' isn't of the form 8n, 8n+1, */ 2839 /* 8n+4, or 8n+5, we enforce it by clearing the */ 2840 /* second bit */ 2841 /* (and sorting the stack indexing to suit) */ 2842 count = count1 & ~2U; 2843 idx += count1 - count; 2844 2845 FT_TRACE4(( "%s\n", alternate ? " hvcurveto" : " vhcurveto" )); 2846 2847 while ( idx < count ) 2848 { 2849 CF2_Fixed x1, x2, x3, y1, y2, y3; 2850 2851 2852 if ( alternate ) 2853 { 2854 x1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curX ); 2855 y1 = curY; 2856 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 ); 2857 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 ); 2858 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), y2 ); 2859 2860 if ( count - idx == 5 ) 2861 { 2862 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), x2 ); 2863 2864 idx++; 2865 } 2866 else 2867 x3 = x2; 2868 2869 alternate = FALSE; 2870 } 2871 else 2872 { 2873 x1 = curX; 2874 y1 = ADD_INT32( cf2_stack_getReal( opStack, idx + 0 ), curY ); 2875 x2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 1 ), x1 ); 2876 y2 = ADD_INT32( cf2_stack_getReal( opStack, idx + 2 ), y1 ); 2877 x3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 3 ), x2 ); 2878 2879 if ( count - idx == 5 ) 2880 { 2881 y3 = ADD_INT32( cf2_stack_getReal( opStack, idx + 4 ), y2 ); 2882 2883 idx++; 2884 } 2885 else 2886 y3 = y2; 2887 2888 alternate = TRUE; 2889 } 2890 2891 cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 ); 2892 2893 curX = x3; 2894 curY = y3; 2895 idx += 4; 2896 } 2897 2898 cf2_stack_clear( opStack ); 2899 } 2900 continue; /* no need to clear stack again */ 2901 2902 case cf2_cmdEXTENDEDNMBR: 2903 { 2904 CF2_Int v; 2905 2906 CF2_Int byte1 = cf2_buf_readByte( charstring ); 2907 CF2_Int byte2 = cf2_buf_readByte( charstring ); 2908 2909 2910 v = (FT_Short)( ( byte1 << 8 ) | 2911 byte2 ); 2912 2913 FT_TRACE4(( " %d", v )); 2914 2915 cf2_stack_pushInt( opStack, v ); 2916 } 2917 continue; 2918 2919 default: 2920 /* numbers */ 2921 { 2922 if ( /* op1 >= 32 && */ op1 <= 246 ) 2923 { 2924 CF2_Int v; 2925 2926 2927 v = op1 - 139; 2928 2929 FT_TRACE4(( " %d", v )); 2930 2931 /* -107 .. 107 */ 2932 cf2_stack_pushInt( opStack, v ); 2933 } 2934 2935 else if ( /* op1 >= 247 && */ op1 <= 250 ) 2936 { 2937 CF2_Int v; 2938 2939 2940 v = op1; 2941 v -= 247; 2942 v *= 256; 2943 v += cf2_buf_readByte( charstring ); 2944 v += 108; 2945 2946 FT_TRACE4(( " %d", v )); 2947 2948 /* 108 .. 1131 */ 2949 cf2_stack_pushInt( opStack, v ); 2950 } 2951 2952 else if ( /* op1 >= 251 && */ op1 <= 254 ) 2953 { 2954 CF2_Int v; 2955 2956 2957 v = op1; 2958 v -= 251; 2959 v *= 256; 2960 v += cf2_buf_readByte( charstring ); 2961 v = -v - 108; 2962 2963 FT_TRACE4(( " %d", v )); 2964 2965 /* -1131 .. -108 */ 2966 cf2_stack_pushInt( opStack, v ); 2967 } 2968 2969 else /* op1 == 255 */ 2970 { 2971 CF2_Fixed v; 2972 2973 FT_UInt32 byte1 = (FT_UInt32)cf2_buf_readByte( charstring ); 2974 FT_UInt32 byte2 = (FT_UInt32)cf2_buf_readByte( charstring ); 2975 FT_UInt32 byte3 = (FT_UInt32)cf2_buf_readByte( charstring ); 2976 FT_UInt32 byte4 = (FT_UInt32)cf2_buf_readByte( charstring ); 2977 2978 2979 v = (CF2_Fixed)( ( byte1 << 24 ) | 2980 ( byte2 << 16 ) | 2981 ( byte3 << 8 ) | 2982 byte4 ); 2983 2984 /* 2985 * For Type 1: 2986 * 2987 * According to the specification, values > 32000 or < -32000 2988 * must be followed by a `div' operator to make the result be 2989 * in the range [-32000;32000]. We expect that the second 2990 * argument of `div' is not a large number. Additionally, we 2991 * don't handle stuff like `<large1> <large2> <num> div <num> 2992 * div' or <large1> <large2> <num> div div'. This is probably 2993 * not allowed anyway. 2994 * 2995 * <large> <num> <num>+ div is not checked but should not be 2996 * allowed as the large value remains untouched. 2997 * 2998 */ 2999 if ( font->isT1 ) 3000 { 3001 if ( v > 32000 || v < -32000 ) 3002 { 3003 if ( large_int ) 3004 FT_ERROR(( "cf2_interpT2CharString (Type 1 mode):" 3005 " no `div' after large integer\n" )); 3006 else 3007 large_int = TRUE; 3008 } 3009 3010 FT_TRACE4(( " %d", v )); 3011 3012 cf2_stack_pushInt( opStack, (CF2_Int)v ); 3013 } 3014 else 3015 { 3016 FT_TRACE4(( " %.5fF", v / 65536.0 )); 3017 3018 cf2_stack_pushFixed( opStack, v ); 3019 } 3020 } 3021 } 3022 continue; /* don't clear stack */ 3023 3024 } /* end of switch statement checking `op1' */ 3025 3026 cf2_stack_clear( opStack ); 3027 3028 } /* end of main interpreter loop */ 3029 3030 /* we get here if the charstring ends without cf2_cmdENDCHAR */ 3031 FT_TRACE4(( "cf2_interpT2CharString:" 3032 " charstring ends without ENDCHAR\n" )); 3033 3034 exit: 3035 /* check whether last error seen is also the first one */ 3036 cf2_setError( error, lastError ); 3037 3038 if ( *error ) 3039 FT_TRACE4(( "charstring error %d\n", *error )); 3040 3041 /* free resources from objects we've used */ 3042 cf2_glyphpath_finalize( &glyphPath ); 3043 cf2_arrstack_finalize( &vStemHintArray ); 3044 cf2_arrstack_finalize( &hStemHintArray ); 3045 cf2_arrstack_finalize( &subrStack ); 3046 cf2_stack_free( opStack ); 3047 3048 FT_TRACE4(( "\n" )); 3049 3050 return; 3051 } 3052 3053 3054 /* END */ 3055