1 /**************************************************************************** 2 * 3 * psft.c 4 * 5 * FreeType Glue Component to Adobe's Interpreter (body). 6 * 7 * Copyright 2013-2014 Adobe Systems Incorporated. 8 * 9 * This software, and all works of authorship, whether in source or 10 * object code form as indicated by the copyright notice(s) included 11 * herein (collectively, the "Work") is made available, and may only be 12 * used, modified, and distributed under the FreeType Project License, 13 * LICENSE.TXT. Additionally, subject to the terms and conditions of the 14 * FreeType Project License, each contributor to the Work hereby grants 15 * to any individual or legal entity exercising permissions granted by 16 * the FreeType Project License and this section (hereafter, "You" or 17 * "Your") a perpetual, worldwide, non-exclusive, no-charge, 18 * royalty-free, irrevocable (except as stated in this section) patent 19 * license to make, have made, use, offer to sell, sell, import, and 20 * otherwise transfer the Work, where such license applies only to those 21 * patent claims licensable by such contributor that are necessarily 22 * infringed by their contribution(s) alone or by combination of their 23 * contribution(s) with the Work to which such contribution(s) was 24 * submitted. If You institute patent litigation against any entity 25 * (including a cross-claim or counterclaim in a lawsuit) alleging that 26 * the Work or a contribution incorporated within the Work constitutes 27 * direct or contributory patent infringement, then any patent licenses 28 * granted to You under this License for that Work shall terminate as of 29 * the date such litigation is filed. 30 * 31 * By using, modifying, or distributing the Work you indicate that you 32 * have read and understood the terms and conditions of the 33 * FreeType Project License as well as those provided in this section, 34 * and you accept them fully. 35 * 36 */ 37 38 39 #include "psft.h" 40 #include FT_INTERNAL_DEBUG_H 41 42 #include "psfont.h" 43 #include "pserror.h" 44 #include "psobjs.h" 45 #include "cffdecode.h" 46 47 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 48 #include FT_MULTIPLE_MASTERS_H 49 #include FT_SERVICE_MULTIPLE_MASTERS_H 50 #endif 51 52 #include FT_SERVICE_CFF_TABLE_LOAD_H 53 54 55 #define CF2_MAX_SIZE cf2_intToFixed( 2000 ) /* max ppem */ 56 57 58 /* 59 * This check should avoid most internal overflow cases. Clients should 60 * generally respond to `Glyph_Too_Big' by getting a glyph outline 61 * at EM size, scaling it and filling it as a graphics operation. 62 * 63 */ 64 static FT_Error cf2_checkTransform(const CF2_Matrix * transform,CF2_Int unitsPerEm)65 cf2_checkTransform( const CF2_Matrix* transform, 66 CF2_Int unitsPerEm ) 67 { 68 CF2_Fixed maxScale; 69 70 71 FT_ASSERT( unitsPerEm > 0 ); 72 73 if ( transform->a <= 0 || transform->d <= 0 ) 74 return FT_THROW( Invalid_Size_Handle ); 75 76 FT_ASSERT( transform->b == 0 && transform->c == 0 ); 77 FT_ASSERT( transform->tx == 0 && transform->ty == 0 ); 78 79 if ( unitsPerEm > 0x7FFF ) 80 return FT_THROW( Glyph_Too_Big ); 81 82 maxScale = FT_DivFix( CF2_MAX_SIZE, cf2_intToFixed( unitsPerEm ) ); 83 84 if ( transform->a > maxScale || transform->d > maxScale ) 85 return FT_THROW( Glyph_Too_Big ); 86 87 return FT_Err_Ok; 88 } 89 90 91 static void cf2_setGlyphWidth(CF2_Outline outline,CF2_Fixed width)92 cf2_setGlyphWidth( CF2_Outline outline, 93 CF2_Fixed width ) 94 { 95 PS_Decoder* decoder = outline->decoder; 96 97 98 FT_ASSERT( decoder ); 99 100 if ( !decoder->builder.is_t1 ) 101 *decoder->glyph_width = cf2_fixedToInt( width ); 102 } 103 104 105 /* Clean up font instance. */ 106 static void cf2_free_instance(void * ptr)107 cf2_free_instance( void* ptr ) 108 { 109 CF2_Font font = (CF2_Font)ptr; 110 111 112 if ( font ) 113 { 114 FT_Memory memory = font->memory; 115 116 117 FT_FREE( font->blend.lastNDV ); 118 FT_FREE( font->blend.BV ); 119 } 120 } 121 122 123 /********************************************* 124 * 125 * functions for handling client outline; 126 * FreeType uses coordinates in 26.6 format 127 * 128 */ 129 130 static void cf2_builder_moveTo(CF2_OutlineCallbacks callbacks,const CF2_CallbackParams params)131 cf2_builder_moveTo( CF2_OutlineCallbacks callbacks, 132 const CF2_CallbackParams params ) 133 { 134 /* downcast the object pointer */ 135 CF2_Outline outline = (CF2_Outline)callbacks; 136 PS_Builder* builder; 137 138 (void)params; /* only used in debug mode */ 139 140 141 FT_ASSERT( outline && outline->decoder ); 142 FT_ASSERT( params->op == CF2_PathOpMoveTo ); 143 144 builder = &outline->decoder->builder; 145 146 /* note: two successive moves simply close the contour twice */ 147 ps_builder_close_contour( builder ); 148 builder->path_begun = 0; 149 } 150 151 152 static void cf2_builder_lineTo(CF2_OutlineCallbacks callbacks,const CF2_CallbackParams params)153 cf2_builder_lineTo( CF2_OutlineCallbacks callbacks, 154 const CF2_CallbackParams params ) 155 { 156 FT_Error error; 157 158 /* downcast the object pointer */ 159 CF2_Outline outline = (CF2_Outline)callbacks; 160 PS_Builder* builder; 161 162 163 FT_ASSERT( outline && outline->decoder ); 164 FT_ASSERT( params->op == CF2_PathOpLineTo ); 165 166 builder = &outline->decoder->builder; 167 168 if ( !builder->path_begun ) 169 { 170 /* record the move before the line; also check points and set */ 171 /* `path_begun' */ 172 error = ps_builder_start_point( builder, 173 params->pt0.x, 174 params->pt0.y ); 175 if ( error ) 176 { 177 if ( !*callbacks->error ) 178 *callbacks->error = error; 179 return; 180 } 181 } 182 183 /* `ps_builder_add_point1' includes a check_points call for one point */ 184 error = ps_builder_add_point1( builder, 185 params->pt1.x, 186 params->pt1.y ); 187 if ( error ) 188 { 189 if ( !*callbacks->error ) 190 *callbacks->error = error; 191 return; 192 } 193 } 194 195 196 static void cf2_builder_cubeTo(CF2_OutlineCallbacks callbacks,const CF2_CallbackParams params)197 cf2_builder_cubeTo( CF2_OutlineCallbacks callbacks, 198 const CF2_CallbackParams params ) 199 { 200 FT_Error error; 201 202 /* downcast the object pointer */ 203 CF2_Outline outline = (CF2_Outline)callbacks; 204 PS_Builder* builder; 205 206 207 FT_ASSERT( outline && outline->decoder ); 208 FT_ASSERT( params->op == CF2_PathOpCubeTo ); 209 210 builder = &outline->decoder->builder; 211 212 if ( !builder->path_begun ) 213 { 214 /* record the move before the line; also check points and set */ 215 /* `path_begun' */ 216 error = ps_builder_start_point( builder, 217 params->pt0.x, 218 params->pt0.y ); 219 if ( error ) 220 { 221 if ( !*callbacks->error ) 222 *callbacks->error = error; 223 return; 224 } 225 } 226 227 /* prepare room for 3 points: 2 off-curve, 1 on-curve */ 228 error = ps_builder_check_points( builder, 3 ); 229 if ( error ) 230 { 231 if ( !*callbacks->error ) 232 *callbacks->error = error; 233 return; 234 } 235 236 ps_builder_add_point( builder, 237 params->pt1.x, 238 params->pt1.y, 0 ); 239 ps_builder_add_point( builder, 240 params->pt2.x, 241 params->pt2.y, 0 ); 242 ps_builder_add_point( builder, 243 params->pt3.x, 244 params->pt3.y, 1 ); 245 } 246 247 248 static void cf2_outline_init(CF2_Outline outline,FT_Memory memory,FT_Error * error)249 cf2_outline_init( CF2_Outline outline, 250 FT_Memory memory, 251 FT_Error* error ) 252 { 253 FT_ZERO( outline ); 254 255 outline->root.memory = memory; 256 outline->root.error = error; 257 258 outline->root.moveTo = cf2_builder_moveTo; 259 outline->root.lineTo = cf2_builder_lineTo; 260 outline->root.cubeTo = cf2_builder_cubeTo; 261 } 262 263 264 /* get scaling and hint flag from GlyphSlot */ 265 static void cf2_getScaleAndHintFlag(PS_Decoder * decoder,CF2_Fixed * x_scale,CF2_Fixed * y_scale,FT_Bool * hinted,FT_Bool * scaled)266 cf2_getScaleAndHintFlag( PS_Decoder* decoder, 267 CF2_Fixed* x_scale, 268 CF2_Fixed* y_scale, 269 FT_Bool* hinted, 270 FT_Bool* scaled ) 271 { 272 FT_ASSERT( decoder && decoder->builder.glyph ); 273 274 /* note: FreeType scale includes a factor of 64 */ 275 *hinted = decoder->builder.glyph->hint; 276 *scaled = decoder->builder.glyph->scaled; 277 278 if ( *hinted ) 279 { 280 *x_scale = ADD_INT32( decoder->builder.glyph->x_scale, 32 ) / 64; 281 *y_scale = ADD_INT32( decoder->builder.glyph->y_scale, 32 ) / 64; 282 } 283 else 284 { 285 /* for unhinted outlines, `cff_slot_load' does the scaling, */ 286 /* thus render at `unity' scale */ 287 288 *x_scale = 0x0400; /* 1/64 as 16.16 */ 289 *y_scale = 0x0400; 290 } 291 } 292 293 294 /* get units per em from `FT_Face' */ 295 /* TODO: should handle font matrix concatenation? */ 296 static FT_UShort cf2_getUnitsPerEm(PS_Decoder * decoder)297 cf2_getUnitsPerEm( PS_Decoder* decoder ) 298 { 299 FT_ASSERT( decoder && decoder->builder.face ); 300 FT_ASSERT( decoder->builder.face->units_per_EM ); 301 302 return decoder->builder.face->units_per_EM; 303 } 304 305 306 /* Main entry point: Render one glyph. */ 307 FT_LOCAL_DEF( FT_Error ) cf2_decoder_parse_charstrings(PS_Decoder * decoder,FT_Byte * charstring_base,FT_ULong charstring_len)308 cf2_decoder_parse_charstrings( PS_Decoder* decoder, 309 FT_Byte* charstring_base, 310 FT_ULong charstring_len ) 311 { 312 FT_Memory memory; 313 FT_Error error = FT_Err_Ok; 314 CF2_Font font; 315 316 FT_Bool is_t1 = decoder->builder.is_t1; 317 318 319 FT_ASSERT( decoder && 320 ( is_t1 || decoder->cff ) ); 321 322 if ( is_t1 && !decoder->current_subfont ) 323 { 324 FT_ERROR(( "cf2_decoder_parse_charstrings (Type 1): " 325 "SubFont missing. Use `t1_make_subfont' first\n" )); 326 return FT_THROW( Invalid_Table ); 327 } 328 329 memory = decoder->builder.memory; 330 331 /* CF2 data is saved here across glyphs */ 332 font = (CF2_Font)decoder->cf2_instance->data; 333 334 /* on first glyph, allocate instance structure */ 335 if ( !decoder->cf2_instance->data ) 336 { 337 decoder->cf2_instance->finalizer = 338 (FT_Generic_Finalizer)cf2_free_instance; 339 340 if ( FT_ALLOC( decoder->cf2_instance->data, 341 sizeof ( CF2_FontRec ) ) ) 342 return FT_THROW( Out_Of_Memory ); 343 344 font = (CF2_Font)decoder->cf2_instance->data; 345 346 font->memory = memory; 347 348 if ( !is_t1 ) 349 font->cffload = (FT_Service_CFFLoad)decoder->cff->cffload; 350 351 /* initialize a client outline, to be shared by each glyph rendered */ 352 cf2_outline_init( &font->outline, font->memory, &font->error ); 353 } 354 355 /* save decoder; it is a stack variable and will be different on each */ 356 /* call */ 357 font->decoder = decoder; 358 font->outline.decoder = decoder; 359 360 { 361 /* build parameters for Adobe engine */ 362 363 PS_Builder* builder = &decoder->builder; 364 PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( builder->face ); 365 366 FT_Bool no_stem_darkening_driver = 367 driver->no_stem_darkening; 368 FT_Char no_stem_darkening_font = 369 builder->face->internal->no_stem_darkening; 370 371 /* local error */ 372 FT_Error error2 = FT_Err_Ok; 373 CF2_BufferRec buf; 374 CF2_Matrix transform; 375 CF2_F16Dot16 glyphWidth; 376 377 FT_Bool hinted; 378 FT_Bool scaled; 379 380 381 /* FreeType has already looked up the GID; convert to */ 382 /* `RegionBuffer', assuming that the input has been validated */ 383 FT_ASSERT( charstring_base + charstring_len >= charstring_base ); 384 385 FT_ZERO( &buf ); 386 buf.start = 387 buf.ptr = charstring_base; 388 buf.end = charstring_base + charstring_len; 389 390 FT_ZERO( &transform ); 391 392 cf2_getScaleAndHintFlag( decoder, 393 &transform.a, 394 &transform.d, 395 &hinted, 396 &scaled ); 397 398 if ( is_t1 ) 399 font->isCFF2 = FALSE; 400 else 401 { 402 /* copy isCFF2 boolean from TT_Face to CF2_Font */ 403 font->isCFF2 = ((TT_Face)builder->face)->is_cff2; 404 } 405 font->isT1 = is_t1; 406 407 font->renderingFlags = 0; 408 if ( hinted ) 409 font->renderingFlags |= CF2_FlagsHinted; 410 if ( scaled && ( !no_stem_darkening_font || 411 ( no_stem_darkening_font < 0 && 412 !no_stem_darkening_driver ) ) ) 413 font->renderingFlags |= CF2_FlagsDarkened; 414 415 font->darkenParams[0] = driver->darken_params[0]; 416 font->darkenParams[1] = driver->darken_params[1]; 417 font->darkenParams[2] = driver->darken_params[2]; 418 font->darkenParams[3] = driver->darken_params[3]; 419 font->darkenParams[4] = driver->darken_params[4]; 420 font->darkenParams[5] = driver->darken_params[5]; 421 font->darkenParams[6] = driver->darken_params[6]; 422 font->darkenParams[7] = driver->darken_params[7]; 423 424 /* now get an outline for this glyph; */ 425 /* also get units per em to validate scale */ 426 font->unitsPerEm = (CF2_Int)cf2_getUnitsPerEm( decoder ); 427 428 if ( scaled ) 429 { 430 error2 = cf2_checkTransform( &transform, font->unitsPerEm ); 431 if ( error2 ) 432 return error2; 433 } 434 435 error2 = cf2_getGlyphOutline( font, &buf, &transform, &glyphWidth ); 436 if ( error2 ) 437 return FT_ERR( Invalid_File_Format ); 438 439 cf2_setGlyphWidth( &font->outline, glyphWidth ); 440 441 return FT_Err_Ok; 442 } 443 } 444 445 446 /* get pointer to current FreeType subfont (based on current glyphID) */ 447 FT_LOCAL_DEF( CFF_SubFont ) cf2_getSubfont(PS_Decoder * decoder)448 cf2_getSubfont( PS_Decoder* decoder ) 449 { 450 FT_ASSERT( decoder && decoder->current_subfont ); 451 452 return decoder->current_subfont; 453 } 454 455 456 /* get pointer to VStore structure */ 457 FT_LOCAL_DEF( CFF_VStore ) cf2_getVStore(PS_Decoder * decoder)458 cf2_getVStore( PS_Decoder* decoder ) 459 { 460 FT_ASSERT( decoder && decoder->cff ); 461 462 return &decoder->cff->vstore; 463 } 464 465 466 /* get maxstack value from CFF2 Top DICT */ 467 FT_LOCAL_DEF( FT_UInt ) cf2_getMaxstack(PS_Decoder * decoder)468 cf2_getMaxstack( PS_Decoder* decoder ) 469 { 470 FT_ASSERT( decoder && decoder->cff ); 471 472 return decoder->cff->top_font.font_dict.maxstack; 473 } 474 475 476 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 477 /* Get normalized design vector for current render request; */ 478 /* return pointer and length. */ 479 /* */ 480 /* Note: Uses FT_Fixed not CF2_Fixed for the vector. */ 481 FT_LOCAL_DEF( FT_Error ) cf2_getNormalizedVector(PS_Decoder * decoder,CF2_UInt * len,FT_Fixed ** vec)482 cf2_getNormalizedVector( PS_Decoder* decoder, 483 CF2_UInt *len, 484 FT_Fixed* *vec ) 485 { 486 TT_Face face; 487 FT_Service_MultiMasters mm; 488 489 490 FT_ASSERT( decoder && decoder->builder.face ); 491 FT_ASSERT( vec && len ); 492 FT_ASSERT( !decoder->builder.is_t1 ); 493 494 face = (TT_Face)decoder->builder.face; 495 mm = (FT_Service_MultiMasters)face->mm; 496 497 return mm->get_var_blend( FT_FACE( face ), len, NULL, vec, NULL ); 498 } 499 #endif 500 501 502 /* get `y_ppem' from `CFF_Size' */ 503 FT_LOCAL_DEF( CF2_Fixed ) cf2_getPpemY(PS_Decoder * decoder)504 cf2_getPpemY( PS_Decoder* decoder ) 505 { 506 FT_ASSERT( decoder && 507 decoder->builder.face && 508 decoder->builder.face->size ); 509 510 /* 511 * Note that `y_ppem' can be zero if there wasn't a call to 512 * `FT_Set_Char_Size' or something similar. However, this isn't a 513 * problem since we come to this place in the code only if 514 * FT_LOAD_NO_SCALE is set (the other case gets caught by 515 * `cf2_checkTransform'). The ppem value is needed to compute the stem 516 * darkening, which is disabled for getting the unscaled outline. 517 * 518 */ 519 return cf2_intToFixed( 520 decoder->builder.face->size->metrics.y_ppem ); 521 } 522 523 524 /* get standard stem widths for the current subfont; */ 525 /* FreeType stores these as integer font units */ 526 /* (note: variable names seem swapped) */ 527 FT_LOCAL_DEF( CF2_Fixed ) cf2_getStdVW(PS_Decoder * decoder)528 cf2_getStdVW( PS_Decoder* decoder ) 529 { 530 FT_ASSERT( decoder && decoder->current_subfont ); 531 532 return cf2_intToFixed( 533 decoder->current_subfont->private_dict.standard_height ); 534 } 535 536 537 FT_LOCAL_DEF( CF2_Fixed ) cf2_getStdHW(PS_Decoder * decoder)538 cf2_getStdHW( PS_Decoder* decoder ) 539 { 540 FT_ASSERT( decoder && decoder->current_subfont ); 541 542 return cf2_intToFixed( 543 decoder->current_subfont->private_dict.standard_width ); 544 } 545 546 547 /* note: FreeType stores 1000 times the actual value for `BlueScale' */ 548 FT_LOCAL_DEF( void ) cf2_getBlueMetrics(PS_Decoder * decoder,CF2_Fixed * blueScale,CF2_Fixed * blueShift,CF2_Fixed * blueFuzz)549 cf2_getBlueMetrics( PS_Decoder* decoder, 550 CF2_Fixed* blueScale, 551 CF2_Fixed* blueShift, 552 CF2_Fixed* blueFuzz ) 553 { 554 FT_ASSERT( decoder && decoder->current_subfont ); 555 556 *blueScale = FT_DivFix( 557 decoder->current_subfont->private_dict.blue_scale, 558 cf2_intToFixed( 1000 ) ); 559 *blueShift = cf2_intToFixed( 560 decoder->current_subfont->private_dict.blue_shift ); 561 *blueFuzz = cf2_intToFixed( 562 decoder->current_subfont->private_dict.blue_fuzz ); 563 } 564 565 566 /* get blue values counts and arrays; the FreeType parser has validated */ 567 /* the counts and verified that each is an even number */ 568 FT_LOCAL_DEF( void ) cf2_getBlueValues(PS_Decoder * decoder,size_t * count,FT_Pos ** data)569 cf2_getBlueValues( PS_Decoder* decoder, 570 size_t* count, 571 FT_Pos* *data ) 572 { 573 FT_ASSERT( decoder && decoder->current_subfont ); 574 575 *count = decoder->current_subfont->private_dict.num_blue_values; 576 *data = (FT_Pos*) 577 &decoder->current_subfont->private_dict.blue_values; 578 } 579 580 581 FT_LOCAL_DEF( void ) cf2_getOtherBlues(PS_Decoder * decoder,size_t * count,FT_Pos ** data)582 cf2_getOtherBlues( PS_Decoder* decoder, 583 size_t* count, 584 FT_Pos* *data ) 585 { 586 FT_ASSERT( decoder && decoder->current_subfont ); 587 588 *count = decoder->current_subfont->private_dict.num_other_blues; 589 *data = (FT_Pos*) 590 &decoder->current_subfont->private_dict.other_blues; 591 } 592 593 594 FT_LOCAL_DEF( void ) cf2_getFamilyBlues(PS_Decoder * decoder,size_t * count,FT_Pos ** data)595 cf2_getFamilyBlues( PS_Decoder* decoder, 596 size_t* count, 597 FT_Pos* *data ) 598 { 599 FT_ASSERT( decoder && decoder->current_subfont ); 600 601 *count = decoder->current_subfont->private_dict.num_family_blues; 602 *data = (FT_Pos*) 603 &decoder->current_subfont->private_dict.family_blues; 604 } 605 606 607 FT_LOCAL_DEF( void ) cf2_getFamilyOtherBlues(PS_Decoder * decoder,size_t * count,FT_Pos ** data)608 cf2_getFamilyOtherBlues( PS_Decoder* decoder, 609 size_t* count, 610 FT_Pos* *data ) 611 { 612 FT_ASSERT( decoder && decoder->current_subfont ); 613 614 *count = decoder->current_subfont->private_dict.num_family_other_blues; 615 *data = (FT_Pos*) 616 &decoder->current_subfont->private_dict.family_other_blues; 617 } 618 619 620 FT_LOCAL_DEF( CF2_Int ) cf2_getLanguageGroup(PS_Decoder * decoder)621 cf2_getLanguageGroup( PS_Decoder* decoder ) 622 { 623 FT_ASSERT( decoder && decoder->current_subfont ); 624 625 return decoder->current_subfont->private_dict.language_group; 626 } 627 628 629 /* convert unbiased subroutine index to `CF2_Buffer' and */ 630 /* return 0 on success */ 631 FT_LOCAL_DEF( CF2_Int ) cf2_initGlobalRegionBuffer(PS_Decoder * decoder,CF2_Int subrNum,CF2_Buffer buf)632 cf2_initGlobalRegionBuffer( PS_Decoder* decoder, 633 CF2_Int subrNum, 634 CF2_Buffer buf ) 635 { 636 CF2_UInt idx; 637 638 639 FT_ASSERT( decoder ); 640 641 FT_ZERO( buf ); 642 643 idx = (CF2_UInt)( subrNum + decoder->globals_bias ); 644 if ( idx >= decoder->num_globals ) 645 return TRUE; /* error */ 646 647 FT_ASSERT( decoder->globals ); 648 649 buf->start = 650 buf->ptr = decoder->globals[idx]; 651 buf->end = decoder->globals[idx + 1]; 652 653 return FALSE; /* success */ 654 } 655 656 657 /* convert AdobeStandardEncoding code to CF2_Buffer; */ 658 /* used for seac component */ 659 FT_LOCAL_DEF( FT_Error ) cf2_getSeacComponent(PS_Decoder * decoder,CF2_Int code,CF2_Buffer buf)660 cf2_getSeacComponent( PS_Decoder* decoder, 661 CF2_Int code, 662 CF2_Buffer buf ) 663 { 664 CF2_Int gid; 665 FT_Byte* charstring; 666 FT_ULong len; 667 FT_Error error; 668 669 670 FT_ASSERT( decoder ); 671 FT_ASSERT( !decoder->builder.is_t1 ); 672 673 FT_ZERO( buf ); 674 675 #ifdef FT_CONFIG_OPTION_INCREMENTAL 676 /* Incremental fonts don't necessarily have valid charsets. */ 677 /* They use the character code, not the glyph index, in this case. */ 678 if ( decoder->builder.face->internal->incremental_interface ) 679 gid = code; 680 else 681 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 682 { 683 gid = cff_lookup_glyph_by_stdcharcode( decoder->cff, code ); 684 if ( gid < 0 ) 685 return FT_THROW( Invalid_Glyph_Format ); 686 } 687 688 error = decoder->get_glyph_callback( (TT_Face)decoder->builder.face, 689 (CF2_UInt)gid, 690 &charstring, 691 &len ); 692 /* TODO: for now, just pass the FreeType error through */ 693 if ( error ) 694 return error; 695 696 /* assume input has been validated */ 697 FT_ASSERT( charstring + len >= charstring ); 698 699 buf->start = charstring; 700 buf->end = charstring + len; 701 buf->ptr = buf->start; 702 703 return FT_Err_Ok; 704 } 705 706 707 FT_LOCAL_DEF( void ) cf2_freeSeacComponent(PS_Decoder * decoder,CF2_Buffer buf)708 cf2_freeSeacComponent( PS_Decoder* decoder, 709 CF2_Buffer buf ) 710 { 711 FT_ASSERT( decoder ); 712 FT_ASSERT( !decoder->builder.is_t1 ); 713 714 decoder->free_glyph_callback( (TT_Face)decoder->builder.face, 715 (FT_Byte**)&buf->start, 716 (FT_ULong)( buf->end - buf->start ) ); 717 } 718 719 720 FT_LOCAL_DEF( FT_Error ) cf2_getT1SeacComponent(PS_Decoder * decoder,FT_UInt glyph_index,CF2_Buffer buf)721 cf2_getT1SeacComponent( PS_Decoder* decoder, 722 FT_UInt glyph_index, 723 CF2_Buffer buf ) 724 { 725 FT_Data glyph_data; 726 FT_Error error = FT_Err_Ok; 727 T1_Face face = (T1_Face)decoder->builder.face; 728 T1_Font type1 = &face->type1; 729 730 #ifdef FT_CONFIG_OPTION_INCREMENTAL 731 FT_Incremental_InterfaceRec *inc = 732 face->root.internal->incremental_interface; 733 734 735 /* For incremental fonts get the character data using the */ 736 /* callback function. */ 737 if ( inc ) 738 error = inc->funcs->get_glyph_data( inc->object, 739 glyph_index, &glyph_data ); 740 else 741 #endif 742 /* For ordinary fonts get the character data stored in the face record. */ 743 { 744 glyph_data.pointer = type1->charstrings[glyph_index]; 745 glyph_data.length = (FT_Int)type1->charstrings_len[glyph_index]; 746 } 747 748 if ( !error ) 749 { 750 FT_Byte* charstring_base = (FT_Byte*)glyph_data.pointer; 751 FT_ULong charstring_len = (FT_ULong)glyph_data.length; 752 753 754 FT_ASSERT( charstring_base + charstring_len >= charstring_base ); 755 756 FT_ZERO( buf ); 757 buf->start = 758 buf->ptr = charstring_base; 759 buf->end = charstring_base + charstring_len; 760 } 761 762 return error; 763 } 764 765 766 FT_LOCAL_DEF( void ) cf2_freeT1SeacComponent(PS_Decoder * decoder,CF2_Buffer buf)767 cf2_freeT1SeacComponent( PS_Decoder* decoder, 768 CF2_Buffer buf ) 769 { 770 #ifdef FT_CONFIG_OPTION_INCREMENTAL 771 772 T1_Face face; 773 FT_Data data; 774 775 776 FT_ASSERT( decoder ); 777 778 face = (T1_Face)decoder->builder.face; 779 780 data.pointer = buf->start; 781 data.length = (FT_Int)( buf->end - buf->start ); 782 783 if ( face->root.internal->incremental_interface ) 784 face->root.internal->incremental_interface->funcs->free_glyph_data( 785 face->root.internal->incremental_interface->object, 786 &data ); 787 788 #else /* !FT_CONFIG_OPTION_INCREMENTAL */ 789 790 FT_UNUSED( decoder ); 791 FT_UNUSED( buf ); 792 793 #endif /* !FT_CONFIG_OPTION_INCREMENTAL */ 794 } 795 796 797 FT_LOCAL_DEF( CF2_Int ) cf2_initLocalRegionBuffer(PS_Decoder * decoder,CF2_Int subrNum,CF2_Buffer buf)798 cf2_initLocalRegionBuffer( PS_Decoder* decoder, 799 CF2_Int subrNum, 800 CF2_Buffer buf ) 801 { 802 CF2_UInt idx; 803 804 805 FT_ASSERT( decoder ); 806 807 FT_ZERO( buf ); 808 809 idx = (CF2_UInt)( subrNum + decoder->locals_bias ); 810 if ( idx >= decoder->num_locals ) 811 return TRUE; /* error */ 812 813 FT_ASSERT( decoder->locals ); 814 815 buf->start = decoder->locals[idx]; 816 817 if ( decoder->builder.is_t1 ) 818 { 819 /* The Type 1 driver stores subroutines without the seed bytes. */ 820 /* The CID driver stores subroutines with seed bytes. This */ 821 /* case is taken care of when decoder->subrs_len == 0. */ 822 if ( decoder->locals_len ) 823 buf->end = buf->start + decoder->locals_len[idx]; 824 else 825 { 826 /* We are using subroutines from a CID font. We must adjust */ 827 /* for the seed bytes. */ 828 buf->start += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 ); 829 buf->end = decoder->locals[idx + 1]; 830 } 831 832 if ( !buf->start ) 833 { 834 FT_ERROR(( "cf2_initLocalRegionBuffer (Type 1 mode):" 835 " invoking empty subrs\n" )); 836 } 837 } 838 else 839 { 840 buf->end = decoder->locals[idx + 1]; 841 } 842 843 buf->ptr = buf->start; 844 845 return FALSE; /* success */ 846 } 847 848 849 FT_LOCAL_DEF( CF2_Fixed ) cf2_getDefaultWidthX(PS_Decoder * decoder)850 cf2_getDefaultWidthX( PS_Decoder* decoder ) 851 { 852 FT_ASSERT( decoder && decoder->current_subfont ); 853 854 return cf2_intToFixed( 855 decoder->current_subfont->private_dict.default_width ); 856 } 857 858 859 FT_LOCAL_DEF( CF2_Fixed ) cf2_getNominalWidthX(PS_Decoder * decoder)860 cf2_getNominalWidthX( PS_Decoder* decoder ) 861 { 862 FT_ASSERT( decoder && decoder->current_subfont ); 863 864 return cf2_intToFixed( 865 decoder->current_subfont->private_dict.nominal_width ); 866 } 867 868 869 FT_LOCAL_DEF( void ) cf2_outline_reset(CF2_Outline outline)870 cf2_outline_reset( CF2_Outline outline ) 871 { 872 PS_Decoder* decoder = outline->decoder; 873 874 875 FT_ASSERT( decoder ); 876 877 outline->root.windingMomentum = 0; 878 879 FT_GlyphLoader_Rewind( decoder->builder.loader ); 880 } 881 882 883 FT_LOCAL_DEF( void ) cf2_outline_close(CF2_Outline outline)884 cf2_outline_close( CF2_Outline outline ) 885 { 886 PS_Decoder* decoder = outline->decoder; 887 888 889 FT_ASSERT( decoder ); 890 891 ps_builder_close_contour( &decoder->builder ); 892 893 FT_GlyphLoader_Add( decoder->builder.loader ); 894 } 895 896 897 /* END */ 898