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