1 /***************************************************************************/ 2 /* */ 3 /* ttcmap.c */ 4 /* */ 5 /* TrueType character mapping table (cmap) support (body). */ 6 /* */ 7 /* Copyright 2002-2010, 2012-2014 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 <ft2build.h> 20 #include FT_INTERNAL_DEBUG_H 21 22 #include "sferrors.h" /* must come before FT_INTERNAL_VALIDATE_H */ 23 24 #include FT_INTERNAL_VALIDATE_H 25 #include FT_INTERNAL_STREAM_H 26 #include "ttload.h" 27 #include "ttcmap.h" 28 #include "sfntpic.h" 29 30 31 /*************************************************************************/ 32 /* */ 33 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 34 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 35 /* messages during execution. */ 36 /* */ 37 #undef FT_COMPONENT 38 #define FT_COMPONENT trace_ttcmap 39 40 41 #define TT_PEEK_SHORT FT_PEEK_SHORT 42 #define TT_PEEK_USHORT FT_PEEK_USHORT 43 #define TT_PEEK_UINT24 FT_PEEK_UOFF3 44 #define TT_PEEK_LONG FT_PEEK_LONG 45 #define TT_PEEK_ULONG FT_PEEK_ULONG 46 47 #define TT_NEXT_SHORT FT_NEXT_SHORT 48 #define TT_NEXT_USHORT FT_NEXT_USHORT 49 #define TT_NEXT_UINT24 FT_NEXT_UOFF3 50 #define TT_NEXT_LONG FT_NEXT_LONG 51 #define TT_NEXT_ULONG FT_NEXT_ULONG 52 53 54 FT_CALLBACK_DEF( FT_Error ) 55 tt_cmap_init( TT_CMap cmap, 56 FT_Byte* table ) 57 { 58 cmap->data = table; 59 return FT_Err_Ok; 60 } 61 62 63 /*************************************************************************/ 64 /*************************************************************************/ 65 /***** *****/ 66 /***** FORMAT 0 *****/ 67 /***** *****/ 68 /*************************************************************************/ 69 /*************************************************************************/ 70 71 /*************************************************************************/ 72 /* */ 73 /* TABLE OVERVIEW */ 74 /* -------------- */ 75 /* */ 76 /* NAME OFFSET TYPE DESCRIPTION */ 77 /* */ 78 /* format 0 USHORT must be 0 */ 79 /* length 2 USHORT table length in bytes */ 80 /* language 4 USHORT Mac language code */ 81 /* glyph_ids 6 BYTE[256] array of glyph indices */ 82 /* 262 */ 83 /* */ 84 85 #ifdef TT_CONFIG_CMAP_FORMAT_0 86 87 FT_CALLBACK_DEF( FT_Error ) 88 tt_cmap0_validate( FT_Byte* table, 89 FT_Validator valid ) 90 { 91 FT_Byte* p; 92 FT_UInt length; 93 94 95 if ( table + 2 + 2 > valid->limit ) 96 FT_INVALID_TOO_SHORT; 97 98 p = table + 2; /* skip format */ 99 length = TT_NEXT_USHORT( p ); 100 101 if ( table + length > valid->limit || length < 262 ) 102 FT_INVALID_TOO_SHORT; 103 104 /* check glyph indices whenever necessary */ 105 if ( valid->level >= FT_VALIDATE_TIGHT ) 106 { 107 FT_UInt n, idx; 108 109 110 p = table + 6; 111 for ( n = 0; n < 256; n++ ) 112 { 113 idx = *p++; 114 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) 115 FT_INVALID_GLYPH_ID; 116 } 117 } 118 119 return FT_Err_Ok; 120 } 121 122 123 FT_CALLBACK_DEF( FT_UInt ) 124 tt_cmap0_char_index( TT_CMap cmap, 125 FT_UInt32 char_code ) 126 { 127 FT_Byte* table = cmap->data; 128 129 130 return char_code < 256 ? table[6 + char_code] : 0; 131 } 132 133 134 FT_CALLBACK_DEF( FT_UInt32 ) 135 tt_cmap0_char_next( TT_CMap cmap, 136 FT_UInt32 *pchar_code ) 137 { 138 FT_Byte* table = cmap->data; 139 FT_UInt32 charcode = *pchar_code; 140 FT_UInt32 result = 0; 141 FT_UInt gindex = 0; 142 143 144 table += 6; /* go to glyph IDs */ 145 while ( ++charcode < 256 ) 146 { 147 gindex = table[charcode]; 148 if ( gindex != 0 ) 149 { 150 result = charcode; 151 break; 152 } 153 } 154 155 *pchar_code = result; 156 return gindex; 157 } 158 159 160 FT_CALLBACK_DEF( FT_Error ) 161 tt_cmap0_get_info( TT_CMap cmap, 162 TT_CMapInfo *cmap_info ) 163 { 164 FT_Byte* p = cmap->data + 4; 165 166 167 cmap_info->format = 0; 168 cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); 169 170 return FT_Err_Ok; 171 } 172 173 174 FT_DEFINE_TT_CMAP( 175 tt_cmap0_class_rec, 176 sizeof ( TT_CMapRec ), 177 178 (FT_CMap_InitFunc) tt_cmap_init, 179 (FT_CMap_DoneFunc) NULL, 180 (FT_CMap_CharIndexFunc)tt_cmap0_char_index, 181 (FT_CMap_CharNextFunc) tt_cmap0_char_next, 182 183 NULL, 184 NULL, 185 NULL, 186 NULL, 187 NULL, 188 189 0, 190 (TT_CMap_ValidateFunc)tt_cmap0_validate, 191 (TT_CMap_Info_GetFunc)tt_cmap0_get_info ) 192 193 #endif /* TT_CONFIG_CMAP_FORMAT_0 */ 194 195 196 /*************************************************************************/ 197 /*************************************************************************/ 198 /***** *****/ 199 /***** FORMAT 2 *****/ 200 /***** *****/ 201 /***** This is used for certain CJK encodings that encode text in a *****/ 202 /***** mixed 8/16 bits encoding along the following lines: *****/ 203 /***** *****/ 204 /***** * Certain byte values correspond to an 8-bit character code *****/ 205 /***** (typically in the range 0..127 for ASCII compatibility). *****/ 206 /***** *****/ 207 /***** * Certain byte values signal the first byte of a 2-byte *****/ 208 /***** character code (but these values are also valid as the *****/ 209 /***** second byte of a 2-byte character). *****/ 210 /***** *****/ 211 /***** The following charmap lookup and iteration functions all *****/ 212 /***** assume that the value "charcode" correspond to following: *****/ 213 /***** *****/ 214 /***** - For one byte characters, "charcode" is simply the *****/ 215 /***** character code. *****/ 216 /***** *****/ 217 /***** - For two byte characters, "charcode" is the 2-byte *****/ 218 /***** character code in big endian format. More exactly: *****/ 219 /***** *****/ 220 /***** (charcode >> 8) is the first byte value *****/ 221 /***** (charcode & 0xFF) is the second byte value *****/ 222 /***** *****/ 223 /***** Note that not all values of "charcode" are valid according *****/ 224 /***** to these rules, and the function moderately check the *****/ 225 /***** arguments. *****/ 226 /***** *****/ 227 /*************************************************************************/ 228 /*************************************************************************/ 229 230 /*************************************************************************/ 231 /* */ 232 /* TABLE OVERVIEW */ 233 /* -------------- */ 234 /* */ 235 /* NAME OFFSET TYPE DESCRIPTION */ 236 /* */ 237 /* format 0 USHORT must be 2 */ 238 /* length 2 USHORT table length in bytes */ 239 /* language 4 USHORT Mac language code */ 240 /* keys 6 USHORT[256] sub-header keys */ 241 /* subs 518 SUBHEAD[NSUBS] sub-headers array */ 242 /* glyph_ids 518+NSUB*8 USHORT[] glyph ID array */ 243 /* */ 244 /* The `keys' table is used to map charcode high-bytes to sub-headers. */ 245 /* The value of `NSUBS' is the number of sub-headers defined in the */ 246 /* table and is computed by finding the maximum of the `keys' table. */ 247 /* */ 248 /* Note that for any n, `keys[n]' is a byte offset within the `subs' */ 249 /* table, i.e., it is the corresponding sub-header index multiplied */ 250 /* by 8. */ 251 /* */ 252 /* Each sub-header has the following format: */ 253 /* */ 254 /* NAME OFFSET TYPE DESCRIPTION */ 255 /* */ 256 /* first 0 USHORT first valid low-byte */ 257 /* count 2 USHORT number of valid low-bytes */ 258 /* delta 4 SHORT see below */ 259 /* offset 6 USHORT see below */ 260 /* */ 261 /* A sub-header defines, for each high-byte, the range of valid */ 262 /* low-bytes within the charmap. Note that the range defined by `first' */ 263 /* and `count' must be completely included in the interval [0..255] */ 264 /* according to the specification. */ 265 /* */ 266 /* If a character code is contained within a given sub-header, then */ 267 /* mapping it to a glyph index is done as follows: */ 268 /* */ 269 /* * The value of `offset' is read. This is a _byte_ distance from the */ 270 /* location of the `offset' field itself into a slice of the */ 271 /* `glyph_ids' table. Let's call it `slice' (it is a USHORT[] too). */ 272 /* */ 273 /* * The value `slice[char.lo - first]' is read. If it is 0, there is */ 274 /* no glyph for the charcode. Otherwise, the value of `delta' is */ 275 /* added to it (modulo 65536) to form a new glyph index. */ 276 /* */ 277 /* It is up to the validation routine to check that all offsets fall */ 278 /* within the glyph IDs table (and not within the `subs' table itself or */ 279 /* outside of the CMap). */ 280 /* */ 281 282 #ifdef TT_CONFIG_CMAP_FORMAT_2 283 284 FT_CALLBACK_DEF( FT_Error ) 285 tt_cmap2_validate( FT_Byte* table, 286 FT_Validator valid ) 287 { 288 FT_Byte* p; 289 FT_UInt length; 290 291 FT_UInt n, max_subs; 292 FT_Byte* keys; /* keys table */ 293 FT_Byte* subs; /* sub-headers */ 294 FT_Byte* glyph_ids; /* glyph ID array */ 295 296 297 if ( table + 2 + 2 > valid->limit ) 298 FT_INVALID_TOO_SHORT; 299 300 p = table + 2; /* skip format */ 301 length = TT_NEXT_USHORT( p ); 302 303 if ( table + length > valid->limit || length < 6 + 512 ) 304 FT_INVALID_TOO_SHORT; 305 306 keys = table + 6; 307 308 /* parse keys to compute sub-headers count */ 309 p = keys; 310 max_subs = 0; 311 for ( n = 0; n < 256; n++ ) 312 { 313 FT_UInt idx = TT_NEXT_USHORT( p ); 314 315 316 /* value must be multiple of 8 */ 317 if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 ) 318 FT_INVALID_DATA; 319 320 idx >>= 3; 321 322 if ( idx > max_subs ) 323 max_subs = idx; 324 } 325 326 FT_ASSERT( p == table + 518 ); 327 328 subs = p; 329 glyph_ids = subs + (max_subs + 1) * 8; 330 if ( glyph_ids > valid->limit ) 331 FT_INVALID_TOO_SHORT; 332 333 /* parse sub-headers */ 334 for ( n = 0; n <= max_subs; n++ ) 335 { 336 FT_UInt first_code, code_count, offset; 337 FT_Int delta; 338 339 340 first_code = TT_NEXT_USHORT( p ); 341 code_count = TT_NEXT_USHORT( p ); 342 delta = TT_NEXT_SHORT( p ); 343 offset = TT_NEXT_USHORT( p ); 344 345 /* many Dynalab fonts have empty sub-headers */ 346 if ( code_count == 0 ) 347 continue; 348 349 /* check range within 0..255 */ 350 if ( valid->level >= FT_VALIDATE_PARANOID ) 351 { 352 if ( first_code >= 256 || first_code + code_count > 256 ) 353 FT_INVALID_DATA; 354 } 355 356 /* check offset */ 357 if ( offset != 0 ) 358 { 359 FT_Byte* ids; 360 361 362 ids = p - 2 + offset; 363 if ( ids < glyph_ids || ids + code_count*2 > table + length ) 364 FT_INVALID_OFFSET; 365 366 /* check glyph IDs */ 367 if ( valid->level >= FT_VALIDATE_TIGHT ) 368 { 369 FT_Byte* limit = p + code_count * 2; 370 FT_UInt idx; 371 372 373 for ( ; p < limit; ) 374 { 375 idx = TT_NEXT_USHORT( p ); 376 if ( idx != 0 ) 377 { 378 idx = ( idx + delta ) & 0xFFFFU; 379 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) 380 FT_INVALID_GLYPH_ID; 381 } 382 } 383 } 384 } 385 } 386 387 return FT_Err_Ok; 388 } 389 390 391 /* return sub header corresponding to a given character code */ 392 /* NULL on invalid charcode */ 393 static FT_Byte* 394 tt_cmap2_get_subheader( FT_Byte* table, 395 FT_UInt32 char_code ) 396 { 397 FT_Byte* result = NULL; 398 399 400 if ( char_code < 0x10000UL ) 401 { 402 FT_UInt char_lo = (FT_UInt)( char_code & 0xFF ); 403 FT_UInt char_hi = (FT_UInt)( char_code >> 8 ); 404 FT_Byte* p = table + 6; /* keys table */ 405 FT_Byte* subs = table + 518; /* subheaders table */ 406 FT_Byte* sub; 407 408 409 if ( char_hi == 0 ) 410 { 411 /* an 8-bit character code -- we use subHeader 0 in this case */ 412 /* to test whether the character code is in the charmap */ 413 /* */ 414 sub = subs; /* jump to first sub-header */ 415 416 /* check that the sub-header for this byte is 0, which */ 417 /* indicates that it is really a valid one-byte value */ 418 /* Otherwise, return 0 */ 419 /* */ 420 p += char_lo * 2; 421 if ( TT_PEEK_USHORT( p ) != 0 ) 422 goto Exit; 423 } 424 else 425 { 426 /* a 16-bit character code */ 427 428 /* jump to key entry */ 429 p += char_hi * 2; 430 /* jump to sub-header */ 431 sub = subs + ( FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 8 ) ); 432 433 /* check that the high byte isn't a valid one-byte value */ 434 if ( sub == subs ) 435 goto Exit; 436 } 437 result = sub; 438 } 439 Exit: 440 return result; 441 } 442 443 444 FT_CALLBACK_DEF( FT_UInt ) 445 tt_cmap2_char_index( TT_CMap cmap, 446 FT_UInt32 char_code ) 447 { 448 FT_Byte* table = cmap->data; 449 FT_UInt result = 0; 450 FT_Byte* subheader; 451 452 453 subheader = tt_cmap2_get_subheader( table, char_code ); 454 if ( subheader ) 455 { 456 FT_Byte* p = subheader; 457 FT_UInt idx = (FT_UInt)(char_code & 0xFF); 458 FT_UInt start, count; 459 FT_Int delta; 460 FT_UInt offset; 461 462 463 start = TT_NEXT_USHORT( p ); 464 count = TT_NEXT_USHORT( p ); 465 delta = TT_NEXT_SHORT ( p ); 466 offset = TT_PEEK_USHORT( p ); 467 468 idx -= start; 469 if ( idx < count && offset != 0 ) 470 { 471 p += offset + 2 * idx; 472 idx = TT_PEEK_USHORT( p ); 473 474 if ( idx != 0 ) 475 result = (FT_UInt)( idx + delta ) & 0xFFFFU; 476 } 477 } 478 return result; 479 } 480 481 482 FT_CALLBACK_DEF( FT_UInt32 ) 483 tt_cmap2_char_next( TT_CMap cmap, 484 FT_UInt32 *pcharcode ) 485 { 486 FT_Byte* table = cmap->data; 487 FT_UInt gindex = 0; 488 FT_UInt32 result = 0; 489 FT_UInt32 charcode = *pcharcode + 1; 490 FT_Byte* subheader; 491 492 493 while ( charcode < 0x10000UL ) 494 { 495 subheader = tt_cmap2_get_subheader( table, charcode ); 496 if ( subheader ) 497 { 498 FT_Byte* p = subheader; 499 FT_UInt start = TT_NEXT_USHORT( p ); 500 FT_UInt count = TT_NEXT_USHORT( p ); 501 FT_Int delta = TT_NEXT_SHORT ( p ); 502 FT_UInt offset = TT_PEEK_USHORT( p ); 503 FT_UInt char_lo = (FT_UInt)( charcode & 0xFF ); 504 FT_UInt pos, idx; 505 506 507 if ( offset == 0 ) 508 goto Next_SubHeader; 509 510 if ( char_lo < start ) 511 { 512 char_lo = start; 513 pos = 0; 514 } 515 else 516 pos = (FT_UInt)( char_lo - start ); 517 518 p += offset + pos * 2; 519 charcode = FT_PAD_FLOOR( charcode, 256 ) + char_lo; 520 521 for ( ; pos < count; pos++, charcode++ ) 522 { 523 idx = TT_NEXT_USHORT( p ); 524 525 if ( idx != 0 ) 526 { 527 gindex = ( idx + delta ) & 0xFFFFU; 528 if ( gindex != 0 ) 529 { 530 result = charcode; 531 goto Exit; 532 } 533 } 534 } 535 } 536 537 /* jump to next sub-header, i.e. higher byte value */ 538 Next_SubHeader: 539 charcode = FT_PAD_FLOOR( charcode, 256 ) + 256; 540 } 541 542 Exit: 543 *pcharcode = result; 544 545 return gindex; 546 } 547 548 549 FT_CALLBACK_DEF( FT_Error ) 550 tt_cmap2_get_info( TT_CMap cmap, 551 TT_CMapInfo *cmap_info ) 552 { 553 FT_Byte* p = cmap->data + 4; 554 555 556 cmap_info->format = 2; 557 cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); 558 559 return FT_Err_Ok; 560 } 561 562 563 FT_DEFINE_TT_CMAP( 564 tt_cmap2_class_rec, 565 sizeof ( TT_CMapRec ), 566 567 (FT_CMap_InitFunc) tt_cmap_init, 568 (FT_CMap_DoneFunc) NULL, 569 (FT_CMap_CharIndexFunc)tt_cmap2_char_index, 570 (FT_CMap_CharNextFunc) tt_cmap2_char_next, 571 572 NULL, 573 NULL, 574 NULL, 575 NULL, 576 NULL, 577 578 2, 579 (TT_CMap_ValidateFunc)tt_cmap2_validate, 580 (TT_CMap_Info_GetFunc)tt_cmap2_get_info ) 581 582 #endif /* TT_CONFIG_CMAP_FORMAT_2 */ 583 584 585 /*************************************************************************/ 586 /*************************************************************************/ 587 /***** *****/ 588 /***** FORMAT 4 *****/ 589 /***** *****/ 590 /*************************************************************************/ 591 /*************************************************************************/ 592 593 /*************************************************************************/ 594 /* */ 595 /* TABLE OVERVIEW */ 596 /* -------------- */ 597 /* */ 598 /* NAME OFFSET TYPE DESCRIPTION */ 599 /* */ 600 /* format 0 USHORT must be 4 */ 601 /* length 2 USHORT table length */ 602 /* in bytes */ 603 /* language 4 USHORT Mac language code */ 604 /* */ 605 /* segCountX2 6 USHORT 2*NUM_SEGS */ 606 /* searchRange 8 USHORT 2*(1 << LOG_SEGS) */ 607 /* entrySelector 10 USHORT LOG_SEGS */ 608 /* rangeShift 12 USHORT segCountX2 - */ 609 /* searchRange */ 610 /* */ 611 /* endCount 14 USHORT[NUM_SEGS] end charcode for */ 612 /* each segment; last */ 613 /* is 0xFFFF */ 614 /* */ 615 /* pad 14+NUM_SEGS*2 USHORT padding */ 616 /* */ 617 /* startCount 16+NUM_SEGS*2 USHORT[NUM_SEGS] first charcode for */ 618 /* each segment */ 619 /* */ 620 /* idDelta 16+NUM_SEGS*4 SHORT[NUM_SEGS] delta for each */ 621 /* segment */ 622 /* idOffset 16+NUM_SEGS*6 SHORT[NUM_SEGS] range offset for */ 623 /* each segment; can be */ 624 /* zero */ 625 /* */ 626 /* glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph ID */ 627 /* ranges */ 628 /* */ 629 /* Character codes are modelled by a series of ordered (increasing) */ 630 /* intervals called segments. Each segment has start and end codes, */ 631 /* provided by the `startCount' and `endCount' arrays. Segments must */ 632 /* not overlap, and the last segment should always contain the value */ 633 /* 0xFFFF for `endCount'. */ 634 /* */ 635 /* The fields `searchRange', `entrySelector' and `rangeShift' are better */ 636 /* ignored (they are traces of over-engineering in the TrueType */ 637 /* specification). */ 638 /* */ 639 /* Each segment also has a signed `delta', as well as an optional offset */ 640 /* within the `glyphIds' table. */ 641 /* */ 642 /* If a segment's idOffset is 0, the glyph index corresponding to any */ 643 /* charcode within the segment is obtained by adding the value of */ 644 /* `idDelta' directly to the charcode, modulo 65536. */ 645 /* */ 646 /* Otherwise, a glyph index is taken from the glyph IDs sub-array for */ 647 /* the segment, and the value of `idDelta' is added to it. */ 648 /* */ 649 /* */ 650 /* Finally, note that a lot of fonts contain an invalid last segment, */ 651 /* where `start' and `end' are correctly set to 0xFFFF but both `delta' */ 652 /* and `offset' are incorrect (e.g., `opens___.ttf' which comes with */ 653 /* OpenOffice.org). We need special code to deal with them correctly. */ 654 /* */ 655 656 #ifdef TT_CONFIG_CMAP_FORMAT_4 657 658 typedef struct TT_CMap4Rec_ 659 { 660 TT_CMapRec cmap; 661 FT_UInt32 cur_charcode; /* current charcode */ 662 FT_UInt cur_gindex; /* current glyph index */ 663 664 FT_UInt num_ranges; 665 FT_UInt cur_range; 666 FT_UInt cur_start; 667 FT_UInt cur_end; 668 FT_Int cur_delta; 669 FT_Byte* cur_values; 670 671 } TT_CMap4Rec, *TT_CMap4; 672 673 674 FT_CALLBACK_DEF( FT_Error ) 675 tt_cmap4_init( TT_CMap4 cmap, 676 FT_Byte* table ) 677 { 678 FT_Byte* p; 679 680 681 cmap->cmap.data = table; 682 683 p = table + 6; 684 cmap->num_ranges = FT_PEEK_USHORT( p ) >> 1; 685 cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL; 686 cmap->cur_gindex = 0; 687 688 return FT_Err_Ok; 689 } 690 691 692 static FT_Int 693 tt_cmap4_set_range( TT_CMap4 cmap, 694 FT_UInt range_index ) 695 { 696 FT_Byte* table = cmap->cmap.data; 697 FT_Byte* p; 698 FT_UInt num_ranges = cmap->num_ranges; 699 700 701 while ( range_index < num_ranges ) 702 { 703 FT_UInt offset; 704 705 706 p = table + 14 + range_index * 2; 707 cmap->cur_end = FT_PEEK_USHORT( p ); 708 709 p += 2 + num_ranges * 2; 710 cmap->cur_start = FT_PEEK_USHORT( p ); 711 712 p += num_ranges * 2; 713 cmap->cur_delta = FT_PEEK_SHORT( p ); 714 715 p += num_ranges * 2; 716 offset = FT_PEEK_USHORT( p ); 717 718 /* some fonts have an incorrect last segment; */ 719 /* we have to catch it */ 720 if ( range_index >= num_ranges - 1 && 721 cmap->cur_start == 0xFFFFU && 722 cmap->cur_end == 0xFFFFU ) 723 { 724 TT_Face face = (TT_Face)cmap->cmap.cmap.charmap.face; 725 FT_Byte* limit = face->cmap_table + face->cmap_size; 726 727 728 if ( offset && p + offset + 2 > limit ) 729 { 730 cmap->cur_delta = 1; 731 offset = 0; 732 } 733 } 734 735 if ( offset != 0xFFFFU ) 736 { 737 cmap->cur_values = offset ? p + offset : NULL; 738 cmap->cur_range = range_index; 739 return 0; 740 } 741 742 /* we skip empty segments */ 743 range_index++; 744 } 745 746 return -1; 747 } 748 749 750 /* search the index of the charcode next to cmap->cur_charcode; */ 751 /* caller should call tt_cmap4_set_range with proper range */ 752 /* before calling this function */ 753 /* */ 754 static void 755 tt_cmap4_next( TT_CMap4 cmap ) 756 { 757 FT_UInt charcode; 758 759 760 if ( cmap->cur_charcode >= 0xFFFFUL ) 761 goto Fail; 762 763 charcode = (FT_UInt)cmap->cur_charcode + 1; 764 765 if ( charcode < cmap->cur_start ) 766 charcode = cmap->cur_start; 767 768 for ( ;; ) 769 { 770 FT_Byte* values = cmap->cur_values; 771 FT_UInt end = cmap->cur_end; 772 FT_Int delta = cmap->cur_delta; 773 774 775 if ( charcode <= end ) 776 { 777 if ( values ) 778 { 779 FT_Byte* p = values + 2 * ( charcode - cmap->cur_start ); 780 781 782 do 783 { 784 FT_UInt gindex = FT_NEXT_USHORT( p ); 785 786 787 if ( gindex != 0 ) 788 { 789 gindex = (FT_UInt)( ( gindex + delta ) & 0xFFFFU ); 790 if ( gindex != 0 ) 791 { 792 cmap->cur_charcode = charcode; 793 cmap->cur_gindex = gindex; 794 return; 795 } 796 } 797 } while ( ++charcode <= end ); 798 } 799 else 800 { 801 do 802 { 803 FT_UInt gindex = (FT_UInt)( ( charcode + delta ) & 0xFFFFU ); 804 805 806 if ( gindex != 0 ) 807 { 808 cmap->cur_charcode = charcode; 809 cmap->cur_gindex = gindex; 810 return; 811 } 812 } while ( ++charcode <= end ); 813 } 814 } 815 816 /* we need to find another range */ 817 if ( tt_cmap4_set_range( cmap, cmap->cur_range + 1 ) < 0 ) 818 break; 819 820 if ( charcode < cmap->cur_start ) 821 charcode = cmap->cur_start; 822 } 823 824 Fail: 825 cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL; 826 cmap->cur_gindex = 0; 827 } 828 829 830 FT_CALLBACK_DEF( FT_Error ) 831 tt_cmap4_validate( FT_Byte* table, 832 FT_Validator valid ) 833 { 834 FT_Byte* p; 835 FT_UInt length; 836 837 FT_Byte *ends, *starts, *offsets, *deltas, *glyph_ids; 838 FT_UInt num_segs; 839 FT_Error error = FT_Err_Ok; 840 841 842 if ( table + 2 + 2 > valid->limit ) 843 FT_INVALID_TOO_SHORT; 844 845 p = table + 2; /* skip format */ 846 length = TT_NEXT_USHORT( p ); 847 848 if ( length < 16 ) 849 FT_INVALID_TOO_SHORT; 850 851 /* in certain fonts, the `length' field is invalid and goes */ 852 /* out of bound. We try to correct this here... */ 853 if ( table + length > valid->limit ) 854 { 855 if ( valid->level >= FT_VALIDATE_TIGHT ) 856 FT_INVALID_TOO_SHORT; 857 858 length = (FT_UInt)( valid->limit - table ); 859 } 860 861 p = table + 6; 862 num_segs = TT_NEXT_USHORT( p ); /* read segCountX2 */ 863 864 if ( valid->level >= FT_VALIDATE_PARANOID ) 865 { 866 /* check that we have an even value here */ 867 if ( num_segs & 1 ) 868 FT_INVALID_DATA; 869 } 870 871 num_segs /= 2; 872 873 if ( length < 16 + num_segs * 2 * 4 ) 874 FT_INVALID_TOO_SHORT; 875 876 /* check the search parameters - even though we never use them */ 877 /* */ 878 if ( valid->level >= FT_VALIDATE_PARANOID ) 879 { 880 /* check the values of `searchRange', `entrySelector', `rangeShift' */ 881 FT_UInt search_range = TT_NEXT_USHORT( p ); 882 FT_UInt entry_selector = TT_NEXT_USHORT( p ); 883 FT_UInt range_shift = TT_NEXT_USHORT( p ); 884 885 886 if ( ( search_range | range_shift ) & 1 ) /* must be even values */ 887 FT_INVALID_DATA; 888 889 search_range /= 2; 890 range_shift /= 2; 891 892 /* `search range' is the greatest power of 2 that is <= num_segs */ 893 894 if ( search_range > num_segs || 895 search_range * 2 < num_segs || 896 search_range + range_shift != num_segs || 897 search_range != ( 1U << entry_selector ) ) 898 FT_INVALID_DATA; 899 } 900 901 ends = table + 14; 902 starts = table + 16 + num_segs * 2; 903 deltas = starts + num_segs * 2; 904 offsets = deltas + num_segs * 2; 905 glyph_ids = offsets + num_segs * 2; 906 907 /* check last segment; its end count value must be 0xFFFF */ 908 if ( valid->level >= FT_VALIDATE_PARANOID ) 909 { 910 p = ends + ( num_segs - 1 ) * 2; 911 if ( TT_PEEK_USHORT( p ) != 0xFFFFU ) 912 FT_INVALID_DATA; 913 } 914 915 { 916 FT_UInt start, end, offset, n; 917 FT_UInt last_start = 0, last_end = 0; 918 FT_Int delta; 919 FT_Byte* p_start = starts; 920 FT_Byte* p_end = ends; 921 FT_Byte* p_delta = deltas; 922 FT_Byte* p_offset = offsets; 923 924 925 for ( n = 0; n < num_segs; n++ ) 926 { 927 p = p_offset; 928 start = TT_NEXT_USHORT( p_start ); 929 end = TT_NEXT_USHORT( p_end ); 930 delta = TT_NEXT_SHORT( p_delta ); 931 offset = TT_NEXT_USHORT( p_offset ); 932 933 if ( start > end ) 934 FT_INVALID_DATA; 935 936 /* this test should be performed at default validation level; */ 937 /* unfortunately, some popular Asian fonts have overlapping */ 938 /* ranges in their charmaps */ 939 /* */ 940 if ( start <= last_end && n > 0 ) 941 { 942 if ( valid->level >= FT_VALIDATE_TIGHT ) 943 FT_INVALID_DATA; 944 else 945 { 946 /* allow overlapping segments, provided their start points */ 947 /* and end points, respectively, are in ascending order */ 948 /* */ 949 if ( last_start > start || last_end > end ) 950 error |= TT_CMAP_FLAG_UNSORTED; 951 else 952 error |= TT_CMAP_FLAG_OVERLAPPING; 953 } 954 } 955 956 if ( offset && offset != 0xFFFFU ) 957 { 958 p += offset; /* start of glyph ID array */ 959 960 /* check that we point within the glyph IDs table only */ 961 if ( valid->level >= FT_VALIDATE_TIGHT ) 962 { 963 if ( p < glyph_ids || 964 p + ( end - start + 1 ) * 2 > table + length ) 965 FT_INVALID_DATA; 966 } 967 /* Some fonts handle the last segment incorrectly. In */ 968 /* theory, 0xFFFF might point to an ordinary glyph -- */ 969 /* a cmap 4 is versatile and could be used for any */ 970 /* encoding, not only Unicode. However, reality shows */ 971 /* that far too many fonts are sloppy and incorrectly */ 972 /* set all fields but `start' and `end' for the last */ 973 /* segment if it contains only a single character. */ 974 /* */ 975 /* We thus omit the test here, delaying it to the */ 976 /* routines which actually access the cmap. */ 977 else if ( n != num_segs - 1 || 978 !( start == 0xFFFFU && end == 0xFFFFU ) ) 979 { 980 if ( p < glyph_ids || 981 p + ( end - start + 1 ) * 2 > valid->limit ) 982 FT_INVALID_DATA; 983 } 984 985 /* check glyph indices within the segment range */ 986 if ( valid->level >= FT_VALIDATE_TIGHT ) 987 { 988 FT_UInt i, idx; 989 990 991 for ( i = start; i < end; i++ ) 992 { 993 idx = FT_NEXT_USHORT( p ); 994 if ( idx != 0 ) 995 { 996 idx = (FT_UInt)( idx + delta ) & 0xFFFFU; 997 998 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) 999 FT_INVALID_GLYPH_ID; 1000 } 1001 } 1002 } 1003 } 1004 else if ( offset == 0xFFFFU ) 1005 { 1006 /* some fonts (erroneously?) use a range offset of 0xFFFF */ 1007 /* to mean missing glyph in cmap table */ 1008 /* */ 1009 if ( valid->level >= FT_VALIDATE_PARANOID || 1010 n != num_segs - 1 || 1011 !( start == 0xFFFFU && end == 0xFFFFU ) ) 1012 FT_INVALID_DATA; 1013 } 1014 1015 last_start = start; 1016 last_end = end; 1017 } 1018 } 1019 1020 return error; 1021 } 1022 1023 1024 static FT_UInt 1025 tt_cmap4_char_map_linear( TT_CMap cmap, 1026 FT_UInt32* pcharcode, 1027 FT_Bool next ) 1028 { 1029 FT_UInt num_segs2, start, end, offset; 1030 FT_Int delta; 1031 FT_UInt i, num_segs; 1032 FT_UInt32 charcode = *pcharcode; 1033 FT_UInt gindex = 0; 1034 FT_Byte* p; 1035 1036 1037 p = cmap->data + 6; 1038 num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); 1039 1040 num_segs = num_segs2 >> 1; 1041 1042 if ( !num_segs ) 1043 return 0; 1044 1045 if ( next ) 1046 charcode++; 1047 1048 /* linear search */ 1049 for ( ; charcode <= 0xFFFFU; charcode++ ) 1050 { 1051 FT_Byte* q; 1052 1053 1054 p = cmap->data + 14; /* ends table */ 1055 q = cmap->data + 16 + num_segs2; /* starts table */ 1056 1057 for ( i = 0; i < num_segs; i++ ) 1058 { 1059 end = TT_NEXT_USHORT( p ); 1060 start = TT_NEXT_USHORT( q ); 1061 1062 if ( charcode >= start && charcode <= end ) 1063 { 1064 p = q - 2 + num_segs2; 1065 delta = TT_PEEK_SHORT( p ); 1066 p += num_segs2; 1067 offset = TT_PEEK_USHORT( p ); 1068 1069 /* some fonts have an incorrect last segment; */ 1070 /* we have to catch it */ 1071 if ( i >= num_segs - 1 && 1072 start == 0xFFFFU && end == 0xFFFFU ) 1073 { 1074 TT_Face face = (TT_Face)cmap->cmap.charmap.face; 1075 FT_Byte* limit = face->cmap_table + face->cmap_size; 1076 1077 1078 if ( offset && p + offset + 2 > limit ) 1079 { 1080 delta = 1; 1081 offset = 0; 1082 } 1083 } 1084 1085 if ( offset == 0xFFFFU ) 1086 continue; 1087 1088 if ( offset ) 1089 { 1090 p += offset + ( charcode - start ) * 2; 1091 gindex = TT_PEEK_USHORT( p ); 1092 if ( gindex != 0 ) 1093 gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU; 1094 } 1095 else 1096 gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU; 1097 1098 break; 1099 } 1100 } 1101 1102 if ( !next || gindex ) 1103 break; 1104 } 1105 1106 if ( next && gindex ) 1107 *pcharcode = charcode; 1108 1109 return gindex; 1110 } 1111 1112 1113 static FT_UInt 1114 tt_cmap4_char_map_binary( TT_CMap cmap, 1115 FT_UInt32* pcharcode, 1116 FT_Bool next ) 1117 { 1118 FT_UInt num_segs2, start, end, offset; 1119 FT_Int delta; 1120 FT_UInt max, min, mid, num_segs; 1121 FT_UInt charcode = (FT_UInt)*pcharcode; 1122 FT_UInt gindex = 0; 1123 FT_Byte* p; 1124 1125 1126 p = cmap->data + 6; 1127 num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); 1128 1129 if ( !num_segs2 ) 1130 return 0; 1131 1132 num_segs = num_segs2 >> 1; 1133 1134 /* make compiler happy */ 1135 mid = num_segs; 1136 end = 0xFFFFU; 1137 1138 if ( next ) 1139 charcode++; 1140 1141 min = 0; 1142 max = num_segs; 1143 1144 /* binary search */ 1145 while ( min < max ) 1146 { 1147 mid = ( min + max ) >> 1; 1148 p = cmap->data + 14 + mid * 2; 1149 end = TT_PEEK_USHORT( p ); 1150 p += 2 + num_segs2; 1151 start = TT_PEEK_USHORT( p ); 1152 1153 if ( charcode < start ) 1154 max = mid; 1155 else if ( charcode > end ) 1156 min = mid + 1; 1157 else 1158 { 1159 p += num_segs2; 1160 delta = TT_PEEK_SHORT( p ); 1161 p += num_segs2; 1162 offset = TT_PEEK_USHORT( p ); 1163 1164 /* some fonts have an incorrect last segment; */ 1165 /* we have to catch it */ 1166 if ( mid >= num_segs - 1 && 1167 start == 0xFFFFU && end == 0xFFFFU ) 1168 { 1169 TT_Face face = (TT_Face)cmap->cmap.charmap.face; 1170 FT_Byte* limit = face->cmap_table + face->cmap_size; 1171 1172 1173 if ( offset && p + offset + 2 > limit ) 1174 { 1175 delta = 1; 1176 offset = 0; 1177 } 1178 } 1179 1180 /* search the first segment containing `charcode' */ 1181 if ( cmap->flags & TT_CMAP_FLAG_OVERLAPPING ) 1182 { 1183 FT_UInt i; 1184 1185 1186 /* call the current segment `max' */ 1187 max = mid; 1188 1189 if ( offset == 0xFFFFU ) 1190 mid = max + 1; 1191 1192 /* search in segments before the current segment */ 1193 for ( i = max ; i > 0; i-- ) 1194 { 1195 FT_UInt prev_end; 1196 FT_Byte* old_p; 1197 1198 1199 old_p = p; 1200 p = cmap->data + 14 + ( i - 1 ) * 2; 1201 prev_end = TT_PEEK_USHORT( p ); 1202 1203 if ( charcode > prev_end ) 1204 { 1205 p = old_p; 1206 break; 1207 } 1208 1209 end = prev_end; 1210 p += 2 + num_segs2; 1211 start = TT_PEEK_USHORT( p ); 1212 p += num_segs2; 1213 delta = TT_PEEK_SHORT( p ); 1214 p += num_segs2; 1215 offset = TT_PEEK_USHORT( p ); 1216 1217 if ( offset != 0xFFFFU ) 1218 mid = i - 1; 1219 } 1220 1221 /* no luck */ 1222 if ( mid == max + 1 ) 1223 { 1224 if ( i != max ) 1225 { 1226 p = cmap->data + 14 + max * 2; 1227 end = TT_PEEK_USHORT( p ); 1228 p += 2 + num_segs2; 1229 start = TT_PEEK_USHORT( p ); 1230 p += num_segs2; 1231 delta = TT_PEEK_SHORT( p ); 1232 p += num_segs2; 1233 offset = TT_PEEK_USHORT( p ); 1234 } 1235 1236 mid = max; 1237 1238 /* search in segments after the current segment */ 1239 for ( i = max + 1; i < num_segs; i++ ) 1240 { 1241 FT_UInt next_end, next_start; 1242 1243 1244 p = cmap->data + 14 + i * 2; 1245 next_end = TT_PEEK_USHORT( p ); 1246 p += 2 + num_segs2; 1247 next_start = TT_PEEK_USHORT( p ); 1248 1249 if ( charcode < next_start ) 1250 break; 1251 1252 end = next_end; 1253 start = next_start; 1254 p += num_segs2; 1255 delta = TT_PEEK_SHORT( p ); 1256 p += num_segs2; 1257 offset = TT_PEEK_USHORT( p ); 1258 1259 if ( offset != 0xFFFFU ) 1260 mid = i; 1261 } 1262 i--; 1263 1264 /* still no luck */ 1265 if ( mid == max ) 1266 { 1267 mid = i; 1268 1269 break; 1270 } 1271 } 1272 1273 /* end, start, delta, and offset are for the i'th segment */ 1274 if ( mid != i ) 1275 { 1276 p = cmap->data + 14 + mid * 2; 1277 end = TT_PEEK_USHORT( p ); 1278 p += 2 + num_segs2; 1279 start = TT_PEEK_USHORT( p ); 1280 p += num_segs2; 1281 delta = TT_PEEK_SHORT( p ); 1282 p += num_segs2; 1283 offset = TT_PEEK_USHORT( p ); 1284 } 1285 } 1286 else 1287 { 1288 if ( offset == 0xFFFFU ) 1289 break; 1290 } 1291 1292 if ( offset ) 1293 { 1294 p += offset + ( charcode - start ) * 2; 1295 gindex = TT_PEEK_USHORT( p ); 1296 if ( gindex != 0 ) 1297 gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU; 1298 } 1299 else 1300 gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU; 1301 1302 break; 1303 } 1304 } 1305 1306 if ( next ) 1307 { 1308 TT_CMap4 cmap4 = (TT_CMap4)cmap; 1309 1310 1311 /* if `charcode' is not in any segment, then `mid' is */ 1312 /* the segment nearest to `charcode' */ 1313 /* */ 1314 1315 if ( charcode > end ) 1316 { 1317 mid++; 1318 if ( mid == num_segs ) 1319 return 0; 1320 } 1321 1322 if ( tt_cmap4_set_range( cmap4, mid ) ) 1323 { 1324 if ( gindex ) 1325 *pcharcode = charcode; 1326 } 1327 else 1328 { 1329 cmap4->cur_charcode = charcode; 1330 1331 if ( gindex ) 1332 cmap4->cur_gindex = gindex; 1333 else 1334 { 1335 cmap4->cur_charcode = charcode; 1336 tt_cmap4_next( cmap4 ); 1337 gindex = cmap4->cur_gindex; 1338 } 1339 1340 if ( gindex ) 1341 *pcharcode = cmap4->cur_charcode; 1342 } 1343 } 1344 1345 return gindex; 1346 } 1347 1348 1349 FT_CALLBACK_DEF( FT_UInt ) 1350 tt_cmap4_char_index( TT_CMap cmap, 1351 FT_UInt32 char_code ) 1352 { 1353 if ( char_code >= 0x10000UL ) 1354 return 0; 1355 1356 if ( cmap->flags & TT_CMAP_FLAG_UNSORTED ) 1357 return tt_cmap4_char_map_linear( cmap, &char_code, 0 ); 1358 else 1359 return tt_cmap4_char_map_binary( cmap, &char_code, 0 ); 1360 } 1361 1362 1363 FT_CALLBACK_DEF( FT_UInt32 ) 1364 tt_cmap4_char_next( TT_CMap cmap, 1365 FT_UInt32 *pchar_code ) 1366 { 1367 FT_UInt gindex; 1368 1369 1370 if ( *pchar_code >= 0xFFFFU ) 1371 return 0; 1372 1373 if ( cmap->flags & TT_CMAP_FLAG_UNSORTED ) 1374 gindex = tt_cmap4_char_map_linear( cmap, pchar_code, 1 ); 1375 else 1376 { 1377 TT_CMap4 cmap4 = (TT_CMap4)cmap; 1378 1379 1380 /* no need to search */ 1381 if ( *pchar_code == cmap4->cur_charcode ) 1382 { 1383 tt_cmap4_next( cmap4 ); 1384 gindex = cmap4->cur_gindex; 1385 if ( gindex ) 1386 *pchar_code = cmap4->cur_charcode; 1387 } 1388 else 1389 gindex = tt_cmap4_char_map_binary( cmap, pchar_code, 1 ); 1390 } 1391 1392 return gindex; 1393 } 1394 1395 1396 FT_CALLBACK_DEF( FT_Error ) 1397 tt_cmap4_get_info( TT_CMap cmap, 1398 TT_CMapInfo *cmap_info ) 1399 { 1400 FT_Byte* p = cmap->data + 4; 1401 1402 1403 cmap_info->format = 4; 1404 cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); 1405 1406 return FT_Err_Ok; 1407 } 1408 1409 1410 FT_DEFINE_TT_CMAP( 1411 tt_cmap4_class_rec, 1412 sizeof ( TT_CMap4Rec ), 1413 (FT_CMap_InitFunc) tt_cmap4_init, 1414 (FT_CMap_DoneFunc) NULL, 1415 (FT_CMap_CharIndexFunc)tt_cmap4_char_index, 1416 (FT_CMap_CharNextFunc) tt_cmap4_char_next, 1417 1418 NULL, 1419 NULL, 1420 NULL, 1421 NULL, 1422 NULL, 1423 1424 4, 1425 (TT_CMap_ValidateFunc)tt_cmap4_validate, 1426 (TT_CMap_Info_GetFunc)tt_cmap4_get_info ) 1427 1428 #endif /* TT_CONFIG_CMAP_FORMAT_4 */ 1429 1430 1431 /*************************************************************************/ 1432 /*************************************************************************/ 1433 /***** *****/ 1434 /***** FORMAT 6 *****/ 1435 /***** *****/ 1436 /*************************************************************************/ 1437 /*************************************************************************/ 1438 1439 /*************************************************************************/ 1440 /* */ 1441 /* TABLE OVERVIEW */ 1442 /* -------------- */ 1443 /* */ 1444 /* NAME OFFSET TYPE DESCRIPTION */ 1445 /* */ 1446 /* format 0 USHORT must be 4 */ 1447 /* length 2 USHORT table length in bytes */ 1448 /* language 4 USHORT Mac language code */ 1449 /* */ 1450 /* first 6 USHORT first segment code */ 1451 /* count 8 USHORT segment size in chars */ 1452 /* glyphIds 10 USHORT[count] glyph IDs */ 1453 /* */ 1454 /* A very simplified segment mapping. */ 1455 /* */ 1456 1457 #ifdef TT_CONFIG_CMAP_FORMAT_6 1458 1459 FT_CALLBACK_DEF( FT_Error ) 1460 tt_cmap6_validate( FT_Byte* table, 1461 FT_Validator valid ) 1462 { 1463 FT_Byte* p; 1464 FT_UInt length, count; 1465 1466 1467 if ( table + 10 > valid->limit ) 1468 FT_INVALID_TOO_SHORT; 1469 1470 p = table + 2; 1471 length = TT_NEXT_USHORT( p ); 1472 1473 p = table + 8; /* skip language and start index */ 1474 count = TT_NEXT_USHORT( p ); 1475 1476 if ( table + length > valid->limit || length < 10 + count * 2 ) 1477 FT_INVALID_TOO_SHORT; 1478 1479 /* check glyph indices */ 1480 if ( valid->level >= FT_VALIDATE_TIGHT ) 1481 { 1482 FT_UInt gindex; 1483 1484 1485 for ( ; count > 0; count-- ) 1486 { 1487 gindex = TT_NEXT_USHORT( p ); 1488 if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) ) 1489 FT_INVALID_GLYPH_ID; 1490 } 1491 } 1492 1493 return FT_Err_Ok; 1494 } 1495 1496 1497 FT_CALLBACK_DEF( FT_UInt ) 1498 tt_cmap6_char_index( TT_CMap cmap, 1499 FT_UInt32 char_code ) 1500 { 1501 FT_Byte* table = cmap->data; 1502 FT_UInt result = 0; 1503 FT_Byte* p = table + 6; 1504 FT_UInt start = TT_NEXT_USHORT( p ); 1505 FT_UInt count = TT_NEXT_USHORT( p ); 1506 FT_UInt idx = (FT_UInt)( char_code - start ); 1507 1508 1509 if ( idx < count ) 1510 { 1511 p += 2 * idx; 1512 result = TT_PEEK_USHORT( p ); 1513 } 1514 return result; 1515 } 1516 1517 1518 FT_CALLBACK_DEF( FT_UInt32 ) 1519 tt_cmap6_char_next( TT_CMap cmap, 1520 FT_UInt32 *pchar_code ) 1521 { 1522 FT_Byte* table = cmap->data; 1523 FT_UInt32 result = 0; 1524 FT_UInt32 char_code = *pchar_code + 1; 1525 FT_UInt gindex = 0; 1526 1527 FT_Byte* p = table + 6; 1528 FT_UInt start = TT_NEXT_USHORT( p ); 1529 FT_UInt count = TT_NEXT_USHORT( p ); 1530 FT_UInt idx; 1531 1532 1533 if ( char_code >= 0x10000UL ) 1534 goto Exit; 1535 1536 if ( char_code < start ) 1537 char_code = start; 1538 1539 idx = (FT_UInt)( char_code - start ); 1540 p += 2 * idx; 1541 1542 for ( ; idx < count; idx++ ) 1543 { 1544 gindex = TT_NEXT_USHORT( p ); 1545 if ( gindex != 0 ) 1546 { 1547 result = char_code; 1548 break; 1549 } 1550 char_code++; 1551 } 1552 1553 Exit: 1554 *pchar_code = result; 1555 return gindex; 1556 } 1557 1558 1559 FT_CALLBACK_DEF( FT_Error ) 1560 tt_cmap6_get_info( TT_CMap cmap, 1561 TT_CMapInfo *cmap_info ) 1562 { 1563 FT_Byte* p = cmap->data + 4; 1564 1565 1566 cmap_info->format = 6; 1567 cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); 1568 1569 return FT_Err_Ok; 1570 } 1571 1572 1573 FT_DEFINE_TT_CMAP( 1574 tt_cmap6_class_rec, 1575 sizeof ( TT_CMapRec ), 1576 1577 (FT_CMap_InitFunc) tt_cmap_init, 1578 (FT_CMap_DoneFunc) NULL, 1579 (FT_CMap_CharIndexFunc)tt_cmap6_char_index, 1580 (FT_CMap_CharNextFunc) tt_cmap6_char_next, 1581 1582 NULL, 1583 NULL, 1584 NULL, 1585 NULL, 1586 NULL, 1587 1588 6, 1589 (TT_CMap_ValidateFunc)tt_cmap6_validate, 1590 (TT_CMap_Info_GetFunc)tt_cmap6_get_info ) 1591 1592 #endif /* TT_CONFIG_CMAP_FORMAT_6 */ 1593 1594 1595 /*************************************************************************/ 1596 /*************************************************************************/ 1597 /***** *****/ 1598 /***** FORMAT 8 *****/ 1599 /***** *****/ 1600 /***** It is hard to completely understand what the OpenType spec *****/ 1601 /***** says about this format, but here is my conclusion. *****/ 1602 /***** *****/ 1603 /***** The purpose of this format is to easily map UTF-16 text to *****/ 1604 /***** glyph indices. Basically, the `char_code' must be in one of *****/ 1605 /***** the following formats: *****/ 1606 /***** *****/ 1607 /***** - A 16-bit value that isn't part of the Unicode Surrogates *****/ 1608 /***** Area (i.e. U+D800-U+DFFF). *****/ 1609 /***** *****/ 1610 /***** - A 32-bit value, made of two surrogate values, i.e.. if *****/ 1611 /***** `char_code = (char_hi << 16) | char_lo', then both *****/ 1612 /***** `char_hi' and `char_lo' must be in the Surrogates Area. *****/ 1613 /***** Area. *****/ 1614 /***** *****/ 1615 /***** The `is32' table embedded in the charmap indicates whether a *****/ 1616 /***** given 16-bit value is in the surrogates area or not. *****/ 1617 /***** *****/ 1618 /***** So, for any given `char_code', we can assert the following: *****/ 1619 /***** *****/ 1620 /***** If `char_hi == 0' then we must have `is32[char_lo] == 0'. *****/ 1621 /***** *****/ 1622 /***** If `char_hi != 0' then we must have both *****/ 1623 /***** `is32[char_hi] != 0' and `is32[char_lo] != 0'. *****/ 1624 /***** *****/ 1625 /*************************************************************************/ 1626 /*************************************************************************/ 1627 1628 /*************************************************************************/ 1629 /* */ 1630 /* TABLE OVERVIEW */ 1631 /* -------------- */ 1632 /* */ 1633 /* NAME OFFSET TYPE DESCRIPTION */ 1634 /* */ 1635 /* format 0 USHORT must be 8 */ 1636 /* reserved 2 USHORT reserved */ 1637 /* length 4 ULONG length in bytes */ 1638 /* language 8 ULONG Mac language code */ 1639 /* is32 12 BYTE[8192] 32-bitness bitmap */ 1640 /* count 8204 ULONG number of groups */ 1641 /* */ 1642 /* This header is followed by `count' groups of the following format: */ 1643 /* */ 1644 /* start 0 ULONG first charcode */ 1645 /* end 4 ULONG last charcode */ 1646 /* startId 8 ULONG start glyph ID for the group */ 1647 /* */ 1648 1649 #ifdef TT_CONFIG_CMAP_FORMAT_8 1650 1651 FT_CALLBACK_DEF( FT_Error ) 1652 tt_cmap8_validate( FT_Byte* table, 1653 FT_Validator valid ) 1654 { 1655 FT_Byte* p = table + 4; 1656 FT_Byte* is32; 1657 FT_UInt32 length; 1658 FT_UInt32 num_groups; 1659 1660 1661 if ( table + 16 + 8192 > valid->limit ) 1662 FT_INVALID_TOO_SHORT; 1663 1664 length = TT_NEXT_ULONG( p ); 1665 if ( length > (FT_UInt32)( valid->limit - table ) || length < 8192 + 16 ) 1666 FT_INVALID_TOO_SHORT; 1667 1668 is32 = table + 12; 1669 p = is32 + 8192; /* skip `is32' array */ 1670 num_groups = TT_NEXT_ULONG( p ); 1671 1672 if ( p + num_groups * 12 > valid->limit ) 1673 FT_INVALID_TOO_SHORT; 1674 1675 /* check groups, they must be in increasing order */ 1676 { 1677 FT_UInt32 n, start, end, start_id, count, last = 0; 1678 1679 1680 for ( n = 0; n < num_groups; n++ ) 1681 { 1682 FT_UInt hi, lo; 1683 1684 1685 start = TT_NEXT_ULONG( p ); 1686 end = TT_NEXT_ULONG( p ); 1687 start_id = TT_NEXT_ULONG( p ); 1688 1689 if ( start > end ) 1690 FT_INVALID_DATA; 1691 1692 if ( n > 0 && start <= last ) 1693 FT_INVALID_DATA; 1694 1695 if ( valid->level >= FT_VALIDATE_TIGHT ) 1696 { 1697 if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ) 1698 FT_INVALID_GLYPH_ID; 1699 1700 count = (FT_UInt32)( end - start + 1 ); 1701 1702 if ( start & ~0xFFFFU ) 1703 { 1704 /* start_hi != 0; check that is32[i] is 1 for each i in */ 1705 /* the `hi' and `lo' of the range [start..end] */ 1706 for ( ; count > 0; count--, start++ ) 1707 { 1708 hi = (FT_UInt)( start >> 16 ); 1709 lo = (FT_UInt)( start & 0xFFFFU ); 1710 1711 if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 ) 1712 FT_INVALID_DATA; 1713 1714 if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 ) 1715 FT_INVALID_DATA; 1716 } 1717 } 1718 else 1719 { 1720 /* start_hi == 0; check that is32[i] is 0 for each i in */ 1721 /* the range [start..end] */ 1722 1723 /* end_hi cannot be != 0! */ 1724 if ( end & ~0xFFFFU ) 1725 FT_INVALID_DATA; 1726 1727 for ( ; count > 0; count--, start++ ) 1728 { 1729 lo = (FT_UInt)( start & 0xFFFFU ); 1730 1731 if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 ) 1732 FT_INVALID_DATA; 1733 } 1734 } 1735 } 1736 1737 last = end; 1738 } 1739 } 1740 1741 return FT_Err_Ok; 1742 } 1743 1744 1745 FT_CALLBACK_DEF( FT_UInt ) 1746 tt_cmap8_char_index( TT_CMap cmap, 1747 FT_UInt32 char_code ) 1748 { 1749 FT_Byte* table = cmap->data; 1750 FT_UInt result = 0; 1751 FT_Byte* p = table + 8204; 1752 FT_UInt32 num_groups = TT_NEXT_ULONG( p ); 1753 FT_UInt32 start, end, start_id; 1754 1755 1756 for ( ; num_groups > 0; num_groups-- ) 1757 { 1758 start = TT_NEXT_ULONG( p ); 1759 end = TT_NEXT_ULONG( p ); 1760 start_id = TT_NEXT_ULONG( p ); 1761 1762 if ( char_code < start ) 1763 break; 1764 1765 if ( char_code <= end ) 1766 { 1767 result = (FT_UInt)( start_id + char_code - start ); 1768 break; 1769 } 1770 } 1771 return result; 1772 } 1773 1774 1775 FT_CALLBACK_DEF( FT_UInt32 ) 1776 tt_cmap8_char_next( TT_CMap cmap, 1777 FT_UInt32 *pchar_code ) 1778 { 1779 FT_UInt32 result = 0; 1780 FT_UInt32 char_code = *pchar_code + 1; 1781 FT_UInt gindex = 0; 1782 FT_Byte* table = cmap->data; 1783 FT_Byte* p = table + 8204; 1784 FT_UInt32 num_groups = TT_NEXT_ULONG( p ); 1785 FT_UInt32 start, end, start_id; 1786 1787 1788 p = table + 8208; 1789 1790 for ( ; num_groups > 0; num_groups-- ) 1791 { 1792 start = TT_NEXT_ULONG( p ); 1793 end = TT_NEXT_ULONG( p ); 1794 start_id = TT_NEXT_ULONG( p ); 1795 1796 if ( char_code < start ) 1797 char_code = start; 1798 1799 if ( char_code <= end ) 1800 { 1801 gindex = (FT_UInt)( char_code - start + start_id ); 1802 if ( gindex != 0 ) 1803 { 1804 result = char_code; 1805 goto Exit; 1806 } 1807 } 1808 } 1809 1810 Exit: 1811 *pchar_code = result; 1812 return gindex; 1813 } 1814 1815 1816 FT_CALLBACK_DEF( FT_Error ) 1817 tt_cmap8_get_info( TT_CMap cmap, 1818 TT_CMapInfo *cmap_info ) 1819 { 1820 FT_Byte* p = cmap->data + 8; 1821 1822 1823 cmap_info->format = 8; 1824 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); 1825 1826 return FT_Err_Ok; 1827 } 1828 1829 1830 FT_DEFINE_TT_CMAP( 1831 tt_cmap8_class_rec, 1832 sizeof ( TT_CMapRec ), 1833 1834 (FT_CMap_InitFunc) tt_cmap_init, 1835 (FT_CMap_DoneFunc) NULL, 1836 (FT_CMap_CharIndexFunc)tt_cmap8_char_index, 1837 (FT_CMap_CharNextFunc) tt_cmap8_char_next, 1838 1839 NULL, 1840 NULL, 1841 NULL, 1842 NULL, 1843 NULL, 1844 1845 8, 1846 (TT_CMap_ValidateFunc)tt_cmap8_validate, 1847 (TT_CMap_Info_GetFunc)tt_cmap8_get_info ) 1848 1849 #endif /* TT_CONFIG_CMAP_FORMAT_8 */ 1850 1851 1852 /*************************************************************************/ 1853 /*************************************************************************/ 1854 /***** *****/ 1855 /***** FORMAT 10 *****/ 1856 /***** *****/ 1857 /*************************************************************************/ 1858 /*************************************************************************/ 1859 1860 /*************************************************************************/ 1861 /* */ 1862 /* TABLE OVERVIEW */ 1863 /* -------------- */ 1864 /* */ 1865 /* NAME OFFSET TYPE DESCRIPTION */ 1866 /* */ 1867 /* format 0 USHORT must be 10 */ 1868 /* reserved 2 USHORT reserved */ 1869 /* length 4 ULONG length in bytes */ 1870 /* language 8 ULONG Mac language code */ 1871 /* */ 1872 /* start 12 ULONG first char in range */ 1873 /* count 16 ULONG number of chars in range */ 1874 /* glyphIds 20 USHORT[count] glyph indices covered */ 1875 /* */ 1876 1877 #ifdef TT_CONFIG_CMAP_FORMAT_10 1878 1879 FT_CALLBACK_DEF( FT_Error ) 1880 tt_cmap10_validate( FT_Byte* table, 1881 FT_Validator valid ) 1882 { 1883 FT_Byte* p = table + 4; 1884 FT_ULong length, count; 1885 1886 1887 if ( table + 20 > valid->limit ) 1888 FT_INVALID_TOO_SHORT; 1889 1890 length = TT_NEXT_ULONG( p ); 1891 p = table + 16; 1892 count = TT_NEXT_ULONG( p ); 1893 1894 if ( length > (FT_ULong)( valid->limit - table ) || 1895 length < 20 + count * 2 ) 1896 FT_INVALID_TOO_SHORT; 1897 1898 /* check glyph indices */ 1899 if ( valid->level >= FT_VALIDATE_TIGHT ) 1900 { 1901 FT_UInt gindex; 1902 1903 1904 for ( ; count > 0; count-- ) 1905 { 1906 gindex = TT_NEXT_USHORT( p ); 1907 if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) ) 1908 FT_INVALID_GLYPH_ID; 1909 } 1910 } 1911 1912 return FT_Err_Ok; 1913 } 1914 1915 1916 FT_CALLBACK_DEF( FT_UInt ) 1917 tt_cmap10_char_index( TT_CMap cmap, 1918 FT_UInt32 char_code ) 1919 { 1920 FT_Byte* table = cmap->data; 1921 FT_UInt result = 0; 1922 FT_Byte* p = table + 12; 1923 FT_UInt32 start = TT_NEXT_ULONG( p ); 1924 FT_UInt32 count = TT_NEXT_ULONG( p ); 1925 FT_UInt32 idx = (FT_ULong)( char_code - start ); 1926 1927 1928 if ( idx < count ) 1929 { 1930 p += 2 * idx; 1931 result = TT_PEEK_USHORT( p ); 1932 } 1933 return result; 1934 } 1935 1936 1937 FT_CALLBACK_DEF( FT_UInt32 ) 1938 tt_cmap10_char_next( TT_CMap cmap, 1939 FT_UInt32 *pchar_code ) 1940 { 1941 FT_Byte* table = cmap->data; 1942 FT_UInt32 char_code = *pchar_code + 1; 1943 FT_UInt gindex = 0; 1944 FT_Byte* p = table + 12; 1945 FT_UInt32 start = TT_NEXT_ULONG( p ); 1946 FT_UInt32 count = TT_NEXT_ULONG( p ); 1947 FT_UInt32 idx; 1948 1949 1950 if ( char_code < start ) 1951 char_code = start; 1952 1953 idx = (FT_UInt32)( char_code - start ); 1954 p += 2 * idx; 1955 1956 for ( ; idx < count; idx++ ) 1957 { 1958 gindex = TT_NEXT_USHORT( p ); 1959 if ( gindex != 0 ) 1960 break; 1961 char_code++; 1962 } 1963 1964 *pchar_code = char_code; 1965 return gindex; 1966 } 1967 1968 1969 FT_CALLBACK_DEF( FT_Error ) 1970 tt_cmap10_get_info( TT_CMap cmap, 1971 TT_CMapInfo *cmap_info ) 1972 { 1973 FT_Byte* p = cmap->data + 8; 1974 1975 1976 cmap_info->format = 10; 1977 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); 1978 1979 return FT_Err_Ok; 1980 } 1981 1982 1983 FT_DEFINE_TT_CMAP( 1984 tt_cmap10_class_rec, 1985 sizeof ( TT_CMapRec ), 1986 1987 (FT_CMap_InitFunc) tt_cmap_init, 1988 (FT_CMap_DoneFunc) NULL, 1989 (FT_CMap_CharIndexFunc)tt_cmap10_char_index, 1990 (FT_CMap_CharNextFunc) tt_cmap10_char_next, 1991 1992 NULL, 1993 NULL, 1994 NULL, 1995 NULL, 1996 NULL, 1997 1998 10, 1999 (TT_CMap_ValidateFunc)tt_cmap10_validate, 2000 (TT_CMap_Info_GetFunc)tt_cmap10_get_info ) 2001 2002 #endif /* TT_CONFIG_CMAP_FORMAT_10 */ 2003 2004 2005 /*************************************************************************/ 2006 /*************************************************************************/ 2007 /***** *****/ 2008 /***** FORMAT 12 *****/ 2009 /***** *****/ 2010 /*************************************************************************/ 2011 /*************************************************************************/ 2012 2013 /*************************************************************************/ 2014 /* */ 2015 /* TABLE OVERVIEW */ 2016 /* -------------- */ 2017 /* */ 2018 /* NAME OFFSET TYPE DESCRIPTION */ 2019 /* */ 2020 /* format 0 USHORT must be 12 */ 2021 /* reserved 2 USHORT reserved */ 2022 /* length 4 ULONG length in bytes */ 2023 /* language 8 ULONG Mac language code */ 2024 /* count 12 ULONG number of groups */ 2025 /* 16 */ 2026 /* */ 2027 /* This header is followed by `count' groups of the following format: */ 2028 /* */ 2029 /* start 0 ULONG first charcode */ 2030 /* end 4 ULONG last charcode */ 2031 /* startId 8 ULONG start glyph ID for the group */ 2032 /* */ 2033 2034 #ifdef TT_CONFIG_CMAP_FORMAT_12 2035 2036 typedef struct TT_CMap12Rec_ 2037 { 2038 TT_CMapRec cmap; 2039 FT_Bool valid; 2040 FT_ULong cur_charcode; 2041 FT_UInt cur_gindex; 2042 FT_ULong cur_group; 2043 FT_ULong num_groups; 2044 2045 } TT_CMap12Rec, *TT_CMap12; 2046 2047 2048 FT_CALLBACK_DEF( FT_Error ) 2049 tt_cmap12_init( TT_CMap12 cmap, 2050 FT_Byte* table ) 2051 { 2052 cmap->cmap.data = table; 2053 2054 table += 12; 2055 cmap->num_groups = FT_PEEK_ULONG( table ); 2056 2057 cmap->valid = 0; 2058 2059 return FT_Err_Ok; 2060 } 2061 2062 2063 FT_CALLBACK_DEF( FT_Error ) 2064 tt_cmap12_validate( FT_Byte* table, 2065 FT_Validator valid ) 2066 { 2067 FT_Byte* p; 2068 FT_ULong length; 2069 FT_ULong num_groups; 2070 2071 2072 if ( table + 16 > valid->limit ) 2073 FT_INVALID_TOO_SHORT; 2074 2075 p = table + 4; 2076 length = TT_NEXT_ULONG( p ); 2077 2078 p = table + 12; 2079 num_groups = TT_NEXT_ULONG( p ); 2080 2081 if ( length > (FT_ULong)( valid->limit - table ) || 2082 length < 16 + 12 * num_groups ) 2083 FT_INVALID_TOO_SHORT; 2084 2085 /* check groups, they must be in increasing order */ 2086 { 2087 FT_ULong n, start, end, start_id, last = 0; 2088 2089 2090 for ( n = 0; n < num_groups; n++ ) 2091 { 2092 start = TT_NEXT_ULONG( p ); 2093 end = TT_NEXT_ULONG( p ); 2094 start_id = TT_NEXT_ULONG( p ); 2095 2096 if ( start > end ) 2097 FT_INVALID_DATA; 2098 2099 if ( n > 0 && start <= last ) 2100 FT_INVALID_DATA; 2101 2102 if ( valid->level >= FT_VALIDATE_TIGHT ) 2103 { 2104 if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ) 2105 FT_INVALID_GLYPH_ID; 2106 } 2107 2108 last = end; 2109 } 2110 } 2111 2112 return FT_Err_Ok; 2113 } 2114 2115 2116 /* search the index of the charcode next to cmap->cur_charcode */ 2117 /* cmap->cur_group should be set up properly by caller */ 2118 /* */ 2119 static void 2120 tt_cmap12_next( TT_CMap12 cmap ) 2121 { 2122 FT_Byte* p; 2123 FT_ULong start, end, start_id, char_code; 2124 FT_ULong n; 2125 FT_UInt gindex; 2126 2127 2128 if ( cmap->cur_charcode >= 0xFFFFFFFFUL ) 2129 goto Fail; 2130 2131 char_code = cmap->cur_charcode + 1; 2132 2133 for ( n = cmap->cur_group; n < cmap->num_groups; n++ ) 2134 { 2135 p = cmap->cmap.data + 16 + 12 * n; 2136 start = TT_NEXT_ULONG( p ); 2137 end = TT_NEXT_ULONG( p ); 2138 start_id = TT_PEEK_ULONG( p ); 2139 2140 if ( char_code < start ) 2141 char_code = start; 2142 2143 for ( ; char_code <= end; char_code++ ) 2144 { 2145 gindex = (FT_UInt)( start_id + char_code - start ); 2146 2147 if ( gindex ) 2148 { 2149 cmap->cur_charcode = char_code;; 2150 cmap->cur_gindex = gindex; 2151 cmap->cur_group = n; 2152 2153 return; 2154 } 2155 } 2156 } 2157 2158 Fail: 2159 cmap->valid = 0; 2160 } 2161 2162 2163 static FT_UInt 2164 tt_cmap12_char_map_binary( TT_CMap cmap, 2165 FT_UInt32* pchar_code, 2166 FT_Bool next ) 2167 { 2168 FT_UInt gindex = 0; 2169 FT_Byte* p = cmap->data + 12; 2170 FT_UInt32 num_groups = TT_PEEK_ULONG( p ); 2171 FT_UInt32 char_code = *pchar_code; 2172 FT_UInt32 start, end, start_id; 2173 FT_UInt32 max, min, mid; 2174 2175 2176 if ( !num_groups ) 2177 return 0; 2178 2179 /* make compiler happy */ 2180 mid = num_groups; 2181 end = 0xFFFFFFFFUL; 2182 2183 if ( next ) 2184 char_code++; 2185 2186 min = 0; 2187 max = num_groups; 2188 2189 /* binary search */ 2190 while ( min < max ) 2191 { 2192 mid = ( min + max ) >> 1; 2193 p = cmap->data + 16 + 12 * mid; 2194 2195 start = TT_NEXT_ULONG( p ); 2196 end = TT_NEXT_ULONG( p ); 2197 2198 if ( char_code < start ) 2199 max = mid; 2200 else if ( char_code > end ) 2201 min = mid + 1; 2202 else 2203 { 2204 start_id = TT_PEEK_ULONG( p ); 2205 gindex = (FT_UInt)( start_id + char_code - start ); 2206 2207 break; 2208 } 2209 } 2210 2211 if ( next ) 2212 { 2213 TT_CMap12 cmap12 = (TT_CMap12)cmap; 2214 2215 2216 /* if `char_code' is not in any group, then `mid' is */ 2217 /* the group nearest to `char_code' */ 2218 /* */ 2219 2220 if ( char_code > end ) 2221 { 2222 mid++; 2223 if ( mid == num_groups ) 2224 return 0; 2225 } 2226 2227 cmap12->valid = 1; 2228 cmap12->cur_charcode = char_code; 2229 cmap12->cur_group = mid; 2230 2231 if ( !gindex ) 2232 { 2233 tt_cmap12_next( cmap12 ); 2234 2235 if ( cmap12->valid ) 2236 gindex = cmap12->cur_gindex; 2237 } 2238 else 2239 cmap12->cur_gindex = gindex; 2240 2241 if ( gindex ) 2242 *pchar_code = cmap12->cur_charcode; 2243 } 2244 2245 return gindex; 2246 } 2247 2248 2249 FT_CALLBACK_DEF( FT_UInt ) 2250 tt_cmap12_char_index( TT_CMap cmap, 2251 FT_UInt32 char_code ) 2252 { 2253 return tt_cmap12_char_map_binary( cmap, &char_code, 0 ); 2254 } 2255 2256 2257 FT_CALLBACK_DEF( FT_UInt32 ) 2258 tt_cmap12_char_next( TT_CMap cmap, 2259 FT_UInt32 *pchar_code ) 2260 { 2261 TT_CMap12 cmap12 = (TT_CMap12)cmap; 2262 FT_ULong gindex; 2263 2264 2265 if ( cmap12->cur_charcode >= 0xFFFFFFFFUL ) 2266 return 0; 2267 2268 /* no need to search */ 2269 if ( cmap12->valid && cmap12->cur_charcode == *pchar_code ) 2270 { 2271 tt_cmap12_next( cmap12 ); 2272 if ( cmap12->valid ) 2273 { 2274 gindex = cmap12->cur_gindex; 2275 2276 /* XXX: check cur_charcode overflow is expected */ 2277 if ( gindex ) 2278 *pchar_code = (FT_UInt32)cmap12->cur_charcode; 2279 } 2280 else 2281 gindex = 0; 2282 } 2283 else 2284 gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 ); 2285 2286 /* XXX: check gindex overflow is expected */ 2287 return (FT_UInt32)gindex; 2288 } 2289 2290 2291 FT_CALLBACK_DEF( FT_Error ) 2292 tt_cmap12_get_info( TT_CMap cmap, 2293 TT_CMapInfo *cmap_info ) 2294 { 2295 FT_Byte* p = cmap->data + 8; 2296 2297 2298 cmap_info->format = 12; 2299 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); 2300 2301 return FT_Err_Ok; 2302 } 2303 2304 2305 FT_DEFINE_TT_CMAP( 2306 tt_cmap12_class_rec, 2307 sizeof ( TT_CMap12Rec ), 2308 2309 (FT_CMap_InitFunc) tt_cmap12_init, 2310 (FT_CMap_DoneFunc) NULL, 2311 (FT_CMap_CharIndexFunc)tt_cmap12_char_index, 2312 (FT_CMap_CharNextFunc) tt_cmap12_char_next, 2313 2314 NULL, 2315 NULL, 2316 NULL, 2317 NULL, 2318 NULL, 2319 2320 12, 2321 (TT_CMap_ValidateFunc)tt_cmap12_validate, 2322 (TT_CMap_Info_GetFunc)tt_cmap12_get_info ) 2323 2324 #endif /* TT_CONFIG_CMAP_FORMAT_12 */ 2325 2326 2327 /*************************************************************************/ 2328 /*************************************************************************/ 2329 /***** *****/ 2330 /***** FORMAT 13 *****/ 2331 /***** *****/ 2332 /*************************************************************************/ 2333 /*************************************************************************/ 2334 2335 /*************************************************************************/ 2336 /* */ 2337 /* TABLE OVERVIEW */ 2338 /* -------------- */ 2339 /* */ 2340 /* NAME OFFSET TYPE DESCRIPTION */ 2341 /* */ 2342 /* format 0 USHORT must be 13 */ 2343 /* reserved 2 USHORT reserved */ 2344 /* length 4 ULONG length in bytes */ 2345 /* language 8 ULONG Mac language code */ 2346 /* count 12 ULONG number of groups */ 2347 /* 16 */ 2348 /* */ 2349 /* This header is followed by `count' groups of the following format: */ 2350 /* */ 2351 /* start 0 ULONG first charcode */ 2352 /* end 4 ULONG last charcode */ 2353 /* glyphId 8 ULONG glyph ID for the whole group */ 2354 /* */ 2355 2356 #ifdef TT_CONFIG_CMAP_FORMAT_13 2357 2358 typedef struct TT_CMap13Rec_ 2359 { 2360 TT_CMapRec cmap; 2361 FT_Bool valid; 2362 FT_ULong cur_charcode; 2363 FT_UInt cur_gindex; 2364 FT_ULong cur_group; 2365 FT_ULong num_groups; 2366 2367 } TT_CMap13Rec, *TT_CMap13; 2368 2369 2370 FT_CALLBACK_DEF( FT_Error ) 2371 tt_cmap13_init( TT_CMap13 cmap, 2372 FT_Byte* table ) 2373 { 2374 cmap->cmap.data = table; 2375 2376 table += 12; 2377 cmap->num_groups = FT_PEEK_ULONG( table ); 2378 2379 cmap->valid = 0; 2380 2381 return FT_Err_Ok; 2382 } 2383 2384 2385 FT_CALLBACK_DEF( FT_Error ) 2386 tt_cmap13_validate( FT_Byte* table, 2387 FT_Validator valid ) 2388 { 2389 FT_Byte* p; 2390 FT_ULong length; 2391 FT_ULong num_groups; 2392 2393 2394 if ( table + 16 > valid->limit ) 2395 FT_INVALID_TOO_SHORT; 2396 2397 p = table + 4; 2398 length = TT_NEXT_ULONG( p ); 2399 2400 p = table + 12; 2401 num_groups = TT_NEXT_ULONG( p ); 2402 2403 if ( length > (FT_ULong)( valid->limit - table ) || 2404 length < 16 + 12 * num_groups ) 2405 FT_INVALID_TOO_SHORT; 2406 2407 /* check groups, they must be in increasing order */ 2408 { 2409 FT_ULong n, start, end, glyph_id, last = 0; 2410 2411 2412 for ( n = 0; n < num_groups; n++ ) 2413 { 2414 start = TT_NEXT_ULONG( p ); 2415 end = TT_NEXT_ULONG( p ); 2416 glyph_id = TT_NEXT_ULONG( p ); 2417 2418 if ( start > end ) 2419 FT_INVALID_DATA; 2420 2421 if ( n > 0 && start <= last ) 2422 FT_INVALID_DATA; 2423 2424 if ( valid->level >= FT_VALIDATE_TIGHT ) 2425 { 2426 if ( glyph_id >= TT_VALID_GLYPH_COUNT( valid ) ) 2427 FT_INVALID_GLYPH_ID; 2428 } 2429 2430 last = end; 2431 } 2432 } 2433 2434 return FT_Err_Ok; 2435 } 2436 2437 2438 /* search the index of the charcode next to cmap->cur_charcode */ 2439 /* cmap->cur_group should be set up properly by caller */ 2440 /* */ 2441 static void 2442 tt_cmap13_next( TT_CMap13 cmap ) 2443 { 2444 FT_Byte* p; 2445 FT_ULong start, end, glyph_id, char_code; 2446 FT_ULong n; 2447 FT_UInt gindex; 2448 2449 2450 if ( cmap->cur_charcode >= 0xFFFFFFFFUL ) 2451 goto Fail; 2452 2453 char_code = cmap->cur_charcode + 1; 2454 2455 for ( n = cmap->cur_group; n < cmap->num_groups; n++ ) 2456 { 2457 p = cmap->cmap.data + 16 + 12 * n; 2458 start = TT_NEXT_ULONG( p ); 2459 end = TT_NEXT_ULONG( p ); 2460 glyph_id = TT_PEEK_ULONG( p ); 2461 2462 if ( char_code < start ) 2463 char_code = start; 2464 2465 if ( char_code <= end ) 2466 { 2467 gindex = (FT_UInt)glyph_id; 2468 2469 if ( gindex ) 2470 { 2471 cmap->cur_charcode = char_code;; 2472 cmap->cur_gindex = gindex; 2473 cmap->cur_group = n; 2474 2475 return; 2476 } 2477 } 2478 } 2479 2480 Fail: 2481 cmap->valid = 0; 2482 } 2483 2484 2485 static FT_UInt 2486 tt_cmap13_char_map_binary( TT_CMap cmap, 2487 FT_UInt32* pchar_code, 2488 FT_Bool next ) 2489 { 2490 FT_UInt gindex = 0; 2491 FT_Byte* p = cmap->data + 12; 2492 FT_UInt32 num_groups = TT_PEEK_ULONG( p ); 2493 FT_UInt32 char_code = *pchar_code; 2494 FT_UInt32 start, end; 2495 FT_UInt32 max, min, mid; 2496 2497 2498 if ( !num_groups ) 2499 return 0; 2500 2501 /* make compiler happy */ 2502 mid = num_groups; 2503 end = 0xFFFFFFFFUL; 2504 2505 if ( next ) 2506 char_code++; 2507 2508 min = 0; 2509 max = num_groups; 2510 2511 /* binary search */ 2512 while ( min < max ) 2513 { 2514 mid = ( min + max ) >> 1; 2515 p = cmap->data + 16 + 12 * mid; 2516 2517 start = TT_NEXT_ULONG( p ); 2518 end = TT_NEXT_ULONG( p ); 2519 2520 if ( char_code < start ) 2521 max = mid; 2522 else if ( char_code > end ) 2523 min = mid + 1; 2524 else 2525 { 2526 gindex = (FT_UInt)TT_PEEK_ULONG( p ); 2527 2528 break; 2529 } 2530 } 2531 2532 if ( next ) 2533 { 2534 TT_CMap13 cmap13 = (TT_CMap13)cmap; 2535 2536 2537 /* if `char_code' is not in any group, then `mid' is */ 2538 /* the group nearest to `char_code' */ 2539 2540 if ( char_code > end ) 2541 { 2542 mid++; 2543 if ( mid == num_groups ) 2544 return 0; 2545 } 2546 2547 cmap13->valid = 1; 2548 cmap13->cur_charcode = char_code; 2549 cmap13->cur_group = mid; 2550 2551 if ( !gindex ) 2552 { 2553 tt_cmap13_next( cmap13 ); 2554 2555 if ( cmap13->valid ) 2556 gindex = cmap13->cur_gindex; 2557 } 2558 else 2559 cmap13->cur_gindex = gindex; 2560 2561 if ( gindex ) 2562 *pchar_code = cmap13->cur_charcode; 2563 } 2564 2565 return gindex; 2566 } 2567 2568 2569 FT_CALLBACK_DEF( FT_UInt ) 2570 tt_cmap13_char_index( TT_CMap cmap, 2571 FT_UInt32 char_code ) 2572 { 2573 return tt_cmap13_char_map_binary( cmap, &char_code, 0 ); 2574 } 2575 2576 2577 FT_CALLBACK_DEF( FT_UInt32 ) 2578 tt_cmap13_char_next( TT_CMap cmap, 2579 FT_UInt32 *pchar_code ) 2580 { 2581 TT_CMap13 cmap13 = (TT_CMap13)cmap; 2582 FT_UInt gindex; 2583 2584 2585 if ( cmap13->cur_charcode >= 0xFFFFFFFFUL ) 2586 return 0; 2587 2588 /* no need to search */ 2589 if ( cmap13->valid && cmap13->cur_charcode == *pchar_code ) 2590 { 2591 tt_cmap13_next( cmap13 ); 2592 if ( cmap13->valid ) 2593 { 2594 gindex = cmap13->cur_gindex; 2595 if ( gindex ) 2596 *pchar_code = cmap13->cur_charcode; 2597 } 2598 else 2599 gindex = 0; 2600 } 2601 else 2602 gindex = tt_cmap13_char_map_binary( cmap, pchar_code, 1 ); 2603 2604 return gindex; 2605 } 2606 2607 2608 FT_CALLBACK_DEF( FT_Error ) 2609 tt_cmap13_get_info( TT_CMap cmap, 2610 TT_CMapInfo *cmap_info ) 2611 { 2612 FT_Byte* p = cmap->data + 8; 2613 2614 2615 cmap_info->format = 13; 2616 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); 2617 2618 return FT_Err_Ok; 2619 } 2620 2621 2622 FT_DEFINE_TT_CMAP( 2623 tt_cmap13_class_rec, 2624 sizeof ( TT_CMap13Rec ), 2625 2626 (FT_CMap_InitFunc) tt_cmap13_init, 2627 (FT_CMap_DoneFunc) NULL, 2628 (FT_CMap_CharIndexFunc)tt_cmap13_char_index, 2629 (FT_CMap_CharNextFunc) tt_cmap13_char_next, 2630 2631 NULL, 2632 NULL, 2633 NULL, 2634 NULL, 2635 NULL, 2636 2637 13, 2638 (TT_CMap_ValidateFunc)tt_cmap13_validate, 2639 (TT_CMap_Info_GetFunc)tt_cmap13_get_info ) 2640 2641 #endif /* TT_CONFIG_CMAP_FORMAT_13 */ 2642 2643 2644 /*************************************************************************/ 2645 /*************************************************************************/ 2646 /***** *****/ 2647 /***** FORMAT 14 *****/ 2648 /***** *****/ 2649 /*************************************************************************/ 2650 /*************************************************************************/ 2651 2652 /*************************************************************************/ 2653 /* */ 2654 /* TABLE OVERVIEW */ 2655 /* -------------- */ 2656 /* */ 2657 /* NAME OFFSET TYPE DESCRIPTION */ 2658 /* */ 2659 /* format 0 USHORT must be 14 */ 2660 /* length 2 ULONG table length in bytes */ 2661 /* numSelector 6 ULONG number of variation sel. records */ 2662 /* */ 2663 /* Followed by numSelector records, each of which looks like */ 2664 /* */ 2665 /* varSelector 0 UINT24 Unicode codepoint of sel. */ 2666 /* defaultOff 3 ULONG offset to a default UVS table */ 2667 /* describing any variants to be found in */ 2668 /* the normal Unicode subtable. */ 2669 /* nonDefOff 7 ULONG offset to a non-default UVS table */ 2670 /* describing any variants not in the */ 2671 /* standard cmap, with GIDs here */ 2672 /* (either offset may be 0 NULL) */ 2673 /* */ 2674 /* Selectors are sorted by code point. */ 2675 /* */ 2676 /* A default Unicode Variation Selector (UVS) subtable is just a list of */ 2677 /* ranges of code points which are to be found in the standard cmap. No */ 2678 /* glyph IDs (GIDs) here. */ 2679 /* */ 2680 /* numRanges 0 ULONG number of ranges following */ 2681 /* */ 2682 /* A range looks like */ 2683 /* */ 2684 /* uniStart 0 UINT24 code point of the first character in */ 2685 /* this range */ 2686 /* additionalCnt 3 UBYTE count of additional characters in this */ 2687 /* range (zero means a range of a single */ 2688 /* character) */ 2689 /* */ 2690 /* Ranges are sorted by `uniStart'. */ 2691 /* */ 2692 /* A non-default Unicode Variation Selector (UVS) subtable is a list of */ 2693 /* mappings from codepoint to GID. */ 2694 /* */ 2695 /* numMappings 0 ULONG number of mappings */ 2696 /* */ 2697 /* A range looks like */ 2698 /* */ 2699 /* uniStart 0 UINT24 code point of the first character in */ 2700 /* this range */ 2701 /* GID 3 USHORT and its GID */ 2702 /* */ 2703 /* Ranges are sorted by `uniStart'. */ 2704 2705 #ifdef TT_CONFIG_CMAP_FORMAT_14 2706 2707 typedef struct TT_CMap14Rec_ 2708 { 2709 TT_CMapRec cmap; 2710 FT_ULong num_selectors; 2711 2712 /* This array is used to store the results of various 2713 * cmap 14 query functions. The data is overwritten 2714 * on each call to these functions. 2715 */ 2716 FT_UInt32 max_results; 2717 FT_UInt32* results; 2718 FT_Memory memory; 2719 2720 } TT_CMap14Rec, *TT_CMap14; 2721 2722 2723 FT_CALLBACK_DEF( void ) 2724 tt_cmap14_done( TT_CMap14 cmap ) 2725 { 2726 FT_Memory memory = cmap->memory; 2727 2728 2729 cmap->max_results = 0; 2730 if ( memory != NULL && cmap->results != NULL ) 2731 FT_FREE( cmap->results ); 2732 } 2733 2734 2735 static FT_Error 2736 tt_cmap14_ensure( TT_CMap14 cmap, 2737 FT_UInt32 num_results, 2738 FT_Memory memory ) 2739 { 2740 FT_UInt32 old_max = cmap->max_results; 2741 FT_Error error = FT_Err_Ok; 2742 2743 2744 if ( num_results > cmap->max_results ) 2745 { 2746 cmap->memory = memory; 2747 2748 if ( FT_QRENEW_ARRAY( cmap->results, old_max, num_results ) ) 2749 return error; 2750 2751 cmap->max_results = num_results; 2752 } 2753 2754 return error; 2755 } 2756 2757 2758 FT_CALLBACK_DEF( FT_Error ) 2759 tt_cmap14_init( TT_CMap14 cmap, 2760 FT_Byte* table ) 2761 { 2762 cmap->cmap.data = table; 2763 2764 table += 6; 2765 cmap->num_selectors = FT_PEEK_ULONG( table ); 2766 cmap->max_results = 0; 2767 cmap->results = NULL; 2768 2769 return FT_Err_Ok; 2770 } 2771 2772 2773 FT_CALLBACK_DEF( FT_Error ) 2774 tt_cmap14_validate( FT_Byte* table, 2775 FT_Validator valid ) 2776 { 2777 FT_Byte* p; 2778 FT_ULong length; 2779 FT_ULong num_selectors; 2780 2781 2782 if ( table + 2 + 4 + 4 > valid->limit ) 2783 FT_INVALID_TOO_SHORT; 2784 2785 p = table + 2; 2786 length = TT_NEXT_ULONG( p ); 2787 num_selectors = TT_NEXT_ULONG( p ); 2788 2789 if ( length > (FT_ULong)( valid->limit - table ) || 2790 length < 10 + 11 * num_selectors ) 2791 FT_INVALID_TOO_SHORT; 2792 2793 /* check selectors, they must be in increasing order */ 2794 { 2795 /* we start lastVarSel at 1 because a variant selector value of 0 2796 * isn't valid. 2797 */ 2798 FT_ULong n, lastVarSel = 1; 2799 2800 2801 for ( n = 0; n < num_selectors; n++ ) 2802 { 2803 FT_ULong varSel = TT_NEXT_UINT24( p ); 2804 FT_ULong defOff = TT_NEXT_ULONG( p ); 2805 FT_ULong nondefOff = TT_NEXT_ULONG( p ); 2806 2807 2808 if ( defOff >= length || nondefOff >= length ) 2809 FT_INVALID_TOO_SHORT; 2810 2811 if ( varSel < lastVarSel ) 2812 FT_INVALID_DATA; 2813 2814 lastVarSel = varSel + 1; 2815 2816 /* check the default table (these glyphs should be reached */ 2817 /* through the normal Unicode cmap, no GIDs, just check order) */ 2818 if ( defOff != 0 ) 2819 { 2820 FT_Byte* defp = table + defOff; 2821 FT_ULong numRanges = TT_NEXT_ULONG( defp ); 2822 FT_ULong i; 2823 FT_ULong lastBase = 0; 2824 2825 2826 if ( defp + numRanges * 4 > valid->limit ) 2827 FT_INVALID_TOO_SHORT; 2828 2829 for ( i = 0; i < numRanges; ++i ) 2830 { 2831 FT_ULong base = TT_NEXT_UINT24( defp ); 2832 FT_ULong cnt = FT_NEXT_BYTE( defp ); 2833 2834 2835 if ( base + cnt >= 0x110000UL ) /* end of Unicode */ 2836 FT_INVALID_DATA; 2837 2838 if ( base < lastBase ) 2839 FT_INVALID_DATA; 2840 2841 lastBase = base + cnt + 1U; 2842 } 2843 } 2844 2845 /* and the non-default table (these glyphs are specified here) */ 2846 if ( nondefOff != 0 ) 2847 { 2848 FT_Byte* ndp = table + nondefOff; 2849 FT_ULong numMappings = TT_NEXT_ULONG( ndp ); 2850 FT_ULong i, lastUni = 0; 2851 2852 2853 if ( numMappings * 4 > (FT_ULong)( valid->limit - ndp ) ) 2854 FT_INVALID_TOO_SHORT; 2855 2856 for ( i = 0; i < numMappings; ++i ) 2857 { 2858 FT_ULong uni = TT_NEXT_UINT24( ndp ); 2859 FT_ULong gid = TT_NEXT_USHORT( ndp ); 2860 2861 2862 if ( uni >= 0x110000UL ) /* end of Unicode */ 2863 FT_INVALID_DATA; 2864 2865 if ( uni < lastUni ) 2866 FT_INVALID_DATA; 2867 2868 lastUni = uni + 1U; 2869 2870 if ( valid->level >= FT_VALIDATE_TIGHT && 2871 gid >= TT_VALID_GLYPH_COUNT( valid ) ) 2872 FT_INVALID_GLYPH_ID; 2873 } 2874 } 2875 } 2876 } 2877 2878 return FT_Err_Ok; 2879 } 2880 2881 2882 FT_CALLBACK_DEF( FT_UInt ) 2883 tt_cmap14_char_index( TT_CMap cmap, 2884 FT_UInt32 char_code ) 2885 { 2886 FT_UNUSED( cmap ); 2887 FT_UNUSED( char_code ); 2888 2889 /* This can't happen */ 2890 return 0; 2891 } 2892 2893 2894 FT_CALLBACK_DEF( FT_UInt32 ) 2895 tt_cmap14_char_next( TT_CMap cmap, 2896 FT_UInt32 *pchar_code ) 2897 { 2898 FT_UNUSED( cmap ); 2899 2900 /* This can't happen */ 2901 *pchar_code = 0; 2902 return 0; 2903 } 2904 2905 2906 FT_CALLBACK_DEF( FT_Error ) 2907 tt_cmap14_get_info( TT_CMap cmap, 2908 TT_CMapInfo *cmap_info ) 2909 { 2910 FT_UNUSED( cmap ); 2911 2912 cmap_info->format = 14; 2913 /* subtable 14 does not define a language field */ 2914 cmap_info->language = 0xFFFFFFFFUL; 2915 2916 return FT_Err_Ok; 2917 } 2918 2919 2920 static FT_UInt 2921 tt_cmap14_char_map_def_binary( FT_Byte *base, 2922 FT_UInt32 char_code ) 2923 { 2924 FT_UInt32 numRanges = TT_PEEK_ULONG( base ); 2925 FT_UInt32 max, min; 2926 2927 2928 min = 0; 2929 max = numRanges; 2930 2931 base += 4; 2932 2933 /* binary search */ 2934 while ( min < max ) 2935 { 2936 FT_UInt32 mid = ( min + max ) >> 1; 2937 FT_Byte* p = base + 4 * mid; 2938 FT_ULong start = TT_NEXT_UINT24( p ); 2939 FT_UInt cnt = FT_NEXT_BYTE( p ); 2940 2941 2942 if ( char_code < start ) 2943 max = mid; 2944 else if ( char_code > start+cnt ) 2945 min = mid + 1; 2946 else 2947 return TRUE; 2948 } 2949 2950 return FALSE; 2951 } 2952 2953 2954 static FT_UInt 2955 tt_cmap14_char_map_nondef_binary( FT_Byte *base, 2956 FT_UInt32 char_code ) 2957 { 2958 FT_UInt32 numMappings = TT_PEEK_ULONG( base ); 2959 FT_UInt32 max, min; 2960 2961 2962 min = 0; 2963 max = numMappings; 2964 2965 base += 4; 2966 2967 /* binary search */ 2968 while ( min < max ) 2969 { 2970 FT_UInt32 mid = ( min + max ) >> 1; 2971 FT_Byte* p = base + 5 * mid; 2972 FT_UInt32 uni = (FT_UInt32)TT_NEXT_UINT24( p ); 2973 2974 2975 if ( char_code < uni ) 2976 max = mid; 2977 else if ( char_code > uni ) 2978 min = mid + 1; 2979 else 2980 return TT_PEEK_USHORT( p ); 2981 } 2982 2983 return 0; 2984 } 2985 2986 2987 static FT_Byte* 2988 tt_cmap14_find_variant( FT_Byte *base, 2989 FT_UInt32 variantCode ) 2990 { 2991 FT_UInt32 numVar = TT_PEEK_ULONG( base ); 2992 FT_UInt32 max, min; 2993 2994 2995 min = 0; 2996 max = numVar; 2997 2998 base += 4; 2999 3000 /* binary search */ 3001 while ( min < max ) 3002 { 3003 FT_UInt32 mid = ( min + max ) >> 1; 3004 FT_Byte* p = base + 11 * mid; 3005 FT_ULong varSel = TT_NEXT_UINT24( p ); 3006 3007 3008 if ( variantCode < varSel ) 3009 max = mid; 3010 else if ( variantCode > varSel ) 3011 min = mid + 1; 3012 else 3013 return p; 3014 } 3015 3016 return NULL; 3017 } 3018 3019 3020 FT_CALLBACK_DEF( FT_UInt ) 3021 tt_cmap14_char_var_index( TT_CMap cmap, 3022 TT_CMap ucmap, 3023 FT_UInt32 charcode, 3024 FT_UInt32 variantSelector ) 3025 { 3026 FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector ); 3027 FT_ULong defOff; 3028 FT_ULong nondefOff; 3029 3030 3031 if ( !p ) 3032 return 0; 3033 3034 defOff = TT_NEXT_ULONG( p ); 3035 nondefOff = TT_PEEK_ULONG( p ); 3036 3037 if ( defOff != 0 && 3038 tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) ) 3039 { 3040 /* This is the default variant of this charcode. GID not stored */ 3041 /* here; stored in the normal Unicode charmap instead. */ 3042 return ucmap->cmap.clazz->char_index( &ucmap->cmap, charcode ); 3043 } 3044 3045 if ( nondefOff != 0 ) 3046 return tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, 3047 charcode ); 3048 3049 return 0; 3050 } 3051 3052 3053 FT_CALLBACK_DEF( FT_Int ) 3054 tt_cmap14_char_var_isdefault( TT_CMap cmap, 3055 FT_UInt32 charcode, 3056 FT_UInt32 variantSelector ) 3057 { 3058 FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector ); 3059 FT_ULong defOff; 3060 FT_ULong nondefOff; 3061 3062 3063 if ( !p ) 3064 return -1; 3065 3066 defOff = TT_NEXT_ULONG( p ); 3067 nondefOff = TT_NEXT_ULONG( p ); 3068 3069 if ( defOff != 0 && 3070 tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) ) 3071 return 1; 3072 3073 if ( nondefOff != 0 && 3074 tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, 3075 charcode ) != 0 ) 3076 return 0; 3077 3078 return -1; 3079 } 3080 3081 3082 FT_CALLBACK_DEF( FT_UInt32* ) 3083 tt_cmap14_variants( TT_CMap cmap, 3084 FT_Memory memory ) 3085 { 3086 TT_CMap14 cmap14 = (TT_CMap14)cmap; 3087 FT_UInt32 count = cmap14->num_selectors; 3088 FT_Byte* p = cmap->data + 10; 3089 FT_UInt32* result; 3090 FT_UInt32 i; 3091 3092 3093 if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) ) 3094 return NULL; 3095 3096 result = cmap14->results; 3097 for ( i = 0; i < count; ++i ) 3098 { 3099 result[i] = (FT_UInt32)TT_NEXT_UINT24( p ); 3100 p += 8; 3101 } 3102 result[i] = 0; 3103 3104 return result; 3105 } 3106 3107 3108 FT_CALLBACK_DEF( FT_UInt32 * ) 3109 tt_cmap14_char_variants( TT_CMap cmap, 3110 FT_Memory memory, 3111 FT_UInt32 charCode ) 3112 { 3113 TT_CMap14 cmap14 = (TT_CMap14) cmap; 3114 FT_UInt32 count = cmap14->num_selectors; 3115 FT_Byte* p = cmap->data + 10; 3116 FT_UInt32* q; 3117 3118 3119 if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) ) 3120 return NULL; 3121 3122 for ( q = cmap14->results; count > 0; --count ) 3123 { 3124 FT_UInt32 varSel = TT_NEXT_UINT24( p ); 3125 FT_ULong defOff = TT_NEXT_ULONG( p ); 3126 FT_ULong nondefOff = TT_NEXT_ULONG( p ); 3127 3128 3129 if ( ( defOff != 0 && 3130 tt_cmap14_char_map_def_binary( cmap->data + defOff, 3131 charCode ) ) || 3132 ( nondefOff != 0 && 3133 tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, 3134 charCode ) != 0 ) ) 3135 { 3136 q[0] = varSel; 3137 q++; 3138 } 3139 } 3140 q[0] = 0; 3141 3142 return cmap14->results; 3143 } 3144 3145 3146 static FT_UInt 3147 tt_cmap14_def_char_count( FT_Byte *p ) 3148 { 3149 FT_UInt32 numRanges = (FT_UInt32)TT_NEXT_ULONG( p ); 3150 FT_UInt tot = 0; 3151 3152 3153 p += 3; /* point to the first `cnt' field */ 3154 for ( ; numRanges > 0; numRanges-- ) 3155 { 3156 tot += 1 + p[0]; 3157 p += 4; 3158 } 3159 3160 return tot; 3161 } 3162 3163 3164 static FT_UInt32* 3165 tt_cmap14_get_def_chars( TT_CMap cmap, 3166 FT_Byte* p, 3167 FT_Memory memory ) 3168 { 3169 TT_CMap14 cmap14 = (TT_CMap14) cmap; 3170 FT_UInt32 numRanges; 3171 FT_UInt cnt; 3172 FT_UInt32* q; 3173 3174 3175 cnt = tt_cmap14_def_char_count( p ); 3176 numRanges = (FT_UInt32)TT_NEXT_ULONG( p ); 3177 3178 if ( tt_cmap14_ensure( cmap14, ( cnt + 1 ), memory ) ) 3179 return NULL; 3180 3181 for ( q = cmap14->results; numRanges > 0; --numRanges ) 3182 { 3183 FT_UInt32 uni = (FT_UInt32)TT_NEXT_UINT24( p ); 3184 3185 3186 cnt = FT_NEXT_BYTE( p ) + 1; 3187 do 3188 { 3189 q[0] = uni; 3190 uni += 1; 3191 q += 1; 3192 3193 } while ( --cnt != 0 ); 3194 } 3195 q[0] = 0; 3196 3197 return cmap14->results; 3198 } 3199 3200 3201 static FT_UInt32* 3202 tt_cmap14_get_nondef_chars( TT_CMap cmap, 3203 FT_Byte *p, 3204 FT_Memory memory ) 3205 { 3206 TT_CMap14 cmap14 = (TT_CMap14) cmap; 3207 FT_UInt32 numMappings; 3208 FT_UInt i; 3209 FT_UInt32 *ret; 3210 3211 3212 numMappings = (FT_UInt32)TT_NEXT_ULONG( p ); 3213 3214 if ( tt_cmap14_ensure( cmap14, ( numMappings + 1 ), memory ) ) 3215 return NULL; 3216 3217 ret = cmap14->results; 3218 for ( i = 0; i < numMappings; ++i ) 3219 { 3220 ret[i] = (FT_UInt32)TT_NEXT_UINT24( p ); 3221 p += 2; 3222 } 3223 ret[i] = 0; 3224 3225 return ret; 3226 } 3227 3228 3229 FT_CALLBACK_DEF( FT_UInt32 * ) 3230 tt_cmap14_variant_chars( TT_CMap cmap, 3231 FT_Memory memory, 3232 FT_UInt32 variantSelector ) 3233 { 3234 FT_Byte *p = tt_cmap14_find_variant( cmap->data + 6, 3235 variantSelector ); 3236 FT_Int i; 3237 FT_ULong defOff; 3238 FT_ULong nondefOff; 3239 3240 3241 if ( !p ) 3242 return NULL; 3243 3244 defOff = TT_NEXT_ULONG( p ); 3245 nondefOff = TT_NEXT_ULONG( p ); 3246 3247 if ( defOff == 0 && nondefOff == 0 ) 3248 return NULL; 3249 3250 if ( defOff == 0 ) 3251 return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff, 3252 memory ); 3253 else if ( nondefOff == 0 ) 3254 return tt_cmap14_get_def_chars( cmap, cmap->data + defOff, 3255 memory ); 3256 else 3257 { 3258 /* Both a default and a non-default glyph set? That's probably not */ 3259 /* good font design, but the spec allows for it... */ 3260 TT_CMap14 cmap14 = (TT_CMap14) cmap; 3261 FT_UInt32 numRanges; 3262 FT_UInt32 numMappings; 3263 FT_UInt32 duni; 3264 FT_UInt32 dcnt; 3265 FT_UInt32 nuni; 3266 FT_Byte* dp; 3267 FT_UInt di, ni, k; 3268 3269 FT_UInt32 *ret; 3270 3271 3272 p = cmap->data + nondefOff; 3273 dp = cmap->data + defOff; 3274 3275 numMappings = (FT_UInt32)TT_NEXT_ULONG( p ); 3276 dcnt = tt_cmap14_def_char_count( dp ); 3277 numRanges = (FT_UInt32)TT_NEXT_ULONG( dp ); 3278 3279 if ( numMappings == 0 ) 3280 return tt_cmap14_get_def_chars( cmap, cmap->data + defOff, 3281 memory ); 3282 if ( dcnt == 0 ) 3283 return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff, 3284 memory ); 3285 3286 if ( tt_cmap14_ensure( cmap14, ( dcnt + numMappings + 1 ), memory ) ) 3287 return NULL; 3288 3289 ret = cmap14->results; 3290 duni = (FT_UInt32)TT_NEXT_UINT24( dp ); 3291 dcnt = FT_NEXT_BYTE( dp ); 3292 di = 1; 3293 nuni = (FT_UInt32)TT_NEXT_UINT24( p ); 3294 p += 2; 3295 ni = 1; 3296 i = 0; 3297 3298 for ( ;; ) 3299 { 3300 if ( nuni > duni + dcnt ) 3301 { 3302 for ( k = 0; k <= dcnt; ++k ) 3303 ret[i++] = duni + k; 3304 3305 ++di; 3306 3307 if ( di > numRanges ) 3308 break; 3309 3310 duni = (FT_UInt32)TT_NEXT_UINT24( dp ); 3311 dcnt = FT_NEXT_BYTE( dp ); 3312 } 3313 else 3314 { 3315 if ( nuni < duni ) 3316 ret[i++] = nuni; 3317 /* If it is within the default range then ignore it -- */ 3318 /* that should not have happened */ 3319 ++ni; 3320 if ( ni > numMappings ) 3321 break; 3322 3323 nuni = (FT_UInt32)TT_NEXT_UINT24( p ); 3324 p += 2; 3325 } 3326 } 3327 3328 if ( ni <= numMappings ) 3329 { 3330 /* If we get here then we have run out of all default ranges. */ 3331 /* We have read one non-default mapping which we haven't stored */ 3332 /* and there may be others that need to be read. */ 3333 ret[i++] = nuni; 3334 while ( ni < numMappings ) 3335 { 3336 ret[i++] = (FT_UInt32)TT_NEXT_UINT24( p ); 3337 p += 2; 3338 ++ni; 3339 } 3340 } 3341 else if ( di <= numRanges ) 3342 { 3343 /* If we get here then we have run out of all non-default */ 3344 /* mappings. We have read one default range which we haven't */ 3345 /* stored and there may be others that need to be read. */ 3346 for ( k = 0; k <= dcnt; ++k ) 3347 ret[i++] = duni + k; 3348 3349 while ( di < numRanges ) 3350 { 3351 duni = (FT_UInt32)TT_NEXT_UINT24( dp ); 3352 dcnt = FT_NEXT_BYTE( dp ); 3353 3354 for ( k = 0; k <= dcnt; ++k ) 3355 ret[i++] = duni + k; 3356 ++di; 3357 } 3358 } 3359 3360 ret[i] = 0; 3361 3362 return ret; 3363 } 3364 } 3365 3366 3367 FT_DEFINE_TT_CMAP( 3368 tt_cmap14_class_rec, 3369 sizeof ( TT_CMap14Rec ), 3370 3371 (FT_CMap_InitFunc) tt_cmap14_init, 3372 (FT_CMap_DoneFunc) tt_cmap14_done, 3373 (FT_CMap_CharIndexFunc)tt_cmap14_char_index, 3374 (FT_CMap_CharNextFunc) tt_cmap14_char_next, 3375 3376 /* Format 14 extension functions */ 3377 (FT_CMap_CharVarIndexFunc) tt_cmap14_char_var_index, 3378 (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault, 3379 (FT_CMap_VariantListFunc) tt_cmap14_variants, 3380 (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants, 3381 (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars, 3382 3383 14, 3384 (TT_CMap_ValidateFunc)tt_cmap14_validate, 3385 (TT_CMap_Info_GetFunc)tt_cmap14_get_info ) 3386 3387 #endif /* TT_CONFIG_CMAP_FORMAT_14 */ 3388 3389 3390 #ifndef FT_CONFIG_OPTION_PIC 3391 3392 static const TT_CMap_Class tt_cmap_classes[] = 3393 { 3394 #define TTCMAPCITEM( a ) &a, 3395 #include "ttcmapc.h" 3396 NULL, 3397 }; 3398 3399 #else /*FT_CONFIG_OPTION_PIC*/ 3400 3401 void 3402 FT_Destroy_Class_tt_cmap_classes( FT_Library library, 3403 TT_CMap_Class* clazz ) 3404 { 3405 FT_Memory memory = library->memory; 3406 3407 3408 if ( clazz ) 3409 FT_FREE( clazz ); 3410 } 3411 3412 3413 FT_Error 3414 FT_Create_Class_tt_cmap_classes( FT_Library library, 3415 TT_CMap_Class** output_class ) 3416 { 3417 TT_CMap_Class* clazz = NULL; 3418 TT_CMap_ClassRec* recs; 3419 FT_Error error; 3420 FT_Memory memory = library->memory; 3421 3422 int i = 0; 3423 3424 3425 #define TTCMAPCITEM( a ) i++; 3426 #include "ttcmapc.h" 3427 3428 /* allocate enough space for both the pointers */ 3429 /* plus terminator and the class instances */ 3430 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * ( i + 1 ) + 3431 sizeof ( TT_CMap_ClassRec ) * i ) ) 3432 return error; 3433 3434 /* the location of the class instances follows the array of pointers */ 3435 recs = (TT_CMap_ClassRec*)( (char*)clazz + 3436 sizeof ( *clazz ) * ( i + 1 ) ); 3437 i = 0; 3438 3439 #undef TTCMAPCITEM 3440 #define TTCMAPCITEM( a ) \ 3441 FT_Init_Class_ ## a( &recs[i] ); \ 3442 clazz[i] = &recs[i]; \ 3443 i++; 3444 #include "ttcmapc.h" 3445 3446 clazz[i] = NULL; 3447 3448 *output_class = clazz; 3449 return FT_Err_Ok; 3450 } 3451 3452 #endif /*FT_CONFIG_OPTION_PIC*/ 3453 3454 3455 /* parse the `cmap' table and build the corresponding TT_CMap objects */ 3456 /* in the current face */ 3457 /* */ 3458 FT_LOCAL_DEF( FT_Error ) 3459 tt_face_build_cmaps( TT_Face face ) 3460 { 3461 FT_Byte* table = face->cmap_table; 3462 FT_Byte* limit = table + face->cmap_size; 3463 FT_UInt volatile num_cmaps; 3464 FT_Byte* volatile p = table; 3465 FT_Library library = FT_FACE_LIBRARY( face ); 3466 3467 FT_UNUSED( library ); 3468 3469 3470 if ( !p || p + 4 > limit ) 3471 return FT_THROW( Invalid_Table ); 3472 3473 /* only recognize format 0 */ 3474 if ( TT_NEXT_USHORT( p ) != 0 ) 3475 { 3476 FT_ERROR(( "tt_face_build_cmaps:" 3477 " unsupported `cmap' table format = %d\n", 3478 TT_PEEK_USHORT( p - 2) )); 3479 return FT_THROW( Invalid_Table ); 3480 } 3481 3482 num_cmaps = TT_NEXT_USHORT( p ); 3483 3484 #ifdef FT_MAX_CHARMAP_CACHEABLE 3485 if ( num_cmaps > FT_MAX_CHARMAP_CACHEABLE ) 3486 FT_ERROR(( "tt_face_build_cmaps: too many cmap subtables (%d)\n" 3487 " subtable #%d and higher are loaded" 3488 " but cannot be searched\n", 3489 num_cmaps, FT_MAX_CHARMAP_CACHEABLE + 1 )); 3490 #endif 3491 3492 for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- ) 3493 { 3494 FT_CharMapRec charmap; 3495 FT_UInt32 offset; 3496 3497 3498 charmap.platform_id = TT_NEXT_USHORT( p ); 3499 charmap.encoding_id = TT_NEXT_USHORT( p ); 3500 charmap.face = FT_FACE( face ); 3501 charmap.encoding = FT_ENCODING_NONE; /* will be filled later */ 3502 offset = TT_NEXT_ULONG( p ); 3503 3504 if ( offset && offset <= face->cmap_size - 2 ) 3505 { 3506 FT_Byte* volatile cmap = table + offset; 3507 volatile FT_UInt format = TT_PEEK_USHORT( cmap ); 3508 const TT_CMap_Class* volatile pclazz = TT_CMAP_CLASSES_GET; 3509 TT_CMap_Class volatile clazz; 3510 3511 3512 for ( ; *pclazz; pclazz++ ) 3513 { 3514 clazz = *pclazz; 3515 if ( clazz->format == format ) 3516 { 3517 volatile TT_ValidatorRec valid; 3518 volatile FT_Error error = FT_Err_Ok; 3519 3520 3521 ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit, 3522 FT_VALIDATE_DEFAULT ); 3523 3524 valid.num_glyphs = (FT_UInt)face->max_profile.numGlyphs; 3525 3526 if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer) == 0 ) 3527 { 3528 /* validate this cmap sub-table */ 3529 error = clazz->validate( cmap, FT_VALIDATOR( &valid ) ); 3530 } 3531 3532 if ( valid.validator.error == 0 ) 3533 { 3534 FT_CMap ttcmap; 3535 3536 3537 /* It might make sense to store the single variation */ 3538 /* selector cmap somewhere special. But it would have to be */ 3539 /* in the public FT_FaceRec, and we can't change that. */ 3540 3541 if ( !FT_CMap_New( (FT_CMap_Class)clazz, 3542 cmap, &charmap, &ttcmap ) ) 3543 { 3544 /* it is simpler to directly set `flags' than adding */ 3545 /* a parameter to FT_CMap_New */ 3546 ((TT_CMap)ttcmap)->flags = (FT_Int)error; 3547 } 3548 } 3549 else 3550 { 3551 FT_TRACE0(( "tt_face_build_cmaps:" 3552 " broken cmap sub-table ignored\n" )); 3553 } 3554 break; 3555 } 3556 } 3557 3558 if ( *pclazz == NULL ) 3559 { 3560 FT_TRACE0(( "tt_face_build_cmaps:" 3561 " unsupported cmap sub-table ignored\n" )); 3562 } 3563 } 3564 } 3565 3566 return FT_Err_Ok; 3567 } 3568 3569 3570 FT_LOCAL( FT_Error ) 3571 tt_get_cmap_info( FT_CharMap charmap, 3572 TT_CMapInfo *cmap_info ) 3573 { 3574 FT_CMap cmap = (FT_CMap)charmap; 3575 TT_CMap_Class clazz = (TT_CMap_Class)cmap->clazz; 3576 3577 3578 return clazz->get_cmap_info( charmap, cmap_info ); 3579 } 3580 3581 3582 /* END */ 3583