1 /***************************************************************************/ 2 /* */ 3 /* ttcmap0.c */ 4 /* */ 5 /* TrueType new character mapping table (cmap) support (body). */ 6 /* */ 7 /* Copyright 2002 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 #include FT_INTERNAL_OBJECTS_H 22 #include FT_INTERNAL_STREAM_H 23 #include "ttload.h" 24 #include "ttcmap0.h" 25 26 #include "sferrors.h" 27 28 /*************************************************************************/ 29 /* */ 30 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 31 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 32 /* messages during execution. */ 33 /* */ 34 #undef FT_COMPONENT 35 #define FT_COMPONENT trace_ttcmap 36 37 38 #define TT_PEEK_SHORT FT_PEEK_SHORT 39 #define TT_PEEK_USHORT FT_PEEK_USHORT 40 #define TT_PEEK_LONG FT_PEEK_LONG 41 #define TT_PEEK_ULONG FT_PEEK_ULONG 42 43 #define TT_NEXT_SHORT FT_NEXT_SHORT 44 #define TT_NEXT_USHORT FT_NEXT_USHORT 45 #define TT_NEXT_LONG FT_NEXT_LONG 46 #define TT_NEXT_ULONG FT_NEXT_ULONG 47 48 49 FT_CALLBACK_DEF( FT_Error ) 50 tt_cmap_init( TT_CMap cmap, 51 FT_Byte* table ) 52 { 53 cmap->data = table; 54 return 0; 55 } 56 57 58 /*************************************************************************/ 59 /*************************************************************************/ 60 /***** *****/ 61 /***** FORMAT 0 *****/ 62 /***** *****/ 63 /*************************************************************************/ 64 /*************************************************************************/ 65 66 /*************************************************************************/ 67 /* */ 68 /* TABLE OVERVIEW */ 69 /* -------------- */ 70 /* */ 71 /* NAME OFFSET TYPE DESCRIPTION */ 72 /* */ 73 /* format 0 USHORT must be 0 */ 74 /* length 2 USHORT table length in bytes */ 75 /* language 4 USHORT Mac language code */ 76 /* glyph_ids 6 BYTE[256] array of glyph indices */ 77 /* 262 */ 78 /* */ 79 80 #ifdef TT_CONFIG_CMAP_FORMAT_0 81 82 FT_CALLBACK_DEF( void ) 83 tt_cmap0_validate( FT_Byte* table, 84 FT_Validator valid ) 85 { 86 FT_Byte* p = table + 2; 87 FT_UInt length = TT_NEXT_USHORT( p ); 88 89 90 if ( table + length > valid->limit || length < 262 ) 91 FT_INVALID_TOO_SHORT; 92 93 /* check glyph indices whenever necessary */ 94 if ( valid->level >= FT_VALIDATE_TIGHT ) 95 { 96 FT_UInt n, idx; 97 98 99 p = table + 6; 100 for ( n = 0; n < 256; n++ ) 101 { 102 idx = *p++; 103 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) 104 FT_INVALID_GLYPH_ID; 105 } 106 } 107 } 108 109 110 FT_CALLBACK_DEF( FT_UInt ) 111 tt_cmap0_char_index( TT_CMap cmap, 112 FT_UInt32 char_code ) 113 { 114 FT_Byte* table = cmap->data; 115 116 117 return char_code < 256 ? table[6 + char_code] : 0; 118 } 119 120 121 FT_CALLBACK_DEF( FT_UInt ) 122 tt_cmap0_char_next( TT_CMap cmap, 123 FT_UInt32 *pchar_code ) 124 { 125 FT_Byte* table = cmap->data; 126 FT_UInt32 charcode = *pchar_code; 127 FT_UInt32 result = 0; 128 FT_UInt gindex = 0; 129 130 131 table += 6; /* go to glyph ids */ 132 while ( ++charcode < 256 ) 133 { 134 gindex = table[charcode]; 135 if ( gindex != 0 ) 136 { 137 result = charcode; 138 break; 139 } 140 } 141 142 *pchar_code = result; 143 return gindex; 144 } 145 146 147 FT_CALLBACK_TABLE_DEF 148 const TT_CMap_ClassRec tt_cmap0_class_rec = 149 { 150 { 151 sizeof( TT_CMapRec ), 152 153 (FT_CMap_InitFunc) tt_cmap_init, 154 (FT_CMap_DoneFunc) NULL, 155 (FT_CMap_CharIndexFunc)tt_cmap0_char_index, 156 (FT_CMap_CharNextFunc) tt_cmap0_char_next 157 }, 158 0, 159 (TT_CMap_ValidateFunc) tt_cmap0_validate 160 }; 161 162 #endif /* TT_CONFIG_CMAP_FORMAT_0 */ 163 164 165 /*************************************************************************/ 166 /*************************************************************************/ 167 /***** *****/ 168 /***** FORMAT 2 *****/ 169 /***** *****/ 170 /***** This is used for certain CJK encodings that encode text in a *****/ 171 /***** mixed 8/16 bits encoding along the following lines: *****/ 172 /***** *****/ 173 /***** * Certain byte values correspond to an 8-bit character code *****/ 174 /***** (typically in the range 0..127 for ASCII compatibility). *****/ 175 /***** *****/ 176 /***** * Certain byte values signal the first byte of a 2-byte *****/ 177 /***** character code (but these values are also valid as the *****/ 178 /***** second byte of a 2-byte character). *****/ 179 /***** *****/ 180 /***** The following charmap lookup and iteration functions all *****/ 181 /***** assume that the value "charcode" correspond to following: *****/ 182 /***** *****/ 183 /***** - For one byte characters, "charcode" is simply the *****/ 184 /***** character code. *****/ 185 /***** *****/ 186 /***** - For two byte characters, "charcode" is the 2-byte *****/ 187 /***** character code in big endian format. More exactly: *****/ 188 /***** *****/ 189 /***** (charcode >> 8) is the first byte value *****/ 190 /***** (charcode & 0xFF) is the second byte value *****/ 191 /***** *****/ 192 /***** Note that not all values of "charcode" are valid according *****/ 193 /***** to these rules, and the function moderately check the *****/ 194 /***** arguments. *****/ 195 /***** *****/ 196 /*************************************************************************/ 197 /*************************************************************************/ 198 199 /*************************************************************************/ 200 /* */ 201 /* TABLE OVERVIEW */ 202 /* -------------- */ 203 /* */ 204 /* NAME OFFSET TYPE DESCRIPTION */ 205 /* */ 206 /* format 0 USHORT must be 2 */ 207 /* length 2 USHORT table length in bytes */ 208 /* language 4 USHORT Mac language code */ 209 /* keys 6 USHORT[256] sub-header keys */ 210 /* subs 518 SUBHEAD[NSUBS] sub-headers array */ 211 /* glyph_ids 518+NSUB*8 USHORT[] glyph id array */ 212 /* */ 213 /* The `keys' table is used to map charcode high-bytes to sub-headers. */ 214 /* The value of `NSUBS' is the number of sub-headers defined in the */ 215 /* table and is computed by finding the maximum of the `keys' table. */ 216 /* */ 217 /* Note that for any n, `keys[n]' is a byte offset within the `subs' */ 218 /* table, i.e., it is the corresponding sub-header index multiplied */ 219 /* by 8. */ 220 /* */ 221 /* Each sub-header has the following format: */ 222 /* */ 223 /* NAME OFFSET TYPE DESCRIPTION */ 224 /* */ 225 /* first 0 USHORT first valid low-byte */ 226 /* count 2 USHORT number of valid low-bytes */ 227 /* delta 4 SHORT see below */ 228 /* offset 6 USHORT see below */ 229 /* */ 230 /* A sub-header defines, for each high-byte, the range of valid */ 231 /* low-bytes within the charmap. Note that the range defined by `first' */ 232 /* and `count' must be completely included in the interval [0..255] */ 233 /* according to the specification. */ 234 /* */ 235 /* If a character code is contained within a given sub-header, then */ 236 /* mapping it to a glyph index is done as follows: */ 237 /* */ 238 /* * The value of `offset' is read. This is a _byte_ distance from the */ 239 /* location of the `offset' field itself into a slice of the */ 240 /* `glyph_ids' table. Let's call it `slice' (it's a USHORT[] too). */ 241 /* */ 242 /* * The value `slice[char.lo - first]' is read. If it is 0, there is */ 243 /* no glyph for the charcode. Otherwise, the value of `delta' is */ 244 /* added to it (modulo 65536) to form a new glyph index. */ 245 /* */ 246 /* It is up to the validation routine to check that all offsets fall */ 247 /* within the glyph ids table (and not within the `subs' table itself or */ 248 /* outside of the CMap). */ 249 /* */ 250 251 #ifdef TT_CONFIG_CMAP_FORMAT_2 252 253 FT_CALLBACK_DEF( void ) 254 tt_cmap2_validate( FT_Byte* table, 255 FT_Validator valid ) 256 { 257 FT_Byte* p = table + 2; /* skip format */ 258 FT_UInt length = TT_PEEK_USHORT( p ); 259 FT_UInt n, max_subs; 260 FT_Byte* keys; /* keys table */ 261 FT_Byte* subs; /* sub-headers */ 262 FT_Byte* glyph_ids; /* glyph id array */ 263 264 265 if ( table + length > valid->limit || length < 6 + 512 ) 266 FT_INVALID_TOO_SHORT; 267 268 keys = table + 6; 269 270 /* parse keys to compute sub-headers count */ 271 p = keys; 272 max_subs = 0; 273 for ( n = 0; n < 256; n++ ) 274 { 275 FT_UInt idx = TT_NEXT_USHORT( p ); 276 277 278 /* value must be multiple of 8 */ 279 if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 ) 280 FT_INVALID_DATA; 281 282 idx >>= 3; 283 284 if ( idx > max_subs ) 285 max_subs = idx; 286 } 287 288 FT_ASSERT( p == table + 518 ); 289 290 subs = p; 291 glyph_ids = subs + (max_subs + 1) * 8; 292 if ( glyph_ids > valid->limit ) 293 FT_INVALID_TOO_SHORT; 294 295 /* parse sub-headers */ 296 for ( n = 0; n <= max_subs; n++ ) 297 { 298 FT_UInt first_code, code_count, offset; 299 FT_Int delta; 300 FT_Byte* ids; 301 302 303 first_code = TT_NEXT_USHORT( p ); 304 code_count = TT_NEXT_USHORT( p ); 305 delta = TT_NEXT_SHORT( p ); 306 offset = TT_NEXT_USHORT( p ); 307 308 /* check range within 0..255 */ 309 if ( valid->level >= FT_VALIDATE_PARANOID ) 310 { 311 if ( first_code >= 256 || first_code + code_count > 256 ) 312 FT_INVALID_DATA; 313 } 314 315 /* check offset */ 316 if ( offset != 0 ) 317 { 318 ids = p - 2 + offset; 319 if ( ids < glyph_ids || ids + code_count*2 > table + length ) 320 FT_INVALID_OFFSET; 321 322 /* check glyph ids */ 323 if ( valid->level >= FT_VALIDATE_TIGHT ) 324 { 325 FT_Byte* limit = p + code_count * 2; 326 FT_UInt idx; 327 328 329 for ( ; p < limit; ) 330 { 331 idx = TT_NEXT_USHORT( p ); 332 if ( idx != 0 ) 333 { 334 idx = ( idx + delta ) & 0xFFFFU; 335 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) 336 FT_INVALID_GLYPH_ID; 337 } 338 } 339 } 340 } 341 } 342 } 343 344 345 /* return sub header corresponding to a given character code */ 346 /* NULL on invalid charcode */ 347 static FT_Byte* 348 tt_cmap2_get_subheader( FT_Byte* table, 349 FT_UInt32 char_code ) 350 { 351 FT_Byte* result = NULL; 352 353 354 if ( char_code < 0x10000UL ) 355 { 356 FT_UInt char_lo = (FT_UInt)( char_code & 0xFF ); 357 FT_UInt char_hi = (FT_UInt)( char_code >> 8 ); 358 FT_Byte* p = table + 6; /* keys table */ 359 FT_Byte* subs = table + 518; /* subheaders table */ 360 FT_Byte* sub; 361 362 363 if ( char_hi == 0 ) 364 { 365 /* an 8-bit character code -- we use subHeader 0 in this case */ 366 /* to test whether the character code is in the charmap */ 367 /* */ 368 sub = subs; /* jump to first sub-header */ 369 370 /* check that the sub-header for this byte is 0, which */ 371 /* indicates that it's really a valid one-byte value */ 372 /* Otherwise, return 0 */ 373 /* */ 374 p += char_lo * 2; 375 if ( TT_PEEK_USHORT( p ) != 0 ) 376 goto Exit; 377 } 378 else 379 { 380 /* a 16-bit character code */ 381 p += char_hi * 2; /* jump to key entry */ 382 sub = subs + ( TT_PEEK_USHORT( p ) & -8 ); /* jump to sub-header */ 383 384 /* check that the hi byte isn't a valid one-byte value */ 385 if ( sub == subs ) 386 goto Exit; 387 } 388 result = sub; 389 } 390 Exit: 391 return result; 392 } 393 394 395 FT_CALLBACK_DEF( FT_UInt ) 396 tt_cmap2_char_index( TT_CMap cmap, 397 FT_UInt32 char_code ) 398 { 399 FT_Byte* table = cmap->data; 400 FT_UInt result = 0; 401 FT_Byte* subheader; 402 403 404 subheader = tt_cmap2_get_subheader( table, char_code ); 405 if ( subheader ) 406 { 407 FT_Byte* p = subheader; 408 FT_UInt idx = (FT_UInt)(char_code & 0xFF); 409 FT_UInt start, count; 410 FT_Int delta; 411 FT_UInt offset; 412 413 414 start = TT_NEXT_USHORT( p ); 415 count = TT_NEXT_USHORT( p ); 416 delta = TT_NEXT_SHORT ( p ); 417 offset = TT_PEEK_USHORT( p ); 418 419 idx -= start; 420 if ( idx < count && offset != 0 ) 421 { 422 p += offset + 2 * idx; 423 idx = TT_PEEK_USHORT( p ); 424 425 if ( idx != 0 ) 426 result = (FT_UInt)( idx + delta ) & 0xFFFFU; 427 } 428 } 429 return result; 430 } 431 432 433 FT_CALLBACK_DEF( FT_UInt ) 434 tt_cmap2_char_next( TT_CMap cmap, 435 FT_UInt32 *pcharcode ) 436 { 437 FT_Byte* table = cmap->data; 438 FT_UInt gindex = 0; 439 FT_UInt32 result = 0; 440 FT_UInt32 charcode = *pcharcode + 1; 441 FT_Byte* subheader; 442 443 444 while ( charcode < 0x10000UL ) 445 { 446 subheader = tt_cmap2_get_subheader( table, charcode ); 447 if ( subheader ) 448 { 449 FT_Byte* p = subheader; 450 FT_UInt start = TT_NEXT_USHORT( p ); 451 FT_UInt count = TT_NEXT_USHORT( p ); 452 FT_Int delta = TT_NEXT_SHORT ( p ); 453 FT_UInt offset = TT_PEEK_USHORT( p ); 454 FT_UInt char_lo = (FT_UInt)( charcode & 0xFF ); 455 FT_UInt pos, idx; 456 457 458 if ( offset == 0 ) 459 goto Next_SubHeader; 460 461 if ( char_lo < start ) 462 { 463 char_lo = start; 464 pos = 0; 465 } 466 else 467 pos = (FT_UInt)( char_lo - start ); 468 469 p += offset + pos * 2; 470 charcode = ( charcode & -256 ) + char_lo; 471 472 for ( ; pos < count; pos++, charcode++ ) 473 { 474 idx = TT_NEXT_USHORT( p ); 475 476 if ( idx != 0 ) 477 { 478 gindex = ( idx + delta ) & 0xFFFFU; 479 if ( gindex != 0 ) 480 { 481 result = charcode; 482 goto Exit; 483 } 484 } 485 } 486 } 487 488 /* jump to next sub-header, i.e. higher byte value */ 489 Next_SubHeader: 490 charcode = ( charcode & -256 ) + 256; 491 } 492 493 Exit: 494 *pcharcode = result; 495 496 return gindex; 497 } 498 499 500 FT_CALLBACK_TABLE_DEF 501 const TT_CMap_ClassRec tt_cmap2_class_rec = 502 { 503 { 504 sizeof( TT_CMapRec ), 505 506 (FT_CMap_InitFunc) tt_cmap_init, 507 (FT_CMap_DoneFunc) NULL, 508 (FT_CMap_CharIndexFunc)tt_cmap2_char_index, 509 (FT_CMap_CharNextFunc) tt_cmap2_char_next 510 }, 511 2, 512 (TT_CMap_ValidateFunc) tt_cmap2_validate 513 }; 514 515 #endif /* TT_CONFIG_CMAP_FORMAT_2 */ 516 517 518 /*************************************************************************/ 519 /*************************************************************************/ 520 /***** *****/ 521 /***** FORMAT 4 *****/ 522 /***** *****/ 523 /*************************************************************************/ 524 /*************************************************************************/ 525 526 /*************************************************************************/ 527 /* */ 528 /* TABLE OVERVIEW */ 529 /* -------------- */ 530 /* */ 531 /* NAME OFFSET TYPE DESCRIPTION */ 532 /* */ 533 /* format 0 USHORT must be 4 */ 534 /* length 2 USHORT table length */ 535 /* in bytes */ 536 /* language 4 USHORT Mac language code */ 537 /* */ 538 /* segCountX2 6 USHORT 2*NUM_SEGS */ 539 /* searchRange 8 USHORT 2*(1 << LOG_SEGS) */ 540 /* entrySelector 10 USHORT LOG_SEGS */ 541 /* rangeShift 12 USHORT segCountX2 - */ 542 /* searchRange */ 543 /* */ 544 /* endCount 14 USHORT[NUM_SEGS] end charcode for */ 545 /* each segment; last */ 546 /* is 0xFFFF */ 547 /* */ 548 /* pad 14+NUM_SEGS*2 USHORT padding */ 549 /* */ 550 /* startCount 16+NUM_SEGS*2 USHORT[NUM_SEGS] first charcode for */ 551 /* each segment */ 552 /* */ 553 /* idDelta 16+NUM_SEGS*4 SHORT[NUM_SEGS] delta for each */ 554 /* segment */ 555 /* idOffset 16+NUM_SEGS*6 SHORT[NUM_SEGS] range offset for */ 556 /* each segment; can be */ 557 /* zero */ 558 /* */ 559 /* glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph id */ 560 /* ranges */ 561 /* */ 562 /* Character codes are modelled by a series of ordered (increasing) */ 563 /* intervals called segments. Each segment has start and end codes, */ 564 /* provided by the `startCount' and `endCount' arrays. Segments must */ 565 /* not be overlapping and the last segment should always contain the */ 566 /* `0xFFFF' endCount. */ 567 /* */ 568 /* The fields `searchRange', `entrySelector' and `rangeShift' are better */ 569 /* ignored (they are traces of over-engineering in the TrueType */ 570 /* specification). */ 571 /* */ 572 /* Each segment also has a signed `delta', as well as an optional offset */ 573 /* within the `glyphIds' table. */ 574 /* */ 575 /* If a segment's idOffset is 0, the glyph index corresponding to any */ 576 /* charcode within the segment is obtained by adding the value of */ 577 /* `idDelta' directly to the charcode, modulo 65536. */ 578 /* */ 579 /* Otherwise, a glyph index is taken from the glyph ids sub-array for */ 580 /* the segment, and the value of `idDelta' is added to it. */ 581 /* */ 582 /* */ 583 /* Finally, note that certain fonts contain invalid charmaps that */ 584 /* contain end=0xFFFF, start=0xFFFF, delta=0x0001, offset=0xFFFF at the */ 585 /* of their charmaps (e.g. opens___.ttf which comes with OpenOffice.org) */ 586 /* we need special code to deal with them correctly... */ 587 /* */ 588 589 #ifdef TT_CONFIG_CMAP_FORMAT_4 590 591 FT_CALLBACK_DEF( void ) 592 tt_cmap4_validate( FT_Byte* table, 593 FT_Validator valid ) 594 { 595 FT_Byte* p = table + 2; /* skip format */ 596 FT_UInt length = TT_NEXT_USHORT( p ); 597 FT_Byte *ends, *starts, *offsets, *deltas, *glyph_ids; 598 FT_UInt num_segs; 599 600 601 /* in certain fonts, the `length' field is invalid and goes */ 602 /* out of bound. We try to correct this here... */ 603 if ( length < 16 ) 604 FT_INVALID_TOO_SHORT; 605 606 if ( table + length > valid->limit ) 607 { 608 if ( valid->level >= FT_VALIDATE_TIGHT ) 609 FT_INVALID_TOO_SHORT; 610 611 length = (FT_UInt)( valid->limit - table ); 612 } 613 614 p = table + 6; 615 num_segs = TT_NEXT_USHORT( p ); /* read segCountX2 */ 616 617 if ( valid->level >= FT_VALIDATE_PARANOID ) 618 { 619 /* check that we have an even value here */ 620 if ( num_segs & 1 ) 621 FT_INVALID_DATA; 622 } 623 624 num_segs /= 2; 625 626 /* check the search parameters - even though we never use them */ 627 /* */ 628 if ( valid->level >= FT_VALIDATE_PARANOID ) 629 { 630 /* check the values of 'searchRange', 'entrySelector', 'rangeShift' */ 631 FT_UInt search_range = TT_NEXT_USHORT( p ); 632 FT_UInt entry_selector = TT_NEXT_USHORT( p ); 633 FT_UInt range_shift = TT_NEXT_USHORT( p ); 634 635 636 if ( ( search_range | range_shift ) & 1 ) /* must be even values */ 637 FT_INVALID_DATA; 638 639 search_range /= 2; 640 range_shift /= 2; 641 642 /* `search range' is the greatest power of 2 that is <= num_segs */ 643 644 if ( search_range > num_segs || 645 search_range * 2 < num_segs || 646 search_range + range_shift != num_segs || 647 search_range != ( 1U << entry_selector ) ) 648 FT_INVALID_DATA; 649 } 650 651 ends = table + 14; 652 starts = table + 16 + num_segs * 2; 653 deltas = starts + num_segs * 2; 654 offsets = deltas + num_segs * 2; 655 glyph_ids = offsets + num_segs * 2; 656 657 if ( glyph_ids > table + length ) 658 FT_INVALID_TOO_SHORT; 659 660 /* check last segment, its end count must be FFFF */ 661 if ( valid->level >= FT_VALIDATE_PARANOID ) 662 { 663 p = ends + ( num_segs - 1 ) * 2; 664 if ( TT_PEEK_USHORT( p ) != 0xFFFFU ) 665 FT_INVALID_DATA; 666 } 667 668 /* check that segments are sorted in increasing order and do not */ 669 /* overlap; check also the offsets */ 670 { 671 FT_UInt start, end, last = 0, offset, n; 672 FT_Int delta; 673 674 675 for ( n = 0; n < num_segs; n++ ) 676 { 677 p = starts + n * 2; 678 start = TT_PEEK_USHORT( p ); 679 p = ends + n * 2; 680 end = TT_PEEK_USHORT( p ); 681 p = deltas + n * 2; 682 delta = TT_PEEK_SHORT( p ); 683 p = offsets + n * 2; 684 offset = TT_PEEK_USHORT( p ); 685 686 if ( start > end ) 687 FT_INVALID_DATA; 688 689 /* this test should be performed at default validation level; */ 690 /* unfortunately, some popular Asian fonts present overlapping */ 691 /* ranges in their charmaps */ 692 /* */ 693 if ( valid->level >= FT_VALIDATE_TIGHT ) 694 { 695 if ( n > 0 && start <= last ) 696 FT_INVALID_DATA; 697 } 698 699 if ( offset && offset != 0xFFFFU ) 700 { 701 p += offset; /* start of glyph id array */ 702 703 /* check that we point within the glyph ids table only */ 704 if ( p < glyph_ids || 705 p + ( end - start + 1 ) * 2 > table + length ) 706 FT_INVALID_DATA; 707 708 /* check glyph indices within the segment range */ 709 if ( valid->level >= FT_VALIDATE_TIGHT ) 710 { 711 FT_UInt i, idx; 712 713 714 for ( i = start; i < end; i++ ) 715 { 716 idx = FT_NEXT_USHORT( p ); 717 if ( idx != 0 ) 718 { 719 idx = (FT_UInt)( idx + delta ) & 0xFFFFU; 720 721 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) 722 FT_INVALID_GLYPH_ID; 723 } 724 } 725 } 726 } 727 else if ( offset == 0xFFFFU ) 728 { 729 /* Some fonts (erroneously?) use a range offset of 0xFFFF */ 730 /* to mean missing glyph in cmap table */ 731 /* */ 732 if ( valid->level >= FT_VALIDATE_PARANOID || 733 n != num_segs - 1 || 734 !( start == 0xFFFFU && end == 0xFFFFU && delta == 0x1U ) ) 735 FT_INVALID_DATA; 736 } 737 738 last = end; 739 } 740 } 741 } 742 743 744 FT_CALLBACK_DEF( FT_UInt ) 745 tt_cmap4_char_index( TT_CMap cmap, 746 FT_UInt32 char_code ) 747 { 748 FT_Byte* table = cmap->data; 749 FT_UInt result = 0; 750 751 752 if ( char_code < 0x10000UL ) 753 { 754 FT_UInt idx, num_segs2; 755 FT_Int delta; 756 FT_UInt code = (FT_UInt)char_code; 757 FT_Byte* p; 758 759 760 p = table + 6; 761 num_segs2 = TT_PEEK_USHORT( p ) & -2; /* be paranoid! */ 762 763 #if 1 764 /* Some fonts have more than 170 segments in their charmaps! */ 765 /* We changed this function to use a more efficient binary */ 766 /* search for improving performance */ 767 { 768 FT_UInt min = 0; 769 FT_UInt max = num_segs2 >> 1; 770 FT_UInt mid, start, end, offset; 771 772 773 while ( min < max ) 774 { 775 mid = ( min + max ) >> 1; 776 p = table + 14 + mid * 2; 777 end = TT_NEXT_USHORT( p ); 778 p += num_segs2; 779 start = TT_PEEK_USHORT( p); 780 781 if ( code < start ) 782 max = mid; 783 784 else if ( code > end ) 785 min = mid + 1; 786 787 else 788 { 789 /* we found the segment */ 790 idx = code; 791 792 p += num_segs2; 793 delta = TT_PEEK_SHORT( p ); 794 795 p += num_segs2; 796 offset = TT_PEEK_USHORT( p ); 797 798 if ( offset == 0xFFFFU ) 799 goto Exit; 800 801 if ( offset != 0 ) 802 { 803 p += offset + 2 * ( idx - start ); 804 idx = TT_PEEK_USHORT( p ); 805 } 806 807 if ( idx != 0 ) 808 result = (FT_UInt)( idx + delta ) & 0xFFFFU; 809 810 goto Exit; 811 } 812 } 813 } 814 815 #else /* 0 - old code */ 816 817 { 818 FT_UInt n; 819 FT_Byte* q; 820 821 822 p = table + 14; /* ends table */ 823 q = table + 16 + num_segs2; /* starts table */ 824 825 826 for ( n = 0; n < num_segs2; n += 2 ) 827 { 828 FT_UInt end = TT_NEXT_USHORT( p ); 829 FT_UInt start = TT_NEXT_USHORT( q ); 830 FT_UInt offset; 831 832 833 if ( code < start ) 834 break; 835 836 if ( code <= end ) 837 { 838 idx = code; 839 840 p = q + num_segs2 - 2; 841 delta = TT_PEEK_SHORT( p ); 842 p += num_segs2; 843 offset = TT_PEEK_USHORT( p ); 844 845 if ( offset == 0xFFFFU ) 846 goto Exit; 847 848 if ( offset != 0 ) 849 { 850 p += offset + 2 * ( idx - start ); 851 idx = TT_PEEK_USHORT( p ); 852 } 853 854 if ( idx != 0 ) 855 result = (FT_UInt)( idx + delta ) & 0xFFFFU; 856 } 857 } 858 } 859 860 #endif /* 0 */ 861 862 } 863 864 Exit: 865 return result; 866 } 867 868 869 FT_CALLBACK_DEF( FT_UInt ) 870 tt_cmap4_char_next( TT_CMap cmap, 871 FT_UInt32 *pchar_code ) 872 { 873 FT_Byte* table = cmap->data; 874 FT_UInt32 result = 0; 875 FT_UInt32 char_code = *pchar_code + 1; 876 FT_UInt gindex = 0; 877 FT_Byte* p; 878 FT_Byte* q; 879 FT_UInt code, num_segs2; 880 881 882 if ( char_code >= 0x10000UL ) 883 goto Exit; 884 885 code = (FT_UInt)char_code; 886 p = table + 6; 887 num_segs2 = TT_PEEK_USHORT(p) & -2; /* ensure even-ness */ 888 889 for (;;) 890 { 891 FT_UInt offset, n; 892 FT_Int delta; 893 894 895 p = table + 14; /* ends table */ 896 q = table + 16 + num_segs2; /* starts table */ 897 898 for ( n = 0; n < num_segs2; n += 2 ) 899 { 900 FT_UInt end = TT_NEXT_USHORT( p ); 901 FT_UInt start = TT_NEXT_USHORT( q ); 902 903 904 if ( code < start ) 905 code = start; 906 907 if ( code <= end ) 908 { 909 p = q + num_segs2 - 2; 910 delta = TT_PEEK_SHORT( p ); 911 p += num_segs2; 912 offset = TT_PEEK_USHORT( p ); 913 914 if ( offset != 0 && offset != 0xFFFFU ) 915 { 916 /* parse the glyph ids array for non-0 index */ 917 p += offset + ( code - start ) * 2; 918 while ( code <= end ) 919 { 920 gindex = TT_NEXT_USHORT( p ); 921 if ( gindex != 0 ) 922 { 923 gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU; 924 if ( gindex != 0 ) 925 break; 926 } 927 code++; 928 } 929 } 930 else if ( offset == 0xFFFFU ) 931 { 932 /* an offset of 0xFFFF means an empty glyph in certain fonts! */ 933 code = end; 934 break; 935 } 936 else 937 gindex = (FT_UInt)( code + delta ) & 0xFFFFU; 938 939 if ( gindex == 0 ) 940 break; 941 942 result = code; 943 goto Exit; 944 } 945 } 946 947 /* loop to next trial charcode */ 948 if ( code >= 0xFFFFU ) 949 break; 950 951 code++; 952 } 953 return (FT_UInt)result; 954 955 Exit: 956 *pchar_code = result; 957 return gindex; 958 } 959 960 961 FT_CALLBACK_TABLE_DEF 962 const TT_CMap_ClassRec tt_cmap4_class_rec = 963 { 964 { 965 sizeof ( TT_CMapRec ), 966 967 (FT_CMap_InitFunc) tt_cmap_init, 968 (FT_CMap_DoneFunc) NULL, 969 (FT_CMap_CharIndexFunc)tt_cmap4_char_index, 970 (FT_CMap_CharNextFunc) tt_cmap4_char_next 971 }, 972 4, 973 (TT_CMap_ValidateFunc) tt_cmap4_validate 974 }; 975 976 #endif /* TT_CONFIG_CMAP_FORMAT_4 */ 977 978 979 /*************************************************************************/ 980 /*************************************************************************/ 981 /***** *****/ 982 /***** FORMAT 6 *****/ 983 /***** *****/ 984 /*************************************************************************/ 985 /*************************************************************************/ 986 987 /*************************************************************************/ 988 /* */ 989 /* TABLE OVERVIEW */ 990 /* -------------- */ 991 /* */ 992 /* NAME OFFSET TYPE DESCRIPTION */ 993 /* */ 994 /* format 0 USHORT must be 4 */ 995 /* length 2 USHORT table length in bytes */ 996 /* language 4 USHORT Mac language code */ 997 /* */ 998 /* first 6 USHORT first segment code */ 999 /* count 8 USHORT segment size in chars */ 1000 /* glyphIds 10 USHORT[count] glyph ids */ 1001 /* */ 1002 /* A very simplified segment mapping. */ 1003 /* */ 1004 1005 #ifdef TT_CONFIG_CMAP_FORMAT_6 1006 1007 FT_CALLBACK_DEF( void ) 1008 tt_cmap6_validate( FT_Byte* table, 1009 FT_Validator valid ) 1010 { 1011 FT_Byte* p; 1012 FT_UInt length, start, count; 1013 1014 1015 if ( table + 10 > valid->limit ) 1016 FT_INVALID_TOO_SHORT; 1017 1018 p = table + 2; 1019 length = TT_NEXT_USHORT( p ); 1020 1021 p = table + 6; /* skip language */ 1022 start = TT_NEXT_USHORT( p ); 1023 count = TT_NEXT_USHORT( p ); 1024 1025 if ( table + length > valid->limit || length < 10 + count * 2 ) 1026 FT_INVALID_TOO_SHORT; 1027 1028 /* check glyph indices */ 1029 if ( valid->level >= FT_VALIDATE_TIGHT ) 1030 { 1031 FT_UInt gindex; 1032 1033 1034 for ( ; count > 0; count-- ) 1035 { 1036 gindex = TT_NEXT_USHORT( p ); 1037 if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) ) 1038 FT_INVALID_GLYPH_ID; 1039 } 1040 } 1041 } 1042 1043 1044 FT_CALLBACK_DEF( FT_UInt ) 1045 tt_cmap6_char_index( TT_CMap cmap, 1046 FT_UInt32 char_code ) 1047 { 1048 FT_Byte* table = cmap->data; 1049 FT_UInt result = 0; 1050 FT_Byte* p = table + 6; 1051 FT_UInt start = TT_NEXT_USHORT( p ); 1052 FT_UInt count = TT_NEXT_USHORT( p ); 1053 FT_UInt idx = (FT_UInt)( char_code - start ); 1054 1055 1056 if ( idx < count ) 1057 { 1058 p += 2 * idx; 1059 result = TT_PEEK_USHORT( p ); 1060 } 1061 return result; 1062 } 1063 1064 1065 FT_CALLBACK_DEF( FT_UInt ) 1066 tt_cmap6_char_next( TT_CMap cmap, 1067 FT_UInt32 *pchar_code ) 1068 { 1069 FT_Byte* table = cmap->data; 1070 FT_UInt32 result = 0; 1071 FT_UInt32 char_code = *pchar_code + 1; 1072 FT_UInt gindex = 0; 1073 1074 FT_Byte* p = table + 6; 1075 FT_UInt start = TT_NEXT_USHORT( p ); 1076 FT_UInt count = TT_NEXT_USHORT( p ); 1077 FT_UInt idx; 1078 1079 1080 if ( char_code >= 0x10000UL ) 1081 goto Exit; 1082 1083 if ( char_code < start ) 1084 char_code = start; 1085 1086 idx = (FT_UInt)( char_code - start ); 1087 p += 2 * idx; 1088 1089 for ( ; idx < count; idx++ ) 1090 { 1091 gindex = TT_NEXT_USHORT( p ); 1092 if ( gindex != 0 ) 1093 { 1094 result = char_code; 1095 break; 1096 } 1097 char_code++; 1098 } 1099 1100 Exit: 1101 *pchar_code = result; 1102 return gindex; 1103 } 1104 1105 1106 FT_CALLBACK_TABLE_DEF 1107 const TT_CMap_ClassRec tt_cmap6_class_rec = 1108 { 1109 { 1110 sizeof ( TT_CMapRec ), 1111 1112 (FT_CMap_InitFunc) tt_cmap_init, 1113 (FT_CMap_DoneFunc) NULL, 1114 (FT_CMap_CharIndexFunc)tt_cmap6_char_index, 1115 (FT_CMap_CharNextFunc) tt_cmap6_char_next 1116 }, 1117 6, 1118 (TT_CMap_ValidateFunc) tt_cmap6_validate 1119 }; 1120 1121 #endif /* TT_CONFIG_CMAP_FORMAT_6 */ 1122 1123 1124 /*************************************************************************/ 1125 /*************************************************************************/ 1126 /***** *****/ 1127 /***** FORMAT 8 *****/ 1128 /***** *****/ 1129 /***** It's hard to completely understand what the OpenType spec *****/ 1130 /***** says about this format, but here is my conclusion. *****/ 1131 /***** *****/ 1132 /***** The purpose of this format is to easily map UTF-16 text to *****/ 1133 /***** glyph indices. Basically, the `char_code' must be in one of *****/ 1134 /***** the following formats: *****/ 1135 /***** *****/ 1136 /***** - A 16-bit value that isn't part of the Unicode Surrogates *****/ 1137 /***** Area (i.e. U+D800-U+DFFF). *****/ 1138 /***** *****/ 1139 /***** - A 32-bit value, made of two surrogate values, i.e.. if *****/ 1140 /***** `char_code = (char_hi << 16) | char_lo', then both *****/ 1141 /***** `char_hi' and `char_lo' must be in the Surrogates Area. *****/ 1142 /***** Area. *****/ 1143 /***** *****/ 1144 /***** The 'is32' table embedded in the charmap indicates whether a *****/ 1145 /***** given 16-bit value is in the surrogates area or not. *****/ 1146 /***** *****/ 1147 /***** So, for any given `char_code', we can assert the following: *****/ 1148 /***** *****/ 1149 /***** If `char_hi == 0' then we must have `is32[char_lo] == 0'. *****/ 1150 /***** *****/ 1151 /***** If `char_hi != 0' then we must have both *****/ 1152 /***** `is32[char_hi] != 0' and `is32[char_lo] != 0'. *****/ 1153 /***** *****/ 1154 /*************************************************************************/ 1155 /*************************************************************************/ 1156 1157 /*************************************************************************/ 1158 /* */ 1159 /* TABLE OVERVIEW */ 1160 /* -------------- */ 1161 /* */ 1162 /* NAME OFFSET TYPE DESCRIPTION */ 1163 /* */ 1164 /* format 0 USHORT must be 8 */ 1165 /* reseved 2 USHORT reserved */ 1166 /* length 4 ULONG length in bytes */ 1167 /* language 8 ULONG Mac language code */ 1168 /* is32 12 BYTE[8192] 32-bitness bitmap */ 1169 /* count 8204 ULONG number of groups */ 1170 /* */ 1171 /* This header is followed by 'count' groups of the following format: */ 1172 /* */ 1173 /* start 0 ULONG first charcode */ 1174 /* end 4 ULONG last charcode */ 1175 /* startId 8 ULONG start glyph id for the group */ 1176 /* */ 1177 1178 #ifdef TT_CONFIG_CMAP_FORMAT_8 1179 1180 FT_CALLBACK_DEF( void ) 1181 tt_cmap8_validate( FT_Byte* table, 1182 FT_Validator valid ) 1183 { 1184 FT_Byte* p = table + 4; 1185 FT_Byte* is32; 1186 FT_UInt32 length; 1187 FT_UInt32 num_groups; 1188 1189 1190 if ( table + 16 + 8192 > valid->limit ) 1191 FT_INVALID_TOO_SHORT; 1192 1193 length = TT_NEXT_ULONG( p ); 1194 if ( table + length > valid->limit || length < 8208 ) 1195 FT_INVALID_TOO_SHORT; 1196 1197 is32 = table + 12; 1198 p = is32 + 8192; /* skip `is32' array */ 1199 num_groups = TT_NEXT_ULONG( p ); 1200 1201 if ( p + num_groups * 12 > valid->limit ) 1202 FT_INVALID_TOO_SHORT; 1203 1204 /* check groups, they must be in increasing order */ 1205 { 1206 FT_UInt32 n, start, end, start_id, count, last = 0; 1207 1208 1209 for ( n = 0; n < num_groups; n++ ) 1210 { 1211 FT_UInt hi, lo; 1212 1213 1214 start = TT_NEXT_ULONG( p ); 1215 end = TT_NEXT_ULONG( p ); 1216 start_id = TT_NEXT_ULONG( p ); 1217 1218 if ( start > end ) 1219 FT_INVALID_DATA; 1220 1221 if ( n > 0 && start <= last ) 1222 FT_INVALID_DATA; 1223 1224 if ( valid->level >= FT_VALIDATE_TIGHT ) 1225 { 1226 if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ) 1227 FT_INVALID_GLYPH_ID; 1228 1229 count = (FT_UInt32)( end - start + 1 ); 1230 1231 if ( start & ~0xFFFFU ) 1232 { 1233 /* start_hi != 0; check that is32[i] is 1 for each i in */ 1234 /* the `hi' and `lo' of the range [start..end] */ 1235 for ( ; count > 0; count--, start++ ) 1236 { 1237 hi = (FT_UInt)( start >> 16 ); 1238 lo = (FT_UInt)( start & 0xFFFFU ); 1239 1240 if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 ) 1241 FT_INVALID_DATA; 1242 1243 if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 ) 1244 FT_INVALID_DATA; 1245 } 1246 } 1247 else 1248 { 1249 /* start_hi == 0; check that is32[i] is 0 for each i in */ 1250 /* the range [start..end] */ 1251 1252 /* end_hi cannot be != 0! */ 1253 if ( end & ~0xFFFFU ) 1254 FT_INVALID_DATA; 1255 1256 for ( ; count > 0; count--, start++ ) 1257 { 1258 lo = (FT_UInt)( start & 0xFFFFU ); 1259 1260 if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 ) 1261 FT_INVALID_DATA; 1262 } 1263 } 1264 } 1265 1266 last = end; 1267 } 1268 } 1269 } 1270 1271 1272 FT_CALLBACK_DEF( FT_UInt ) 1273 tt_cmap8_char_index( TT_CMap cmap, 1274 FT_UInt32 char_code ) 1275 { 1276 FT_Byte* table = cmap->data; 1277 FT_UInt result = 0; 1278 FT_Byte* p = table + 8204; 1279 FT_UInt32 num_groups = TT_NEXT_ULONG( p ); 1280 FT_UInt32 start, end, start_id; 1281 1282 1283 for ( ; num_groups > 0; num_groups-- ) 1284 { 1285 start = TT_NEXT_ULONG( p ); 1286 end = TT_NEXT_ULONG( p ); 1287 start_id = TT_NEXT_ULONG( p ); 1288 1289 if ( char_code < start ) 1290 break; 1291 1292 if ( char_code <= end ) 1293 { 1294 result = (FT_UInt)( start_id + char_code - start ); 1295 break; 1296 } 1297 } 1298 return result; 1299 } 1300 1301 1302 FT_CALLBACK_DEF( FT_UInt ) 1303 tt_cmap8_char_next( TT_CMap cmap, 1304 FT_UInt32 *pchar_code ) 1305 { 1306 FT_UInt32 result = 0; 1307 FT_UInt32 char_code = *pchar_code + 1; 1308 FT_UInt gindex = 0; 1309 FT_Byte* table = cmap->data; 1310 FT_Byte* p = table + 8204; 1311 FT_UInt32 num_groups = TT_NEXT_ULONG( p ); 1312 FT_UInt32 start, end, start_id; 1313 1314 1315 p = table + 8208; 1316 1317 for ( ; num_groups > 0; num_groups-- ) 1318 { 1319 start = TT_NEXT_ULONG( p ); 1320 end = TT_NEXT_ULONG( p ); 1321 start_id = TT_NEXT_ULONG( p ); 1322 1323 if ( char_code < start ) 1324 char_code = start; 1325 1326 if ( char_code <= end ) 1327 { 1328 gindex = (FT_UInt)( char_code - start + start_id ); 1329 if ( gindex != 0 ) 1330 { 1331 result = char_code; 1332 goto Exit; 1333 } 1334 } 1335 } 1336 1337 Exit: 1338 *pchar_code = result; 1339 return gindex; 1340 } 1341 1342 1343 FT_CALLBACK_TABLE_DEF 1344 const TT_CMap_ClassRec tt_cmap8_class_rec = 1345 { 1346 { 1347 sizeof ( TT_CMapRec ), 1348 1349 (FT_CMap_InitFunc) tt_cmap_init, 1350 (FT_CMap_DoneFunc) NULL, 1351 (FT_CMap_CharIndexFunc)tt_cmap8_char_index, 1352 (FT_CMap_CharNextFunc) tt_cmap8_char_next 1353 }, 1354 8, 1355 (TT_CMap_ValidateFunc) tt_cmap8_validate 1356 }; 1357 1358 #endif /* TT_CONFIG_CMAP_FORMAT_8 */ 1359 1360 1361 /*************************************************************************/ 1362 /*************************************************************************/ 1363 /***** *****/ 1364 /***** FORMAT 10 *****/ 1365 /***** *****/ 1366 /*************************************************************************/ 1367 /*************************************************************************/ 1368 1369 /*************************************************************************/ 1370 /* */ 1371 /* TABLE OVERVIEW */ 1372 /* -------------- */ 1373 /* */ 1374 /* NAME OFFSET TYPE DESCRIPTION */ 1375 /* */ 1376 /* format 0 USHORT must be 10 */ 1377 /* reserved 2 USHORT reserved */ 1378 /* length 4 ULONG length in bytes */ 1379 /* language 8 ULONG Mac language code */ 1380 /* */ 1381 /* start 12 ULONG first char in range */ 1382 /* count 16 ULONG number of chars in range */ 1383 /* glyphIds 20 USHORT[count] glyph indices covered */ 1384 /* */ 1385 1386 #ifdef TT_CONFIG_CMAP_FORMAT_10 1387 1388 FT_CALLBACK_DEF( void ) 1389 tt_cmap10_validate( FT_Byte* table, 1390 FT_Validator valid ) 1391 { 1392 FT_Byte* p = table + 4; 1393 FT_ULong length, start, count; 1394 1395 1396 if ( table + 20 > valid->limit ) 1397 FT_INVALID_TOO_SHORT; 1398 1399 length = TT_NEXT_ULONG( p ); 1400 p = table + 12; 1401 start = TT_NEXT_ULONG( p ); 1402 count = TT_NEXT_ULONG( p ); 1403 1404 if ( table + length > valid->limit || length < 20 + count * 2 ) 1405 FT_INVALID_TOO_SHORT; 1406 1407 /* check glyph indices */ 1408 if ( valid->level >= FT_VALIDATE_TIGHT ) 1409 { 1410 FT_UInt gindex; 1411 1412 1413 for ( ; count > 0; count-- ) 1414 { 1415 gindex = TT_NEXT_USHORT( p ); 1416 if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) ) 1417 FT_INVALID_GLYPH_ID; 1418 } 1419 } 1420 } 1421 1422 1423 FT_CALLBACK_DEF( FT_UInt ) 1424 tt_cmap10_char_index( TT_CMap cmap, 1425 FT_UInt32 char_code ) 1426 { 1427 FT_Byte* table = cmap->data; 1428 FT_UInt result = 0; 1429 FT_Byte* p = table + 12; 1430 FT_UInt32 start = TT_NEXT_ULONG( p ); 1431 FT_UInt32 count = TT_NEXT_ULONG( p ); 1432 FT_UInt32 idx = (FT_ULong)( char_code - start ); 1433 1434 1435 if ( idx < count ) 1436 { 1437 p += 2 * idx; 1438 result = TT_PEEK_USHORT( p ); 1439 } 1440 return result; 1441 } 1442 1443 1444 FT_CALLBACK_DEF( FT_UInt ) 1445 tt_cmap10_char_next( TT_CMap cmap, 1446 FT_UInt32 *pchar_code ) 1447 { 1448 FT_Byte* table = cmap->data; 1449 FT_UInt32 result = 0; 1450 FT_UInt32 char_code = *pchar_code + 1; 1451 FT_UInt gindex = 0; 1452 FT_Byte* p = table + 12; 1453 FT_UInt32 start = TT_NEXT_ULONG( p ); 1454 FT_UInt32 count = TT_NEXT_ULONG( p ); 1455 FT_UInt32 idx; 1456 1457 1458 if ( char_code < start ) 1459 char_code = start; 1460 1461 idx = (FT_UInt32)( char_code - start ); 1462 p += 2 * idx; 1463 1464 for ( ; idx < count; idx++ ) 1465 { 1466 gindex = TT_NEXT_USHORT( p ); 1467 if ( gindex != 0 ) 1468 { 1469 result = char_code; 1470 break; 1471 } 1472 char_code++; 1473 } 1474 1475 *pchar_code = char_code; 1476 return gindex; 1477 } 1478 1479 1480 FT_CALLBACK_TABLE_DEF 1481 const TT_CMap_ClassRec tt_cmap10_class_rec = 1482 { 1483 { 1484 sizeof ( TT_CMapRec ), 1485 1486 (FT_CMap_InitFunc) tt_cmap_init, 1487 (FT_CMap_DoneFunc) NULL, 1488 (FT_CMap_CharIndexFunc)tt_cmap10_char_index, 1489 (FT_CMap_CharNextFunc) tt_cmap10_char_next 1490 }, 1491 10, 1492 (TT_CMap_ValidateFunc) tt_cmap10_validate 1493 }; 1494 1495 #endif /* TT_CONFIG_CMAP_FORMAT_10 */ 1496 1497 1498 /*************************************************************************/ 1499 /*************************************************************************/ 1500 /***** *****/ 1501 /***** FORMAT 12 *****/ 1502 /***** *****/ 1503 /*************************************************************************/ 1504 /*************************************************************************/ 1505 1506 /*************************************************************************/ 1507 /* */ 1508 /* TABLE OVERVIEW */ 1509 /* -------------- */ 1510 /* */ 1511 /* NAME OFFSET TYPE DESCRIPTION */ 1512 /* */ 1513 /* format 0 USHORT must be 12 */ 1514 /* reserved 2 USHORT reserved */ 1515 /* length 4 ULONG length in bytes */ 1516 /* language 8 ULONG Mac language code */ 1517 /* count 12 ULONG number of groups */ 1518 /* 16 */ 1519 /* */ 1520 /* This header is followed by `count' groups of the following format: */ 1521 /* */ 1522 /* start 0 ULONG first charcode */ 1523 /* end 4 ULONG last charcode */ 1524 /* startId 8 ULONG start glyph id for the group */ 1525 /* */ 1526 1527 #ifdef TT_CONFIG_CMAP_FORMAT_12 1528 1529 FT_CALLBACK_DEF( void ) 1530 tt_cmap12_validate( FT_Byte* table, 1531 FT_Validator valid ) 1532 { 1533 FT_Byte* p; 1534 FT_ULong length; 1535 FT_ULong num_groups; 1536 1537 1538 if ( table + 16 > valid->limit ) 1539 FT_INVALID_TOO_SHORT; 1540 1541 p = table + 4; 1542 length = TT_NEXT_ULONG( p ); 1543 1544 p = table + 12; 1545 num_groups = TT_NEXT_ULONG( p ); 1546 1547 if ( table + length > valid->limit || length < 16 + 12 * num_groups ) 1548 FT_INVALID_TOO_SHORT; 1549 1550 /* check groups, they must be in increasing order */ 1551 { 1552 FT_ULong n, start, end, start_id, last = 0; 1553 1554 1555 for ( n = 0; n < num_groups; n++ ) 1556 { 1557 start = TT_NEXT_ULONG( p ); 1558 end = TT_NEXT_ULONG( p ); 1559 start_id = TT_NEXT_ULONG( p ); 1560 1561 if ( start > end ) 1562 FT_INVALID_DATA; 1563 1564 if ( n > 0 && start <= last ) 1565 FT_INVALID_DATA; 1566 1567 if ( valid->level >= FT_VALIDATE_TIGHT ) 1568 { 1569 if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ) 1570 FT_INVALID_GLYPH_ID; 1571 } 1572 1573 last = end; 1574 } 1575 } 1576 } 1577 1578 1579 FT_CALLBACK_DEF( FT_UInt ) 1580 tt_cmap12_char_index( TT_CMap cmap, 1581 FT_UInt32 char_code ) 1582 { 1583 FT_UInt result = 0; 1584 FT_Byte* table = cmap->data; 1585 FT_Byte* p = table + 12; 1586 FT_UInt32 num_groups = TT_NEXT_ULONG( p ); 1587 FT_UInt32 start, end, start_id; 1588 1589 1590 for ( ; num_groups > 0; num_groups-- ) 1591 { 1592 start = TT_NEXT_ULONG( p ); 1593 end = TT_NEXT_ULONG( p ); 1594 start_id = TT_NEXT_ULONG( p ); 1595 1596 if ( char_code < start ) 1597 break; 1598 1599 if ( char_code <= end ) 1600 { 1601 result = (FT_UInt)( start_id + char_code - start ); 1602 break; 1603 } 1604 } 1605 return result; 1606 } 1607 1608 1609 FT_CALLBACK_DEF( FT_UInt ) 1610 tt_cmap12_char_next( TT_CMap cmap, 1611 FT_UInt32 *pchar_code ) 1612 { 1613 FT_Byte* table = cmap->data; 1614 FT_UInt32 result = 0; 1615 FT_UInt32 char_code = *pchar_code + 1; 1616 FT_UInt gindex = 0; 1617 FT_Byte* p = table + 12; 1618 FT_UInt32 num_groups = TT_NEXT_ULONG( p ); 1619 FT_UInt32 start, end, start_id; 1620 1621 1622 p = table + 16; 1623 1624 for ( ; num_groups > 0; num_groups-- ) 1625 { 1626 start = TT_NEXT_ULONG( p ); 1627 end = TT_NEXT_ULONG( p ); 1628 start_id = TT_NEXT_ULONG( p ); 1629 1630 if ( char_code < start ) 1631 char_code = start; 1632 1633 if ( char_code <= end ) 1634 { 1635 gindex = (FT_UInt)(char_code - start + start_id); 1636 if ( gindex != 0 ) 1637 { 1638 result = char_code; 1639 goto Exit; 1640 } 1641 } 1642 } 1643 1644 Exit: 1645 *pchar_code = result; 1646 return gindex; 1647 } 1648 1649 1650 FT_CALLBACK_TABLE_DEF 1651 const TT_CMap_ClassRec tt_cmap12_class_rec = 1652 { 1653 { 1654 sizeof ( TT_CMapRec ), 1655 1656 (FT_CMap_InitFunc) tt_cmap_init, 1657 (FT_CMap_DoneFunc) NULL, 1658 (FT_CMap_CharIndexFunc)tt_cmap12_char_index, 1659 (FT_CMap_CharNextFunc) tt_cmap12_char_next 1660 }, 1661 12, 1662 (TT_CMap_ValidateFunc) tt_cmap12_validate 1663 }; 1664 1665 1666 #endif /* TT_CONFIG_CMAP_FORMAT_12 */ 1667 1668 1669 static const TT_CMap_Class tt_cmap_classes[] = 1670 { 1671 #ifdef TT_CONFIG_CMAP_FORMAT_0 1672 &tt_cmap0_class_rec, 1673 #endif 1674 1675 #ifdef TT_CONFIG_CMAP_FORMAT_2 1676 &tt_cmap2_class_rec, 1677 #endif 1678 1679 #ifdef TT_CONFIG_CMAP_FORMAT_4 1680 &tt_cmap4_class_rec, 1681 #endif 1682 1683 #ifdef TT_CONFIG_CMAP_FORMAT_6 1684 &tt_cmap6_class_rec, 1685 #endif 1686 1687 #ifdef TT_CONFIG_CMAP_FORMAT_8 1688 &tt_cmap8_class_rec, 1689 #endif 1690 1691 #ifdef TT_CONFIG_CMAP_FORMAT_10 1692 &tt_cmap10_class_rec, 1693 #endif 1694 1695 #ifdef TT_CONFIG_CMAP_FORMAT_12 1696 &tt_cmap12_class_rec, 1697 #endif 1698 1699 NULL, 1700 }; 1701 1702 1703 /* parse the `cmap' table and build the corresponding TT_CMap objects */ 1704 /* in the current face */ 1705 /* */ 1706 FT_LOCAL_DEF( FT_Error ) 1707 tt_face_build_cmaps( TT_Face face ) 1708 { 1709 FT_Byte* table = face->cmap_table; 1710 FT_Byte* limit = table + face->cmap_size; 1711 FT_UInt volatile num_cmaps; 1712 FT_Byte* volatile p = table; 1713 1714 1715 if ( p + 4 > limit ) 1716 return FT_Err_Invalid_Table; 1717 1718 /* only recognize format 0 */ 1719 if ( TT_NEXT_USHORT( p ) != 0 ) 1720 { 1721 p -= 2; 1722 FT_ERROR(( "tt_face_build_cmaps: unsupported `cmap' table format = %d\n", 1723 TT_PEEK_USHORT( p ) )); 1724 return FT_Err_Invalid_Table; 1725 } 1726 1727 num_cmaps = TT_NEXT_USHORT( p ); 1728 1729 for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- ) 1730 { 1731 FT_CharMapRec charmap; 1732 FT_UInt32 offset; 1733 1734 1735 charmap.platform_id = TT_NEXT_USHORT( p ); 1736 charmap.encoding_id = TT_NEXT_USHORT( p ); 1737 charmap.face = FT_FACE( face ); 1738 charmap.encoding = FT_ENCODING_NONE; /* will be filled later */ 1739 offset = TT_NEXT_ULONG( p ); 1740 1741 if ( offset && table + offset + 2 < limit ) 1742 { 1743 FT_Byte* cmap = table + offset; 1744 FT_UInt format = TT_PEEK_USHORT( cmap ); 1745 const TT_CMap_Class* volatile pclazz = tt_cmap_classes; 1746 TT_CMap_Class clazz; 1747 1748 1749 for ( ; *pclazz; pclazz++ ) 1750 { 1751 clazz = *pclazz; 1752 if ( clazz->format == format ) 1753 { 1754 volatile TT_ValidatorRec valid; 1755 1756 1757 ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit, 1758 FT_VALIDATE_DEFAULT ); 1759 1760 valid.num_glyphs = (FT_UInt)face->root.num_glyphs; 1761 1762 if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer ) == 0 ) 1763 { 1764 /* validate this cmap sub-table */ 1765 clazz->validate( cmap, FT_VALIDATOR( &valid ) ); 1766 } 1767 1768 if ( valid.validator.error == 0 ) 1769 (void)FT_CMap_New( (FT_CMap_Class)clazz, cmap, &charmap, NULL ); 1770 else 1771 { 1772 FT_ERROR(( "tt_face_build_cmaps:" )); 1773 FT_ERROR(( " broken cmap sub-table ignored!\n" )); 1774 } 1775 } 1776 } 1777 } 1778 } 1779 1780 return 0; 1781 } 1782 1783 1784 /* END */ 1785