1 /***************************************************************************/ 2 /* */ 3 /* cffdrivr.c */ 4 /* */ 5 /* OpenType font driver implementation (body). */ 6 /* */ 7 /* Copyright 1996-2012 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_SERVICE_CID_H 25 #include FT_SERVICE_POSTSCRIPT_INFO_H 26 #include FT_SERVICE_POSTSCRIPT_NAME_H 27 #include FT_SERVICE_TT_CMAP_H 28 29 #include "cffdrivr.h" 30 #include "cffgload.h" 31 #include "cffload.h" 32 #include "cffcmap.h" 33 #include "cffparse.h" 34 35 #include "cfferrs.h" 36 #include "cffpic.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 /* cff_glyph_load */ 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 ) cff_glyph_load(FT_GlyphSlot cffslot,FT_Size cffsize,FT_UInt glyph_index,FT_Int32 load_flags)152 cff_glyph_load( 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_UInt32)FT_LOAD_ADVANCE_ONLY; 203 204 for ( nn = 0; nn < count; nn++ ) 205 { 206 error = cff_glyph_load( 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_String* gname; 232 FT_UShort sid; 233 FT_Error error; 234 235 236 if ( !font->psnames ) 237 { 238 FT_ERROR(( "cff_get_glyph_name:" 239 " cannot get glyph name from CFF & CEF fonts\n" 240 " " 241 " without the `PSNames' module\n" )); 242 error = CFF_Err_Missing_Module; 243 goto Exit; 244 } 245 246 /* first, locate the sid in the charset table */ 247 sid = font->charset.sids[glyph_index]; 248 249 /* now, lookup the name itself */ 250 gname = cff_index_get_sid_string( font, sid ); 251 252 if ( gname ) 253 FT_STRCPYN( buffer, gname, buffer_max ); 254 255 error = CFF_Err_Ok; 256 257 Exit: 258 return error; 259 } 260 261 262 static FT_UInt cff_get_name_index(CFF_Face face,FT_String * glyph_name)263 cff_get_name_index( CFF_Face face, 264 FT_String* glyph_name ) 265 { 266 CFF_Font cff; 267 CFF_Charset charset; 268 FT_Service_PsCMaps psnames; 269 FT_String* name; 270 FT_UShort sid; 271 FT_UInt i; 272 273 274 cff = (CFF_FontRec *)face->extra.data; 275 charset = &cff->charset; 276 277 FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); 278 if ( !psnames ) 279 return 0; 280 281 for ( i = 0; i < cff->num_glyphs; i++ ) 282 { 283 sid = charset->sids[i]; 284 285 if ( sid > 390 ) 286 name = cff_index_get_string( cff, sid - 391 ); 287 else 288 name = (FT_String *)psnames->adobe_std_strings( sid ); 289 290 if ( !name ) 291 continue; 292 293 if ( !ft_strcmp( glyph_name, name ) ) 294 return i; 295 } 296 297 return 0; 298 } 299 300 301 FT_DEFINE_SERVICE_GLYPHDICTREC(cff_service_glyph_dict, 302 (FT_GlyphDict_GetNameFunc) cff_get_glyph_name, 303 (FT_GlyphDict_NameIndexFunc)cff_get_name_index 304 ) 305 306 307 /* 308 * POSTSCRIPT INFO SERVICE 309 * 310 */ 311 312 static FT_Int cff_ps_has_glyph_names(FT_Face face)313 cff_ps_has_glyph_names( FT_Face face ) 314 { 315 return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0; 316 } 317 318 319 static FT_Error cff_ps_get_font_info(CFF_Face face,PS_FontInfoRec * afont_info)320 cff_ps_get_font_info( CFF_Face face, 321 PS_FontInfoRec* afont_info ) 322 { 323 CFF_Font cff = (CFF_Font)face->extra.data; 324 FT_Error error = CFF_Err_Ok; 325 326 327 if ( cff && cff->font_info == NULL ) 328 { 329 CFF_FontRecDict dict = &cff->top_font.font_dict; 330 PS_FontInfoRec *font_info = NULL; 331 FT_Memory memory = face->root.memory; 332 333 334 if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) ) 335 goto Fail; 336 337 font_info->version = cff_index_get_sid_string( cff, 338 dict->version ); 339 font_info->notice = cff_index_get_sid_string( cff, 340 dict->notice ); 341 font_info->full_name = cff_index_get_sid_string( cff, 342 dict->full_name ); 343 font_info->family_name = cff_index_get_sid_string( cff, 344 dict->family_name ); 345 font_info->weight = cff_index_get_sid_string( cff, 346 dict->weight ); 347 font_info->italic_angle = dict->italic_angle; 348 font_info->is_fixed_pitch = dict->is_fixed_pitch; 349 font_info->underline_position = (FT_Short)dict->underline_position; 350 font_info->underline_thickness = (FT_Short)dict->underline_thickness; 351 352 cff->font_info = font_info; 353 } 354 355 if ( cff ) 356 *afont_info = *cff->font_info; 357 358 Fail: 359 return error; 360 } 361 362 363 FT_DEFINE_SERVICE_PSINFOREC(cff_service_ps_info, 364 (PS_GetFontInfoFunc) cff_ps_get_font_info, 365 (PS_GetFontExtraFunc) NULL, 366 (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names, 367 (PS_GetFontPrivateFunc)NULL, /* unsupported with CFF fonts */ 368 (PS_GetFontValueFunc) NULL /* not implemented */ 369 ) 370 371 372 /* 373 * POSTSCRIPT NAME SERVICE 374 * 375 */ 376 377 static const char* cff_get_ps_name(CFF_Face face)378 cff_get_ps_name( CFF_Face face ) 379 { 380 CFF_Font cff = (CFF_Font)face->extra.data; 381 382 383 return (const char*)cff->font_name; 384 } 385 386 387 FT_DEFINE_SERVICE_PSFONTNAMEREC(cff_service_ps_name, 388 (FT_PsName_GetFunc)cff_get_ps_name 389 ) 390 391 392 /* 393 * TT CMAP INFO 394 * 395 * If the charmap is a synthetic Unicode encoding cmap or 396 * a Type 1 standard (or expert) encoding cmap, hide TT CMAP INFO 397 * service defined in SFNT module. 398 * 399 * Otherwise call the service function in the sfnt module. 400 * 401 */ 402 static FT_Error cff_get_cmap_info(FT_CharMap charmap,TT_CMapInfo * cmap_info)403 cff_get_cmap_info( FT_CharMap charmap, 404 TT_CMapInfo *cmap_info ) 405 { 406 FT_CMap cmap = FT_CMAP( charmap ); 407 FT_Error error = CFF_Err_Ok; 408 FT_Face face = FT_CMAP_FACE( cmap ); 409 FT_Library library = FT_FACE_LIBRARY( face ); 410 411 412 cmap_info->language = 0; 413 cmap_info->format = 0; 414 415 if ( cmap->clazz != &FT_CFF_CMAP_ENCODING_CLASS_REC_GET && 416 cmap->clazz != &FT_CFF_CMAP_UNICODE_CLASS_REC_GET ) 417 { 418 FT_Module sfnt = FT_Get_Module( library, "sfnt" ); 419 FT_Service_TTCMaps service = 420 (FT_Service_TTCMaps)ft_module_get_service( sfnt, 421 FT_SERVICE_ID_TT_CMAP ); 422 423 424 if ( service && service->get_cmap_info ) 425 error = service->get_cmap_info( charmap, cmap_info ); 426 } 427 428 return error; 429 } 430 431 432 FT_DEFINE_SERVICE_TTCMAPSREC(cff_service_get_cmap_info, 433 (TT_CMap_Info_GetFunc)cff_get_cmap_info 434 ) 435 436 437 /* 438 * CID INFO SERVICE 439 * 440 */ 441 static FT_Error cff_get_ros(CFF_Face face,const char ** registry,const char ** ordering,FT_Int * supplement)442 cff_get_ros( CFF_Face face, 443 const char* *registry, 444 const char* *ordering, 445 FT_Int *supplement ) 446 { 447 FT_Error error = CFF_Err_Ok; 448 CFF_Font cff = (CFF_Font)face->extra.data; 449 450 451 if ( cff ) 452 { 453 CFF_FontRecDict dict = &cff->top_font.font_dict; 454 455 456 if ( dict->cid_registry == 0xFFFFU ) 457 { 458 error = CFF_Err_Invalid_Argument; 459 goto Fail; 460 } 461 462 if ( registry ) 463 { 464 if ( cff->registry == NULL ) 465 cff->registry = cff_index_get_sid_string( cff, 466 dict->cid_registry ); 467 *registry = cff->registry; 468 } 469 470 if ( ordering ) 471 { 472 if ( cff->ordering == NULL ) 473 cff->ordering = cff_index_get_sid_string( cff, 474 dict->cid_ordering ); 475 *ordering = cff->ordering; 476 } 477 478 /* 479 * XXX: According to Adobe TechNote #5176, the supplement in CFF 480 * can be a real number. We truncate it to fit public API 481 * since freetype-2.3.6. 482 */ 483 if ( supplement ) 484 { 485 if ( dict->cid_supplement < FT_INT_MIN || 486 dict->cid_supplement > FT_INT_MAX ) 487 FT_TRACE1(( "cff_get_ros: too large supplement %d is truncated\n", 488 dict->cid_supplement )); 489 *supplement = (FT_Int)dict->cid_supplement; 490 } 491 } 492 493 Fail: 494 return error; 495 } 496 497 498 static FT_Error cff_get_is_cid(CFF_Face face,FT_Bool * is_cid)499 cff_get_is_cid( CFF_Face face, 500 FT_Bool *is_cid ) 501 { 502 FT_Error error = CFF_Err_Ok; 503 CFF_Font cff = (CFF_Font)face->extra.data; 504 505 506 *is_cid = 0; 507 508 if ( cff ) 509 { 510 CFF_FontRecDict dict = &cff->top_font.font_dict; 511 512 513 if ( dict->cid_registry != 0xFFFFU ) 514 *is_cid = 1; 515 } 516 517 return error; 518 } 519 520 521 static FT_Error cff_get_cid_from_glyph_index(CFF_Face face,FT_UInt glyph_index,FT_UInt * cid)522 cff_get_cid_from_glyph_index( CFF_Face face, 523 FT_UInt glyph_index, 524 FT_UInt *cid ) 525 { 526 FT_Error error = CFF_Err_Ok; 527 CFF_Font cff; 528 529 530 cff = (CFF_Font)face->extra.data; 531 532 if ( cff ) 533 { 534 FT_UInt c; 535 CFF_FontRecDict dict = &cff->top_font.font_dict; 536 537 538 if ( dict->cid_registry == 0xFFFFU ) 539 { 540 error = CFF_Err_Invalid_Argument; 541 goto Fail; 542 } 543 544 if ( glyph_index > cff->num_glyphs ) 545 { 546 error = CFF_Err_Invalid_Argument; 547 goto Fail; 548 } 549 550 c = cff->charset.sids[glyph_index]; 551 552 if ( cid ) 553 *cid = c; 554 } 555 556 Fail: 557 return error; 558 } 559 560 561 FT_DEFINE_SERVICE_CIDREC(cff_service_cid_info, 562 (FT_CID_GetRegistryOrderingSupplementFunc)cff_get_ros, 563 (FT_CID_GetIsInternallyCIDKeyedFunc) cff_get_is_cid, 564 (FT_CID_GetCIDFromGlyphIndexFunc) cff_get_cid_from_glyph_index 565 ) 566 567 568 /*************************************************************************/ 569 /*************************************************************************/ 570 /*************************************************************************/ 571 /**** ****/ 572 /**** ****/ 573 /**** D R I V E R I N T E R F A C E ****/ 574 /**** ****/ 575 /**** ****/ 576 /*************************************************************************/ 577 /*************************************************************************/ 578 /*************************************************************************/ 579 #ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES 580 FT_DEFINE_SERVICEDESCREC6(cff_services, 581 FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_CFF, 582 FT_SERVICE_ID_POSTSCRIPT_INFO, &FT_CFF_SERVICE_PS_INFO_GET, 583 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_CFF_SERVICE_PS_NAME_GET, 584 FT_SERVICE_ID_GLYPH_DICT, &FT_CFF_SERVICE_GLYPH_DICT_GET, 585 FT_SERVICE_ID_TT_CMAP, &FT_CFF_SERVICE_GET_CMAP_INFO_GET, 586 FT_SERVICE_ID_CID, &FT_CFF_SERVICE_CID_INFO_GET 587 ) 588 #else 589 FT_DEFINE_SERVICEDESCREC5(cff_services, 590 FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_CFF, 591 FT_SERVICE_ID_POSTSCRIPT_INFO, &FT_CFF_SERVICE_PS_INFO_GET, 592 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_CFF_SERVICE_PS_NAME_GET, 593 FT_SERVICE_ID_TT_CMAP, &FT_CFF_SERVICE_GET_CMAP_INFO_GET, 594 FT_SERVICE_ID_CID, &FT_CFF_SERVICE_CID_INFO_GET 595 ) 596 #endif 597 FT_CALLBACK_DEF(FT_Module_Interface)598 FT_CALLBACK_DEF( FT_Module_Interface ) 599 cff_get_interface( FT_Module driver, /* CFF_Driver */ 600 const char* module_interface ) 601 { 602 FT_Library library; 603 FT_Module sfnt; 604 FT_Module_Interface result; 605 606 607 /* FT_CFF_SERVICES_GET derefers `library' in PIC mode */ 608 #ifdef FT_CONFIG_OPTION_PIC 609 if ( !driver ) 610 return NULL; 611 library = driver->library; 612 if ( !library ) 613 return NULL; 614 #endif 615 616 result = ft_service_list_lookup( FT_CFF_SERVICES_GET, module_interface ); 617 if ( result != NULL ) 618 return result; 619 620 /* `driver' is not yet evaluated in non-PIC mode */ 621 #ifndef FT_CONFIG_OPTION_PIC 622 if ( !driver ) 623 return NULL; 624 library = driver->library; 625 if ( !library ) 626 return NULL; 627 #endif 628 629 /* we pass our request to the `sfnt' module */ 630 sfnt = FT_Get_Module( library, "sfnt" ); 631 632 return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0; 633 } 634 635 636 /* The FT_DriverInterface structure is defined in ftdriver.h. */ 637 638 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 639 #define CFF_SIZE_SELECT cff_size_select 640 #else 641 #define CFF_SIZE_SELECT 0 642 #endif 643 644 FT_DEFINE_DRIVER( cff_driver_class, 645 646 FT_MODULE_FONT_DRIVER | 647 FT_MODULE_DRIVER_SCALABLE | 648 FT_MODULE_DRIVER_HAS_HINTER, 649 650 sizeof ( CFF_DriverRec ), 651 "cff", 652 0x10000L, 653 0x20000L, 654 655 0, /* module-specific interface */ 656 657 cff_driver_init, 658 cff_driver_done, 659 cff_get_interface, 660 661 /* now the specific driver fields */ 662 sizeof ( TT_FaceRec ), 663 sizeof ( CFF_SizeRec ), 664 sizeof ( CFF_GlyphSlotRec ), 665 666 cff_face_init, 667 cff_face_done, 668 cff_size_init, 669 cff_size_done, 670 cff_slot_init, 671 cff_slot_done, 672 673 ft_stub_set_char_sizes, /* FT_CONFIG_OPTION_OLD_INTERNALS */ 674 ft_stub_set_pixel_sizes, /* FT_CONFIG_OPTION_OLD_INTERNALS */ 675 676 cff_glyph_load, 677 678 cff_get_kerning, 679 0, /* FT_Face_AttachFunc */ 680 cff_get_advances, 681 682 cff_size_request, 683 684 CFF_SIZE_SELECT 685 ) 686 687 688 /* END */ 689