1 /**************************************************************************** 2 * 3 * cffdrivr.c 4 * 5 * OpenType font driver implementation (body). 6 * 7 * Copyright (C) 1996-2023 by 8 * David Turner, Robert Wilhelm, Werner Lemberg, and Dominik Röttsches. 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 face,FT_UInt left_glyph,FT_UInt right_glyph,FT_Vector * kerning)111 cff_get_kerning( FT_Face face, /* CFF_Face */ 112 FT_UInt left_glyph, 113 FT_UInt right_glyph, 114 FT_Vector* kerning ) 115 { 116 CFF_Face cffface = (CFF_Face)face; 117 SFNT_Service sfnt = (SFNT_Service)cffface->sfnt; 118 119 120 kerning->x = 0; 121 kerning->y = 0; 122 123 if ( sfnt ) 124 kerning->x = sfnt->get_kerning( cffface, 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 slot,FT_Size size,FT_UInt glyph_index,FT_Int32 load_flags)161 cff_glyph_load( FT_GlyphSlot slot, /* CFF_GlyphSlot */ 162 FT_Size size, /* CFF_Size */ 163 FT_UInt glyph_index, 164 FT_Int32 load_flags ) 165 { 166 FT_Error error; 167 CFF_GlyphSlot cffslot = (CFF_GlyphSlot)slot; 168 CFF_Size cffsize = (CFF_Size)size; 169 170 171 if ( !cffslot ) 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 ( !cffsize ) 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 ( size->face != slot->face ) 188 return FT_THROW( Invalid_Face_Handle ); 189 } 190 191 /* now load the glyph outline if necessary */ 192 error = cff_slot_load( cffslot, cffsize, 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 CFF_Face cffface = (CFF_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 !( cffface->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 ( !cffface->vertical_info ) 237 goto Missing_Table; 238 239 for ( nn = 0; nn < count; nn++ ) 240 { 241 FT_UShort ah; 242 243 244 ( (SFNT_Service)cffface->sfnt )->get_metrics( cffface, 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 !( cffface->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 ( !cffface->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)cffface->sfnt )->get_metrics( cffface, 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 FT_CALLBACK_DEF( FT_Error ) cff_get_glyph_name(FT_Face face,FT_UInt glyph_index,FT_Pointer buffer,FT_UInt buffer_max)316 cff_get_glyph_name( FT_Face face, /* CFF_Face */ 317 FT_UInt glyph_index, 318 FT_Pointer buffer, 319 FT_UInt buffer_max ) 320 { 321 CFF_Face cffface = (CFF_Face)face; 322 CFF_Font font = (CFF_Font)cffface->extra.data; 323 FT_String* gname; 324 FT_UShort sid; 325 FT_Error error; 326 327 328 /* CFF2 table does not have glyph names; */ 329 /* we need to use `post' table method */ 330 if ( font->version_major == 2 ) 331 { 332 FT_Library library = FT_FACE_LIBRARY( face ); 333 FT_Module sfnt_module = FT_Get_Module( library, "sfnt" ); 334 FT_Service_GlyphDict service = 335 (FT_Service_GlyphDict)ft_module_get_service( 336 sfnt_module, 337 FT_SERVICE_ID_GLYPH_DICT, 338 0 ); 339 340 341 if ( service && service->get_name ) 342 return service->get_name( face, glyph_index, buffer, buffer_max ); 343 else 344 { 345 FT_ERROR(( "cff_get_glyph_name:" 346 " cannot get glyph name from a CFF2 font\n" )); 347 FT_ERROR(( " " 348 " without the `psnames' module\n" )); 349 error = FT_THROW( Missing_Module ); 350 goto Exit; 351 } 352 } 353 354 if ( !font->psnames ) 355 { 356 FT_ERROR(( "cff_get_glyph_name:" 357 " cannot get glyph name from CFF & CEF fonts\n" )); 358 FT_ERROR(( " " 359 " without the `psnames' module\n" )); 360 error = FT_THROW( Missing_Module ); 361 goto Exit; 362 } 363 364 /* first, locate the sid in the charset table */ 365 sid = font->charset.sids[glyph_index]; 366 367 /* now, look up the name itself */ 368 gname = cff_index_get_sid_string( font, sid ); 369 370 if ( gname ) 371 FT_STRCPYN( buffer, gname, buffer_max ); 372 373 error = FT_Err_Ok; 374 375 Exit: 376 return error; 377 } 378 379 380 FT_CALLBACK_DEF( FT_UInt ) cff_get_name_index(FT_Face face,const FT_String * glyph_name)381 cff_get_name_index( FT_Face face, /* CFF_Face */ 382 const FT_String* glyph_name ) 383 { 384 CFF_Face cffface = (CFF_Face)face; 385 CFF_Font cff = (CFF_Font)cffface->extra.data; 386 CFF_Charset charset = &cff->charset; 387 FT_Service_PsCMaps psnames; 388 FT_String* name; 389 FT_UShort sid; 390 FT_UInt i; 391 392 393 /* CFF2 table does not have glyph names; */ 394 /* we need to use `post' table method */ 395 if ( cff->version_major == 2 ) 396 { 397 FT_Library library = FT_FACE_LIBRARY( face ); 398 FT_Module sfnt_module = FT_Get_Module( library, "sfnt" ); 399 FT_Service_GlyphDict service = 400 (FT_Service_GlyphDict)ft_module_get_service( 401 sfnt_module, 402 FT_SERVICE_ID_GLYPH_DICT, 403 0 ); 404 405 406 if ( service && service->name_index ) 407 return service->name_index( face, glyph_name ); 408 else 409 { 410 FT_ERROR(( "cff_get_name_index:" 411 " cannot get glyph index from a CFF2 font\n" )); 412 FT_ERROR(( " " 413 " without the `psnames' module\n" )); 414 return 0; 415 } 416 } 417 418 FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); 419 if ( !psnames ) 420 return 0; 421 422 for ( i = 0; i < cff->num_glyphs; i++ ) 423 { 424 sid = charset->sids[i]; 425 426 if ( sid > 390 ) 427 name = cff_index_get_string( cff, sid - 391 ); 428 else 429 name = (FT_String *)psnames->adobe_std_strings( sid ); 430 431 if ( !name ) 432 continue; 433 434 if ( !ft_strcmp( glyph_name, name ) ) 435 return i; 436 } 437 438 return 0; 439 } 440 441 FT_DEFINE_SERVICE_GLYPHDICTREC(cff_service_glyph_dict,cff_get_glyph_name,cff_get_name_index)442 FT_DEFINE_SERVICE_GLYPHDICTREC( 443 cff_service_glyph_dict, 444 445 cff_get_glyph_name, /* FT_GlyphDict_GetNameFunc get_name */ 446 cff_get_name_index /* FT_GlyphDict_NameIndexFunc name_index */ 447 ) 448 449 450 /* 451 * POSTSCRIPT INFO SERVICE 452 * 453 */ 454 455 FT_CALLBACK_DEF( FT_Int ) 456 cff_ps_has_glyph_names( FT_Face face ) 457 { 458 return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0; 459 } 460 461 462 FT_CALLBACK_DEF( FT_Error ) cff_ps_get_font_info(FT_Face face,PS_FontInfoRec * afont_info)463 cff_ps_get_font_info( FT_Face face, /* CFF_Face */ 464 PS_FontInfoRec* afont_info ) 465 { 466 CFF_Face cffface = (CFF_Face)face; 467 CFF_Font cff = (CFF_Font)cffface->extra.data; 468 FT_Error error = FT_Err_Ok; 469 470 471 if ( cffface->is_cff2 ) 472 { 473 error = FT_THROW( Invalid_Argument ); 474 goto Fail; 475 } 476 477 if ( cff && !cff->font_info ) 478 { 479 CFF_FontRecDict dict = &cff->top_font.font_dict; 480 FT_Memory memory = FT_FACE_MEMORY( face ); 481 PS_FontInfoRec* font_info = NULL; 482 483 484 if ( FT_QNEW( font_info ) ) 485 goto Fail; 486 487 font_info->version = cff_index_get_sid_string( cff, 488 dict->version ); 489 font_info->notice = cff_index_get_sid_string( cff, 490 dict->notice ); 491 font_info->full_name = cff_index_get_sid_string( cff, 492 dict->full_name ); 493 font_info->family_name = cff_index_get_sid_string( cff, 494 dict->family_name ); 495 font_info->weight = cff_index_get_sid_string( cff, 496 dict->weight ); 497 font_info->italic_angle = dict->italic_angle; 498 font_info->is_fixed_pitch = dict->is_fixed_pitch; 499 font_info->underline_position = (FT_Short)dict->underline_position; 500 font_info->underline_thickness = (FT_UShort)dict->underline_thickness; 501 502 cff->font_info = font_info; 503 } 504 505 if ( cff ) 506 *afont_info = *cff->font_info; 507 508 Fail: 509 return error; 510 } 511 512 513 FT_CALLBACK_DEF( FT_Error ) cff_ps_get_font_extra(FT_Face face,PS_FontExtraRec * afont_extra)514 cff_ps_get_font_extra( FT_Face face, /* CFF_Face */ 515 PS_FontExtraRec* afont_extra ) 516 { 517 CFF_Face cffface = (CFF_Face)face; 518 CFF_Font cff = (CFF_Font)cffface->extra.data; 519 FT_Error error = FT_Err_Ok; 520 521 522 if ( cff && !cff->font_extra ) 523 { 524 CFF_FontRecDict dict = &cff->top_font.font_dict; 525 FT_Memory memory = FT_FACE_MEMORY( face ); 526 PS_FontExtraRec* font_extra = NULL; 527 FT_String* embedded_postscript; 528 529 530 if ( FT_QNEW( font_extra ) ) 531 goto Fail; 532 533 font_extra->fs_type = 0U; 534 535 embedded_postscript = cff_index_get_sid_string( 536 cff, 537 dict->embedded_postscript ); 538 if ( embedded_postscript ) 539 { 540 FT_String* start_fstype; 541 FT_String* start_def; 542 543 544 /* Identify the XYZ integer in `/FSType XYZ def' substring. */ 545 if ( ( start_fstype = ft_strstr( embedded_postscript, 546 "/FSType" ) ) != NULL && 547 ( start_def = ft_strstr( start_fstype + 548 sizeof ( "/FSType" ) - 1, 549 "def" ) ) != NULL ) 550 { 551 FT_String* s; 552 553 554 for ( s = start_fstype + sizeof ( "/FSType" ) - 1; 555 s != start_def; 556 s++ ) 557 { 558 if ( *s >= '0' && *s <= '9' ) 559 { 560 if ( font_extra->fs_type >= ( FT_USHORT_MAX - 9 ) / 10 ) 561 { 562 /* Overflow - ignore the FSType value. */ 563 font_extra->fs_type = 0U; 564 break; 565 } 566 567 font_extra->fs_type *= 10; 568 font_extra->fs_type += (FT_UShort)( *s - '0' ); 569 } 570 else if ( *s != ' ' && *s != '\n' && *s != '\r' ) 571 { 572 /* Non-whitespace character between `/FSType' and next `def' */ 573 /* - ignore the FSType value. */ 574 font_extra->fs_type = 0U; 575 break; 576 } 577 } 578 } 579 } 580 581 cff->font_extra = font_extra; 582 } 583 584 if ( cff ) 585 *afont_extra = *cff->font_extra; 586 587 Fail: 588 return error; 589 } 590 591 FT_DEFINE_SERVICE_PSINFOREC(cff_service_ps_info,cff_ps_get_font_info,cff_ps_get_font_extra,cff_ps_has_glyph_names,NULL,NULL)592 FT_DEFINE_SERVICE_PSINFOREC( 593 cff_service_ps_info, 594 595 cff_ps_get_font_info, /* PS_GetFontInfoFunc ps_get_font_info */ 596 cff_ps_get_font_extra, /* PS_GetFontExtraFunc ps_get_font_extra */ 597 cff_ps_has_glyph_names, /* PS_HasGlyphNamesFunc ps_has_glyph_names */ 598 /* unsupported with CFF fonts */ 599 NULL, /* PS_GetFontPrivateFunc ps_get_font_private */ 600 /* not implemented */ 601 NULL /* PS_GetFontValueFunc ps_get_font_value */ 602 ) 603 604 605 /* 606 * POSTSCRIPT NAME SERVICE 607 * 608 */ 609 610 FT_CALLBACK_DEF( const char* ) 611 cff_get_ps_name( FT_Face face ) /* CFF_Face */ 612 { 613 CFF_Face cffface = (CFF_Face)face; 614 CFF_Font cff = (CFF_Font)cffface->extra.data; 615 SFNT_Service sfnt = (SFNT_Service)cffface->sfnt; 616 617 618 /* following the OpenType specification 1.7, we return the name stored */ 619 /* in the `name' table for a CFF wrapped into an SFNT container */ 620 621 if ( FT_IS_SFNT( face ) && sfnt ) 622 { 623 FT_Library library = FT_FACE_LIBRARY( face ); 624 FT_Module sfnt_module = FT_Get_Module( library, "sfnt" ); 625 FT_Service_PsFontName service = 626 (FT_Service_PsFontName)ft_module_get_service( 627 sfnt_module, 628 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, 629 0 ); 630 631 632 if ( service && service->get_ps_font_name ) 633 return service->get_ps_font_name( face ); 634 } 635 636 return cff ? (const char*)cff->font_name : NULL; 637 } 638 639 FT_DEFINE_SERVICE_PSFONTNAMEREC(cff_service_ps_name,cff_get_ps_name)640 FT_DEFINE_SERVICE_PSFONTNAMEREC( 641 cff_service_ps_name, 642 643 cff_get_ps_name /* FT_PsName_GetFunc get_ps_font_name */ 644 ) 645 646 647 /* 648 * TT CMAP INFO 649 * 650 * If the charmap is a synthetic Unicode encoding cmap or 651 * a Type 1 standard (or expert) encoding cmap, hide TT CMAP INFO 652 * service defined in SFNT module. 653 * 654 * Otherwise call the service function in the sfnt module. 655 * 656 */ 657 FT_CALLBACK_DEF( FT_Error ) 658 cff_get_cmap_info( FT_CharMap charmap, 659 TT_CMapInfo *cmap_info ) 660 { 661 FT_CMap cmap = FT_CMAP( charmap ); 662 FT_Error error = FT_Err_Ok; 663 664 FT_Face face = FT_CMAP_FACE( cmap ); 665 FT_Library library = FT_FACE_LIBRARY( face ); 666 667 668 if ( cmap->clazz != &cff_cmap_encoding_class_rec && 669 cmap->clazz != &cff_cmap_unicode_class_rec ) 670 { 671 FT_Module sfnt = FT_Get_Module( library, "sfnt" ); 672 FT_Service_TTCMaps service = 673 (FT_Service_TTCMaps)ft_module_get_service( sfnt, 674 FT_SERVICE_ID_TT_CMAP, 675 0 ); 676 677 678 if ( service && service->get_cmap_info ) 679 error = service->get_cmap_info( charmap, cmap_info ); 680 } 681 else 682 error = FT_THROW( Invalid_CharMap_Format ); 683 684 return error; 685 } 686 687 FT_DEFINE_SERVICE_TTCMAPSREC(cff_service_get_cmap_info,cff_get_cmap_info)688 FT_DEFINE_SERVICE_TTCMAPSREC( 689 cff_service_get_cmap_info, 690 691 cff_get_cmap_info /* TT_CMap_Info_GetFunc get_cmap_info */ 692 ) 693 694 695 /* 696 * CID INFO SERVICE 697 * 698 */ 699 FT_CALLBACK_DEF( FT_Error ) 700 cff_get_ros( FT_Face face, /* FT_Face */ 701 const char* *registry, 702 const char* *ordering, 703 FT_Int *supplement ) 704 { 705 FT_Error error = FT_Err_Ok; 706 CFF_Face cffface = (CFF_Face)face; 707 CFF_Font cff = (CFF_Font)cffface->extra.data; 708 709 710 if ( cff ) 711 { 712 CFF_FontRecDict dict = &cff->top_font.font_dict; 713 714 715 if ( dict->cid_registry == 0xFFFFU ) 716 { 717 error = FT_THROW( Invalid_Argument ); 718 goto Fail; 719 } 720 721 if ( registry ) 722 { 723 if ( !cff->registry ) 724 cff->registry = cff_index_get_sid_string( cff, 725 dict->cid_registry ); 726 *registry = cff->registry; 727 } 728 729 if ( ordering ) 730 { 731 if ( !cff->ordering ) 732 cff->ordering = cff_index_get_sid_string( cff, 733 dict->cid_ordering ); 734 *ordering = cff->ordering; 735 } 736 737 /* 738 * XXX: According to Adobe TechNote #5176, the supplement in CFF 739 * can be a real number. We truncate it to fit public API 740 * since freetype-2.3.6. 741 */ 742 if ( supplement ) 743 { 744 if ( dict->cid_supplement < FT_INT_MIN || 745 dict->cid_supplement > FT_INT_MAX ) 746 FT_TRACE1(( "cff_get_ros: too large supplement %ld is truncated\n", 747 dict->cid_supplement )); 748 *supplement = (FT_Int)dict->cid_supplement; 749 } 750 } 751 752 Fail: 753 return error; 754 } 755 756 757 FT_CALLBACK_DEF( FT_Error ) cff_get_is_cid(FT_Face face,FT_Bool * is_cid)758 cff_get_is_cid( FT_Face face, /* CFF_Face */ 759 FT_Bool *is_cid ) 760 { 761 FT_Error error = FT_Err_Ok; 762 CFF_Face cffface = (CFF_Face)face; 763 CFF_Font cff = (CFF_Font)cffface->extra.data; 764 765 766 *is_cid = 0; 767 768 if ( cff ) 769 { 770 CFF_FontRecDict dict = &cff->top_font.font_dict; 771 772 773 if ( dict->cid_registry != 0xFFFFU ) 774 *is_cid = 1; 775 } 776 777 return error; 778 } 779 780 781 FT_CALLBACK_DEF( FT_Error ) cff_get_cid_from_glyph_index(FT_Face face,FT_UInt glyph_index,FT_UInt * cid)782 cff_get_cid_from_glyph_index( FT_Face face, /* CFF_Face */ 783 FT_UInt glyph_index, 784 FT_UInt *cid ) 785 { 786 FT_Error error = FT_Err_Ok; 787 CFF_Face cffface = (CFF_Face)face; 788 CFF_Font cff = (CFF_Font)cffface->extra.data; 789 790 791 if ( cff ) 792 { 793 FT_UInt c; 794 CFF_FontRecDict dict = &cff->top_font.font_dict; 795 796 797 if ( dict->cid_registry == 0xFFFFU ) 798 { 799 error = FT_THROW( Invalid_Argument ); 800 goto Fail; 801 } 802 803 if ( glyph_index >= cff->num_glyphs ) 804 { 805 error = FT_THROW( Invalid_Argument ); 806 goto Fail; 807 } 808 809 c = cff->charset.sids[glyph_index]; 810 811 if ( cid ) 812 *cid = c; 813 } 814 815 Fail: 816 return error; 817 } 818 819 FT_DEFINE_SERVICE_CIDREC(cff_service_cid_info,cff_get_ros,cff_get_is_cid,cff_get_cid_from_glyph_index)820 FT_DEFINE_SERVICE_CIDREC( 821 cff_service_cid_info, 822 823 cff_get_ros, 824 /* FT_CID_GetRegistryOrderingSupplementFunc get_ros */ 825 cff_get_is_cid, 826 /* FT_CID_GetIsInternallyCIDKeyedFunc get_is_cid */ 827 cff_get_cid_from_glyph_index 828 /* FT_CID_GetCIDFromGlyphIndexFunc get_cid_from_glyph_index */ 829 ) 830 831 832 /* 833 * PROPERTY SERVICE 834 * 835 */ 836 837 FT_DEFINE_SERVICE_PROPERTIESREC( 838 cff_service_properties, 839 840 ps_property_set, /* FT_Properties_SetFunc set_property */ 841 ps_property_get /* FT_Properties_GetFunc get_property */ 842 ) 843 844 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 845 846 /* 847 * MULTIPLE MASTER SERVICE 848 * 849 */ 850 851 FT_CALLBACK_DEF( FT_Error ) 852 cff_set_mm_blend( FT_Face face, /* CFF_Face */ 853 FT_UInt num_coords, 854 FT_Fixed* coords ) 855 { 856 CFF_Face cffface = (CFF_Face)face; 857 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; 858 859 860 return mm->set_mm_blend( face, num_coords, coords ); 861 } 862 863 864 FT_CALLBACK_DEF( FT_Error ) cff_get_mm_blend(FT_Face face,FT_UInt num_coords,FT_Fixed * coords)865 cff_get_mm_blend( FT_Face face, /* CFF_Face */ 866 FT_UInt num_coords, 867 FT_Fixed* coords ) 868 { 869 CFF_Face cffface = (CFF_Face)face; 870 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; 871 872 873 return mm->get_mm_blend( face, num_coords, coords ); 874 } 875 876 877 FT_CALLBACK_DEF( FT_Error ) cff_set_mm_weightvector(FT_Face face,FT_UInt len,FT_Fixed * weightvector)878 cff_set_mm_weightvector( FT_Face face, /* CFF_Face */ 879 FT_UInt len, 880 FT_Fixed* weightvector ) 881 { 882 CFF_Face cffface = (CFF_Face)face; 883 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; 884 885 886 return mm->set_mm_weightvector( face, len, weightvector ); 887 } 888 889 890 FT_CALLBACK_DEF( FT_Error ) cff_get_mm_weightvector(FT_Face face,FT_UInt * len,FT_Fixed * weightvector)891 cff_get_mm_weightvector( FT_Face face, /* CFF_Face */ 892 FT_UInt* len, 893 FT_Fixed* weightvector ) 894 { 895 CFF_Face cffface = (CFF_Face)face; 896 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; 897 898 899 return mm->get_mm_weightvector( face, len, weightvector ); 900 } 901 902 903 FT_CALLBACK_DEF( void ) cff_construct_ps_name(FT_Face face)904 cff_construct_ps_name( FT_Face face ) /* CFF_Face */ 905 { 906 CFF_Face cffface = (CFF_Face)face; 907 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; 908 909 910 mm->construct_ps_name( face ); 911 } 912 913 914 FT_CALLBACK_DEF( FT_Error ) cff_get_mm_var(FT_Face face,FT_MM_Var ** master)915 cff_get_mm_var( FT_Face face, /* CFF_Face */ 916 FT_MM_Var* *master ) 917 { 918 CFF_Face cffface = (CFF_Face)face; 919 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; 920 921 922 return mm->get_mm_var( face, master ); 923 } 924 925 926 FT_CALLBACK_DEF( FT_Error ) cff_set_var_design(FT_Face face,FT_UInt num_coords,FT_Fixed * coords)927 cff_set_var_design( FT_Face face, /* CFF_Face */ 928 FT_UInt num_coords, 929 FT_Fixed* coords ) 930 { 931 CFF_Face cffface = (CFF_Face)face; 932 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; 933 934 935 return mm->set_var_design( face, num_coords, coords ); 936 } 937 938 939 FT_CALLBACK_DEF( FT_Error ) cff_get_var_design(FT_Face face,FT_UInt num_coords,FT_Fixed * coords)940 cff_get_var_design( FT_Face face, /* CFF_Face */ 941 FT_UInt num_coords, 942 FT_Fixed* coords ) 943 { 944 CFF_Face cffface = (CFF_Face)face; 945 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; 946 947 948 return mm->get_var_design( face, num_coords, coords ); 949 } 950 951 952 FT_CALLBACK_DEF( FT_Error ) cff_set_named_instance(FT_Face face,FT_UInt instance_index)953 cff_set_named_instance( FT_Face face, /* CFF_Face */ 954 FT_UInt instance_index ) 955 { 956 CFF_Face cffface = (CFF_Face)face; 957 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; 958 959 960 return mm->set_named_instance( face, instance_index ); 961 } 962 963 964 FT_CALLBACK_DEF( FT_Error ) cff_get_default_named_instance(FT_Face face,FT_UInt * instance_index)965 cff_get_default_named_instance( FT_Face face, /* CFF_Face */ 966 FT_UInt *instance_index ) 967 { 968 CFF_Face cffface = (CFF_Face)face; 969 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; 970 971 972 return mm->get_default_named_instance( face, instance_index ); 973 } 974 975 976 FT_CALLBACK_DEF( FT_Error ) cff_load_item_variation_store(FT_Face face,FT_ULong offset,GX_ItemVarStore itemStore)977 cff_load_item_variation_store( FT_Face face, /* CFF_Face */ 978 FT_ULong offset, 979 GX_ItemVarStore itemStore ) 980 { 981 CFF_Face cffface = (CFF_Face)face; 982 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; 983 984 985 return mm->load_item_var_store( face, offset, itemStore ); 986 } 987 988 989 FT_CALLBACK_DEF( FT_Error ) cff_load_delta_set_index_mapping(FT_Face face,FT_ULong offset,GX_DeltaSetIdxMap map,GX_ItemVarStore itemStore,FT_ULong table_len)990 cff_load_delta_set_index_mapping( FT_Face face, /* CFF_Face */ 991 FT_ULong offset, 992 GX_DeltaSetIdxMap map, 993 GX_ItemVarStore itemStore, 994 FT_ULong table_len ) 995 { 996 CFF_Face cffface = (CFF_Face)face; 997 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; 998 999 1000 return mm->load_delta_set_idx_map( face, offset, map, 1001 itemStore, table_len ); 1002 } 1003 1004 1005 FT_CALLBACK_DEF( FT_Int ) cff_get_item_delta(FT_Face face,GX_ItemVarStore itemStore,FT_UInt outerIndex,FT_UInt innerIndex)1006 cff_get_item_delta( FT_Face face, /* CFF_Face */ 1007 GX_ItemVarStore itemStore, 1008 FT_UInt outerIndex, 1009 FT_UInt innerIndex ) 1010 { 1011 CFF_Face cffface = (CFF_Face)face; 1012 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; 1013 1014 1015 return mm->get_item_delta( face, itemStore, outerIndex, innerIndex ); 1016 } 1017 1018 1019 FT_CALLBACK_DEF( void ) cff_done_item_variation_store(FT_Face face,GX_ItemVarStore itemStore)1020 cff_done_item_variation_store( FT_Face face, /* CFF_Face */ 1021 GX_ItemVarStore itemStore ) 1022 { 1023 CFF_Face cffface = (CFF_Face)face; 1024 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; 1025 1026 1027 mm->done_item_var_store( face, itemStore ); 1028 } 1029 1030 1031 FT_CALLBACK_DEF( void ) cff_done_delta_set_index_map(FT_Face face,GX_DeltaSetIdxMap deltaSetIdxMap)1032 cff_done_delta_set_index_map( FT_Face face, /* CFF_Face */ 1033 GX_DeltaSetIdxMap deltaSetIdxMap ) 1034 { 1035 CFF_Face cffface = (CFF_Face)face; 1036 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)cffface->mm; 1037 1038 1039 mm->done_delta_set_idx_map( face, deltaSetIdxMap ); 1040 } 1041 1042 1043 FT_DEFINE_SERVICE_MULTIMASTERSREC(cff_service_multi_masters,NULL,NULL,cff_set_mm_blend,cff_get_mm_blend,cff_get_mm_var,cff_set_var_design,cff_get_var_design,cff_set_named_instance,cff_get_default_named_instance,cff_set_mm_weightvector,cff_get_mm_weightvector,cff_construct_ps_name,cff_load_delta_set_index_mapping,cff_load_item_variation_store,cff_get_item_delta,cff_done_item_variation_store,cff_done_delta_set_index_map,cff_get_var_blend,cff_done_blend)1044 FT_DEFINE_SERVICE_MULTIMASTERSREC( 1045 cff_service_multi_masters, 1046 1047 NULL, /* FT_Get_MM_Func get_mm */ 1048 NULL, /* FT_Set_MM_Design_Func set_mm_design */ 1049 cff_set_mm_blend, /* FT_Set_MM_Blend_Func set_mm_blend */ 1050 cff_get_mm_blend, /* FT_Get_MM_Blend_Func get_mm_blend */ 1051 cff_get_mm_var, /* FT_Get_MM_Var_Func get_mm_var */ 1052 cff_set_var_design, /* FT_Set_Var_Design_Func set_var_design */ 1053 cff_get_var_design, /* FT_Get_Var_Design_Func get_var_design */ 1054 cff_set_named_instance, 1055 /* FT_Set_Named_Instance_Func set_named_instance */ 1056 cff_get_default_named_instance, 1057 /* FT_Get_Default_Named_Instance_Func get_default_named_instance */ 1058 cff_set_mm_weightvector, 1059 /* FT_Set_MM_WeightVector_Func set_mm_weightvector */ 1060 cff_get_mm_weightvector, 1061 /* FT_Get_MM_WeightVector_Func get_mm_weightvector */ 1062 cff_construct_ps_name, 1063 /* FT_Construct_PS_Name_Func construct_ps_name */ 1064 cff_load_delta_set_index_mapping, 1065 /* FT_Var_Load_Delta_Set_Idx_Map_Func load_delta_set_idx_map */ 1066 cff_load_item_variation_store, 1067 /* FT_Var_Load_Item_Var_Store_Func load_item_variation_store */ 1068 cff_get_item_delta, 1069 /* FT_Var_Get_Item_Delta_Func get_item_delta */ 1070 cff_done_item_variation_store, 1071 /* FT_Var_Done_Item_Var_Store_Func done_item_variation_store */ 1072 cff_done_delta_set_index_map, 1073 /* FT_Var_Done_Delta_Set_Idx_Map_Func done_delta_set_index_map */ 1074 cff_get_var_blend, /* FT_Get_Var_Blend_Func get_var_blend */ 1075 cff_done_blend /* FT_Done_Blend_Func done_blend */ 1076 ) 1077 1078 1079 /* 1080 * METRICS VARIATIONS SERVICE 1081 * 1082 */ 1083 1084 FT_CALLBACK_DEF( FT_Error ) 1085 cff_hadvance_adjust( FT_Face face, /* CFF_Face */ 1086 FT_UInt gindex, 1087 FT_Int *avalue ) 1088 { 1089 CFF_Face cffface = (CFF_Face)face; 1090 FT_Service_MetricsVariations 1091 var = (FT_Service_MetricsVariations)cffface->tt_var; 1092 1093 1094 return var->hadvance_adjust( face, gindex, avalue ); 1095 } 1096 1097 1098 FT_CALLBACK_DEF( void ) cff_metrics_adjust(FT_Face face)1099 cff_metrics_adjust( FT_Face face ) /* CFF_Face */ 1100 { 1101 CFF_Face cffface = (CFF_Face)face; 1102 FT_Service_MetricsVariations 1103 var = (FT_Service_MetricsVariations)cffface->tt_var; 1104 1105 1106 var->metrics_adjust( face ); 1107 } 1108 1109 FT_DEFINE_SERVICE_METRICSVARIATIONSREC(cff_service_metrics_variations,cff_hadvance_adjust,NULL,NULL,NULL,NULL,NULL,NULL,cff_metrics_adjust,NULL)1110 FT_DEFINE_SERVICE_METRICSVARIATIONSREC( 1111 cff_service_metrics_variations, 1112 1113 cff_hadvance_adjust, /* FT_HAdvance_Adjust_Func hadvance_adjust */ 1114 NULL, /* FT_LSB_Adjust_Func lsb_adjust */ 1115 NULL, /* FT_RSB_Adjust_Func rsb_adjust */ 1116 1117 NULL, /* FT_VAdvance_Adjust_Func vadvance_adjust */ 1118 NULL, /* FT_TSB_Adjust_Func tsb_adjust */ 1119 NULL, /* FT_BSB_Adjust_Func bsb_adjust */ 1120 NULL, /* FT_VOrg_Adjust_Func vorg_adjust */ 1121 1122 cff_metrics_adjust, /* FT_Metrics_Adjust_Func metrics_adjust */ 1123 NULL /* FT_Size_Reset_Func size_reset */ 1124 ) 1125 #endif 1126 1127 1128 /* 1129 * CFFLOAD SERVICE 1130 * 1131 */ 1132 1133 FT_DEFINE_SERVICE_CFFLOADREC( 1134 cff_service_cff_load, 1135 1136 cff_get_standard_encoding, /* FT_Get_Standard_Encoding_Func get_standard_encoding */ 1137 cff_load_private_dict, /* FT_Load_Private_Dict_Func load_private_dict */ 1138 cff_fd_select_get, /* FT_FD_Select_Get_Func fd_select_get */ 1139 cff_blend_check_vector, /* FT_Blend_Check_Vector_Func blend_check_vector */ 1140 cff_blend_build_vector /* FT_Blend_Build_Vector_Func blend_build_vector */ 1141 ) 1142 1143 1144 /*************************************************************************/ 1145 /*************************************************************************/ 1146 /*************************************************************************/ 1147 /**** ****/ 1148 /**** ****/ 1149 /**** D R I V E R I N T E R F A C E ****/ 1150 /**** ****/ 1151 /**** ****/ 1152 /*************************************************************************/ 1153 /*************************************************************************/ 1154 /*************************************************************************/ 1155 1156 #if defined TT_CONFIG_OPTION_GX_VAR_SUPPORT 1157 FT_DEFINE_SERVICEDESCREC10( 1158 cff_services, 1159 1160 FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF, 1161 FT_SERVICE_ID_MULTI_MASTERS, &cff_service_multi_masters, 1162 FT_SERVICE_ID_METRICS_VARIATIONS, &cff_service_metrics_variations, 1163 FT_SERVICE_ID_POSTSCRIPT_INFO, &cff_service_ps_info, 1164 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name, 1165 FT_SERVICE_ID_GLYPH_DICT, &cff_service_glyph_dict, 1166 FT_SERVICE_ID_TT_CMAP, &cff_service_get_cmap_info, 1167 FT_SERVICE_ID_CID, &cff_service_cid_info, 1168 FT_SERVICE_ID_PROPERTIES, &cff_service_properties, 1169 FT_SERVICE_ID_CFF_LOAD, &cff_service_cff_load 1170 ) 1171 #else 1172 FT_DEFINE_SERVICEDESCREC8( 1173 cff_services, 1174 1175 FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF, 1176 FT_SERVICE_ID_POSTSCRIPT_INFO, &cff_service_ps_info, 1177 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name, 1178 FT_SERVICE_ID_GLYPH_DICT, &cff_service_glyph_dict, 1179 FT_SERVICE_ID_TT_CMAP, &cff_service_get_cmap_info, 1180 FT_SERVICE_ID_CID, &cff_service_cid_info, 1181 FT_SERVICE_ID_PROPERTIES, &cff_service_properties, 1182 FT_SERVICE_ID_CFF_LOAD, &cff_service_cff_load 1183 ) 1184 #endif 1185 1186 1187 FT_CALLBACK_DEF( FT_Module_Interface ) 1188 cff_get_interface( FT_Module driver, /* CFF_Driver */ 1189 const char* module_interface ) 1190 { 1191 FT_Library library; 1192 FT_Module sfnt; 1193 FT_Module_Interface result; 1194 1195 1196 result = ft_service_list_lookup( cff_services, module_interface ); 1197 if ( result ) 1198 return result; 1199 1200 /* `driver' is not yet evaluated */ 1201 if ( !driver ) 1202 return NULL; 1203 library = driver->library; 1204 if ( !library ) 1205 return NULL; 1206 1207 /* we pass our request to the `sfnt' module */ 1208 sfnt = FT_Get_Module( library, "sfnt" ); 1209 1210 return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0; 1211 } 1212 1213 1214 /* The FT_DriverInterface structure is defined in ftdriver.h. */ 1215 1216 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 1217 #define CFF_SIZE_SELECT cff_size_select 1218 #else 1219 #define CFF_SIZE_SELECT 0 1220 #endif 1221 1222 FT_DEFINE_DRIVER( 1223 cff_driver_class, 1224 1225 FT_MODULE_FONT_DRIVER | 1226 FT_MODULE_DRIVER_SCALABLE | 1227 FT_MODULE_DRIVER_HAS_HINTER | 1228 FT_MODULE_DRIVER_HINTS_LIGHTLY, 1229 1230 sizeof ( PS_DriverRec ), 1231 "cff", 1232 0x10000L, 1233 0x20000L, 1234 1235 NULL, /* module-specific interface */ 1236 1237 cff_driver_init, /* FT_Module_Constructor module_init */ 1238 cff_driver_done, /* FT_Module_Destructor module_done */ 1239 cff_get_interface, /* FT_Module_Requester get_interface */ 1240 1241 sizeof ( TT_FaceRec ), 1242 sizeof ( CFF_SizeRec ), 1243 sizeof ( CFF_GlyphSlotRec ), 1244 1245 cff_face_init, /* FT_Face_InitFunc init_face */ 1246 cff_face_done, /* FT_Face_DoneFunc done_face */ 1247 cff_size_init, /* FT_Size_InitFunc init_size */ 1248 cff_size_done, /* FT_Size_DoneFunc done_size */ 1249 cff_slot_init, /* FT_Slot_InitFunc init_slot */ 1250 cff_slot_done, /* FT_Slot_DoneFunc done_slot */ 1251 1252 cff_glyph_load, /* FT_Slot_LoadFunc load_glyph */ 1253 1254 cff_get_kerning, /* FT_Face_GetKerningFunc get_kerning */ 1255 NULL, /* FT_Face_AttachFunc attach_file */ 1256 cff_get_advances, /* FT_Face_GetAdvancesFunc get_advances */ 1257 1258 cff_size_request, /* FT_Size_RequestFunc request_size */ 1259 CFF_SIZE_SELECT /* FT_Size_SelectFunc select_size */ 1260 ) 1261 1262 1263 /* END */ 1264