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