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