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