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