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