1 /**************************************************************************** 2 * 3 * sfdriver.c 4 * 5 * High-level SFNT driver interface (body). 6 * 7 * Copyright (C) 1996-2023 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/internal/ftdebug.h> 20 #include <freetype/internal/sfnt.h> 21 #include <freetype/internal/ftobjs.h> 22 #include <freetype/ttnameid.h> 23 24 #include "sfdriver.h" 25 #include "ttload.h" 26 #include "sfobjs.h" 27 28 #include "sferrors.h" 29 30 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 31 #include "ttsbit.h" 32 #endif 33 34 #ifdef TT_CONFIG_OPTION_COLOR_LAYERS 35 #include "ttcolr.h" 36 #include "ttcpal.h" 37 #endif 38 39 #ifdef FT_CONFIG_OPTION_SVG 40 #include "ttsvg.h" 41 #endif 42 43 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 44 #include "ttpost.h" 45 #endif 46 47 #ifdef TT_CONFIG_OPTION_BDF 48 #include "ttbdf.h" 49 #include <freetype/internal/services/svbdf.h> 50 #endif 51 52 #include "ttcmap.h" 53 #include "ttkern.h" 54 #include "ttmtx.h" 55 56 #include <freetype/internal/services/svgldict.h> 57 #include <freetype/internal/services/svpostnm.h> 58 #include <freetype/internal/services/svsfnt.h> 59 #include <freetype/internal/services/svttcmap.h> 60 61 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 62 #include <freetype/ftmm.h> 63 #include <freetype/internal/services/svmm.h> 64 #endif 65 66 67 /************************************************************************** 68 * 69 * The macro FT_COMPONENT is used in trace mode. It is an implicit 70 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log 71 * messages during execution. 72 */ 73 #undef FT_COMPONENT 74 #define FT_COMPONENT sfdriver 75 76 77 /* 78 * SFNT TABLE SERVICE 79 * 80 */ 81 82 static void* get_sfnt_table(TT_Face face,FT_Sfnt_Tag tag)83 get_sfnt_table( TT_Face face, 84 FT_Sfnt_Tag tag ) 85 { 86 void* table; 87 88 89 switch ( tag ) 90 { 91 case FT_SFNT_HEAD: 92 table = &face->header; 93 break; 94 95 case FT_SFNT_HHEA: 96 table = &face->horizontal; 97 break; 98 99 case FT_SFNT_VHEA: 100 table = face->vertical_info ? &face->vertical : NULL; 101 break; 102 103 case FT_SFNT_OS2: 104 table = ( face->os2.version == 0xFFFFU ) ? NULL : &face->os2; 105 break; 106 107 case FT_SFNT_POST: 108 table = &face->postscript; 109 break; 110 111 case FT_SFNT_MAXP: 112 table = &face->max_profile; 113 break; 114 115 case FT_SFNT_PCLT: 116 table = face->pclt.Version ? &face->pclt : NULL; 117 break; 118 119 default: 120 table = NULL; 121 } 122 123 return table; 124 } 125 126 127 static FT_Error sfnt_table_info(TT_Face face,FT_UInt idx,FT_ULong * tag,FT_ULong * offset,FT_ULong * length)128 sfnt_table_info( TT_Face face, 129 FT_UInt idx, 130 FT_ULong *tag, 131 FT_ULong *offset, 132 FT_ULong *length ) 133 { 134 if ( !offset || !length ) 135 return FT_THROW( Invalid_Argument ); 136 137 if ( !tag ) 138 *length = face->num_tables; 139 else 140 { 141 if ( idx >= face->num_tables ) 142 return FT_THROW( Table_Missing ); 143 144 *tag = face->dir_tables[idx].Tag; 145 *offset = face->dir_tables[idx].Offset; 146 *length = face->dir_tables[idx].Length; 147 } 148 149 return FT_Err_Ok; 150 } 151 152 153 FT_DEFINE_SERVICE_SFNT_TABLEREC( 154 sfnt_service_sfnt_table, 155 156 (FT_SFNT_TableLoadFunc)tt_face_load_any, /* load_table */ 157 (FT_SFNT_TableGetFunc) get_sfnt_table, /* get_table */ 158 (FT_SFNT_TableInfoFunc)sfnt_table_info /* table_info */ 159 ) 160 161 162 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 163 164 /* 165 * GLYPH DICT SERVICE 166 * 167 */ 168 169 static FT_Error sfnt_get_glyph_name(FT_Face face,FT_UInt glyph_index,FT_Pointer buffer,FT_UInt buffer_max)170 sfnt_get_glyph_name( FT_Face face, 171 FT_UInt glyph_index, 172 FT_Pointer buffer, 173 FT_UInt buffer_max ) 174 { 175 FT_String* gname; 176 FT_Error error; 177 178 179 error = tt_face_get_ps_name( (TT_Face)face, glyph_index, &gname ); 180 if ( !error ) 181 FT_STRCPYN( buffer, gname, buffer_max ); 182 183 return error; 184 } 185 186 187 static FT_UInt sfnt_get_name_index(FT_Face face,const FT_String * glyph_name)188 sfnt_get_name_index( FT_Face face, 189 const FT_String* glyph_name ) 190 { 191 TT_Face ttface = (TT_Face)face; 192 193 FT_UInt i, max_gid = FT_UINT_MAX; 194 195 196 if ( face->num_glyphs < 0 ) 197 return 0; 198 else if ( (FT_ULong)face->num_glyphs < FT_UINT_MAX ) 199 max_gid = (FT_UInt)face->num_glyphs; 200 else 201 FT_TRACE0(( "Ignore glyph names for invalid GID 0x%08x - 0x%08lx\n", 202 FT_UINT_MAX, face->num_glyphs )); 203 204 for ( i = 0; i < max_gid; i++ ) 205 { 206 FT_String* gname; 207 FT_Error error = tt_face_get_ps_name( ttface, i, &gname ); 208 209 210 if ( error ) 211 continue; 212 213 if ( !ft_strcmp( glyph_name, gname ) ) 214 return i; 215 } 216 217 return 0; 218 } 219 220 221 FT_DEFINE_SERVICE_GLYPHDICTREC( 222 sfnt_service_glyph_dict, 223 224 (FT_GlyphDict_GetNameFunc) sfnt_get_glyph_name, /* get_name */ 225 (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index /* name_index */ 226 ) 227 228 #endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ 229 230 231 /* 232 * POSTSCRIPT NAME SERVICE 233 * 234 */ 235 236 /* an array representing allowed ASCII characters in a PS string */ 237 static const unsigned char sfnt_ps_map[16] = 238 { 239 /* 4 0 C 8 */ 240 0x00, 0x00, /* 0x00: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 */ 241 0x00, 0x00, /* 0x10: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 */ 242 0xDE, 0x7C, /* 0x20: 1 1 0 1 1 1 1 0 0 1 1 1 1 1 0 0 */ 243 0xFF, 0xAF, /* 0x30: 1 1 1 1 1 1 1 1 1 0 1 0 1 1 1 1 */ 244 0xFF, 0xFF, /* 0x40: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 */ 245 0xFF, 0xD7, /* 0x50: 1 1 1 1 1 1 1 1 1 1 0 1 0 1 1 1 */ 246 0xFF, 0xFF, /* 0x60: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 */ 247 0xFF, 0x57 /* 0x70: 1 1 1 1 1 1 1 1 0 1 0 1 0 1 1 1 */ 248 }; 249 250 251 static int sfnt_is_postscript(int c)252 sfnt_is_postscript( int c ) 253 { 254 unsigned int cc; 255 256 257 if ( c < 0 || c >= 0x80 ) 258 return 0; 259 260 cc = (unsigned int)c; 261 262 return sfnt_ps_map[cc >> 3] & ( 1 << ( cc & 0x07 ) ); 263 } 264 265 266 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 267 268 /* Only ASCII letters and digits are taken for a variation font */ 269 /* instance's PostScript name. */ 270 /* */ 271 /* `ft_isalnum' is a macro, but we need a function here, thus */ 272 /* this definition. */ 273 static int sfnt_is_alphanumeric(int c)274 sfnt_is_alphanumeric( int c ) 275 { 276 return ft_isalnum( c ); 277 } 278 279 280 /* the implementation of MurmurHash3 is taken and adapted from */ 281 /* https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp */ 282 283 #define ROTL32( x, r ) ( x << r ) | ( x >> ( 32 - r ) ) 284 285 286 static FT_UInt32 fmix32(FT_UInt32 h)287 fmix32( FT_UInt32 h ) 288 { 289 h ^= h >> 16; 290 h *= 0x85ebca6b; 291 h ^= h >> 13; 292 h *= 0xc2b2ae35; 293 h ^= h >> 16; 294 295 return h; 296 } 297 298 299 static void murmur_hash_3_128(const void * key,const unsigned int len,FT_UInt32 seed,void * out)300 murmur_hash_3_128( const void* key, 301 const unsigned int len, 302 FT_UInt32 seed, 303 void* out ) 304 { 305 const FT_Byte* data = (const FT_Byte*)key; 306 const int nblocks = (int)len / 16; 307 308 FT_UInt32 h1 = seed; 309 FT_UInt32 h2 = seed; 310 FT_UInt32 h3 = seed; 311 FT_UInt32 h4 = seed; 312 313 const FT_UInt32 c1 = 0x239b961b; 314 const FT_UInt32 c2 = 0xab0e9789; 315 const FT_UInt32 c3 = 0x38b34ae5; 316 const FT_UInt32 c4 = 0xa1e38b93; 317 318 const FT_UInt32* blocks = (const FT_UInt32*)( data + nblocks * 16 ); 319 320 int i; 321 322 323 for( i = -nblocks; i; i++ ) 324 { 325 FT_UInt32 k1 = blocks[i * 4 + 0]; 326 FT_UInt32 k2 = blocks[i * 4 + 1]; 327 FT_UInt32 k3 = blocks[i * 4 + 2]; 328 FT_UInt32 k4 = blocks[i * 4 + 3]; 329 330 331 k1 *= c1; 332 k1 = ROTL32( k1, 15 ); 333 k1 *= c2; 334 h1 ^= k1; 335 336 h1 = ROTL32( h1, 19 ); 337 h1 += h2; 338 h1 = h1 * 5 + 0x561ccd1b; 339 340 k2 *= c2; 341 k2 = ROTL32( k2, 16 ); 342 k2 *= c3; 343 h2 ^= k2; 344 345 h2 = ROTL32( h2, 17 ); 346 h2 += h3; 347 h2 = h2 * 5 + 0x0bcaa747; 348 349 k3 *= c3; 350 k3 = ROTL32( k3, 17 ); 351 k3 *= c4; 352 h3 ^= k3; 353 354 h3 = ROTL32( h3, 15 ); 355 h3 += h4; 356 h3 = h3 * 5 + 0x96cd1c35; 357 358 k4 *= c4; 359 k4 = ROTL32( k4, 18 ); 360 k4 *= c1; 361 h4 ^= k4; 362 363 h4 = ROTL32( h4, 13 ); 364 h4 += h1; 365 h4 = h4 * 5 + 0x32ac3b17; 366 } 367 368 { 369 const FT_Byte* tail = (const FT_Byte*)( data + nblocks * 16 ); 370 371 FT_UInt32 k1 = 0; 372 FT_UInt32 k2 = 0; 373 FT_UInt32 k3 = 0; 374 FT_UInt32 k4 = 0; 375 376 377 switch ( len & 15 ) 378 { 379 case 15: 380 k4 ^= (FT_UInt32)tail[14] << 16; 381 FALL_THROUGH; 382 case 14: 383 k4 ^= (FT_UInt32)tail[13] << 8; 384 FALL_THROUGH; 385 case 13: 386 k4 ^= (FT_UInt32)tail[12]; 387 k4 *= c4; 388 k4 = ROTL32( k4, 18 ); 389 k4 *= c1; 390 h4 ^= k4; 391 FALL_THROUGH; 392 393 case 12: 394 k3 ^= (FT_UInt32)tail[11] << 24; 395 FALL_THROUGH; 396 case 11: 397 k3 ^= (FT_UInt32)tail[10] << 16; 398 FALL_THROUGH; 399 case 10: 400 k3 ^= (FT_UInt32)tail[9] << 8; 401 FALL_THROUGH; 402 case 9: 403 k3 ^= (FT_UInt32)tail[8]; 404 k3 *= c3; 405 k3 = ROTL32( k3, 17 ); 406 k3 *= c4; 407 h3 ^= k3; 408 FALL_THROUGH; 409 410 case 8: 411 k2 ^= (FT_UInt32)tail[7] << 24; 412 FALL_THROUGH; 413 case 7: 414 k2 ^= (FT_UInt32)tail[6] << 16; 415 FALL_THROUGH; 416 case 6: 417 k2 ^= (FT_UInt32)tail[5] << 8; 418 FALL_THROUGH; 419 case 5: 420 k2 ^= (FT_UInt32)tail[4]; 421 k2 *= c2; 422 k2 = ROTL32( k2, 16 ); 423 k2 *= c3; 424 h2 ^= k2; 425 FALL_THROUGH; 426 427 case 4: 428 k1 ^= (FT_UInt32)tail[3] << 24; 429 FALL_THROUGH; 430 case 3: 431 k1 ^= (FT_UInt32)tail[2] << 16; 432 FALL_THROUGH; 433 case 2: 434 k1 ^= (FT_UInt32)tail[1] << 8; 435 FALL_THROUGH; 436 case 1: 437 k1 ^= (FT_UInt32)tail[0]; 438 k1 *= c1; 439 k1 = ROTL32( k1, 15 ); 440 k1 *= c2; 441 h1 ^= k1; 442 } 443 } 444 445 h1 ^= len; 446 h2 ^= len; 447 h3 ^= len; 448 h4 ^= len; 449 450 h1 += h2; 451 h1 += h3; 452 h1 += h4; 453 454 h2 += h1; 455 h3 += h1; 456 h4 += h1; 457 458 h1 = fmix32( h1 ); 459 h2 = fmix32( h2 ); 460 h3 = fmix32( h3 ); 461 h4 = fmix32( h4 ); 462 463 h1 += h2; 464 h1 += h3; 465 h1 += h4; 466 467 h2 += h1; 468 h3 += h1; 469 h4 += h1; 470 471 ((FT_UInt32*)out)[0] = h1; 472 ((FT_UInt32*)out)[1] = h2; 473 ((FT_UInt32*)out)[2] = h3; 474 ((FT_UInt32*)out)[3] = h4; 475 } 476 477 478 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ 479 480 481 typedef int (*char_type_func)( int c ); 482 483 484 /* Handling of PID/EID 3/0 and 3/1 is the same. */ 485 #define IS_WIN( n ) ( (n)->platformID == 3 && \ 486 ( (n)->encodingID == 1 || (n)->encodingID == 0 ) ) 487 488 #define IS_APPLE( n ) ( (n)->platformID == 1 && \ 489 (n)->encodingID == 0 ) 490 491 static char* get_win_string(FT_Memory memory,FT_Stream stream,TT_Name entry,char_type_func char_type,FT_Bool report_invalid_characters)492 get_win_string( FT_Memory memory, 493 FT_Stream stream, 494 TT_Name entry, 495 char_type_func char_type, 496 FT_Bool report_invalid_characters ) 497 { 498 FT_Error error; 499 500 char* result = NULL; 501 FT_String* r; 502 FT_Char* p; 503 FT_UInt len; 504 505 506 if ( FT_QALLOC( result, entry->stringLength / 2 + 1 ) ) 507 return NULL; 508 509 if ( FT_STREAM_SEEK( entry->stringOffset ) || 510 FT_FRAME_ENTER( entry->stringLength ) ) 511 goto get_win_string_error; 512 513 r = (FT_String*)result; 514 p = (FT_Char*)stream->cursor; 515 516 for ( len = entry->stringLength / 2; len > 0; len--, p += 2 ) 517 { 518 if ( p[0] == 0 && char_type( p[1] ) ) 519 *r++ = p[1]; 520 else 521 { 522 if ( report_invalid_characters ) 523 FT_TRACE0(( "get_win_string:" 524 " Character 0x%X invalid in PS name string\n", 525 ((unsigned)p[0])*256 + (unsigned)p[1] )); 526 break; 527 } 528 } 529 if ( !len ) 530 *r = '\0'; 531 532 FT_FRAME_EXIT(); 533 534 if ( !len ) 535 return result; 536 537 get_win_string_error: 538 FT_FREE( result ); 539 540 entry->stringLength = 0; 541 entry->stringOffset = 0; 542 FT_FREE( entry->string ); 543 544 return NULL; 545 } 546 547 548 static char* get_apple_string(FT_Memory memory,FT_Stream stream,TT_Name entry,char_type_func char_type,FT_Bool report_invalid_characters)549 get_apple_string( FT_Memory memory, 550 FT_Stream stream, 551 TT_Name entry, 552 char_type_func char_type, 553 FT_Bool report_invalid_characters ) 554 { 555 FT_Error error; 556 557 char* result = NULL; 558 FT_String* r; 559 FT_Char* p; 560 FT_UInt len; 561 562 563 if ( FT_QALLOC( result, entry->stringLength + 1 ) ) 564 return NULL; 565 566 if ( FT_STREAM_SEEK( entry->stringOffset ) || 567 FT_FRAME_ENTER( entry->stringLength ) ) 568 goto get_apple_string_error; 569 570 r = (FT_String*)result; 571 p = (FT_Char*)stream->cursor; 572 573 for ( len = entry->stringLength; len > 0; len--, p++ ) 574 { 575 if ( char_type( *p ) ) 576 *r++ = *p; 577 else 578 { 579 if ( report_invalid_characters ) 580 FT_TRACE0(( "get_apple_string:" 581 " Character `%c' (0x%X) invalid in PS name string\n", 582 *p, *p )); 583 break; 584 } 585 } 586 if ( !len ) 587 *r = '\0'; 588 589 FT_FRAME_EXIT(); 590 591 if ( !len ) 592 return result; 593 594 get_apple_string_error: 595 FT_FREE( result ); 596 597 entry->stringOffset = 0; 598 entry->stringLength = 0; 599 FT_FREE( entry->string ); 600 601 return NULL; 602 } 603 604 605 static FT_Bool sfnt_get_name_id(TT_Face face,FT_UShort id,FT_Int * win,FT_Int * apple)606 sfnt_get_name_id( TT_Face face, 607 FT_UShort id, 608 FT_Int *win, 609 FT_Int *apple ) 610 { 611 FT_Int n; 612 613 614 *win = -1; 615 *apple = -1; 616 617 for ( n = 0; n < face->num_names; n++ ) 618 { 619 TT_Name name = face->name_table.names + n; 620 621 622 if ( name->nameID == id && name->stringLength > 0 ) 623 { 624 if ( IS_WIN( name ) && ( name->languageID == 0x409 || *win == -1 ) ) 625 *win = n; 626 627 if ( IS_APPLE( name ) && ( name->languageID == 0 || *apple == -1 ) ) 628 *apple = n; 629 } 630 } 631 632 return ( *win >= 0 ) || ( *apple >= 0 ); 633 } 634 635 636 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 637 638 /* 639 The maximum length of an axis value descriptor. 640 641 We need 65536 different values for the decimal fraction; this fits 642 nicely into five decimal places. Consequently, it consists of 643 644 . the minus sign if the number is negative, 645 . up to five characters for the digits before the decimal point, 646 . the decimal point if there is a fractional part, and 647 . up to five characters for the digits after the decimal point. 648 649 We also need one byte for the leading `_' character and up to four 650 bytes for the axis tag. 651 */ 652 #define MAX_VALUE_DESCRIPTOR_LEN ( 1 + 5 + 1 + 5 + 1 + 4 ) 653 654 655 /* the maximum length of PostScript font names */ 656 #define MAX_PS_NAME_LEN 127 657 658 659 /* 660 * Find the shortest decimal representation of a 16.16 fixed-point 661 * number. The function fills `buf' with the result, returning a pointer 662 * to the position after the representation's last byte. 663 */ 664 665 static char* fixed2float(FT_Int fixed,char * buf)666 fixed2float( FT_Int fixed, 667 char* buf ) 668 { 669 char* p; 670 char* q; 671 char tmp[5]; 672 673 FT_Int int_part; 674 FT_Int frac_part; 675 676 FT_Int i; 677 678 679 p = buf; 680 681 if ( fixed == 0 ) 682 { 683 *p++ = '0'; 684 return p; 685 } 686 687 if ( fixed < 0 ) 688 { 689 *p++ = '-'; 690 fixed = NEG_INT( fixed ); 691 } 692 693 int_part = ( fixed >> 16 ) & 0xFFFF; 694 frac_part = fixed & 0xFFFF; 695 696 /* get digits of integer part (in reverse order) */ 697 q = tmp; 698 while ( int_part > 0 ) 699 { 700 *q++ = '0' + int_part % 10; 701 int_part /= 10; 702 } 703 704 /* copy digits in correct order to buffer */ 705 while ( q > tmp ) 706 *p++ = *--q; 707 708 if ( !frac_part ) 709 return p; 710 711 /* save position of point */ 712 q = p; 713 *p++ = '.'; 714 715 /* apply rounding */ 716 frac_part = frac_part * 10 + 5; 717 718 /* get digits of fractional part */ 719 for ( i = 0; i < 5; i++ ) 720 { 721 *p++ = '0' + (char)( frac_part / 0x10000L ); 722 723 frac_part %= 0x10000L; 724 if ( !frac_part ) 725 break; 726 727 frac_part *= 10; 728 } 729 730 /* 731 If the remainder stored in `frac_part' (after the last FOR loop) is 732 smaller than 34480*10, the resulting decimal value minus 0.00001 is 733 an equivalent representation of `fixed'. 734 735 The above FOR loop always finds the larger of the two values; I 736 verified this by iterating over all possible fixed-point numbers. 737 738 If the remainder is 17232*10, both values are equally good, and we 739 take the next even number (following IEEE 754's `round to nearest, 740 ties to even' rounding rule). 741 742 If the remainder is smaller than 17232*10, the lower of the two 743 numbers is nearer to the exact result (values 17232 and 34480 were 744 also found by testing all possible fixed-point values). 745 746 We use this to find a shorter decimal representation. If not ending 747 with digit zero, we take the representation with less error. 748 */ 749 p--; 750 if ( p - q == 5 ) /* five digits? */ 751 { 752 /* take the representation that has zero as the last digit */ 753 if ( frac_part < 34480 * 10 && 754 *p == '1' ) 755 *p = '0'; 756 757 /* otherwise use the one with less error */ 758 else if ( frac_part == 17232 * 10 && 759 *p & 1 ) 760 *p -= 1; 761 762 else if ( frac_part < 17232 * 10 && 763 *p != '0' ) 764 *p -= 1; 765 } 766 767 /* remove trailing zeros */ 768 while ( *p == '0' ) 769 *p-- = '\0'; 770 771 return p + 1; 772 } 773 774 775 static const char hexdigits[16] = 776 { 777 '0', '1', '2', '3', '4', '5', '6', '7', 778 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' 779 }; 780 781 782 static const char* sfnt_get_var_ps_name(TT_Face face)783 sfnt_get_var_ps_name( TT_Face face ) 784 { 785 FT_Error error; 786 FT_Memory memory = face->root.memory; 787 788 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; 789 790 FT_UInt num_coords; 791 FT_Fixed* coords; 792 FT_MM_Var* mm_var; 793 794 FT_Int found, win, apple; 795 FT_UInt i, j; 796 797 char* result = NULL; 798 char* p; 799 800 801 if ( !face->var_postscript_prefix ) 802 { 803 FT_UInt len; 804 805 806 /* check whether we have a Variations PostScript Name Prefix */ 807 found = sfnt_get_name_id( face, 808 TT_NAME_ID_VARIATIONS_PREFIX, 809 &win, 810 &apple ); 811 if ( !found ) 812 { 813 /* otherwise use the typographic family name */ 814 found = sfnt_get_name_id( face, 815 TT_NAME_ID_TYPOGRAPHIC_FAMILY, 816 &win, 817 &apple ); 818 } 819 820 if ( !found ) 821 { 822 /* as a last resort we try the family name; note that this is */ 823 /* not in the Adobe TechNote, but GX fonts (which predate the */ 824 /* TechNote) benefit from this behaviour */ 825 found = sfnt_get_name_id( face, 826 TT_NAME_ID_FONT_FAMILY, 827 &win, 828 &apple ); 829 } 830 831 if ( !found ) 832 { 833 FT_TRACE0(( "sfnt_get_var_ps_name:" 834 " Can't construct PS name prefix for font instances\n" )); 835 return NULL; 836 } 837 838 /* prefer Windows entries over Apple */ 839 if ( win != -1 ) 840 result = get_win_string( face->root.memory, 841 face->name_table.stream, 842 face->name_table.names + win, 843 sfnt_is_alphanumeric, 844 0 ); 845 if ( !result && apple != -1 ) 846 result = get_apple_string( face->root.memory, 847 face->name_table.stream, 848 face->name_table.names + apple, 849 sfnt_is_alphanumeric, 850 0 ); 851 852 if ( !result ) 853 { 854 FT_TRACE0(( "sfnt_get_var_ps_name:" 855 " No valid PS name prefix for font instances found\n" )); 856 return NULL; 857 } 858 859 len = ft_strlen( result ); 860 861 /* sanitize if necessary; we reserve space for 36 bytes (a 128bit */ 862 /* checksum as a hex number, preceded by `-' and followed by three */ 863 /* ASCII dots, to be used if the constructed PS name would be too */ 864 /* long); this is also sufficient for a single instance */ 865 if ( len > MAX_PS_NAME_LEN - ( 1 + 32 + 3 ) ) 866 { 867 len = MAX_PS_NAME_LEN - ( 1 + 32 + 3 ); 868 result[len] = '\0'; 869 870 FT_TRACE0(( "sfnt_get_var_ps_name:" 871 " Shortening variation PS name prefix\n" )); 872 FT_TRACE0(( " " 873 " to %d characters\n", len )); 874 } 875 876 face->var_postscript_prefix = result; 877 face->var_postscript_prefix_len = len; 878 } 879 880 mm->get_var_blend( FT_FACE( face ), 881 &num_coords, 882 &coords, 883 NULL, 884 &mm_var ); 885 886 if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) && 887 !FT_IS_VARIATION( FT_FACE( face ) ) ) 888 { 889 SFNT_Service sfnt = (SFNT_Service)face->sfnt; 890 891 FT_Long instance = ( ( face->root.face_index & 0x7FFF0000L ) >> 16 ) - 1; 892 FT_UInt psid = mm_var->namedstyle[instance].psid; 893 894 char* ps_name = NULL; 895 896 897 /* try first to load the name string with index `postScriptNameID' */ 898 if ( psid == 6 || 899 ( psid > 255 && psid < 32768 ) ) 900 (void)sfnt->get_name( face, (FT_UShort)psid, &ps_name ); 901 902 if ( ps_name ) 903 { 904 result = ps_name; 905 p = result + ft_strlen( result ) + 1; 906 907 goto check_length; 908 } 909 else 910 { 911 /* otherwise construct a name using `subfamilyNameID' */ 912 FT_UInt strid = mm_var->namedstyle[instance].strid; 913 914 char* subfamily_name; 915 char* s; 916 917 918 (void)sfnt->get_name( face, (FT_UShort)strid, &subfamily_name ); 919 920 if ( !subfamily_name ) 921 { 922 FT_TRACE1(( "sfnt_get_var_ps_name:" 923 " can't construct named instance PS name;\n" )); 924 FT_TRACE1(( " " 925 " trying to construct normal instance PS name\n" )); 926 goto construct_instance_name; 927 } 928 929 /* after the prefix we have character `-' followed by the */ 930 /* subfamily name (using only characters a-z, A-Z, and 0-9) */ 931 if ( FT_QALLOC( result, face->var_postscript_prefix_len + 932 1 + ft_strlen( subfamily_name ) + 1 ) ) 933 return NULL; 934 935 ft_strcpy( result, face->var_postscript_prefix ); 936 937 p = result + face->var_postscript_prefix_len; 938 *p++ = '-'; 939 940 s = subfamily_name; 941 while ( *s ) 942 { 943 if ( ft_isalnum( *s ) ) 944 *p++ = *s; 945 s++; 946 } 947 *p++ = '\0'; 948 949 FT_FREE( subfamily_name ); 950 } 951 } 952 else 953 { 954 FT_Var_Axis* axis; 955 956 957 construct_instance_name: 958 axis = mm_var->axis; 959 960 if ( FT_QALLOC( result, 961 face->var_postscript_prefix_len + 962 num_coords * MAX_VALUE_DESCRIPTOR_LEN + 1 ) ) 963 return NULL; 964 965 p = result; 966 967 ft_strcpy( p, face->var_postscript_prefix ); 968 p += face->var_postscript_prefix_len; 969 970 for ( i = 0; i < num_coords; i++, coords++, axis++ ) 971 { 972 char t; 973 974 975 /* omit axis value descriptor if it is identical */ 976 /* to the default axis value */ 977 if ( *coords == axis->def ) 978 continue; 979 980 *p++ = '_'; 981 p = fixed2float( *coords, p ); 982 983 t = (char)( axis->tag >> 24 ); 984 if ( t != ' ' && ft_isalnum( t ) ) 985 *p++ = t; 986 t = (char)( axis->tag >> 16 ); 987 if ( t != ' ' && ft_isalnum( t ) ) 988 *p++ = t; 989 t = (char)( axis->tag >> 8 ); 990 if ( t != ' ' && ft_isalnum( t ) ) 991 *p++ = t; 992 t = (char)axis->tag; 993 if ( t != ' ' && ft_isalnum( t ) ) 994 *p++ = t; 995 } 996 *p++ = '\0'; 997 } 998 999 check_length: 1000 if ( p - result > MAX_PS_NAME_LEN ) 1001 { 1002 /* the PS name is too long; replace the part after the prefix with */ 1003 /* a checksum; we use MurmurHash 3 with a hash length of 128 bit */ 1004 1005 FT_UInt32 seed = 123456789; 1006 1007 FT_UInt32 hash[4]; 1008 FT_UInt32* h; 1009 1010 1011 murmur_hash_3_128( result, p - result, seed, hash ); 1012 1013 p = result + face->var_postscript_prefix_len; 1014 *p++ = '-'; 1015 1016 /* we convert the hash value to hex digits from back to front */ 1017 p += 32 + 3; 1018 h = hash + 3; 1019 1020 *p-- = '\0'; 1021 *p-- = '.'; 1022 *p-- = '.'; 1023 *p-- = '.'; 1024 1025 for ( i = 0; i < 4; i++, h-- ) 1026 { 1027 FT_UInt32 v = *h; 1028 1029 1030 for ( j = 0; j < 8; j++ ) 1031 { 1032 *p-- = hexdigits[v & 0xF]; 1033 v >>= 4; 1034 } 1035 } 1036 } 1037 1038 return result; 1039 } 1040 1041 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ 1042 1043 1044 static const char* sfnt_get_ps_name(TT_Face face)1045 sfnt_get_ps_name( TT_Face face ) 1046 { 1047 FT_Int found, win, apple; 1048 const char* result = NULL; 1049 1050 1051 if ( face->postscript_name ) 1052 return face->postscript_name; 1053 1054 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1055 if ( face->blend && 1056 ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) || 1057 FT_IS_VARIATION( FT_FACE( face ) ) ) ) 1058 { 1059 face->postscript_name = sfnt_get_var_ps_name( face ); 1060 return face->postscript_name; 1061 } 1062 #endif 1063 1064 /* scan the name table to see whether we have a Postscript name here, */ 1065 /* either in Macintosh or Windows platform encodings */ 1066 found = sfnt_get_name_id( face, TT_NAME_ID_PS_NAME, &win, &apple ); 1067 if ( !found ) 1068 return NULL; 1069 1070 /* prefer Windows entries over Apple */ 1071 if ( win != -1 ) 1072 result = get_win_string( face->root.memory, 1073 face->name_table.stream, 1074 face->name_table.names + win, 1075 sfnt_is_postscript, 1076 1 ); 1077 if ( !result && apple != -1 ) 1078 result = get_apple_string( face->root.memory, 1079 face->name_table.stream, 1080 face->name_table.names + apple, 1081 sfnt_is_postscript, 1082 1 ); 1083 1084 face->postscript_name = result; 1085 1086 return result; 1087 } 1088 1089 1090 FT_DEFINE_SERVICE_PSFONTNAMEREC( 1091 sfnt_service_ps_name, 1092 1093 (FT_PsName_GetFunc)sfnt_get_ps_name /* get_ps_font_name */ 1094 ) 1095 1096 1097 /* 1098 * TT CMAP INFO 1099 */ 1100 FT_DEFINE_SERVICE_TTCMAPSREC( 1101 tt_service_get_cmap_info, 1102 1103 (TT_CMap_Info_GetFunc)tt_get_cmap_info /* get_cmap_info */ 1104 ) 1105 1106 1107 #ifdef TT_CONFIG_OPTION_BDF 1108 1109 static FT_Error sfnt_get_charset_id(TT_Face face,const char ** acharset_encoding,const char ** acharset_registry)1110 sfnt_get_charset_id( TT_Face face, 1111 const char* *acharset_encoding, 1112 const char* *acharset_registry ) 1113 { 1114 BDF_PropertyRec encoding, registry; 1115 FT_Error error; 1116 1117 1118 /* XXX: I don't know whether this is correct, since 1119 * tt_face_find_bdf_prop only returns something correct if we have 1120 * previously selected a size that is listed in the BDF table. 1121 * Should we change the BDF table format to include single offsets 1122 * for `CHARSET_REGISTRY' and `CHARSET_ENCODING'? 1123 */ 1124 error = tt_face_find_bdf_prop( face, "CHARSET_REGISTRY", ®istry ); 1125 if ( !error ) 1126 { 1127 error = tt_face_find_bdf_prop( face, "CHARSET_ENCODING", &encoding ); 1128 if ( !error ) 1129 { 1130 if ( registry.type == BDF_PROPERTY_TYPE_ATOM && 1131 encoding.type == BDF_PROPERTY_TYPE_ATOM ) 1132 { 1133 *acharset_encoding = encoding.u.atom; 1134 *acharset_registry = registry.u.atom; 1135 } 1136 else 1137 error = FT_THROW( Invalid_Argument ); 1138 } 1139 } 1140 1141 return error; 1142 } 1143 1144 1145 FT_DEFINE_SERVICE_BDFRec( 1146 sfnt_service_bdf, 1147 1148 (FT_BDF_GetCharsetIdFunc)sfnt_get_charset_id, /* get_charset_id */ 1149 (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop /* get_property */ 1150 ) 1151 1152 1153 #endif /* TT_CONFIG_OPTION_BDF */ 1154 1155 1156 /* 1157 * SERVICE LIST 1158 */ 1159 1160 #if defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES && defined TT_CONFIG_OPTION_BDF 1161 FT_DEFINE_SERVICEDESCREC5( 1162 sfnt_services, 1163 1164 FT_SERVICE_ID_SFNT_TABLE, &sfnt_service_sfnt_table, 1165 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name, 1166 FT_SERVICE_ID_GLYPH_DICT, &sfnt_service_glyph_dict, 1167 FT_SERVICE_ID_BDF, &sfnt_service_bdf, 1168 FT_SERVICE_ID_TT_CMAP, &tt_service_get_cmap_info ) 1169 #elif defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES 1170 FT_DEFINE_SERVICEDESCREC4( 1171 sfnt_services, 1172 1173 FT_SERVICE_ID_SFNT_TABLE, &sfnt_service_sfnt_table, 1174 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name, 1175 FT_SERVICE_ID_GLYPH_DICT, &sfnt_service_glyph_dict, 1176 FT_SERVICE_ID_TT_CMAP, &tt_service_get_cmap_info ) 1177 #elif defined TT_CONFIG_OPTION_BDF 1178 FT_DEFINE_SERVICEDESCREC4( 1179 sfnt_services, 1180 1181 FT_SERVICE_ID_SFNT_TABLE, &sfnt_service_sfnt_table, 1182 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name, 1183 FT_SERVICE_ID_BDF, &sfnt_service_bdf, 1184 FT_SERVICE_ID_TT_CMAP, &tt_service_get_cmap_info ) 1185 #else 1186 FT_DEFINE_SERVICEDESCREC3( 1187 sfnt_services, 1188 1189 FT_SERVICE_ID_SFNT_TABLE, &sfnt_service_sfnt_table, 1190 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name, 1191 FT_SERVICE_ID_TT_CMAP, &tt_service_get_cmap_info ) 1192 #endif 1193 1194 FT_CALLBACK_DEF(FT_Module_Interface)1195 FT_CALLBACK_DEF( FT_Module_Interface ) 1196 sfnt_get_interface( FT_Module module, 1197 const char* module_interface ) 1198 { 1199 FT_UNUSED( module ); 1200 1201 return ft_service_list_lookup( sfnt_services, module_interface ); 1202 } 1203 1204 1205 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 1206 #define PUT_EMBEDDED_BITMAPS( a ) a 1207 #else 1208 #define PUT_EMBEDDED_BITMAPS( a ) NULL 1209 #endif 1210 1211 #ifdef TT_CONFIG_OPTION_COLOR_LAYERS 1212 #define PUT_COLOR_LAYERS( a ) a 1213 #else 1214 #define PUT_COLOR_LAYERS( a ) NULL 1215 #endif 1216 1217 #ifdef FT_CONFIG_OPTION_SVG 1218 #define PUT_SVG_SUPPORT( a ) a 1219 #else 1220 #define PUT_SVG_SUPPORT( a ) NULL 1221 #endif 1222 1223 #define PUT_COLOR_LAYERS_V1( a ) PUT_COLOR_LAYERS( a ) 1224 1225 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 1226 #define PUT_PS_NAMES( a ) a 1227 #else 1228 #define PUT_PS_NAMES( a ) NULL 1229 #endif 1230 1231 FT_DEFINE_SFNT_INTERFACE( 1232 sfnt_interface, 1233 1234 tt_face_goto_table, /* TT_Loader_GotoTableFunc goto_table */ 1235 1236 sfnt_init_face, /* TT_Init_Face_Func init_face */ 1237 sfnt_load_face, /* TT_Load_Face_Func load_face */ 1238 sfnt_done_face, /* TT_Done_Face_Func done_face */ 1239 sfnt_get_interface, /* FT_Module_Requester get_interface */ 1240 1241 tt_face_load_any, /* TT_Load_Any_Func load_any */ 1242 1243 tt_face_load_head, /* TT_Load_Table_Func load_head */ 1244 tt_face_load_hhea, /* TT_Load_Metrics_Func load_hhea */ 1245 tt_face_load_cmap, /* TT_Load_Table_Func load_cmap */ 1246 tt_face_load_maxp, /* TT_Load_Table_Func load_maxp */ 1247 tt_face_load_os2, /* TT_Load_Table_Func load_os2 */ 1248 tt_face_load_post, /* TT_Load_Table_Func load_post */ 1249 1250 tt_face_load_name, /* TT_Load_Table_Func load_name */ 1251 tt_face_free_name, /* TT_Free_Table_Func free_name */ 1252 1253 tt_face_load_kern, /* TT_Load_Table_Func load_kern */ 1254 tt_face_load_gasp, /* TT_Load_Table_Func load_gasp */ 1255 tt_face_load_pclt, /* TT_Load_Table_Func load_init */ 1256 1257 /* see `ttload.h' */ 1258 PUT_EMBEDDED_BITMAPS( tt_face_load_bhed ), 1259 /* TT_Load_Table_Func load_bhed */ 1260 PUT_EMBEDDED_BITMAPS( tt_face_load_sbit_image ), 1261 /* TT_Load_SBit_Image_Func load_sbit_image */ 1262 1263 /* see `ttpost.h' */ 1264 PUT_PS_NAMES( tt_face_get_ps_name ), 1265 /* TT_Get_PS_Name_Func get_psname */ 1266 PUT_PS_NAMES( tt_face_free_ps_names ), 1267 /* TT_Free_Table_Func free_psnames */ 1268 1269 /* since version 2.1.8 */ 1270 tt_face_get_kerning, /* TT_Face_GetKerningFunc get_kerning */ 1271 1272 /* since version 2.2 */ 1273 tt_face_load_font_dir, /* TT_Load_Table_Func load_font_dir */ 1274 tt_face_load_hmtx, /* TT_Load_Metrics_Func load_hmtx */ 1275 1276 /* see `ttsbit.h' and `sfnt.h' */ 1277 PUT_EMBEDDED_BITMAPS( tt_face_load_sbit ), 1278 /* TT_Load_Table_Func load_eblc */ 1279 PUT_EMBEDDED_BITMAPS( tt_face_free_sbit ), 1280 /* TT_Free_Table_Func free_eblc */ 1281 1282 PUT_EMBEDDED_BITMAPS( tt_face_set_sbit_strike ), 1283 /* TT_Set_SBit_Strike_Func set_sbit_strike */ 1284 PUT_EMBEDDED_BITMAPS( tt_face_load_strike_metrics ), 1285 /* TT_Load_Strike_Metrics_Func load_strike_metrics */ 1286 1287 PUT_COLOR_LAYERS( tt_face_load_cpal ), 1288 /* TT_Load_Table_Func load_cpal */ 1289 PUT_COLOR_LAYERS( tt_face_load_colr ), 1290 /* TT_Load_Table_Func load_colr */ 1291 PUT_COLOR_LAYERS( tt_face_free_cpal ), 1292 /* TT_Free_Table_Func free_cpal */ 1293 PUT_COLOR_LAYERS( tt_face_free_colr ), 1294 /* TT_Free_Table_Func free_colr */ 1295 PUT_COLOR_LAYERS( tt_face_palette_set ), 1296 /* TT_Set_Palette_Func set_palette */ 1297 PUT_COLOR_LAYERS( tt_face_get_colr_layer ), 1298 /* TT_Get_Colr_Layer_Func get_colr_layer */ 1299 1300 PUT_COLOR_LAYERS_V1( tt_face_get_colr_glyph_paint ), 1301 /* TT_Get_Color_Glyph_Paint_Func get_colr_glyph_paint */ 1302 PUT_COLOR_LAYERS_V1( tt_face_get_color_glyph_clipbox ), 1303 /* TT_Get_Color_Glyph_ClipBox_Func get_clipbox */ 1304 PUT_COLOR_LAYERS_V1( tt_face_get_paint_layers ), 1305 /* TT_Get_Paint_Layers_Func get_paint_layers */ 1306 PUT_COLOR_LAYERS_V1( tt_face_get_colorline_stops ), 1307 /* TT_Get_Paint get_paint */ 1308 PUT_COLOR_LAYERS_V1( tt_face_get_paint ), 1309 /* TT_Get_Colorline_Stops_Func get_colorline_stops */ 1310 1311 PUT_COLOR_LAYERS( tt_face_colr_blend_layer ), 1312 /* TT_Blend_Colr_Func colr_blend */ 1313 1314 tt_face_get_metrics, /* TT_Get_Metrics_Func get_metrics */ 1315 1316 tt_face_get_name, /* TT_Get_Name_Func get_name */ 1317 sfnt_get_name_id, /* TT_Get_Name_ID_Func get_name_id */ 1318 1319 PUT_SVG_SUPPORT( tt_face_load_svg ), 1320 /* TT_Load_Table_Func load_svg */ 1321 PUT_SVG_SUPPORT( tt_face_free_svg ), 1322 /* TT_Free_Table_Func free_svg */ 1323 PUT_SVG_SUPPORT( tt_face_load_svg_doc ) 1324 /* TT_Load_Svg_Doc_Func load_svg_doc */ 1325 ) 1326 1327 1328 FT_DEFINE_MODULE( 1329 sfnt_module_class, 1330 1331 0, /* not a font driver or renderer */ 1332 sizeof ( FT_ModuleRec ), 1333 1334 "sfnt", /* driver name */ 1335 0x10000L, /* driver version 1.0 */ 1336 0x20000L, /* driver requires FreeType 2.0 or higher */ 1337 1338 (const void*)&sfnt_interface, /* module specific interface */ 1339 1340 (FT_Module_Constructor)NULL, /* module_init */ 1341 (FT_Module_Destructor) NULL, /* module_done */ 1342 (FT_Module_Requester) sfnt_get_interface /* get_interface */ 1343 ) 1344 1345 1346 /* END */ 1347