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