1 /**************************************************************************** 2 * 3 * cffdrivr.c 4 * 5 * OpenType font driver implementation (body). 6 * 7 * Copyright (C) 1996-2020 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 <freetype/freetype.h> 20 #include <freetype/internal/ftdebug.h> 21 #include <freetype/internal/ftstream.h> 22 #include <freetype/internal/sfnt.h> 23 #include <freetype/internal/psaux.h> 24 #include <freetype/internal/ftpsprop.h> 25 #include <freetype/internal/services/svcid.h> 26 #include <freetype/internal/services/svpsinfo.h> 27 #include <freetype/internal/services/svpostnm.h> 28 #include <freetype/internal/services/svttcmap.h> 29 #include <freetype/internal/services/svcfftl.h> 30 31 #include "cffdrivr.h" 32 #include "cffgload.h" 33 #include "cffload.h" 34 #include "cffcmap.h" 35 #include "cffparse.h" 36 #include "cffobjs.h" 37 38 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 39 #include <freetype/internal/services/svmm.h> 40 #include <freetype/internal/services/svmetric.h> 41 #endif 42 43 #include "cfferrs.h" 44 45 #include <freetype/internal/services/svfntfmt.h> 46 #include <freetype/internal/services/svgldict.h> 47 #include <freetype/internal/services/svprop.h> 48 #include <freetype/ftdriver.h> 49 50 51 /************************************************************************** 52 * 53 * The macro FT_COMPONENT is used in trace mode. It is an implicit 54 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log 55 * messages during execution. 56 */ 57 #undef FT_COMPONENT 58 #define FT_COMPONENT cffdriver 59 60 61 /*************************************************************************/ 62 /*************************************************************************/ 63 /*************************************************************************/ 64 /**** ****/ 65 /**** ****/ 66 /**** F A C E S ****/ 67 /**** ****/ 68 /**** ****/ 69 /*************************************************************************/ 70 /*************************************************************************/ 71 /*************************************************************************/ 72 73 74 /************************************************************************** 75 * 76 * @Function: 77 * cff_get_kerning 78 * 79 * @Description: 80 * A driver method used to return the kerning vector between two 81 * glyphs of the same face. 82 * 83 * @Input: 84 * face :: 85 * A handle to the source face object. 86 * 87 * left_glyph :: 88 * The index of the left glyph in the kern pair. 89 * 90 * right_glyph :: 91 * The index of the right glyph in the kern pair. 92 * 93 * @Output: 94 * kerning :: 95 * The kerning vector. This is in font units for 96 * scalable formats, and in pixels for fixed-sizes 97 * formats. 98 * 99 * @Return: 100 * FreeType error code. 0 means success. 101 * 102 * @Note: 103 * Only horizontal layouts (left-to-right & right-to-left) are 104 * supported by this function. Other layouts, or more sophisticated 105 * kernings, are out of scope of this method (the basic driver 106 * interface is meant to be simple). 107 * 108 * They can be implemented by format-specific interfaces. 109 */ 110 FT_CALLBACK_DEF( FT_Error ) cff_get_kerning(FT_Face ttface,FT_UInt left_glyph,FT_UInt right_glyph,FT_Vector * kerning)111 cff_get_kerning( FT_Face ttface, /* TT_Face */ 112 FT_UInt left_glyph, 113 FT_UInt right_glyph, 114 FT_Vector* kerning ) 115 { 116 TT_Face face = (TT_Face)ttface; 117 SFNT_Service sfnt = (SFNT_Service)face->sfnt; 118 119 120 kerning->x = 0; 121 kerning->y = 0; 122 123 if ( sfnt ) 124 kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph ); 125 126 return FT_Err_Ok; 127 } 128 129 130 /************************************************************************** 131 * 132 * @Function: 133 * cff_glyph_load 134 * 135 * @Description: 136 * A driver method used to load a glyph within a given glyph slot. 137 * 138 * @Input: 139 * slot :: 140 * A handle to the target slot object where the glyph 141 * will be loaded. 142 * 143 * size :: 144 * A handle to the source face size at which the glyph 145 * must be scaled, loaded, etc. 146 * 147 * glyph_index :: 148 * The index of the glyph in the font file. 149 * 150 * load_flags :: 151 * A flag indicating what to load for this glyph. The 152 * FT_LOAD_??? constants can be used to control the 153 * glyph loading process (e.g., whether the outline 154 * should be scaled, whether to load bitmaps or not, 155 * whether to hint the outline, etc). 156 * 157 * @Return: 158 * FreeType error code. 0 means success. 159 */ 160 FT_CALLBACK_DEF( FT_Error ) cff_glyph_load(FT_GlyphSlot cffslot,FT_Size cffsize,FT_UInt glyph_index,FT_Int32 load_flags)161 cff_glyph_load( FT_GlyphSlot cffslot, /* CFF_GlyphSlot */ 162 FT_Size cffsize, /* CFF_Size */ 163 FT_UInt glyph_index, 164 FT_Int32 load_flags ) 165 { 166 FT_Error error; 167 CFF_GlyphSlot slot = (CFF_GlyphSlot)cffslot; 168 CFF_Size size = (CFF_Size)cffsize; 169 170 171 if ( !slot ) 172 return FT_THROW( Invalid_Slot_Handle ); 173 174 FT_TRACE1(( "cff_glyph_load: glyph index %d\n", glyph_index )); 175 176 /* check whether we want a scaled outline or bitmap */ 177 if ( !size ) 178 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; 179 180 /* reset the size object if necessary */ 181 if ( load_flags & FT_LOAD_NO_SCALE ) 182 size = NULL; 183 184 if ( size ) 185 { 186 /* these two objects must have the same parent */ 187 if ( cffsize->face != cffslot->face ) 188 return FT_THROW( Invalid_Face_Handle ); 189 } 190 191 /* now load the glyph outline if necessary */ 192 error = cff_slot_load( slot, size, glyph_index, load_flags ); 193 194 /* force drop-out mode to 2 - irrelevant now */ 195 /* slot->outline.dropout_mode = 2; */ 196 197 return error; 198 } 199 200 201 FT_CALLBACK_DEF( FT_Error ) cff_get_advances(FT_Face face,FT_UInt start,FT_UInt count,FT_Int32 flags,FT_Fixed * advances)202 cff_get_advances( FT_Face face, 203 FT_UInt start, 204 FT_UInt count, 205 FT_Int32 flags, 206 FT_Fixed* advances ) 207 { 208 FT_UInt nn; 209 FT_Error error = FT_Err_Ok; 210 FT_GlyphSlot slot = face->glyph; 211 212 213 if ( FT_IS_SFNT( face ) ) 214 { 215 /* OpenType 1.7 mandates that the data from `hmtx' table be used; */ 216 /* it is no longer necessary that those values are identical to */ 217 /* the values in the `CFF' table */ 218 219 TT_Face ttface = (TT_Face)face; 220 FT_Short dummy; 221 222 223 if ( flags & FT_LOAD_VERTICAL_LAYOUT ) 224 { 225 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 226 /* no fast retrieval for blended MM fonts without VVAR table */ 227 if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && 228 !( ttface->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) 229 return FT_THROW( Unimplemented_Feature ); 230 #endif 231 232 /* check whether we have data from the `vmtx' table at all; */ 233 /* otherwise we extract the info from the CFF glyphstrings */ 234 /* (instead of synthesizing a global value using the `OS/2' */ 235 /* table) */ 236 if ( !ttface->vertical_info ) 237 goto Missing_Table; 238 239 for ( nn = 0; nn < count; nn++ ) 240 { 241 FT_UShort ah; 242 243 244 ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface, 245 1, 246 start + nn, 247 &dummy, 248 &ah ); 249 250 FT_TRACE5(( " idx %d: advance height %d font unit%s\n", 251 start + nn, 252 ah, 253 ah == 1 ? "" : "s" )); 254 advances[nn] = ah; 255 } 256 } 257 else 258 { 259 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 260 /* no fast retrieval for blended MM fonts without HVAR table */ 261 if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && 262 !( ttface->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) 263 return FT_THROW( Unimplemented_Feature ); 264 #endif 265 266 /* check whether we have data from the `hmtx' table at all */ 267 if ( !ttface->horizontal.number_Of_HMetrics ) 268 goto Missing_Table; 269 270 for ( nn = 0; nn < count; nn++ ) 271 { 272 FT_UShort aw; 273 274 275 ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface, 276 0, 277 start + nn, 278 &dummy, 279 &aw ); 280 281 FT_TRACE5(( " idx %d: advance width %d font unit%s\n", 282 start + nn, 283 aw, 284 aw == 1 ? "" : "s" )); 285 advances[nn] = aw; 286 } 287 } 288 289 return error; 290 } 291 292 Missing_Table: 293 flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY; 294 295 for ( nn = 0; nn < count; nn++ ) 296 { 297 error = cff_glyph_load( slot, face->size, start + nn, flags ); 298 if ( error ) 299 break; 300 301 advances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT ) 302 ? slot->linearVertAdvance 303 : slot->linearHoriAdvance; 304 } 305 306 return error; 307 } 308 309 310 /* 311 * GLYPH DICT SERVICE 312 * 313 */ 314 315 static FT_Error cff_get_glyph_name(CFF_Face face,FT_UInt glyph_index,FT_Pointer buffer,FT_UInt buffer_max)316 cff_get_glyph_name( CFF_Face face, 317 FT_UInt glyph_index, 318 FT_Pointer buffer, 319 FT_UInt buffer_max ) 320 { 321 CFF_Font font = (CFF_Font)face->extra.data; 322 FT_String* gname; 323 FT_UShort sid; 324 FT_Error error; 325 326 327 /* CFF2 table does not have glyph names; */ 328 /* we need to use `post' table method */ 329 if ( font->version_major == 2 ) 330 { 331 FT_Library library = FT_FACE_LIBRARY( face ); 332 FT_Module sfnt_module = FT_Get_Module( library, "sfnt" ); 333 FT_Service_GlyphDict service = 334 (FT_Service_GlyphDict)ft_module_get_service( 335 sfnt_module, 336 FT_SERVICE_ID_GLYPH_DICT, 337 0 ); 338 339 340 if ( service && service->get_name ) 341 return service->get_name( FT_FACE( face ), 342 glyph_index, 343 buffer, 344 buffer_max ); 345 else 346 { 347 FT_ERROR(( "cff_get_glyph_name:" 348 " cannot get glyph name from a CFF2 font\n" 349 " " 350 " without the `psnames' module\n" )); 351 error = FT_THROW( Missing_Module ); 352 goto Exit; 353 } 354 } 355 356 if ( !font->psnames ) 357 { 358 FT_ERROR(( "cff_get_glyph_name:" 359 " cannot get glyph name from CFF & CEF fonts\n" 360 " " 361 " without the `psnames' module\n" )); 362 error = FT_THROW( Missing_Module ); 363 goto Exit; 364 } 365 366 /* first, locate the sid in the charset table */ 367 sid = font->charset.sids[glyph_index]; 368 369 /* now, lookup the name itself */ 370 gname = cff_index_get_sid_string( font, sid ); 371 372 if ( gname ) 373 FT_STRCPYN( buffer, gname, buffer_max ); 374 375 error = FT_Err_Ok; 376 377 Exit: 378 return error; 379 } 380 381 382 static FT_UInt cff_get_name_index(CFF_Face face,const FT_String * glyph_name)383 cff_get_name_index( CFF_Face face, 384 const FT_String* glyph_name ) 385 { 386 CFF_Font cff; 387 CFF_Charset charset; 388 FT_Service_PsCMaps psnames; 389 FT_String* name; 390 FT_UShort sid; 391 FT_UInt i; 392 393 394 cff = (CFF_FontRec *)face->extra.data; 395 charset = &cff->charset; 396 397 /* CFF2 table does not have glyph names; */ 398 /* we need to use `post' table method */ 399 if ( cff->version_major == 2 ) 400 { 401 FT_Library library = FT_FACE_LIBRARY( face ); 402 FT_Module sfnt_module = FT_Get_Module( library, "sfnt" ); 403 FT_Service_GlyphDict service = 404 (FT_Service_GlyphDict)ft_module_get_service( 405 sfnt_module, 406 FT_SERVICE_ID_GLYPH_DICT, 407 0 ); 408 409 410 if ( service && service->name_index ) 411 return service->name_index( FT_FACE( face ), glyph_name ); 412 else 413 { 414 FT_ERROR(( "cff_get_name_index:" 415 " cannot get glyph index from a CFF2 font\n" 416 " " 417 " without the `psnames' module\n" )); 418 return 0; 419 } 420 } 421 422 FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); 423 if ( !psnames ) 424 return 0; 425 426 for ( i = 0; i < cff->num_glyphs; i++ ) 427 { 428 sid = charset->sids[i]; 429 430 if ( sid > 390 ) 431 name = cff_index_get_string( cff, sid - 391 ); 432 else 433 name = (FT_String *)psnames->adobe_std_strings( sid ); 434 435 if ( !name ) 436 continue; 437 438 if ( !ft_strcmp( glyph_name, name ) ) 439 return i; 440 } 441 442 return 0; 443 } 444 445 446 FT_DEFINE_SERVICE_GLYPHDICTREC( 447 cff_service_glyph_dict, 448 449 (FT_GlyphDict_GetNameFunc) cff_get_glyph_name, /* get_name */ 450 (FT_GlyphDict_NameIndexFunc)cff_get_name_index /* name_index */ 451 ) 452 453 454 /* 455 * POSTSCRIPT INFO SERVICE 456 * 457 */ 458 459 static FT_Int cff_ps_has_glyph_names(FT_Face face)460 cff_ps_has_glyph_names( FT_Face face ) 461 { 462 return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0; 463 } 464 465 466 static FT_Error cff_ps_get_font_info(CFF_Face face,PS_FontInfoRec * afont_info)467 cff_ps_get_font_info( CFF_Face face, 468 PS_FontInfoRec* afont_info ) 469 { 470 CFF_Font cff = (CFF_Font)face->extra.data; 471 FT_Error error = FT_Err_Ok; 472 473 474 if ( cff && !cff->font_info ) 475 { 476 CFF_FontRecDict dict = &cff->top_font.font_dict; 477 PS_FontInfoRec *font_info = NULL; 478 FT_Memory memory = face->root.memory; 479 480 481 if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) ) 482 goto Fail; 483 484 font_info->version = cff_index_get_sid_string( cff, 485 dict->version ); 486 font_info->notice = cff_index_get_sid_string( cff, 487 dict->notice ); 488 font_info->full_name = cff_index_get_sid_string( cff, 489 dict->full_name ); 490 font_info->family_name = cff_index_get_sid_string( cff, 491 dict->family_name ); 492 font_info->weight = cff_index_get_sid_string( cff, 493 dict->weight ); 494 font_info->italic_angle = dict->italic_angle; 495 font_info->is_fixed_pitch = dict->is_fixed_pitch; 496 font_info->underline_position = (FT_Short)dict->underline_position; 497 font_info->underline_thickness = (FT_UShort)dict->underline_thickness; 498 499 cff->font_info = font_info; 500 } 501 502 if ( cff ) 503 *afont_info = *cff->font_info; 504 505 Fail: 506 return error; 507 } 508 509 510 static FT_Error cff_ps_get_font_extra(CFF_Face face,PS_FontExtraRec * afont_extra)511 cff_ps_get_font_extra( CFF_Face face, 512 PS_FontExtraRec* afont_extra ) 513 { 514 CFF_Font cff = (CFF_Font)face->extra.data; 515 FT_Error error = FT_Err_Ok; 516 517 518 if ( cff && cff->font_extra == NULL ) 519 { 520 CFF_FontRecDict dict = &cff->top_font.font_dict; 521 PS_FontExtraRec* font_extra = NULL; 522 FT_Memory memory = face->root.memory; 523 FT_String* embedded_postscript; 524 525 526 if ( FT_ALLOC( font_extra, sizeof ( *font_extra ) ) ) 527 goto Fail; 528 529 font_extra->fs_type = 0U; 530 531 embedded_postscript = cff_index_get_sid_string( 532 cff, 533 dict->embedded_postscript ); 534 if ( embedded_postscript ) 535 { 536 FT_String* start_fstype; 537 FT_String* start_def; 538 539 540 /* Identify the XYZ integer in `/FSType XYZ def' substring. */ 541 if ( ( start_fstype = ft_strstr( embedded_postscript, 542 "/FSType" ) ) != NULL && 543 ( start_def = ft_strstr( start_fstype + 544 sizeof ( "/FSType" ) - 1, 545 "def" ) ) != NULL ) 546 { 547 FT_String* s; 548 549 550 for ( s = start_fstype + sizeof ( "/FSType" ) - 1; 551 s != start_def; 552 s++ ) 553 { 554 if ( *s >= '0' && *s <= '9' ) 555 { 556 if ( font_extra->fs_type >= ( FT_USHORT_MAX - 9 ) / 10 ) 557 { 558 /* Overflow - ignore the FSType value. */ 559 font_extra->fs_type = 0U; 560 break; 561 } 562 563 font_extra->fs_type *= 10; 564 font_extra->fs_type += (FT_UShort)( *s - '0' ); 565 } 566 else if ( *s != ' ' && *s != '\n' && *s != '\r' ) 567 { 568 /* Non-whitespace character between `/FSType' and next `def' */ 569 /* - ignore the FSType value. */ 570 font_extra->fs_type = 0U; 571 break; 572 } 573 } 574 } 575 } 576 577 cff->font_extra = font_extra; 578 } 579 580 if ( cff ) 581 *afont_extra = *cff->font_extra; 582 583 Fail: 584 return error; 585 } 586 587 588 FT_DEFINE_SERVICE_PSINFOREC( 589 cff_service_ps_info, 590 591 (PS_GetFontInfoFunc) cff_ps_get_font_info, /* ps_get_font_info */ 592 (PS_GetFontExtraFunc) cff_ps_get_font_extra, /* ps_get_font_extra */ 593 (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names, /* ps_has_glyph_names */ 594 /* unsupported with CFF fonts */ 595 (PS_GetFontPrivateFunc)NULL, /* ps_get_font_private */ 596 /* not implemented */ 597 (PS_GetFontValueFunc) NULL /* ps_get_font_value */ 598 ) 599 600 601 /* 602 * POSTSCRIPT NAME SERVICE 603 * 604 */ 605 606 static const char* cff_get_ps_name(CFF_Face face)607 cff_get_ps_name( CFF_Face face ) 608 { 609 CFF_Font cff = (CFF_Font)face->extra.data; 610 SFNT_Service sfnt = (SFNT_Service)face->sfnt; 611 612 613 /* following the OpenType specification 1.7, we return the name stored */ 614 /* in the `name' table for a CFF wrapped into an SFNT container */ 615 616 if ( FT_IS_SFNT( FT_FACE( face ) ) && sfnt ) 617 { 618 FT_Library library = FT_FACE_LIBRARY( face ); 619 FT_Module sfnt_module = FT_Get_Module( library, "sfnt" ); 620 FT_Service_PsFontName service = 621 (FT_Service_PsFontName)ft_module_get_service( 622 sfnt_module, 623 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, 624 0 ); 625 626 627 if ( service && service->get_ps_font_name ) 628 return service->get_ps_font_name( FT_FACE( face ) ); 629 } 630 631 return (const char*)cff->font_name; 632 } 633 634 635 FT_DEFINE_SERVICE_PSFONTNAMEREC( 636 cff_service_ps_name, 637 638 (FT_PsName_GetFunc)cff_get_ps_name /* get_ps_font_name */ 639 ) 640 641 642 /* 643 * TT CMAP INFO 644 * 645 * If the charmap is a synthetic Unicode encoding cmap or 646 * a Type 1 standard (or expert) encoding cmap, hide TT CMAP INFO 647 * service defined in SFNT module. 648 * 649 * Otherwise call the service function in the sfnt module. 650 * 651 */ 652 static FT_Error cff_get_cmap_info(FT_CharMap charmap,TT_CMapInfo * cmap_info)653 cff_get_cmap_info( FT_CharMap charmap, 654 TT_CMapInfo *cmap_info ) 655 { 656 FT_CMap cmap = FT_CMAP( charmap ); 657 FT_Error error = FT_Err_Ok; 658 659 FT_Face face = FT_CMAP_FACE( cmap ); 660 FT_Library library = FT_FACE_LIBRARY( face ); 661 662 663 if ( cmap->clazz != &cff_cmap_encoding_class_rec && 664 cmap->clazz != &cff_cmap_unicode_class_rec ) 665 { 666 FT_Module sfnt = FT_Get_Module( library, "sfnt" ); 667 FT_Service_TTCMaps service = 668 (FT_Service_TTCMaps)ft_module_get_service( sfnt, 669 FT_SERVICE_ID_TT_CMAP, 670 0 ); 671 672 673 if ( service && service->get_cmap_info ) 674 error = service->get_cmap_info( charmap, cmap_info ); 675 } 676 else 677 error = FT_THROW( Invalid_CharMap_Format ); 678 679 return error; 680 } 681 682 683 FT_DEFINE_SERVICE_TTCMAPSREC( 684 cff_service_get_cmap_info, 685 686 (TT_CMap_Info_GetFunc)cff_get_cmap_info /* get_cmap_info */ 687 ) 688 689 690 /* 691 * CID INFO SERVICE 692 * 693 */ 694 static FT_Error cff_get_ros(CFF_Face face,const char ** registry,const char ** ordering,FT_Int * supplement)695 cff_get_ros( CFF_Face face, 696 const char* *registry, 697 const char* *ordering, 698 FT_Int *supplement ) 699 { 700 FT_Error error = FT_Err_Ok; 701 CFF_Font cff = (CFF_Font)face->extra.data; 702 703 704 if ( cff ) 705 { 706 CFF_FontRecDict dict = &cff->top_font.font_dict; 707 708 709 if ( dict->cid_registry == 0xFFFFU ) 710 { 711 error = FT_THROW( Invalid_Argument ); 712 goto Fail; 713 } 714 715 if ( registry ) 716 { 717 if ( !cff->registry ) 718 cff->registry = cff_index_get_sid_string( cff, 719 dict->cid_registry ); 720 *registry = cff->registry; 721 } 722 723 if ( ordering ) 724 { 725 if ( !cff->ordering ) 726 cff->ordering = cff_index_get_sid_string( cff, 727 dict->cid_ordering ); 728 *ordering = cff->ordering; 729 } 730 731 /* 732 * XXX: According to Adobe TechNote #5176, the supplement in CFF 733 * can be a real number. We truncate it to fit public API 734 * since freetype-2.3.6. 735 */ 736 if ( supplement ) 737 { 738 if ( dict->cid_supplement < FT_INT_MIN || 739 dict->cid_supplement > FT_INT_MAX ) 740 FT_TRACE1(( "cff_get_ros: too large supplement %ld is truncated\n", 741 dict->cid_supplement )); 742 *supplement = (FT_Int)dict->cid_supplement; 743 } 744 } 745 746 Fail: 747 return error; 748 } 749 750 751 static FT_Error cff_get_is_cid(CFF_Face face,FT_Bool * is_cid)752 cff_get_is_cid( CFF_Face face, 753 FT_Bool *is_cid ) 754 { 755 FT_Error error = FT_Err_Ok; 756 CFF_Font cff = (CFF_Font)face->extra.data; 757 758 759 *is_cid = 0; 760 761 if ( cff ) 762 { 763 CFF_FontRecDict dict = &cff->top_font.font_dict; 764 765 766 if ( dict->cid_registry != 0xFFFFU ) 767 *is_cid = 1; 768 } 769 770 return error; 771 } 772 773 774 static FT_Error cff_get_cid_from_glyph_index(CFF_Face face,FT_UInt glyph_index,FT_UInt * cid)775 cff_get_cid_from_glyph_index( CFF_Face face, 776 FT_UInt glyph_index, 777 FT_UInt *cid ) 778 { 779 FT_Error error = FT_Err_Ok; 780 CFF_Font cff; 781 782 783 cff = (CFF_Font)face->extra.data; 784 785 if ( cff ) 786 { 787 FT_UInt c; 788 CFF_FontRecDict dict = &cff->top_font.font_dict; 789 790 791 if ( dict->cid_registry == 0xFFFFU ) 792 { 793 error = FT_THROW( Invalid_Argument ); 794 goto Fail; 795 } 796 797 if ( glyph_index >= cff->num_glyphs ) 798 { 799 error = FT_THROW( Invalid_Argument ); 800 goto Fail; 801 } 802 803 c = cff->charset.sids[glyph_index]; 804 805 if ( cid ) 806 *cid = c; 807 } 808 809 Fail: 810 return error; 811 } 812 813 814 FT_DEFINE_SERVICE_CIDREC( 815 cff_service_cid_info, 816 817 (FT_CID_GetRegistryOrderingSupplementFunc) 818 cff_get_ros, /* get_ros */ 819 (FT_CID_GetIsInternallyCIDKeyedFunc) 820 cff_get_is_cid, /* get_is_cid */ 821 (FT_CID_GetCIDFromGlyphIndexFunc) 822 cff_get_cid_from_glyph_index /* get_cid_from_glyph_index */ 823 ) 824 825 826 /* 827 * PROPERTY SERVICE 828 * 829 */ 830 831 FT_DEFINE_SERVICE_PROPERTIESREC( 832 cff_service_properties, 833 834 (FT_Properties_SetFunc)ps_property_set, /* set_property */ 835 (FT_Properties_GetFunc)ps_property_get ) /* get_property */ 836 837 838 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 839 840 /* 841 * MULTIPLE MASTER SERVICE 842 * 843 */ 844 845 static FT_Error cff_set_mm_blend(CFF_Face face,FT_UInt num_coords,FT_Fixed * coords)846 cff_set_mm_blend( CFF_Face face, 847 FT_UInt num_coords, 848 FT_Fixed* coords ) 849 { 850 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; 851 852 853 return mm->set_mm_blend( FT_FACE( face ), num_coords, coords ); 854 } 855 856 857 static FT_Error cff_get_mm_blend(CFF_Face face,FT_UInt num_coords,FT_Fixed * coords)858 cff_get_mm_blend( CFF_Face face, 859 FT_UInt num_coords, 860 FT_Fixed* coords ) 861 { 862 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; 863 864 865 return mm->get_mm_blend( FT_FACE( face ), num_coords, coords ); 866 } 867 868 869 static FT_Error cff_set_mm_weightvector(CFF_Face face,FT_UInt len,FT_Fixed * weightvector)870 cff_set_mm_weightvector( CFF_Face face, 871 FT_UInt len, 872 FT_Fixed* weightvector ) 873 { 874 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; 875 876 877 return mm->set_mm_weightvector( FT_FACE( face ), len, weightvector ); 878 } 879 880 881 static FT_Error cff_get_mm_weightvector(CFF_Face face,FT_UInt * len,FT_Fixed * weightvector)882 cff_get_mm_weightvector( CFF_Face face, 883 FT_UInt* len, 884 FT_Fixed* weightvector ) 885 { 886 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; 887 888 889 return mm->get_mm_weightvector( FT_FACE( face ), len, weightvector ); 890 } 891 892 893 static FT_Error cff_get_mm_var(CFF_Face face,FT_MM_Var ** master)894 cff_get_mm_var( CFF_Face face, 895 FT_MM_Var* *master ) 896 { 897 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; 898 899 900 return mm->get_mm_var( FT_FACE( face ), master ); 901 } 902 903 904 static FT_Error cff_set_var_design(CFF_Face face,FT_UInt num_coords,FT_Fixed * coords)905 cff_set_var_design( CFF_Face face, 906 FT_UInt num_coords, 907 FT_Fixed* coords ) 908 { 909 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; 910 911 912 return mm->set_var_design( FT_FACE( face ), num_coords, coords ); 913 } 914 915 916 static FT_Error cff_get_var_design(CFF_Face face,FT_UInt num_coords,FT_Fixed * coords)917 cff_get_var_design( CFF_Face face, 918 FT_UInt num_coords, 919 FT_Fixed* coords ) 920 { 921 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; 922 923 924 return mm->get_var_design( FT_FACE( face ), num_coords, coords ); 925 } 926 927 928 static FT_Error cff_set_instance(CFF_Face face,FT_UInt instance_index)929 cff_set_instance( CFF_Face face, 930 FT_UInt instance_index ) 931 { 932 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; 933 934 935 return mm->set_instance( FT_FACE( face ), instance_index ); 936 } 937 938 939 FT_DEFINE_SERVICE_MULTIMASTERSREC( 940 cff_service_multi_masters, 941 942 (FT_Get_MM_Func) NULL, /* get_mm */ 943 (FT_Set_MM_Design_Func) NULL, /* set_mm_design */ 944 (FT_Set_MM_Blend_Func) cff_set_mm_blend, /* set_mm_blend */ 945 (FT_Get_MM_Blend_Func) cff_get_mm_blend, /* get_mm_blend */ 946 (FT_Get_MM_Var_Func) cff_get_mm_var, /* get_mm_var */ 947 (FT_Set_Var_Design_Func) cff_set_var_design, /* set_var_design */ 948 (FT_Get_Var_Design_Func) cff_get_var_design, /* get_var_design */ 949 (FT_Set_Instance_Func) cff_set_instance, /* set_instance */ 950 (FT_Set_MM_WeightVector_Func)cff_set_mm_weightvector, /* set_mm_weightvector */ 951 (FT_Get_MM_WeightVector_Func)cff_get_mm_weightvector, /* get_mm_weightvector */ 952 953 (FT_Get_Var_Blend_Func) cff_get_var_blend, /* get_var_blend */ 954 (FT_Done_Blend_Func) cff_done_blend /* done_blend */ 955 ) 956 957 958 /* 959 * METRICS VARIATIONS SERVICE 960 * 961 */ 962 963 static FT_Error cff_hadvance_adjust(CFF_Face face,FT_UInt gindex,FT_Int * avalue)964 cff_hadvance_adjust( CFF_Face face, 965 FT_UInt gindex, 966 FT_Int *avalue ) 967 { 968 FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; 969 970 971 return var->hadvance_adjust( FT_FACE( face ), gindex, avalue ); 972 } 973 974 975 static void cff_metrics_adjust(CFF_Face face)976 cff_metrics_adjust( CFF_Face face ) 977 { 978 FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; 979 980 981 var->metrics_adjust( FT_FACE( face ) ); 982 } 983 984 985 FT_DEFINE_SERVICE_METRICSVARIATIONSREC( 986 cff_service_metrics_variations, 987 988 (FT_HAdvance_Adjust_Func)cff_hadvance_adjust, /* hadvance_adjust */ 989 (FT_LSB_Adjust_Func) NULL, /* lsb_adjust */ 990 (FT_RSB_Adjust_Func) NULL, /* rsb_adjust */ 991 992 (FT_VAdvance_Adjust_Func)NULL, /* vadvance_adjust */ 993 (FT_TSB_Adjust_Func) NULL, /* tsb_adjust */ 994 (FT_BSB_Adjust_Func) NULL, /* bsb_adjust */ 995 (FT_VOrg_Adjust_Func) NULL, /* vorg_adjust */ 996 997 (FT_Metrics_Adjust_Func) cff_metrics_adjust /* metrics_adjust */ 998 ) 999 #endif 1000 1001 1002 /* 1003 * CFFLOAD SERVICE 1004 * 1005 */ 1006 1007 FT_DEFINE_SERVICE_CFFLOADREC( 1008 cff_service_cff_load, 1009 1010 (FT_Get_Standard_Encoding_Func)cff_get_standard_encoding, 1011 (FT_Load_Private_Dict_Func) cff_load_private_dict, 1012 (FT_FD_Select_Get_Func) cff_fd_select_get, 1013 (FT_Blend_Check_Vector_Func) cff_blend_check_vector, 1014 (FT_Blend_Build_Vector_Func) cff_blend_build_vector 1015 ) 1016 1017 1018 /*************************************************************************/ 1019 /*************************************************************************/ 1020 /*************************************************************************/ 1021 /**** ****/ 1022 /**** ****/ 1023 /**** D R I V E R I N T E R F A C E ****/ 1024 /**** ****/ 1025 /**** ****/ 1026 /*************************************************************************/ 1027 /*************************************************************************/ 1028 /*************************************************************************/ 1029 1030 #if !defined FT_CONFIG_OPTION_NO_GLYPH_NAMES && \ 1031 defined TT_CONFIG_OPTION_GX_VAR_SUPPORT 1032 FT_DEFINE_SERVICEDESCREC10( 1033 cff_services, 1034 1035 FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF, 1036 FT_SERVICE_ID_MULTI_MASTERS, &cff_service_multi_masters, 1037 FT_SERVICE_ID_METRICS_VARIATIONS, &cff_service_metrics_variations, 1038 FT_SERVICE_ID_POSTSCRIPT_INFO, &cff_service_ps_info, 1039 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name, 1040 FT_SERVICE_ID_GLYPH_DICT, &cff_service_glyph_dict, 1041 FT_SERVICE_ID_TT_CMAP, &cff_service_get_cmap_info, 1042 FT_SERVICE_ID_CID, &cff_service_cid_info, 1043 FT_SERVICE_ID_PROPERTIES, &cff_service_properties, 1044 FT_SERVICE_ID_CFF_LOAD, &cff_service_cff_load 1045 ) 1046 #elif !defined FT_CONFIG_OPTION_NO_GLYPH_NAMES 1047 FT_DEFINE_SERVICEDESCREC8( 1048 cff_services, 1049 1050 FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF, 1051 FT_SERVICE_ID_POSTSCRIPT_INFO, &cff_service_ps_info, 1052 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name, 1053 FT_SERVICE_ID_GLYPH_DICT, &cff_service_glyph_dict, 1054 FT_SERVICE_ID_TT_CMAP, &cff_service_get_cmap_info, 1055 FT_SERVICE_ID_CID, &cff_service_cid_info, 1056 FT_SERVICE_ID_PROPERTIES, &cff_service_properties, 1057 FT_SERVICE_ID_CFF_LOAD, &cff_service_cff_load 1058 ) 1059 #elif defined TT_CONFIG_OPTION_GX_VAR_SUPPORT 1060 FT_DEFINE_SERVICEDESCREC9( 1061 cff_services, 1062 1063 FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF, 1064 FT_SERVICE_ID_MULTI_MASTERS, &cff_service_multi_masters, 1065 FT_SERVICE_ID_METRICS_VARIATIONS, &cff_service_metrics_var, 1066 FT_SERVICE_ID_POSTSCRIPT_INFO, &cff_service_ps_info, 1067 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name, 1068 FT_SERVICE_ID_TT_CMAP, &cff_service_get_cmap_info, 1069 FT_SERVICE_ID_CID, &cff_service_cid_info, 1070 FT_SERVICE_ID_PROPERTIES, &cff_service_properties, 1071 FT_SERVICE_ID_CFF_LOAD, &cff_service_cff_load 1072 ) 1073 #else 1074 FT_DEFINE_SERVICEDESCREC7( 1075 cff_services, 1076 1077 FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF, 1078 FT_SERVICE_ID_POSTSCRIPT_INFO, &cff_service_ps_info, 1079 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name, 1080 FT_SERVICE_ID_TT_CMAP, &cff_service_get_cmap_info, 1081 FT_SERVICE_ID_CID, &cff_service_cid_info, 1082 FT_SERVICE_ID_PROPERTIES, &cff_service_properties, 1083 FT_SERVICE_ID_CFF_LOAD, &cff_service_cff_load 1084 ) 1085 #endif 1086 1087 FT_CALLBACK_DEF(FT_Module_Interface)1088 FT_CALLBACK_DEF( FT_Module_Interface ) 1089 cff_get_interface( FT_Module driver, /* CFF_Driver */ 1090 const char* module_interface ) 1091 { 1092 FT_Library library; 1093 FT_Module sfnt; 1094 FT_Module_Interface result; 1095 1096 1097 result = ft_service_list_lookup( cff_services, module_interface ); 1098 if ( result ) 1099 return result; 1100 1101 /* `driver' is not yet evaluated */ 1102 if ( !driver ) 1103 return NULL; 1104 library = driver->library; 1105 if ( !library ) 1106 return NULL; 1107 1108 /* we pass our request to the `sfnt' module */ 1109 sfnt = FT_Get_Module( library, "sfnt" ); 1110 1111 return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0; 1112 } 1113 1114 1115 /* The FT_DriverInterface structure is defined in ftdriver.h. */ 1116 1117 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 1118 #define CFF_SIZE_SELECT cff_size_select 1119 #else 1120 #define CFF_SIZE_SELECT 0 1121 #endif 1122 1123 FT_DEFINE_DRIVER( 1124 cff_driver_class, 1125 1126 FT_MODULE_FONT_DRIVER | 1127 FT_MODULE_DRIVER_SCALABLE | 1128 FT_MODULE_DRIVER_HAS_HINTER | 1129 FT_MODULE_DRIVER_HINTS_LIGHTLY, 1130 1131 sizeof ( PS_DriverRec ), 1132 "cff", 1133 0x10000L, 1134 0x20000L, 1135 1136 NULL, /* module-specific interface */ 1137 1138 cff_driver_init, /* FT_Module_Constructor module_init */ 1139 cff_driver_done, /* FT_Module_Destructor module_done */ 1140 cff_get_interface, /* FT_Module_Requester get_interface */ 1141 1142 sizeof ( TT_FaceRec ), 1143 sizeof ( CFF_SizeRec ), 1144 sizeof ( CFF_GlyphSlotRec ), 1145 1146 cff_face_init, /* FT_Face_InitFunc init_face */ 1147 cff_face_done, /* FT_Face_DoneFunc done_face */ 1148 cff_size_init, /* FT_Size_InitFunc init_size */ 1149 cff_size_done, /* FT_Size_DoneFunc done_size */ 1150 cff_slot_init, /* FT_Slot_InitFunc init_slot */ 1151 cff_slot_done, /* FT_Slot_DoneFunc done_slot */ 1152 1153 cff_glyph_load, /* FT_Slot_LoadFunc load_glyph */ 1154 1155 cff_get_kerning, /* FT_Face_GetKerningFunc get_kerning */ 1156 NULL, /* FT_Face_AttachFunc attach_file */ 1157 cff_get_advances, /* FT_Face_GetAdvancesFunc get_advances */ 1158 1159 cff_size_request, /* FT_Size_RequestFunc request_size */ 1160 CFF_SIZE_SELECT /* FT_Size_SelectFunc select_size */ 1161 ) 1162 1163 1164 /* END */ 1165