1 /**************************************************************************** 2 * 3 * sfdriver.c 4 * 5 * High-level SFNT driver interface (body). 6 * 7 * Copyright (C) 1996-2021 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 TT_CONFIG_OPTION_POSTSCRIPT_NAMES 40 #include "ttpost.h" 41 #endif 42 43 #ifdef TT_CONFIG_OPTION_BDF 44 #include "ttbdf.h" 45 #include <freetype/internal/services/svbdf.h> 46 #endif 47 48 #include "ttcmap.h" 49 #include "ttkern.h" 50 #include "ttmtx.h" 51 52 #include <freetype/internal/services/svgldict.h> 53 #include <freetype/internal/services/svpostnm.h> 54 #include <freetype/internal/services/svsfnt.h> 55 #include <freetype/internal/services/svttcmap.h> 56 57 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 58 #include <freetype/ftmm.h> 59 #include <freetype/internal/services/svmm.h> 60 #endif 61 62 63 /************************************************************************** 64 * 65 * The macro FT_COMPONENT is used in trace mode. It is an implicit 66 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log 67 * messages during execution. 68 */ 69 #undef FT_COMPONENT 70 #define FT_COMPONENT sfdriver 71 72 73 /* 74 * SFNT TABLE SERVICE 75 * 76 */ 77 78 static void* get_sfnt_table(TT_Face face,FT_Sfnt_Tag tag)79 get_sfnt_table( TT_Face face, 80 FT_Sfnt_Tag tag ) 81 { 82 void* table; 83 84 85 switch ( tag ) 86 { 87 case FT_SFNT_HEAD: 88 table = &face->header; 89 break; 90 91 case FT_SFNT_HHEA: 92 table = &face->horizontal; 93 break; 94 95 case FT_SFNT_VHEA: 96 table = face->vertical_info ? &face->vertical : NULL; 97 break; 98 99 case FT_SFNT_OS2: 100 table = ( face->os2.version == 0xFFFFU ) ? NULL : &face->os2; 101 break; 102 103 case FT_SFNT_POST: 104 table = &face->postscript; 105 break; 106 107 case FT_SFNT_MAXP: 108 table = &face->max_profile; 109 break; 110 111 case FT_SFNT_PCLT: 112 table = face->pclt.Version ? &face->pclt : NULL; 113 break; 114 115 default: 116 table = NULL; 117 } 118 119 return table; 120 } 121 122 123 static FT_Error sfnt_table_info(TT_Face face,FT_UInt idx,FT_ULong * tag,FT_ULong * offset,FT_ULong * length)124 sfnt_table_info( TT_Face face, 125 FT_UInt idx, 126 FT_ULong *tag, 127 FT_ULong *offset, 128 FT_ULong *length ) 129 { 130 if ( !offset || !length ) 131 return FT_THROW( Invalid_Argument ); 132 133 if ( !tag ) 134 *length = face->num_tables; 135 else 136 { 137 if ( idx >= face->num_tables ) 138 return FT_THROW( Table_Missing ); 139 140 *tag = face->dir_tables[idx].Tag; 141 *offset = face->dir_tables[idx].Offset; 142 *length = face->dir_tables[idx].Length; 143 } 144 145 return FT_Err_Ok; 146 } 147 148 149 FT_DEFINE_SERVICE_SFNT_TABLEREC( 150 sfnt_service_sfnt_table, 151 152 (FT_SFNT_TableLoadFunc)tt_face_load_any, /* load_table */ 153 (FT_SFNT_TableGetFunc) get_sfnt_table, /* get_table */ 154 (FT_SFNT_TableInfoFunc)sfnt_table_info /* table_info */ 155 ) 156 157 158 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 159 160 /* 161 * GLYPH DICT SERVICE 162 * 163 */ 164 165 static FT_Error sfnt_get_glyph_name(FT_Face face,FT_UInt glyph_index,FT_Pointer buffer,FT_UInt buffer_max)166 sfnt_get_glyph_name( FT_Face face, 167 FT_UInt glyph_index, 168 FT_Pointer buffer, 169 FT_UInt buffer_max ) 170 { 171 FT_String* gname; 172 FT_Error error; 173 174 175 error = tt_face_get_ps_name( (TT_Face)face, glyph_index, &gname ); 176 if ( !error ) 177 FT_STRCPYN( buffer, gname, buffer_max ); 178 179 return error; 180 } 181 182 183 static FT_UInt sfnt_get_name_index(FT_Face face,const FT_String * glyph_name)184 sfnt_get_name_index( FT_Face face, 185 const FT_String* glyph_name ) 186 { 187 TT_Face ttface = (TT_Face)face; 188 189 FT_UInt i, max_gid = FT_UINT_MAX; 190 191 192 if ( face->num_glyphs < 0 ) 193 return 0; 194 else if ( (FT_ULong)face->num_glyphs < FT_UINT_MAX ) 195 max_gid = (FT_UInt)face->num_glyphs; 196 else 197 FT_TRACE0(( "Ignore glyph names for invalid GID 0x%08x - 0x%08lx\n", 198 FT_UINT_MAX, face->num_glyphs )); 199 200 for ( i = 0; i < max_gid; i++ ) 201 { 202 FT_String* gname; 203 FT_Error error = tt_face_get_ps_name( ttface, i, &gname ); 204 205 206 if ( error ) 207 continue; 208 209 if ( !ft_strcmp( glyph_name, gname ) ) 210 return i; 211 } 212 213 return 0; 214 } 215 216 217 FT_DEFINE_SERVICE_GLYPHDICTREC( 218 sfnt_service_glyph_dict, 219 220 (FT_GlyphDict_GetNameFunc) sfnt_get_glyph_name, /* get_name */ 221 (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index /* name_index */ 222 ) 223 224 #endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */ 225 226 227 /* 228 * POSTSCRIPT NAME SERVICE 229 * 230 */ 231 232 /* an array representing allowed ASCII characters in a PS string */ 233 static const unsigned char sfnt_ps_map[16] = 234 { 235 /* 4 0 C 8 */ 236 0x00, 0x00, /* 0x00: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 */ 237 0x00, 0x00, /* 0x10: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 */ 238 0xDE, 0x7C, /* 0x20: 1 1 0 1 1 1 1 0 0 1 1 1 1 1 0 0 */ 239 0xFF, 0xAF, /* 0x30: 1 1 1 1 1 1 1 1 1 0 1 0 1 1 1 1 */ 240 0xFF, 0xFF, /* 0x40: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 */ 241 0xFF, 0xD7, /* 0x50: 1 1 1 1 1 1 1 1 1 1 0 1 0 1 1 1 */ 242 0xFF, 0xFF, /* 0x60: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 */ 243 0xFF, 0x57 /* 0x70: 1 1 1 1 1 1 1 1 0 1 0 1 0 1 1 1 */ 244 }; 245 246 247 static int sfnt_is_postscript(int c)248 sfnt_is_postscript( int c ) 249 { 250 unsigned int cc; 251 252 253 if ( c < 0 || c >= 0x80 ) 254 return 0; 255 256 cc = (unsigned int)c; 257 258 return sfnt_ps_map[cc >> 3] & ( 1 << ( cc & 0x07 ) ); 259 } 260 261 262 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 263 264 /* Only ASCII letters and digits are taken for a variation font */ 265 /* instance's PostScript name. */ 266 /* */ 267 /* `ft_isalnum' is a macro, but we need a function here, thus */ 268 /* this definition. */ 269 static int sfnt_is_alphanumeric(int c)270 sfnt_is_alphanumeric( int c ) 271 { 272 return ft_isalnum( c ); 273 } 274 275 276 /* the implementation of MurmurHash3 is taken and adapted from */ 277 /* https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp */ 278 279 #define ROTL32( x, r ) ( x << r ) | ( x >> ( 32 - r ) ) 280 281 282 static FT_UInt32 fmix32(FT_UInt32 h)283 fmix32( FT_UInt32 h ) 284 { 285 h ^= h >> 16; 286 h *= 0x85ebca6b; 287 h ^= h >> 13; 288 h *= 0xc2b2ae35; 289 h ^= h >> 16; 290 291 return h; 292 } 293 294 295 static void murmur_hash_3_128(const void * key,const unsigned int len,FT_UInt32 seed,void * out)296 murmur_hash_3_128( const void* key, 297 const unsigned int len, 298 FT_UInt32 seed, 299 void* out ) 300 { 301 const FT_Byte* data = (const FT_Byte*)key; 302 const int nblocks = (int)len / 16; 303 304 FT_UInt32 h1 = seed; 305 FT_UInt32 h2 = seed; 306 FT_UInt32 h3 = seed; 307 FT_UInt32 h4 = seed; 308 309 const FT_UInt32 c1 = 0x239b961b; 310 const FT_UInt32 c2 = 0xab0e9789; 311 const FT_UInt32 c3 = 0x38b34ae5; 312 const FT_UInt32 c4 = 0xa1e38b93; 313 314 const FT_UInt32* blocks = (const FT_UInt32*)( data + nblocks * 16 ); 315 316 int i; 317 318 319 for( i = -nblocks; i; i++ ) 320 { 321 FT_UInt32 k1 = blocks[i * 4 + 0]; 322 FT_UInt32 k2 = blocks[i * 4 + 1]; 323 FT_UInt32 k3 = blocks[i * 4 + 2]; 324 FT_UInt32 k4 = blocks[i * 4 + 3]; 325 326 327 k1 *= c1; 328 k1 = ROTL32( k1, 15 ); 329 k1 *= c2; 330 h1 ^= k1; 331 332 h1 = ROTL32( h1, 19 ); 333 h1 += h2; 334 h1 = h1 * 5 + 0x561ccd1b; 335 336 k2 *= c2; 337 k2 = ROTL32( k2, 16 ); 338 k2 *= c3; 339 h2 ^= k2; 340 341 h2 = ROTL32( h2, 17 ); 342 h2 += h3; 343 h2 = h2 * 5 + 0x0bcaa747; 344 345 k3 *= c3; 346 k3 = ROTL32( k3, 17 ); 347 k3 *= c4; 348 h3 ^= k3; 349 350 h3 = ROTL32( h3, 15 ); 351 h3 += h4; 352 h3 = h3 * 5 + 0x96cd1c35; 353 354 k4 *= c4; 355 k4 = ROTL32( k4, 18 ); 356 k4 *= c1; 357 h4 ^= k4; 358 359 h4 = ROTL32( h4, 13 ); 360 h4 += h1; 361 h4 = h4 * 5 + 0x32ac3b17; 362 } 363 364 { 365 const FT_Byte* tail = (const FT_Byte*)( data + nblocks * 16 ); 366 367 FT_UInt32 k1 = 0; 368 FT_UInt32 k2 = 0; 369 FT_UInt32 k3 = 0; 370 FT_UInt32 k4 = 0; 371 372 373 switch ( len & 15 ) 374 { 375 case 15: 376 k4 ^= (FT_UInt32)tail[14] << 16; 377 /* fall through */ 378 case 14: 379 k4 ^= (FT_UInt32)tail[13] << 8; 380 /* fall through */ 381 case 13: 382 k4 ^= (FT_UInt32)tail[12]; 383 k4 *= c4; 384 k4 = ROTL32( k4, 18 ); 385 k4 *= c1; 386 h4 ^= k4; 387 /* fall through */ 388 389 case 12: 390 k3 ^= (FT_UInt32)tail[11] << 24; 391 /* fall through */ 392 case 11: 393 k3 ^= (FT_UInt32)tail[10] << 16; 394 /* fall through */ 395 case 10: 396 k3 ^= (FT_UInt32)tail[9] << 8; 397 /* fall through */ 398 case 9: 399 k3 ^= (FT_UInt32)tail[8]; 400 k3 *= c3; 401 k3 = ROTL32( k3, 17 ); 402 k3 *= c4; 403 h3 ^= k3; 404 /* fall through */ 405 406 case 8: 407 k2 ^= (FT_UInt32)tail[7] << 24; 408 /* fall through */ 409 case 7: 410 k2 ^= (FT_UInt32)tail[6] << 16; 411 /* fall through */ 412 case 6: 413 k2 ^= (FT_UInt32)tail[5] << 8; 414 /* fall through */ 415 case 5: 416 k2 ^= (FT_UInt32)tail[4]; 417 k2 *= c2; 418 k2 = ROTL32( k2, 16 ); 419 k2 *= c3; 420 h2 ^= k2; 421 /* fall through */ 422 423 case 4: 424 k1 ^= (FT_UInt32)tail[3] << 24; 425 /* fall through */ 426 case 3: 427 k1 ^= (FT_UInt32)tail[2] << 16; 428 /* fall through */ 429 case 2: 430 k1 ^= (FT_UInt32)tail[1] << 8; 431 /* fall through */ 432 case 1: 433 k1 ^= (FT_UInt32)tail[0]; 434 k1 *= c1; 435 k1 = ROTL32( k1, 15 ); 436 k1 *= c2; 437 h1 ^= k1; 438 } 439 } 440 441 h1 ^= len; 442 h2 ^= len; 443 h3 ^= len; 444 h4 ^= len; 445 446 h1 += h2; 447 h1 += h3; 448 h1 += h4; 449 450 h2 += h1; 451 h3 += h1; 452 h4 += h1; 453 454 h1 = fmix32( h1 ); 455 h2 = fmix32( h2 ); 456 h3 = fmix32( h3 ); 457 h4 = fmix32( h4 ); 458 459 h1 += h2; 460 h1 += h3; 461 h1 += h4; 462 463 h2 += h1; 464 h3 += h1; 465 h4 += h1; 466 467 ((FT_UInt32*)out)[0] = h1; 468 ((FT_UInt32*)out)[1] = h2; 469 ((FT_UInt32*)out)[2] = h3; 470 ((FT_UInt32*)out)[3] = h4; 471 } 472 473 474 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ 475 476 477 typedef int (*char_type_func)( int c ); 478 479 480 /* Handling of PID/EID 3/0 and 3/1 is the same. */ 481 #define IS_WIN( n ) ( (n)->platformID == 3 && \ 482 ( (n)->encodingID == 1 || (n)->encodingID == 0 ) ) 483 484 #define IS_APPLE( n ) ( (n)->platformID == 1 && \ 485 (n)->encodingID == 0 ) 486 487 static char* get_win_string(FT_Memory memory,FT_Stream stream,TT_Name entry,char_type_func char_type,FT_Bool report_invalid_characters)488 get_win_string( FT_Memory memory, 489 FT_Stream stream, 490 TT_Name entry, 491 char_type_func char_type, 492 FT_Bool report_invalid_characters ) 493 { 494 FT_Error error = FT_Err_Ok; 495 496 char* result = NULL; 497 FT_String* r; 498 FT_Char* p; 499 FT_UInt len; 500 501 FT_UNUSED( error ); 502 503 504 if ( FT_QALLOC( result, entry->stringLength / 2 + 1 ) ) 505 return NULL; 506 507 if ( FT_STREAM_SEEK( entry->stringOffset ) || 508 FT_FRAME_ENTER( entry->stringLength ) ) 509 goto get_win_string_error; 510 511 r = (FT_String*)result; 512 p = (FT_Char*)stream->cursor; 513 514 for ( len = entry->stringLength / 2; len > 0; len--, p += 2 ) 515 { 516 if ( p[0] == 0 && char_type( p[1] ) ) 517 *r++ = p[1]; 518 else 519 { 520 if ( report_invalid_characters ) 521 FT_TRACE0(( "get_win_string:" 522 " Character 0x%X invalid in PS name string\n", 523 ((unsigned)p[0])*256 + (unsigned)p[1] )); 524 break; 525 } 526 } 527 if ( !len ) 528 *r = '\0'; 529 530 FT_FRAME_EXIT(); 531 532 if ( !len ) 533 return result; 534 535 get_win_string_error: 536 FT_FREE( result ); 537 538 entry->stringLength = 0; 539 entry->stringOffset = 0; 540 FT_FREE( entry->string ); 541 542 return NULL; 543 } 544 545 546 static char* get_apple_string(FT_Memory memory,FT_Stream stream,TT_Name entry,char_type_func char_type,FT_Bool report_invalid_characters)547 get_apple_string( FT_Memory memory, 548 FT_Stream stream, 549 TT_Name entry, 550 char_type_func char_type, 551 FT_Bool report_invalid_characters ) 552 { 553 FT_Error error = FT_Err_Ok; 554 555 char* result = NULL; 556 FT_String* r; 557 FT_Char* p; 558 FT_UInt len; 559 560 FT_UNUSED( error ); 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 #define PUT_COLOR_LAYERS_V1( a ) PUT_COLOR_LAYERS( a ) 1218 1219 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 1220 #define PUT_PS_NAMES( a ) a 1221 #else 1222 #define PUT_PS_NAMES( a ) NULL 1223 #endif 1224 1225 FT_DEFINE_SFNT_INTERFACE( 1226 sfnt_interface, 1227 1228 tt_face_goto_table, /* TT_Loader_GotoTableFunc goto_table */ 1229 1230 sfnt_init_face, /* TT_Init_Face_Func init_face */ 1231 sfnt_load_face, /* TT_Load_Face_Func load_face */ 1232 sfnt_done_face, /* TT_Done_Face_Func done_face */ 1233 sfnt_get_interface, /* FT_Module_Requester get_interface */ 1234 1235 tt_face_load_any, /* TT_Load_Any_Func load_any */ 1236 1237 tt_face_load_head, /* TT_Load_Table_Func load_head */ 1238 tt_face_load_hhea, /* TT_Load_Metrics_Func load_hhea */ 1239 tt_face_load_cmap, /* TT_Load_Table_Func load_cmap */ 1240 tt_face_load_maxp, /* TT_Load_Table_Func load_maxp */ 1241 tt_face_load_os2, /* TT_Load_Table_Func load_os2 */ 1242 tt_face_load_post, /* TT_Load_Table_Func load_post */ 1243 1244 tt_face_load_name, /* TT_Load_Table_Func load_name */ 1245 tt_face_free_name, /* TT_Free_Table_Func free_name */ 1246 1247 tt_face_load_kern, /* TT_Load_Table_Func load_kern */ 1248 tt_face_load_gasp, /* TT_Load_Table_Func load_gasp */ 1249 tt_face_load_pclt, /* TT_Load_Table_Func load_init */ 1250 1251 /* see `ttload.h' */ 1252 PUT_EMBEDDED_BITMAPS( tt_face_load_bhed ), 1253 /* TT_Load_Table_Func load_bhed */ 1254 PUT_EMBEDDED_BITMAPS( tt_face_load_sbit_image ), 1255 /* TT_Load_SBit_Image_Func load_sbit_image */ 1256 1257 /* see `ttpost.h' */ 1258 PUT_PS_NAMES( tt_face_get_ps_name ), 1259 /* TT_Get_PS_Name_Func get_psname */ 1260 PUT_PS_NAMES( tt_face_free_ps_names ), 1261 /* TT_Free_Table_Func free_psnames */ 1262 1263 /* since version 2.1.8 */ 1264 tt_face_get_kerning, /* TT_Face_GetKerningFunc get_kerning */ 1265 1266 /* since version 2.2 */ 1267 tt_face_load_font_dir, /* TT_Load_Table_Func load_font_dir */ 1268 tt_face_load_hmtx, /* TT_Load_Metrics_Func load_hmtx */ 1269 1270 /* see `ttsbit.h' and `sfnt.h' */ 1271 PUT_EMBEDDED_BITMAPS( tt_face_load_sbit ), 1272 /* TT_Load_Table_Func load_eblc */ 1273 PUT_EMBEDDED_BITMAPS( tt_face_free_sbit ), 1274 /* TT_Free_Table_Func free_eblc */ 1275 1276 PUT_EMBEDDED_BITMAPS( tt_face_set_sbit_strike ), 1277 /* TT_Set_SBit_Strike_Func set_sbit_strike */ 1278 PUT_EMBEDDED_BITMAPS( tt_face_load_strike_metrics ), 1279 /* TT_Load_Strike_Metrics_Func load_strike_metrics */ 1280 1281 PUT_COLOR_LAYERS( tt_face_load_cpal ), 1282 /* TT_Load_Table_Func load_cpal */ 1283 PUT_COLOR_LAYERS( tt_face_load_colr ), 1284 /* TT_Load_Table_Func load_colr */ 1285 PUT_COLOR_LAYERS( tt_face_free_cpal ), 1286 /* TT_Free_Table_Func free_cpal */ 1287 PUT_COLOR_LAYERS( tt_face_free_colr ), 1288 /* TT_Free_Table_Func free_colr */ 1289 PUT_COLOR_LAYERS( tt_face_palette_set ), 1290 /* TT_Set_Palette_Func set_palette */ 1291 PUT_COLOR_LAYERS( tt_face_get_colr_layer ), 1292 /* TT_Get_Colr_Layer_Func get_colr_layer */ 1293 1294 PUT_COLOR_LAYERS_V1( tt_face_get_colr_glyph_paint ), 1295 /* TT_Get_Color_Glyph_Paint_Func get_colr_glyph_paint */ 1296 PUT_COLOR_LAYERS_V1( tt_face_get_color_glyph_clipbox ), 1297 /* TT_Get_Color_Glyph_ClipBox_Func get_clipbox */ 1298 PUT_COLOR_LAYERS_V1( tt_face_get_paint_layers ), 1299 /* TT_Get_Paint_Layers_Func get_paint_layers */ 1300 PUT_COLOR_LAYERS_V1( tt_face_get_colorline_stops ), 1301 /* TT_Get_Paint get_paint */ 1302 PUT_COLOR_LAYERS_V1( tt_face_get_paint ), 1303 /* TT_Get_Colorline_Stops_Func get_colorline_stops */ 1304 1305 PUT_COLOR_LAYERS( tt_face_colr_blend_layer ), 1306 /* TT_Blend_Colr_Func colr_blend */ 1307 1308 tt_face_get_metrics, /* TT_Get_Metrics_Func get_metrics */ 1309 1310 tt_face_get_name, /* TT_Get_Name_Func get_name */ 1311 sfnt_get_name_id /* TT_Get_Name_ID_Func get_name_id */ 1312 ) 1313 1314 1315 FT_DEFINE_MODULE( 1316 sfnt_module_class, 1317 1318 0, /* not a font driver or renderer */ 1319 sizeof ( FT_ModuleRec ), 1320 1321 "sfnt", /* driver name */ 1322 0x10000L, /* driver version 1.0 */ 1323 0x20000L, /* driver requires FreeType 2.0 or higher */ 1324 1325 (const void*)&sfnt_interface, /* module specific interface */ 1326 1327 (FT_Module_Constructor)NULL, /* module_init */ 1328 (FT_Module_Destructor) NULL, /* module_done */ 1329 (FT_Module_Requester) sfnt_get_interface /* get_interface */ 1330 ) 1331 1332 1333 /* END */ 1334