1 #if !defined(_FXFT_VERSION_) || _FXFT_VERSION_ == 2501 2 /***************************************************************************/ 3 /* */ 4 /* psmodule.c */ 5 /* */ 6 /* PSNames module implementation (body). */ 7 /* */ 8 /* Copyright 1996-2003, 2005-2008, 2012, 2013 by */ 9 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 10 /* */ 11 /* This file is part of the FreeType project, and may only be used, */ 12 /* modified, and distributed under the terms of the FreeType project */ 13 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 14 /* this file you indicate that you have read the license and */ 15 /* understand and accept it fully. */ 16 /* */ 17 /***************************************************************************/ 18 19 #define FT2_BUILD_LIBRARY 20 #include "../../include/ft2build.h" 21 #include "../../include/freetype/internal/ftdebug.h" 22 #include "../../include/freetype/internal/ftobjs.h" 23 #include "../../include/freetype/internal/services/svpscmap.h" 24 25 #include "psmodule.h" 26 #include "pstables.h" 27 28 #include "psnamerr.h" 29 #include "pspic.h" 30 31 32 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES 33 34 35 #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST 36 37 38 #define VARIANT_BIT 0x80000000UL 39 #define BASE_GLYPH( code ) ( (FT_UInt32)( (code) & ~VARIANT_BIT ) ) 40 41 #ifdef __cplusplus 42 extern "C" { 43 #endif 44 /* Return the Unicode value corresponding to a given glyph. Note that */ 45 /* we do deal with glyph variants by detecting a non-initial dot in */ 46 /* the name, as in `A.swash' or `e.final'; in this case, the */ 47 /* VARIANT_BIT is set in the return value. */ 48 /* */ 49 int FXFT_unicode_from_adobe_name( const char* glyph_name ) 50 { 51 /* If the name begins with `uni', then the glyph name may be a */ 52 /* hard-coded unicode character code. */ 53 if ( glyph_name[0] == 'u' && 54 glyph_name[1] == 'n' && 55 glyph_name[2] == 'i' ) 56 { 57 /* determine whether the next four characters following are */ 58 /* hexadecimal. */ 59 60 /* XXX: Add code to deal with ligatures, i.e. glyph names like */ 61 /* `uniXXXXYYYYZZZZ'... */ 62 63 FT_Int count; 64 FT_UInt32 value = 0; 65 const char* p = glyph_name + 3; 66 67 68 for ( count = 4; count > 0; count--, p++ ) 69 { 70 char c = *p; 71 unsigned int d; 72 73 74 d = (unsigned char)c - '0'; 75 if ( d >= 10 ) 76 { 77 d = (unsigned char)c - 'A'; 78 if ( d >= 6 ) 79 d = 16; 80 else 81 d += 10; 82 } 83 84 /* Exit if a non-uppercase hexadecimal character was found */ 85 /* -- this also catches character codes below `0' since such */ 86 /* negative numbers cast to `unsigned int' are far too big. */ 87 if ( d >= 16 ) 88 break; 89 90 value = ( value << 4 ) + d; 91 } 92 93 /* there must be exactly four hex digits */ 94 if ( count == 0 ) 95 { 96 if ( *p == '\0' ) 97 return value; 98 if ( *p == '.' ) 99 return (FT_UInt32)( value | VARIANT_BIT ); 100 } 101 } 102 103 /* If the name begins with `u', followed by four to six uppercase */ 104 /* hexadecimal digits, it is a hard-coded unicode character code. */ 105 if ( glyph_name[0] == 'u' ) 106 { 107 FT_Int count; 108 FT_UInt32 value = 0; 109 const char* p = glyph_name + 1; 110 111 112 for ( count = 6; count > 0; count--, p++ ) 113 { 114 char c = *p; 115 unsigned int d; 116 117 118 d = (unsigned char)c - '0'; 119 if ( d >= 10 ) 120 { 121 d = (unsigned char)c - 'A'; 122 if ( d >= 6 ) 123 d = 16; 124 else 125 d += 10; 126 } 127 128 if ( d >= 16 ) 129 break; 130 131 value = ( value << 4 ) + d; 132 } 133 134 if ( count <= 2 ) 135 { 136 if ( *p == '\0' ) 137 return value; 138 if ( *p == '.' ) 139 return (FT_UInt32)( value | VARIANT_BIT ); 140 } 141 } 142 143 /* Look for a non-initial dot in the glyph name in order to */ 144 /* find variants like `A.swash', `e.final', etc. */ 145 { 146 const char* p = glyph_name; 147 const char* dot = NULL; 148 149 150 for ( ; *p; p++ ) 151 { 152 if ( *p == '.' && p > glyph_name ) 153 { 154 dot = p; 155 break; 156 } 157 } 158 159 /* now look up the glyph in the Adobe Glyph List */ 160 if ( !dot ) 161 return (FT_UInt32)ft_get_adobe_glyph_index( glyph_name, p ); 162 else 163 return (FT_UInt32)( ft_get_adobe_glyph_index( glyph_name, dot ) | 164 VARIANT_BIT ); 165 } 166 } 167 #ifdef __cplusplus 168 } 169 #endif 170 171 #if !defined(_FPDFAPI_MINI_) || defined(_FXCORE_FEATURE_ALL_) 172 static int xyq_search_node(char* glyph_name, int name_offset, int table_offset, FT_UInt32 unicode) 173 { 174 int i, count; 175 176 // copy letters 177 while (1) { 178 glyph_name[name_offset] = ft_adobe_glyph_list[table_offset] & 0x7f; 179 name_offset ++; 180 table_offset ++; 181 if (!(ft_adobe_glyph_list[table_offset-1] & 0x80)) break; 182 } 183 glyph_name[name_offset] = 0; 184 185 // get child count 186 count = ft_adobe_glyph_list[table_offset] & 0x7f; 187 188 // check if we have value for this node 189 if (ft_adobe_glyph_list[table_offset] & 0x80) { 190 unsigned short thiscode = ft_adobe_glyph_list[table_offset+1] * 256 + ft_adobe_glyph_list[table_offset+2]; 191 if (thiscode == unicode) // found it! 192 return 1; 193 table_offset += 3; 194 } else 195 table_offset ++; 196 197 // now search in sub-nodes 198 if (count == 0) return 0; 199 for (i = 0; i < count; i ++) { 200 int child_offset = ft_adobe_glyph_list[table_offset+i*2] * 256 + ft_adobe_glyph_list[table_offset+i*2+1]; 201 if (xyq_search_node(glyph_name, name_offset, child_offset, unicode)) 202 // found in child 203 return 1; 204 } 205 return 0; 206 } 207 208 // XYQ: function for searching Unicode in the glyph list 209 void FXFT_adobe_name_from_unicode(char* glyph_name, FT_UInt32 unicode) 210 { 211 int i, count; 212 213 // start from top level node 214 count = ft_adobe_glyph_list[1]; 215 for (i = 0; i < count; i ++) { 216 int child_offset = ft_adobe_glyph_list[i*2+2] * 256 + ft_adobe_glyph_list[i*2+3]; 217 if (xyq_search_node(glyph_name, 0, child_offset, unicode)) 218 return; 219 } 220 221 // failed, clear the buffer 222 glyph_name[0] = 0; 223 } 224 #endif 225 226 /* ft_qsort callback to sort the unicode map */ 227 FT_CALLBACK_DEF( int ) 228 compare_uni_maps( const void* a, 229 const void* b ) 230 { 231 PS_UniMap* map1 = (PS_UniMap*)a; 232 PS_UniMap* map2 = (PS_UniMap*)b; 233 FT_UInt32 unicode1 = BASE_GLYPH( map1->unicode ); 234 FT_UInt32 unicode2 = BASE_GLYPH( map2->unicode ); 235 236 237 /* sort base glyphs before glyph variants */ 238 if ( unicode1 == unicode2 ) 239 { 240 if ( map1->unicode > map2->unicode ) 241 return 1; 242 else if ( map1->unicode < map2->unicode ) 243 return -1; 244 else 245 return 0; 246 } 247 else 248 { 249 if ( unicode1 > unicode2 ) 250 return 1; 251 else if ( unicode1 < unicode2 ) 252 return -1; 253 else 254 return 0; 255 } 256 } 257 258 259 /* support for extra glyphs not handled (well) in AGL; */ 260 /* we add extra mappings for them if necessary */ 261 262 #define EXTRA_GLYPH_LIST_SIZE 10 263 264 static const FT_UInt32 ft_extra_glyph_unicodes[EXTRA_GLYPH_LIST_SIZE] = 265 { 266 /* WGL 4 */ 267 0x0394, 268 0x03A9, 269 0x2215, 270 0x00AD, 271 0x02C9, 272 0x03BC, 273 0x2219, 274 0x00A0, 275 /* Romanian */ 276 0x021A, 277 0x021B 278 }; 279 280 static const char ft_extra_glyph_names[] = 281 { 282 'D','e','l','t','a',0, 283 'O','m','e','g','a',0, 284 'f','r','a','c','t','i','o','n',0, 285 'h','y','p','h','e','n',0, 286 'm','a','c','r','o','n',0, 287 'm','u',0, 288 'p','e','r','i','o','d','c','e','n','t','e','r','e','d',0, 289 's','p','a','c','e',0, 290 'T','c','o','m','m','a','a','c','c','e','n','t',0, 291 't','c','o','m','m','a','a','c','c','e','n','t',0 292 }; 293 294 static const FT_Int 295 ft_extra_glyph_name_offsets[EXTRA_GLYPH_LIST_SIZE] = 296 { 297 0, 298 6, 299 12, 300 21, 301 28, 302 35, 303 38, 304 53, 305 59, 306 72 307 }; 308 309 310 static void 311 ps_check_extra_glyph_name( const char* gname, 312 FT_UInt glyph, 313 FT_UInt* extra_glyphs, 314 FT_UInt *states ) 315 { 316 FT_UInt n; 317 318 319 for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ ) 320 { 321 if ( ft_strcmp( ft_extra_glyph_names + 322 ft_extra_glyph_name_offsets[n], gname ) == 0 ) 323 { 324 if ( states[n] == 0 ) 325 { 326 /* mark this extra glyph as a candidate for the cmap */ 327 states[n] = 1; 328 extra_glyphs[n] = glyph; 329 } 330 331 return; 332 } 333 } 334 } 335 336 337 static void 338 ps_check_extra_glyph_unicode( FT_UInt32 uni_char, 339 FT_UInt *states ) 340 { 341 FT_UInt n; 342 343 344 for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ ) 345 { 346 if ( uni_char == ft_extra_glyph_unicodes[n] ) 347 { 348 /* disable this extra glyph from being added to the cmap */ 349 states[n] = 2; 350 351 return; 352 } 353 } 354 } 355 356 357 /* Build a table that maps Unicode values to glyph indices. */ 358 static FT_Error 359 ps_unicodes_init( FT_Memory memory, 360 PS_Unicodes table, 361 FT_UInt num_glyphs, 362 PS_GetGlyphNameFunc get_glyph_name, 363 PS_FreeGlyphNameFunc free_glyph_name, 364 FT_Pointer glyph_data ) 365 { 366 FT_Error error; 367 368 FT_UInt extra_glyph_list_states[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 369 FT_UInt extra_glyphs[EXTRA_GLYPH_LIST_SIZE]; 370 371 372 /* we first allocate the table */ 373 table->num_maps = 0; 374 table->maps = 0; 375 376 if ( !FT_NEW_ARRAY( table->maps, num_glyphs + EXTRA_GLYPH_LIST_SIZE ) ) 377 { 378 FT_UInt n; 379 FT_UInt count; 380 PS_UniMap* map; 381 FT_UInt32 uni_char; 382 383 384 map = table->maps; 385 386 for ( n = 0; n < num_glyphs; n++ ) 387 { 388 const char* gname = get_glyph_name( glyph_data, n ); 389 390 391 if ( gname ) 392 { 393 ps_check_extra_glyph_name( gname, n, 394 extra_glyphs, extra_glyph_list_states ); 395 uni_char = FXFT_unicode_from_adobe_name( gname ); 396 397 if ( BASE_GLYPH( uni_char ) != 0 ) 398 { 399 ps_check_extra_glyph_unicode( uni_char, 400 extra_glyph_list_states ); 401 map->unicode = uni_char; 402 map->glyph_index = n; 403 map++; 404 } 405 406 if ( free_glyph_name ) 407 free_glyph_name( glyph_data, gname ); 408 } 409 } 410 411 for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ ) 412 { 413 if ( extra_glyph_list_states[n] == 1 ) 414 { 415 /* This glyph name has an additional representation. */ 416 /* Add it to the cmap. */ 417 418 map->unicode = ft_extra_glyph_unicodes[n]; 419 map->glyph_index = extra_glyphs[n]; 420 map++; 421 } 422 } 423 424 /* now compress the table a bit */ 425 count = (FT_UInt)( map - table->maps ); 426 427 if ( count == 0 ) 428 { 429 /* No unicode chars here! */ 430 FT_FREE( table->maps ); 431 if ( !error ) 432 error = FT_THROW( No_Unicode_Glyph_Name ); 433 } 434 else 435 { 436 /* Reallocate if the number of used entries is much smaller. */ 437 if ( count < num_glyphs / 2 ) 438 { 439 (void)FT_RENEW_ARRAY( table->maps, num_glyphs, count ); 440 error = FT_Err_Ok; 441 } 442 443 /* Sort the table in increasing order of unicode values, */ 444 /* taking care of glyph variants. */ 445 ft_qsort( table->maps, count, sizeof ( PS_UniMap ), 446 compare_uni_maps ); 447 } 448 449 table->num_maps = count; 450 } 451 452 return error; 453 } 454 455 456 static FT_UInt 457 ps_unicodes_char_index( PS_Unicodes table, 458 FT_UInt32 unicode ) 459 { 460 PS_UniMap *min, *max, *mid, *result = NULL; 461 462 463 /* Perform a binary search on the table. */ 464 465 min = table->maps; 466 max = min + table->num_maps - 1; 467 468 while ( min <= max ) 469 { 470 FT_UInt32 base_glyph; 471 472 473 mid = min + ( ( max - min ) >> 1 ); 474 475 if ( mid->unicode == unicode ) 476 { 477 result = mid; 478 break; 479 } 480 481 base_glyph = BASE_GLYPH( mid->unicode ); 482 483 if ( base_glyph == unicode ) 484 result = mid; /* remember match but continue search for base glyph */ 485 486 if ( min == max ) 487 break; 488 489 if ( base_glyph < unicode ) 490 min = mid + 1; 491 else 492 max = mid - 1; 493 } 494 495 if ( result ) 496 return result->glyph_index; 497 else 498 return 0; 499 } 500 501 502 static FT_UInt32 503 ps_unicodes_char_next( PS_Unicodes table, 504 FT_UInt32 *unicode ) 505 { 506 FT_UInt result = 0; 507 FT_UInt32 char_code = *unicode + 1; 508 509 510 { 511 FT_UInt min = 0; 512 FT_UInt max = table->num_maps; 513 FT_UInt mid; 514 PS_UniMap* map; 515 FT_UInt32 base_glyph; 516 517 518 while ( min < max ) 519 { 520 mid = min + ( ( max - min ) >> 1 ); 521 map = table->maps + mid; 522 523 if ( map->unicode == char_code ) 524 { 525 result = map->glyph_index; 526 goto Exit; 527 } 528 529 base_glyph = BASE_GLYPH( map->unicode ); 530 531 if ( base_glyph == char_code ) 532 result = map->glyph_index; 533 534 if ( base_glyph < char_code ) 535 min = mid + 1; 536 else 537 max = mid; 538 } 539 540 if ( result ) 541 goto Exit; /* we have a variant glyph */ 542 543 /* we didn't find it; check whether we have a map just above it */ 544 char_code = 0; 545 546 if ( min < table->num_maps ) 547 { 548 map = table->maps + min; 549 result = map->glyph_index; 550 char_code = BASE_GLYPH( map->unicode ); 551 } 552 } 553 554 Exit: 555 *unicode = char_code; 556 return result; 557 } 558 559 560 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ 561 562 563 static const char* 564 ps_get_macintosh_name( FT_UInt name_index ) 565 { 566 if ( name_index >= FT_NUM_MAC_NAMES ) 567 name_index = 0; 568 569 return ft_standard_glyph_names + ft_mac_names[name_index]; 570 } 571 572 573 static const char* 574 ps_get_standard_strings( FT_UInt sid ) 575 { 576 if ( sid >= FT_NUM_SID_NAMES ) 577 return 0; 578 579 return ft_standard_glyph_names + ft_sid_names[sid]; 580 } 581 582 583 #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST 584 585 FT_DEFINE_SERVICE_PSCMAPSREC( 586 pscmaps_interface, 587 (PS_Unicode_ValueFunc) FXFT_unicode_from_adobe_name, 588 (PS_Unicodes_InitFunc) ps_unicodes_init, 589 (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index, 590 (PS_Unicodes_CharNextFunc) ps_unicodes_char_next, 591 592 (PS_Macintosh_NameFunc) ps_get_macintosh_name, 593 (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, 594 595 t1_standard_encoding, 596 t1_expert_encoding ) 597 598 #else 599 600 FT_DEFINE_SERVICE_PSCMAPSREC( 601 pscmaps_interface, 602 NULL, 603 NULL, 604 NULL, 605 NULL, 606 607 (PS_Macintosh_NameFunc) ps_get_macintosh_name, 608 (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, 609 610 t1_standard_encoding, 611 t1_expert_encoding ) 612 613 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */ 614 615 616 FT_DEFINE_SERVICEDESCREC1( 617 pscmaps_services, 618 FT_SERVICE_ID_POSTSCRIPT_CMAPS, &PSCMAPS_INTERFACE_GET ) 619 620 621 static FT_Pointer 622 psnames_get_service( FT_Module module, 623 const char* service_id ) 624 { 625 /* PSCMAPS_SERVICES_GET derefers `library' in PIC mode */ 626 #ifdef FT_CONFIG_OPTION_PIC 627 FT_Library library; 628 629 630 if ( !module ) 631 return NULL; 632 library = module->library; 633 if ( !library ) 634 return NULL; 635 #else 636 FT_UNUSED( module ); 637 #endif 638 639 return ft_service_list_lookup( PSCMAPS_SERVICES_GET, service_id ); 640 } 641 642 #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ 643 644 645 #ifndef FT_CONFIG_OPTION_POSTSCRIPT_NAMES 646 #define PUT_PS_NAMES_SERVICE( a ) NULL 647 #else 648 #define PUT_PS_NAMES_SERVICE( a ) a 649 #endif 650 651 FT_DEFINE_MODULE( 652 psnames_module_class, 653 654 0, /* this is not a font driver, nor a renderer */ 655 sizeof ( FT_ModuleRec ), 656 657 "psnames", /* driver name */ 658 0x10000L, /* driver version */ 659 0x20000L, /* driver requires FreeType 2 or above */ 660 661 PUT_PS_NAMES_SERVICE( 662 (void*)&PSCMAPS_INTERFACE_GET ), /* module specific interface */ 663 (FT_Module_Constructor)NULL, 664 (FT_Module_Destructor) NULL, 665 (FT_Module_Requester) PUT_PS_NAMES_SERVICE( psnames_get_service ) ) 666 667 668 /* END */ 669 #endif 670 671