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