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