1 /**************************************************************************** 2 * 3 * sfdriver.c 4 * 5 * High-level SFNT driver interface (body). 6 * 7 * Copyright (C) 1996-2020 by 8 * David Turner, Robert Wilhelm, and Werner Lemberg. 9 * 10 * This file is part of the FreeType project, and may only be used, 11 * modified, and distributed under the terms of the FreeType project 12 * license, LICENSE.TXT. By continuing to use, modify, or distribute 13 * this file you indicate that you have read the license and 14 * understand and accept it fully. 15 * 16 */ 17 18 19 #include <freetype/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_ALLOC( 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_ALLOC( 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 " " 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 " " 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_ALLOC( 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_ALLOC( 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 } 997 998 check_length: 999 if ( p - result > MAX_PS_NAME_LEN ) 1000 { 1001 /* the PS name is too long; replace the part after the prefix with */ 1002 /* a checksum; we use MurmurHash 3 with a hash length of 128 bit */ 1003 1004 FT_UInt32 seed = 123456789; 1005 1006 FT_UInt32 hash[4]; 1007 FT_UInt32* h; 1008 1009 1010 murmur_hash_3_128( result, p - result, seed, hash ); 1011 1012 p = result + face->var_postscript_prefix_len; 1013 *p++ = '-'; 1014 1015 /* we convert the hash value to hex digits from back to front */ 1016 p += 32 + 3; 1017 h = hash + 3; 1018 1019 *p-- = '\0'; 1020 *p-- = '.'; 1021 *p-- = '.'; 1022 *p-- = '.'; 1023 1024 for ( i = 0; i < 4; i++, h-- ) 1025 { 1026 FT_UInt32 v = *h; 1027 1028 1029 for ( j = 0; j < 8; j++ ) 1030 { 1031 *p-- = hexdigits[v & 0xF]; 1032 v >>= 4; 1033 } 1034 } 1035 } 1036 1037 return result; 1038 } 1039 1040 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ 1041 1042 1043 static const char* sfnt_get_ps_name(TT_Face face)1044 sfnt_get_ps_name( TT_Face face ) 1045 { 1046 FT_Int found, win, apple; 1047 const char* result = NULL; 1048 1049 1050 if ( face->postscript_name ) 1051 return face->postscript_name; 1052 1053 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1054 if ( face->blend && 1055 ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) || 1056 FT_IS_VARIATION( FT_FACE( face ) ) ) ) 1057 { 1058 face->postscript_name = sfnt_get_var_ps_name( face ); 1059 return face->postscript_name; 1060 } 1061 #endif 1062 1063 /* scan the name table to see whether we have a Postscript name here, */ 1064 /* either in Macintosh or Windows platform encodings */ 1065 found = sfnt_get_name_id( face, TT_NAME_ID_PS_NAME, &win, &apple ); 1066 if ( !found ) 1067 return NULL; 1068 1069 /* prefer Windows entries over Apple */ 1070 if ( win != -1 ) 1071 result = get_win_string( face->root.memory, 1072 face->name_table.stream, 1073 face->name_table.names + win, 1074 sfnt_is_postscript, 1075 1 ); 1076 if ( !result && apple != -1 ) 1077 result = get_apple_string( face->root.memory, 1078 face->name_table.stream, 1079 face->name_table.names + apple, 1080 sfnt_is_postscript, 1081 1 ); 1082 1083 face->postscript_name = result; 1084 1085 return result; 1086 } 1087 1088 1089 FT_DEFINE_SERVICE_PSFONTNAMEREC( 1090 sfnt_service_ps_name, 1091 1092 (FT_PsName_GetFunc)sfnt_get_ps_name /* get_ps_font_name */ 1093 ) 1094 1095 1096 /* 1097 * TT CMAP INFO 1098 */ 1099 FT_DEFINE_SERVICE_TTCMAPSREC( 1100 tt_service_get_cmap_info, 1101 1102 (TT_CMap_Info_GetFunc)tt_get_cmap_info /* get_cmap_info */ 1103 ) 1104 1105 1106 #ifdef TT_CONFIG_OPTION_BDF 1107 1108 static FT_Error sfnt_get_charset_id(TT_Face face,const char ** acharset_encoding,const char ** acharset_registry)1109 sfnt_get_charset_id( TT_Face face, 1110 const char* *acharset_encoding, 1111 const char* *acharset_registry ) 1112 { 1113 BDF_PropertyRec encoding, registry; 1114 FT_Error error; 1115 1116 1117 /* XXX: I don't know whether this is correct, since 1118 * tt_face_find_bdf_prop only returns something correct if we have 1119 * previously selected a size that is listed in the BDF table. 1120 * Should we change the BDF table format to include single offsets 1121 * for `CHARSET_REGISTRY' and `CHARSET_ENCODING'? 1122 */ 1123 error = tt_face_find_bdf_prop( face, "CHARSET_REGISTRY", ®istry ); 1124 if ( !error ) 1125 { 1126 error = tt_face_find_bdf_prop( face, "CHARSET_ENCODING", &encoding ); 1127 if ( !error ) 1128 { 1129 if ( registry.type == BDF_PROPERTY_TYPE_ATOM && 1130 encoding.type == BDF_PROPERTY_TYPE_ATOM ) 1131 { 1132 *acharset_encoding = encoding.u.atom; 1133 *acharset_registry = registry.u.atom; 1134 } 1135 else 1136 error = FT_THROW( Invalid_Argument ); 1137 } 1138 } 1139 1140 return error; 1141 } 1142 1143 1144 FT_DEFINE_SERVICE_BDFRec( 1145 sfnt_service_bdf, 1146 1147 (FT_BDF_GetCharsetIdFunc)sfnt_get_charset_id, /* get_charset_id */ 1148 (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop /* get_property */ 1149 ) 1150 1151 1152 #endif /* TT_CONFIG_OPTION_BDF */ 1153 1154 1155 /* 1156 * SERVICE LIST 1157 */ 1158 1159 #if defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES && defined TT_CONFIG_OPTION_BDF 1160 FT_DEFINE_SERVICEDESCREC5( 1161 sfnt_services, 1162 1163 FT_SERVICE_ID_SFNT_TABLE, &sfnt_service_sfnt_table, 1164 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name, 1165 FT_SERVICE_ID_GLYPH_DICT, &sfnt_service_glyph_dict, 1166 FT_SERVICE_ID_BDF, &sfnt_service_bdf, 1167 FT_SERVICE_ID_TT_CMAP, &tt_service_get_cmap_info ) 1168 #elif defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES 1169 FT_DEFINE_SERVICEDESCREC4( 1170 sfnt_services, 1171 1172 FT_SERVICE_ID_SFNT_TABLE, &sfnt_service_sfnt_table, 1173 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name, 1174 FT_SERVICE_ID_GLYPH_DICT, &sfnt_service_glyph_dict, 1175 FT_SERVICE_ID_TT_CMAP, &tt_service_get_cmap_info ) 1176 #elif defined TT_CONFIG_OPTION_BDF 1177 FT_DEFINE_SERVICEDESCREC4( 1178 sfnt_services, 1179 1180 FT_SERVICE_ID_SFNT_TABLE, &sfnt_service_sfnt_table, 1181 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name, 1182 FT_SERVICE_ID_BDF, &sfnt_service_bdf, 1183 FT_SERVICE_ID_TT_CMAP, &tt_service_get_cmap_info ) 1184 #else 1185 FT_DEFINE_SERVICEDESCREC3( 1186 sfnt_services, 1187 1188 FT_SERVICE_ID_SFNT_TABLE, &sfnt_service_sfnt_table, 1189 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name, 1190 FT_SERVICE_ID_TT_CMAP, &tt_service_get_cmap_info ) 1191 #endif 1192 1193 FT_CALLBACK_DEF(FT_Module_Interface)1194 FT_CALLBACK_DEF( FT_Module_Interface ) 1195 sfnt_get_interface( FT_Module module, 1196 const char* module_interface ) 1197 { 1198 FT_UNUSED( module ); 1199 1200 return ft_service_list_lookup( sfnt_services, module_interface ); 1201 } 1202 1203 1204 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 1205 #define PUT_EMBEDDED_BITMAPS( a ) a 1206 #else 1207 #define PUT_EMBEDDED_BITMAPS( a ) NULL 1208 #endif 1209 1210 #ifdef TT_CONFIG_OPTION_COLOR_LAYERS 1211 #define PUT_COLOR_LAYERS( a ) a 1212 #else 1213 #define PUT_COLOR_LAYERS( a ) NULL 1214 #endif 1215 1216 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 1217 #define PUT_PS_NAMES( a ) a 1218 #else 1219 #define PUT_PS_NAMES( a ) NULL 1220 #endif 1221 1222 FT_DEFINE_SFNT_INTERFACE( 1223 sfnt_interface, 1224 1225 tt_face_goto_table, /* TT_Loader_GotoTableFunc goto_table */ 1226 1227 sfnt_init_face, /* TT_Init_Face_Func init_face */ 1228 sfnt_load_face, /* TT_Load_Face_Func load_face */ 1229 sfnt_done_face, /* TT_Done_Face_Func done_face */ 1230 sfnt_get_interface, /* FT_Module_Requester get_interface */ 1231 1232 tt_face_load_any, /* TT_Load_Any_Func load_any */ 1233 1234 tt_face_load_head, /* TT_Load_Table_Func load_head */ 1235 tt_face_load_hhea, /* TT_Load_Metrics_Func load_hhea */ 1236 tt_face_load_cmap, /* TT_Load_Table_Func load_cmap */ 1237 tt_face_load_maxp, /* TT_Load_Table_Func load_maxp */ 1238 tt_face_load_os2, /* TT_Load_Table_Func load_os2 */ 1239 tt_face_load_post, /* TT_Load_Table_Func load_post */ 1240 1241 tt_face_load_name, /* TT_Load_Table_Func load_name */ 1242 tt_face_free_name, /* TT_Free_Table_Func free_name */ 1243 1244 tt_face_load_kern, /* TT_Load_Table_Func load_kern */ 1245 tt_face_load_gasp, /* TT_Load_Table_Func load_gasp */ 1246 tt_face_load_pclt, /* TT_Load_Table_Func load_init */ 1247 1248 /* see `ttload.h' */ 1249 PUT_EMBEDDED_BITMAPS( tt_face_load_bhed ), 1250 /* TT_Load_Table_Func load_bhed */ 1251 PUT_EMBEDDED_BITMAPS( tt_face_load_sbit_image ), 1252 /* TT_Load_SBit_Image_Func load_sbit_image */ 1253 1254 /* see `ttpost.h' */ 1255 PUT_PS_NAMES( tt_face_get_ps_name ), 1256 /* TT_Get_PS_Name_Func get_psname */ 1257 PUT_PS_NAMES( tt_face_free_ps_names ), 1258 /* TT_Free_Table_Func free_psnames */ 1259 1260 /* since version 2.1.8 */ 1261 tt_face_get_kerning, /* TT_Face_GetKerningFunc get_kerning */ 1262 1263 /* since version 2.2 */ 1264 tt_face_load_font_dir, /* TT_Load_Table_Func load_font_dir */ 1265 tt_face_load_hmtx, /* TT_Load_Metrics_Func load_hmtx */ 1266 1267 /* see `ttsbit.h' and `sfnt.h' */ 1268 PUT_EMBEDDED_BITMAPS( tt_face_load_sbit ), 1269 /* TT_Load_Table_Func load_eblc */ 1270 PUT_EMBEDDED_BITMAPS( tt_face_free_sbit ), 1271 /* TT_Free_Table_Func free_eblc */ 1272 1273 PUT_EMBEDDED_BITMAPS( tt_face_set_sbit_strike ), 1274 /* TT_Set_SBit_Strike_Func set_sbit_strike */ 1275 PUT_EMBEDDED_BITMAPS( tt_face_load_strike_metrics ), 1276 /* TT_Load_Strike_Metrics_Func load_strike_metrics */ 1277 1278 PUT_COLOR_LAYERS( tt_face_load_cpal ), 1279 /* TT_Load_Table_Func load_cpal */ 1280 PUT_COLOR_LAYERS( tt_face_load_colr ), 1281 /* TT_Load_Table_Func load_colr */ 1282 PUT_COLOR_LAYERS( tt_face_free_cpal ), 1283 /* TT_Free_Table_Func free_cpal */ 1284 PUT_COLOR_LAYERS( tt_face_free_colr ), 1285 /* TT_Free_Table_Func free_colr */ 1286 PUT_COLOR_LAYERS( tt_face_palette_set ), 1287 /* TT_Set_Palette_Func set_palette */ 1288 PUT_COLOR_LAYERS( tt_face_get_colr_layer ), 1289 /* TT_Get_Colr_Layer_Func get_colr_layer */ 1290 PUT_COLOR_LAYERS( tt_face_colr_blend_layer ), 1291 /* TT_Blend_Colr_Func colr_blend */ 1292 1293 tt_face_get_metrics, /* TT_Get_Metrics_Func get_metrics */ 1294 1295 tt_face_get_name, /* TT_Get_Name_Func get_name */ 1296 sfnt_get_name_id /* TT_Get_Name_ID_Func get_name_id */ 1297 ) 1298 1299 1300 FT_DEFINE_MODULE( 1301 sfnt_module_class, 1302 1303 0, /* not a font driver or renderer */ 1304 sizeof ( FT_ModuleRec ), 1305 1306 "sfnt", /* driver name */ 1307 0x10000L, /* driver version 1.0 */ 1308 0x20000L, /* driver requires FreeType 2.0 or higher */ 1309 1310 (const void*)&sfnt_interface, /* module specific interface */ 1311 1312 (FT_Module_Constructor)NULL, /* module_init */ 1313 (FT_Module_Destructor) NULL, /* module_done */ 1314 (FT_Module_Requester) sfnt_get_interface /* get_interface */ 1315 ) 1316 1317 1318 /* END */ 1319