1 /***************************************************************************/ 2 /* */ 3 /* cffdrivr.c */ 4 /* */ 5 /* OpenType font driver implementation (body). */ 6 /* */ 7 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 by */ 8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9 /* */ 10 /* This file is part of the FreeType project, and may only be used, */ 11 /* modified, and distributed under the terms of the FreeType project */ 12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13 /* this file you indicate that you have read the license and */ 14 /* understand and accept it fully. */ 15 /* */ 16 /***************************************************************************/ 17 18 19 #include <ft2build.h> 20 #include FT_FREETYPE_H 21 #include FT_INTERNAL_DEBUG_H 22 #include FT_INTERNAL_STREAM_H 23 #include FT_INTERNAL_SFNT_H 24 #include FT_TRUETYPE_IDS_H 25 #include FT_SERVICE_CID_H 26 #include FT_SERVICE_POSTSCRIPT_CMAPS_H 27 #include FT_SERVICE_POSTSCRIPT_INFO_H 28 #include FT_SERVICE_POSTSCRIPT_NAME_H 29 #include FT_SERVICE_TT_CMAP_H 30 31 #include "cffdrivr.h" 32 #include "cffgload.h" 33 #include "cffload.h" 34 #include "cffcmap.h" 35 36 #include "cfferrs.h" 37 38 #include FT_SERVICE_XFREE86_NAME_H 39 #include FT_SERVICE_GLYPH_DICT_H 40 41 42 /*************************************************************************/ 43 /* */ 44 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 45 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 46 /* messages during execution. */ 47 /* */ 48 #undef FT_COMPONENT 49 #define FT_COMPONENT trace_cffdriver 50 51 52 /*************************************************************************/ 53 /*************************************************************************/ 54 /*************************************************************************/ 55 /**** ****/ 56 /**** ****/ 57 /**** F A C E S ****/ 58 /**** ****/ 59 /**** ****/ 60 /*************************************************************************/ 61 /*************************************************************************/ 62 /*************************************************************************/ 63 64 65 #undef PAIR_TAG 66 #define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \ 67 (FT_ULong)right ) 68 69 70 /*************************************************************************/ 71 /* */ 72 /* <Function> */ 73 /* cff_get_kerning */ 74 /* */ 75 /* <Description> */ 76 /* A driver method used to return the kerning vector between two */ 77 /* glyphs of the same face. */ 78 /* */ 79 /* <Input> */ 80 /* face :: A handle to the source face object. */ 81 /* */ 82 /* left_glyph :: The index of the left glyph in the kern pair. */ 83 /* */ 84 /* right_glyph :: The index of the right glyph in the kern pair. */ 85 /* */ 86 /* <Output> */ 87 /* kerning :: The kerning vector. This is in font units for */ 88 /* scalable formats, and in pixels for fixed-sizes */ 89 /* formats. */ 90 /* */ 91 /* <Return> */ 92 /* FreeType error code. 0 means success. */ 93 /* */ 94 /* <Note> */ 95 /* Only horizontal layouts (left-to-right & right-to-left) are */ 96 /* supported by this function. Other layouts, or more sophisticated */ 97 /* kernings, are out of scope of this method (the basic driver */ 98 /* interface is meant to be simple). */ 99 /* */ 100 /* They can be implemented by format-specific interfaces. */ 101 /* */ 102 FT_CALLBACK_DEF( FT_Error ) cff_get_kerning(FT_Face ttface,FT_UInt left_glyph,FT_UInt right_glyph,FT_Vector * kerning)103 cff_get_kerning( FT_Face ttface, /* TT_Face */ 104 FT_UInt left_glyph, 105 FT_UInt right_glyph, 106 FT_Vector* kerning ) 107 { 108 TT_Face face = (TT_Face)ttface; 109 SFNT_Service sfnt = (SFNT_Service)face->sfnt; 110 111 112 kerning->x = 0; 113 kerning->y = 0; 114 115 if ( sfnt ) 116 kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph ); 117 118 return CFF_Err_Ok; 119 } 120 121 122 #undef PAIR_TAG 123 124 125 /*************************************************************************/ 126 /* */ 127 /* <Function> */ 128 /* Load_Glyph */ 129 /* */ 130 /* <Description> */ 131 /* A driver method used to load a glyph within a given glyph slot. */ 132 /* */ 133 /* <Input> */ 134 /* slot :: A handle to the target slot object where the glyph */ 135 /* will be loaded. */ 136 /* */ 137 /* size :: A handle to the source face size at which the glyph */ 138 /* must be scaled, loaded, etc. */ 139 /* */ 140 /* glyph_index :: The index of the glyph in the font file. */ 141 /* */ 142 /* load_flags :: A flag indicating what to load for this glyph. The */ 143 /* FT_LOAD_??? constants can be used to control the */ 144 /* glyph loading process (e.g., whether the outline */ 145 /* should be scaled, whether to load bitmaps or not, */ 146 /* whether to hint the outline, etc). */ 147 /* */ 148 /* <Return> */ 149 /* FreeType error code. 0 means success. */ 150 /* */ 151 FT_CALLBACK_DEF( FT_Error ) Load_Glyph(FT_GlyphSlot cffslot,FT_Size cffsize,FT_UInt glyph_index,FT_Int32 load_flags)152 Load_Glyph( FT_GlyphSlot cffslot, /* CFF_GlyphSlot */ 153 FT_Size cffsize, /* CFF_Size */ 154 FT_UInt glyph_index, 155 FT_Int32 load_flags ) 156 { 157 FT_Error error; 158 CFF_GlyphSlot slot = (CFF_GlyphSlot)cffslot; 159 CFF_Size size = (CFF_Size)cffsize; 160 161 162 if ( !slot ) 163 return CFF_Err_Invalid_Slot_Handle; 164 165 /* check whether we want a scaled outline or bitmap */ 166 if ( !size ) 167 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; 168 169 /* reset the size object if necessary */ 170 if ( load_flags & FT_LOAD_NO_SCALE ) 171 size = NULL; 172 173 if ( size ) 174 { 175 /* these two objects must have the same parent */ 176 if ( cffsize->face != cffslot->face ) 177 return CFF_Err_Invalid_Face_Handle; 178 } 179 180 /* now load the glyph outline if necessary */ 181 error = cff_slot_load( slot, size, glyph_index, load_flags ); 182 183 /* force drop-out mode to 2 - irrelevant now */ 184 /* slot->outline.dropout_mode = 2; */ 185 186 return error; 187 } 188 189 190 FT_CALLBACK_DEF( FT_Error ) cff_get_advances(FT_Face face,FT_UInt start,FT_UInt count,FT_Int32 flags,FT_Fixed * advances)191 cff_get_advances( FT_Face face, 192 FT_UInt start, 193 FT_UInt count, 194 FT_Int32 flags, 195 FT_Fixed* advances ) 196 { 197 FT_UInt nn; 198 FT_Error error = CFF_Err_Ok; 199 FT_GlyphSlot slot = face->glyph; 200 201 202 flags |= FT_LOAD_ADVANCE_ONLY; 203 204 for ( nn = 0; nn < count; nn++ ) 205 { 206 error = Load_Glyph( slot, face->size, start + nn, flags ); 207 if ( error ) 208 break; 209 210 advances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT ) 211 ? slot->linearVertAdvance 212 : slot->linearHoriAdvance; 213 } 214 215 return error; 216 } 217 218 219 /* 220 * GLYPH DICT SERVICE 221 * 222 */ 223 224 static FT_Error cff_get_glyph_name(CFF_Face face,FT_UInt glyph_index,FT_Pointer buffer,FT_UInt buffer_max)225 cff_get_glyph_name( CFF_Face face, 226 FT_UInt glyph_index, 227 FT_Pointer buffer, 228 FT_UInt buffer_max ) 229 { 230 CFF_Font font = (CFF_Font)face->extra.data; 231 FT_Memory memory = FT_FACE_MEMORY( face ); 232 FT_String* gname; 233 FT_UShort sid; 234 FT_Service_PsCMaps psnames; 235 FT_Error error; 236 237 238 FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); 239 if ( !psnames ) 240 { 241 FT_ERROR(( "cff_get_glyph_name:" )); 242 FT_ERROR(( " cannot get glyph name from CFF & CEF fonts\n" )); 243 FT_ERROR(( " " )); 244 FT_ERROR(( " without the `PSNames' module\n" )); 245 error = CFF_Err_Unknown_File_Format; 246 goto Exit; 247 } 248 249 /* first, locate the sid in the charset table */ 250 sid = font->charset.sids[glyph_index]; 251 252 /* now, lookup the name itself */ 253 gname = cff_index_get_sid_string( &font->string_index, sid, psnames ); 254 255 if ( gname ) 256 FT_STRCPYN( buffer, gname, buffer_max ); 257 258 FT_FREE( gname ); 259 error = CFF_Err_Ok; 260 261 Exit: 262 return error; 263 } 264 265 266 static FT_UInt cff_get_name_index(CFF_Face face,FT_String * glyph_name)267 cff_get_name_index( CFF_Face face, 268 FT_String* glyph_name ) 269 { 270 CFF_Font cff; 271 CFF_Charset charset; 272 FT_Service_PsCMaps psnames; 273 FT_Memory memory = FT_FACE_MEMORY( face ); 274 FT_String* name; 275 FT_UShort sid; 276 FT_UInt i; 277 FT_Int result; 278 279 280 cff = (CFF_FontRec *)face->extra.data; 281 charset = &cff->charset; 282 283 FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); 284 if ( !psnames ) 285 return 0; 286 287 for ( i = 0; i < cff->num_glyphs; i++ ) 288 { 289 sid = charset->sids[i]; 290 291 if ( sid > 390 ) 292 name = cff_index_get_name( &cff->string_index, sid - 391 ); 293 else 294 name = (FT_String *)psnames->adobe_std_strings( sid ); 295 296 if ( !name ) 297 continue; 298 299 result = ft_strcmp( glyph_name, name ); 300 301 if ( sid > 390 ) 302 FT_FREE( name ); 303 304 if ( !result ) 305 return i; 306 } 307 308 return 0; 309 } 310 311 312 static const FT_Service_GlyphDictRec cff_service_glyph_dict = 313 { 314 (FT_GlyphDict_GetNameFunc) cff_get_glyph_name, 315 (FT_GlyphDict_NameIndexFunc)cff_get_name_index, 316 }; 317 318 319 /* 320 * POSTSCRIPT INFO SERVICE 321 * 322 */ 323 324 static FT_Int cff_ps_has_glyph_names(FT_Face face)325 cff_ps_has_glyph_names( FT_Face face ) 326 { 327 return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0; 328 } 329 330 331 static FT_Error cff_ps_get_font_info(CFF_Face face,PS_FontInfoRec * afont_info)332 cff_ps_get_font_info( CFF_Face face, 333 PS_FontInfoRec* afont_info ) 334 { 335 CFF_Font cff = (CFF_Font)face->extra.data; 336 FT_Error error = FT_Err_Ok; 337 338 339 if ( cff && cff->font_info == NULL ) 340 { 341 CFF_FontRecDict dict = &cff->top_font.font_dict; 342 PS_FontInfoRec *font_info; 343 FT_Memory memory = face->root.memory; 344 FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; 345 346 347 if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) ) 348 goto Fail; 349 350 font_info->version = cff_index_get_sid_string( &cff->string_index, 351 dict->version, 352 psnames ); 353 font_info->notice = cff_index_get_sid_string( &cff->string_index, 354 dict->notice, 355 psnames ); 356 font_info->full_name = cff_index_get_sid_string( &cff->string_index, 357 dict->full_name, 358 psnames ); 359 font_info->family_name = cff_index_get_sid_string( &cff->string_index, 360 dict->family_name, 361 psnames ); 362 font_info->weight = cff_index_get_sid_string( &cff->string_index, 363 dict->weight, 364 psnames ); 365 font_info->italic_angle = dict->italic_angle; 366 font_info->is_fixed_pitch = dict->is_fixed_pitch; 367 font_info->underline_position = (FT_Short)dict->underline_position; 368 font_info->underline_thickness = (FT_Short)dict->underline_thickness; 369 370 cff->font_info = font_info; 371 } 372 373 if ( cff ) 374 *afont_info = *cff->font_info; 375 376 Fail: 377 return error; 378 } 379 380 381 static const FT_Service_PsInfoRec cff_service_ps_info = 382 { 383 (PS_GetFontInfoFunc) cff_ps_get_font_info, 384 (PS_GetFontExtraFunc) NULL, 385 (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names, 386 (PS_GetFontPrivateFunc)NULL /* unsupported with CFF fonts */ 387 }; 388 389 390 /* 391 * POSTSCRIPT NAME SERVICE 392 * 393 */ 394 395 static const char* cff_get_ps_name(CFF_Face face)396 cff_get_ps_name( CFF_Face face ) 397 { 398 CFF_Font cff = (CFF_Font)face->extra.data; 399 400 401 return (const char*)cff->font_name; 402 } 403 404 405 static const FT_Service_PsFontNameRec cff_service_ps_name = 406 { 407 (FT_PsName_GetFunc)cff_get_ps_name 408 }; 409 410 411 /* 412 * TT CMAP INFO 413 * 414 * If the charmap is a synthetic Unicode encoding cmap or 415 * a Type 1 standard (or expert) encoding cmap, hide TT CMAP INFO 416 * service defined in SFNT module. 417 * 418 * Otherwise call the service function in the sfnt module. 419 * 420 */ 421 static FT_Error cff_get_cmap_info(FT_CharMap charmap,TT_CMapInfo * cmap_info)422 cff_get_cmap_info( FT_CharMap charmap, 423 TT_CMapInfo *cmap_info ) 424 { 425 FT_CMap cmap = FT_CMAP( charmap ); 426 FT_Error error = CFF_Err_Ok; 427 428 429 cmap_info->language = 0; 430 cmap_info->format = 0; 431 432 if ( cmap->clazz != &cff_cmap_encoding_class_rec && 433 cmap->clazz != &cff_cmap_unicode_class_rec ) 434 { 435 FT_Face face = FT_CMAP_FACE( cmap ); 436 FT_Library library = FT_FACE_LIBRARY( face ); 437 FT_Module sfnt = FT_Get_Module( library, "sfnt" ); 438 FT_Service_TTCMaps service = 439 (FT_Service_TTCMaps)ft_module_get_service( sfnt, 440 FT_SERVICE_ID_TT_CMAP ); 441 442 443 if ( service && service->get_cmap_info ) 444 error = service->get_cmap_info( charmap, cmap_info ); 445 } 446 447 return error; 448 } 449 450 451 static const FT_Service_TTCMapsRec cff_service_get_cmap_info = 452 { 453 (TT_CMap_Info_GetFunc)cff_get_cmap_info 454 }; 455 456 457 /* 458 * CID INFO SERVICE 459 * 460 */ 461 static FT_Error cff_get_ros(CFF_Face face,const char ** registry,const char ** ordering,FT_Int * supplement)462 cff_get_ros( CFF_Face face, 463 const char* *registry, 464 const char* *ordering, 465 FT_Int *supplement ) 466 { 467 FT_Error error = CFF_Err_Ok; 468 CFF_Font cff = (CFF_Font)face->extra.data; 469 470 471 if ( cff ) 472 { 473 CFF_FontRecDict dict = &cff->top_font.font_dict; 474 FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; 475 476 477 if ( dict->cid_registry == 0xFFFFU ) 478 { 479 error = CFF_Err_Invalid_Argument; 480 goto Fail; 481 } 482 483 if ( registry ) 484 { 485 if ( cff->registry == NULL ) 486 cff->registry = cff_index_get_sid_string( &cff->string_index, 487 dict->cid_registry, 488 psnames ); 489 *registry = cff->registry; 490 } 491 492 if ( ordering ) 493 { 494 if ( cff->ordering == NULL ) 495 cff->ordering = cff_index_get_sid_string( &cff->string_index, 496 dict->cid_ordering, 497 psnames ); 498 *ordering = cff->ordering; 499 } 500 501 if ( supplement ) 502 *supplement = dict->cid_supplement; 503 } 504 505 Fail: 506 return error; 507 } 508 509 510 static FT_Error cff_get_is_cid(CFF_Face face,FT_Bool * is_cid)511 cff_get_is_cid( CFF_Face face, 512 FT_Bool *is_cid ) 513 { 514 FT_Error error = CFF_Err_Ok; 515 CFF_Font cff = (CFF_Font)face->extra.data; 516 517 518 *is_cid = 0; 519 520 if ( cff ) 521 { 522 CFF_FontRecDict dict = &cff->top_font.font_dict; 523 524 525 if ( dict->cid_registry != 0xFFFFU ) 526 *is_cid = 1; 527 } 528 529 return error; 530 } 531 532 533 static FT_Error cff_get_cid_from_glyph_index(CFF_Face face,FT_UInt glyph_index,FT_UInt * cid)534 cff_get_cid_from_glyph_index( CFF_Face face, 535 FT_UInt glyph_index, 536 FT_UInt *cid ) 537 { 538 FT_Error error = CFF_Err_Ok; 539 CFF_Font cff; 540 541 542 cff = (CFF_Font)face->extra.data; 543 544 if ( cff ) 545 { 546 FT_UInt c; 547 CFF_FontRecDict dict = &cff->top_font.font_dict; 548 549 550 if ( dict->cid_registry == 0xFFFFU ) 551 { 552 error = CFF_Err_Invalid_Argument; 553 goto Fail; 554 } 555 556 if ( glyph_index > cff->num_glyphs ) 557 { 558 error = CFF_Err_Invalid_Argument; 559 goto Fail; 560 } 561 562 c = cff->charset.sids[glyph_index]; 563 564 if ( cid ) 565 *cid = c; 566 } 567 568 Fail: 569 return error; 570 } 571 572 573 static const FT_Service_CIDRec cff_service_cid_info = 574 { 575 (FT_CID_GetRegistryOrderingSupplementFunc)cff_get_ros, 576 (FT_CID_GetIsInternallyCIDKeyedFunc) cff_get_is_cid, 577 (FT_CID_GetCIDFromGlyphIndexFunc) cff_get_cid_from_glyph_index 578 }; 579 580 581 /*************************************************************************/ 582 /*************************************************************************/ 583 /*************************************************************************/ 584 /**** ****/ 585 /**** ****/ 586 /**** D R I V E R I N T E R F A C E ****/ 587 /**** ****/ 588 /**** ****/ 589 /*************************************************************************/ 590 /*************************************************************************/ 591 /*************************************************************************/ 592 593 static const FT_ServiceDescRec cff_services[] = 594 { 595 { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_CFF }, 596 { FT_SERVICE_ID_POSTSCRIPT_INFO, &cff_service_ps_info }, 597 { FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name }, 598 #ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES 599 { FT_SERVICE_ID_GLYPH_DICT, &cff_service_glyph_dict }, 600 #endif 601 { FT_SERVICE_ID_TT_CMAP, &cff_service_get_cmap_info }, 602 { FT_SERVICE_ID_CID, &cff_service_cid_info }, 603 { NULL, NULL } 604 }; 605 606 607 FT_CALLBACK_DEF( FT_Module_Interface ) cff_get_interface(FT_Module driver,const char * module_interface)608 cff_get_interface( FT_Module driver, /* CFF_Driver */ 609 const char* module_interface ) 610 { 611 FT_Module sfnt; 612 FT_Module_Interface result; 613 614 615 result = ft_service_list_lookup( cff_services, module_interface ); 616 if ( result != NULL ) 617 return result; 618 619 /* we pass our request to the `sfnt' module */ 620 sfnt = FT_Get_Module( driver->library, "sfnt" ); 621 622 return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0; 623 } 624 625 626 /* The FT_DriverInterface structure is defined in ftdriver.h. */ 627 628 FT_CALLBACK_TABLE_DEF 629 const FT_Driver_ClassRec cff_driver_class = 630 { 631 /* begin with the FT_Module_Class fields */ 632 { 633 FT_MODULE_FONT_DRIVER | 634 FT_MODULE_DRIVER_SCALABLE | 635 FT_MODULE_DRIVER_HAS_HINTER, 636 637 sizeof( CFF_DriverRec ), 638 "cff", 639 0x10000L, 640 0x20000L, 641 642 0, /* module-specific interface */ 643 644 cff_driver_init, 645 cff_driver_done, 646 cff_get_interface, 647 }, 648 649 /* now the specific driver fields */ 650 sizeof( TT_FaceRec ), 651 sizeof( CFF_SizeRec ), 652 sizeof( CFF_GlyphSlotRec ), 653 654 cff_face_init, 655 cff_face_done, 656 cff_size_init, 657 cff_size_done, 658 cff_slot_init, 659 cff_slot_done, 660 661 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS 662 ft_stub_set_char_sizes, 663 ft_stub_set_pixel_sizes, 664 #endif 665 666 Load_Glyph, 667 668 cff_get_kerning, 669 0, /* FT_Face_AttachFunc */ 670 cff_get_advances, /* FT_Face_GetAdvancesFunc */ 671 672 cff_size_request, 673 674 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 675 cff_size_select 676 #else 677 0 /* FT_Size_SelectFunc */ 678 #endif 679 }; 680 681 682 /* END */ 683