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