1 /***************************************************************************/ 2 /* */ 3 /* cf2ft.c */ 4 /* */ 5 /* FreeType Glue Component to Adobe's Interpreter (body). */ 6 /* */ 7 /* Copyright 2013 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 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 FT_ASSERT( transform->a > 0 && transform->d > 0 ); 65 FT_ASSERT( transform->b == 0 && transform->c == 0 ); 66 FT_ASSERT( transform->tx == 0 && transform->ty == 0 ); 67 68 if ( unitsPerEm > 0x7FFF ) 69 return FT_THROW( Glyph_Too_Big ); 70 71 maxScale = FT_DivFix( CF2_MAX_SIZE, cf2_intToFixed( unitsPerEm ) ); 72 73 if ( transform->a > maxScale || transform->d > maxScale ) 74 return FT_THROW( Glyph_Too_Big ); 75 76 return FT_Err_Ok; 77 } 78 79 80 static void 81 cf2_setGlyphWidth( CF2_Outline outline, 82 CF2_Fixed width ) 83 { 84 CFF_Decoder* decoder = outline->decoder; 85 86 87 FT_ASSERT( decoder ); 88 89 decoder->glyph_width = cf2_fixedToInt( width ); 90 } 91 92 93 /* Clean up font instance. */ 94 static void 95 cf2_free_instance( void* ptr ) 96 { 97 CF2_Font font = (CF2_Font)ptr; 98 99 100 if ( font ) 101 { 102 FT_Memory memory = font->memory; 103 104 105 (void)memory; 106 } 107 } 108 109 110 /********************************************/ 111 /* */ 112 /* functions for handling client outline; */ 113 /* FreeType uses coordinates in 26.6 format */ 114 /* */ 115 /********************************************/ 116 117 static void 118 cf2_builder_moveTo( CF2_OutlineCallbacks callbacks, 119 const CF2_CallbackParams params ) 120 { 121 /* downcast the object pointer */ 122 CF2_Outline outline = (CF2_Outline)callbacks; 123 CFF_Builder* builder; 124 125 (void)params; /* only used in debug mode */ 126 127 128 FT_ASSERT( outline && outline->decoder ); 129 FT_ASSERT( params->op == CF2_PathOpMoveTo ); 130 131 builder = &outline->decoder->builder; 132 133 /* note: two successive moves simply close the contour twice */ 134 cff_builder_close_contour( builder ); 135 builder->path_begun = 0; 136 } 137 138 139 static void 140 cf2_builder_lineTo( CF2_OutlineCallbacks callbacks, 141 const CF2_CallbackParams params ) 142 { 143 /* downcast the object pointer */ 144 CF2_Outline outline = (CF2_Outline)callbacks; 145 CFF_Builder* builder; 146 147 148 FT_ASSERT( outline && outline->decoder ); 149 FT_ASSERT( params->op == CF2_PathOpLineTo ); 150 151 builder = &outline->decoder->builder; 152 153 if ( !builder->path_begun ) 154 { 155 /* record the move before the line; also check points and set */ 156 /* `path_begun' */ 157 cff_builder_start_point( builder, 158 params->pt0.x, 159 params->pt0.y ); 160 } 161 162 /* `cff_builder_add_point1' includes a check_points call for one point */ 163 cff_builder_add_point1( builder, 164 params->pt1.x, 165 params->pt1.y ); 166 } 167 168 169 static void 170 cf2_builder_cubeTo( CF2_OutlineCallbacks callbacks, 171 const CF2_CallbackParams params ) 172 { 173 /* downcast the object pointer */ 174 CF2_Outline outline = (CF2_Outline)callbacks; 175 CFF_Builder* builder; 176 177 178 FT_ASSERT( outline && outline->decoder ); 179 FT_ASSERT( params->op == CF2_PathOpCubeTo ); 180 181 builder = &outline->decoder->builder; 182 183 if ( !builder->path_begun ) 184 { 185 /* record the move before the line; also check points and set */ 186 /* `path_begun' */ 187 cff_builder_start_point( builder, 188 params->pt0.x, 189 params->pt0.y ); 190 } 191 192 /* prepare room for 3 points: 2 off-curve, 1 on-curve */ 193 cff_check_points( builder, 3 ); 194 195 cff_builder_add_point( builder, 196 params->pt1.x, 197 params->pt1.y, 0 ); 198 cff_builder_add_point( builder, 199 params->pt2.x, 200 params->pt2.y, 0 ); 201 cff_builder_add_point( builder, 202 params->pt3.x, 203 params->pt3.y, 1 ); 204 } 205 206 207 static void 208 cf2_outline_init( CF2_Outline outline, 209 FT_Memory memory, 210 FT_Error* error ) 211 { 212 FT_MEM_ZERO( outline, sizeof ( CF2_OutlineRec ) ); 213 214 outline->root.memory = memory; 215 outline->root.error = error; 216 217 outline->root.moveTo = cf2_builder_moveTo; 218 outline->root.lineTo = cf2_builder_lineTo; 219 outline->root.cubeTo = cf2_builder_cubeTo; 220 } 221 222 223 /* get scaling and hint flag from GlyphSlot */ 224 static void 225 cf2_getScaleAndHintFlag( CFF_Decoder* decoder, 226 CF2_Fixed* x_scale, 227 CF2_Fixed* y_scale, 228 FT_Bool* hinted, 229 FT_Bool* scaled ) 230 { 231 FT_ASSERT( decoder && decoder->builder.glyph ); 232 233 /* note: FreeType scale includes a factor of 64 */ 234 *hinted = decoder->builder.glyph->hint; 235 *scaled = decoder->builder.glyph->scaled; 236 237 if ( *hinted ) 238 { 239 *x_scale = FT_DivFix( decoder->builder.glyph->x_scale, 240 cf2_intToFixed( 64 ) ); 241 *y_scale = FT_DivFix( decoder->builder.glyph->y_scale, 242 cf2_intToFixed( 64 ) ); 243 } 244 else 245 { 246 /* for unhinted outlines, `cff_slot_load' does the scaling, */ 247 /* thus render at `unity' scale */ 248 249 *x_scale = 0x0400; /* 1/64 as 16.16 */ 250 *y_scale = 0x0400; 251 } 252 } 253 254 255 /* get units per em from `FT_Face' */ 256 /* TODO: should handle font matrix concatenation? */ 257 static FT_UShort 258 cf2_getUnitsPerEm( CFF_Decoder* decoder ) 259 { 260 FT_ASSERT( decoder && decoder->builder.face ); 261 FT_ASSERT( decoder->builder.face->root.units_per_EM ); 262 263 return decoder->builder.face->root.units_per_EM; 264 } 265 266 267 /* Main entry point: Render one glyph. */ 268 FT_LOCAL_DEF( FT_Error ) 269 cf2_decoder_parse_charstrings( CFF_Decoder* decoder, 270 FT_Byte* charstring_base, 271 FT_ULong charstring_len ) 272 { 273 FT_Memory memory; 274 FT_Error error = FT_Err_Ok; 275 CF2_Font font; 276 277 278 FT_ASSERT( decoder && decoder->cff ); 279 280 memory = decoder->builder.memory; 281 282 /* CF2 data is saved here across glyphs */ 283 font = (CF2_Font)decoder->cff->cf2_instance.data; 284 285 /* on first glyph, allocate instance structure */ 286 if ( decoder->cff->cf2_instance.data == NULL ) 287 { 288 decoder->cff->cf2_instance.finalizer = 289 (FT_Generic_Finalizer)cf2_free_instance; 290 291 if ( FT_ALLOC( decoder->cff->cf2_instance.data, 292 sizeof ( CF2_FontRec ) ) ) 293 return FT_THROW( Out_Of_Memory ); 294 295 font = (CF2_Font)decoder->cff->cf2_instance.data; 296 297 font->memory = memory; 298 299 /* initialize a client outline, to be shared by each glyph rendered */ 300 cf2_outline_init( &font->outline, font->memory, &font->error ); 301 } 302 303 /* save decoder; it is a stack variable and will be different on each */ 304 /* call */ 305 font->decoder = decoder; 306 font->outline.decoder = decoder; 307 308 { 309 /* build parameters for Adobe engine */ 310 311 CFF_Builder* builder = &decoder->builder; 312 CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( builder->face ); 313 314 /* local error */ 315 FT_Error error2 = FT_Err_Ok; 316 CF2_BufferRec buf; 317 CF2_Matrix transform; 318 CF2_F16Dot16 glyphWidth; 319 320 FT_Bool hinted; 321 FT_Bool scaled; 322 323 324 /* FreeType has already looked up the GID; convert to */ 325 /* `RegionBuffer', assuming that the input has been validated */ 326 FT_ASSERT( charstring_base + charstring_len >= charstring_base ); 327 328 FT_ZERO( &buf ); 329 buf.start = 330 buf.ptr = charstring_base; 331 buf.end = charstring_base + charstring_len; 332 333 FT_ZERO( &transform ); 334 335 cf2_getScaleAndHintFlag( decoder, 336 &transform.a, 337 &transform.d, 338 &hinted, 339 &scaled ); 340 341 font->renderingFlags = 0; 342 if ( hinted ) 343 font->renderingFlags |= CF2_FlagsHinted; 344 if ( scaled && !driver->no_stem_darkening ) 345 font->renderingFlags |= CF2_FlagsDarkened; 346 347 /* now get an outline for this glyph; */ 348 /* also get units per em to validate scale */ 349 font->unitsPerEm = (CF2_Int)cf2_getUnitsPerEm( decoder ); 350 351 error2 = cf2_checkTransform( &transform, font->unitsPerEm ); 352 if ( error2 ) 353 return error2; 354 355 error2 = cf2_getGlyphOutline( font, &buf, &transform, &glyphWidth ); 356 if ( error2 ) 357 return FT_ERR( Invalid_File_Format ); 358 359 cf2_setGlyphWidth( &font->outline, glyphWidth ); 360 361 return FT_Err_Ok; 362 } 363 } 364 365 366 /* get pointer to current FreeType subfont (based on current glyphID) */ 367 FT_LOCAL_DEF( CFF_SubFont ) 368 cf2_getSubfont( CFF_Decoder* decoder ) 369 { 370 FT_ASSERT( decoder && decoder->current_subfont ); 371 372 return decoder->current_subfont; 373 } 374 375 376 /* get `y_ppem' from `CFF_Size' */ 377 FT_LOCAL_DEF( CF2_Fixed ) 378 cf2_getPpemY( CFF_Decoder* decoder ) 379 { 380 FT_ASSERT( decoder && 381 decoder->builder.face && 382 decoder->builder.face->root.size ); 383 FT_ASSERT( decoder->builder.face->root.size->metrics.y_ppem ); 384 385 return cf2_intToFixed( 386 decoder->builder.face->root.size->metrics.y_ppem ); 387 } 388 389 390 /* get standard stem widths for the current subfont; */ 391 /* FreeType stores these as integer font units */ 392 /* (note: variable names seem swapped) */ 393 FT_LOCAL_DEF( CF2_Fixed ) 394 cf2_getStdVW( CFF_Decoder* decoder ) 395 { 396 FT_ASSERT( decoder && decoder->current_subfont ); 397 398 return cf2_intToFixed( 399 decoder->current_subfont->private_dict.standard_height ); 400 } 401 402 403 FT_LOCAL_DEF( CF2_Fixed ) 404 cf2_getStdHW( CFF_Decoder* decoder ) 405 { 406 FT_ASSERT( decoder && decoder->current_subfont ); 407 408 return cf2_intToFixed( 409 decoder->current_subfont->private_dict.standard_width ); 410 } 411 412 413 /* note: FreeType stores 1000 times the actual value for `BlueScale' */ 414 FT_LOCAL_DEF( void ) 415 cf2_getBlueMetrics( CFF_Decoder* decoder, 416 CF2_Fixed* blueScale, 417 CF2_Fixed* blueShift, 418 CF2_Fixed* blueFuzz ) 419 { 420 FT_ASSERT( decoder && decoder->current_subfont ); 421 422 *blueScale = FT_DivFix( 423 decoder->current_subfont->private_dict.blue_scale, 424 cf2_intToFixed( 1000 ) ); 425 *blueShift = cf2_intToFixed( 426 decoder->current_subfont->private_dict.blue_shift ); 427 *blueFuzz = cf2_intToFixed( 428 decoder->current_subfont->private_dict.blue_fuzz ); 429 } 430 431 432 /* get blue values counts and arrays; the FreeType parser has validated */ 433 /* the counts and verified that each is an even number */ 434 FT_LOCAL_DEF( void ) 435 cf2_getBlueValues( CFF_Decoder* decoder, 436 size_t* count, 437 FT_Pos* *data ) 438 { 439 FT_ASSERT( decoder && decoder->current_subfont ); 440 441 *count = decoder->current_subfont->private_dict.num_blue_values; 442 *data = (FT_Pos*) 443 &decoder->current_subfont->private_dict.blue_values; 444 } 445 446 447 FT_LOCAL_DEF( void ) 448 cf2_getOtherBlues( CFF_Decoder* decoder, 449 size_t* count, 450 FT_Pos* *data ) 451 { 452 FT_ASSERT( decoder && decoder->current_subfont ); 453 454 *count = decoder->current_subfont->private_dict.num_other_blues; 455 *data = (FT_Pos*) 456 &decoder->current_subfont->private_dict.other_blues; 457 } 458 459 460 FT_LOCAL_DEF( void ) 461 cf2_getFamilyBlues( CFF_Decoder* decoder, 462 size_t* count, 463 FT_Pos* *data ) 464 { 465 FT_ASSERT( decoder && decoder->current_subfont ); 466 467 *count = decoder->current_subfont->private_dict.num_family_blues; 468 *data = (FT_Pos*) 469 &decoder->current_subfont->private_dict.family_blues; 470 } 471 472 473 FT_LOCAL_DEF( void ) 474 cf2_getFamilyOtherBlues( CFF_Decoder* decoder, 475 size_t* count, 476 FT_Pos* *data ) 477 { 478 FT_ASSERT( decoder && decoder->current_subfont ); 479 480 *count = decoder->current_subfont->private_dict.num_family_other_blues; 481 *data = (FT_Pos*) 482 &decoder->current_subfont->private_dict.family_other_blues; 483 } 484 485 486 FT_LOCAL_DEF( CF2_Int ) 487 cf2_getLanguageGroup( CFF_Decoder* decoder ) 488 { 489 FT_ASSERT( decoder && decoder->current_subfont ); 490 491 return decoder->current_subfont->private_dict.language_group; 492 } 493 494 495 /* convert unbiased subroutine index to `CF2_Buffer' and */ 496 /* return 0 on success */ 497 FT_LOCAL_DEF( CF2_Int ) 498 cf2_initGlobalRegionBuffer( CFF_Decoder* decoder, 499 CF2_UInt idx, 500 CF2_Buffer buf ) 501 { 502 FT_ASSERT( decoder && decoder->globals ); 503 504 FT_ZERO( buf ); 505 506 idx += decoder->globals_bias; 507 if ( idx >= decoder->num_globals ) 508 return TRUE; /* error */ 509 510 buf->start = 511 buf->ptr = decoder->globals[idx]; 512 buf->end = decoder->globals[idx + 1]; 513 514 return FALSE; /* success */ 515 } 516 517 518 /* convert AdobeStandardEncoding code to CF2_Buffer; */ 519 /* used for seac component */ 520 FT_LOCAL_DEF( FT_Error ) 521 cf2_getSeacComponent( CFF_Decoder* decoder, 522 CF2_UInt code, 523 CF2_Buffer buf ) 524 { 525 CF2_Int gid; 526 FT_Byte* charstring; 527 FT_ULong len; 528 FT_Error error; 529 530 531 FT_ASSERT( decoder ); 532 533 FT_ZERO( buf ); 534 535 gid = cff_lookup_glyph_by_stdcharcode( decoder->cff, code ); 536 if ( gid < 0 ) 537 return FT_THROW( Invalid_Glyph_Format ); 538 539 error = cff_get_glyph_data( decoder->builder.face, 540 gid, 541 &charstring, 542 &len ); 543 /* TODO: for now, just pass the FreeType error through */ 544 if ( error ) 545 return error; 546 547 /* assume input has been validated */ 548 FT_ASSERT( charstring + len >= charstring ); 549 550 buf->start = charstring; 551 buf->end = charstring + len; 552 buf->ptr = buf->start; 553 554 return FT_Err_Ok; 555 } 556 557 558 FT_LOCAL_DEF( void ) 559 cf2_freeSeacComponent( CFF_Decoder* decoder, 560 CF2_Buffer buf ) 561 { 562 FT_ASSERT( decoder ); 563 564 cff_free_glyph_data( decoder->builder.face, 565 (FT_Byte**)&buf->start, 566 (FT_ULong)( buf->end - buf->start ) ); 567 } 568 569 570 FT_LOCAL_DEF( CF2_Int ) 571 cf2_initLocalRegionBuffer( CFF_Decoder* decoder, 572 CF2_UInt idx, 573 CF2_Buffer buf ) 574 { 575 FT_ASSERT( decoder && decoder->locals ); 576 577 FT_ZERO( buf ); 578 579 idx += decoder->locals_bias; 580 if ( idx >= decoder->num_locals ) 581 return TRUE; /* error */ 582 583 buf->start = 584 buf->ptr = decoder->locals[idx]; 585 buf->end = decoder->locals[idx + 1]; 586 587 return FALSE; /* success */ 588 } 589 590 591 FT_LOCAL_DEF( CF2_Fixed ) 592 cf2_getDefaultWidthX( CFF_Decoder* decoder ) 593 { 594 FT_ASSERT( decoder && decoder->current_subfont ); 595 596 return cf2_intToFixed( 597 decoder->current_subfont->private_dict.default_width ); 598 } 599 600 601 FT_LOCAL_DEF( CF2_Fixed ) 602 cf2_getNominalWidthX( CFF_Decoder* decoder ) 603 { 604 FT_ASSERT( decoder && decoder->current_subfont ); 605 606 return cf2_intToFixed( 607 decoder->current_subfont->private_dict.nominal_width ); 608 } 609 610 611 FT_LOCAL_DEF( void ) 612 cf2_outline_reset( CF2_Outline outline ) 613 { 614 CFF_Decoder* decoder = outline->decoder; 615 616 617 FT_ASSERT( decoder ); 618 619 outline->root.windingMomentum = 0; 620 621 FT_GlyphLoader_Rewind( decoder->builder.loader ); 622 } 623 624 625 FT_LOCAL_DEF( void ) 626 cf2_outline_close( CF2_Outline outline ) 627 { 628 CFF_Decoder* decoder = outline->decoder; 629 630 631 FT_ASSERT( decoder ); 632 633 cff_builder_close_contour( &decoder->builder ); 634 635 FT_GlyphLoader_Add( decoder->builder.loader ); 636 } 637 638 639 /* END */ 640