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