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 FT_UInt charcode; 767 768 769 if ( cmap->cur_charcode >= 0xFFFFUL ) 770 goto Fail; 771 772 charcode = (FT_UInt)cmap->cur_charcode + 1; 773 774 if ( charcode < cmap->cur_start ) 775 charcode = cmap->cur_start; 776 777 for (;;) 778 { 779 FT_Byte* values = cmap->cur_values; 780 FT_UInt end = cmap->cur_end; 781 FT_Int delta = cmap->cur_delta; 782 783 784 if ( charcode <= end ) 785 { 786 if ( values ) 787 { 788 FT_Byte* p = values + 2 * ( charcode - cmap->cur_start ); 789 790 791 do 792 { 793 FT_UInt gindex = FT_NEXT_USHORT( p ); 794 795 796 if ( gindex != 0 ) 797 { 798 gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU; 799 if ( gindex != 0 ) 800 { 801 cmap->cur_charcode = charcode; 802 cmap->cur_gindex = gindex; 803 return; 804 } 805 } 806 } while ( ++charcode <= end ); 807 } 808 else 809 { 810 do 811 { 812 FT_UInt gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU; 813 814 815 if ( gindex != 0 ) 816 { 817 cmap->cur_charcode = charcode; 818 cmap->cur_gindex = gindex; 819 return; 820 } 821 } while ( ++charcode <= end ); 822 } 823 } 824 825 /* we need to find another range */ 826 if ( tt_cmap4_set_range( cmap, cmap->cur_range + 1 ) < 0 ) 827 break; 828 829 if ( charcode < cmap->cur_start ) 830 charcode = cmap->cur_start; 831 } 832 833 Fail: 834 cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL; 835 cmap->cur_gindex = 0; 836 } 837 838 839 FT_CALLBACK_DEF( FT_Error ) tt_cmap4_validate(FT_Byte * table,FT_Validator valid)840 tt_cmap4_validate( FT_Byte* table, 841 FT_Validator valid ) 842 { 843 FT_Byte* p; 844 FT_UInt length; 845 846 FT_Byte *ends, *starts, *offsets, *deltas, *glyph_ids; 847 FT_UInt num_segs; 848 FT_Error error = FT_Err_Ok; 849 850 851 if ( table + 2 + 2 > valid->limit ) 852 FT_INVALID_TOO_SHORT; 853 854 p = table + 2; /* skip format */ 855 length = TT_NEXT_USHORT( p ); 856 857 /* in certain fonts, the `length' field is invalid and goes */ 858 /* out of bound. We try to correct this here... */ 859 if ( table + length > valid->limit ) 860 { 861 if ( valid->level >= FT_VALIDATE_TIGHT ) 862 FT_INVALID_TOO_SHORT; 863 864 length = (FT_UInt)( valid->limit - table ); 865 } 866 867 if ( length < 16 ) 868 FT_INVALID_TOO_SHORT; 869 870 p = table + 6; 871 num_segs = TT_NEXT_USHORT( p ); /* read segCountX2 */ 872 873 if ( valid->level >= FT_VALIDATE_PARANOID ) 874 { 875 /* check that we have an even value here */ 876 if ( num_segs & 1 ) 877 FT_INVALID_DATA; 878 } 879 880 num_segs /= 2; 881 882 if ( length < 16 + num_segs * 2 * 4 ) 883 FT_INVALID_TOO_SHORT; 884 885 /* check the search parameters - even though we never use them */ 886 /* */ 887 if ( valid->level >= FT_VALIDATE_PARANOID ) 888 { 889 /* check the values of `searchRange', `entrySelector', `rangeShift' */ 890 FT_UInt search_range = TT_NEXT_USHORT( p ); 891 FT_UInt entry_selector = TT_NEXT_USHORT( p ); 892 FT_UInt range_shift = TT_NEXT_USHORT( p ); 893 894 895 if ( ( search_range | range_shift ) & 1 ) /* must be even values */ 896 FT_INVALID_DATA; 897 898 search_range /= 2; 899 range_shift /= 2; 900 901 /* `search range' is the greatest power of 2 that is <= num_segs */ 902 903 if ( search_range > num_segs || 904 search_range * 2 < num_segs || 905 search_range + range_shift != num_segs || 906 search_range != ( 1U << entry_selector ) ) 907 FT_INVALID_DATA; 908 } 909 910 ends = table + 14; 911 starts = table + 16 + num_segs * 2; 912 deltas = starts + num_segs * 2; 913 offsets = deltas + num_segs * 2; 914 glyph_ids = offsets + num_segs * 2; 915 916 /* check last segment; its end count value must be 0xFFFF */ 917 if ( valid->level >= FT_VALIDATE_PARANOID ) 918 { 919 p = ends + ( num_segs - 1 ) * 2; 920 if ( TT_PEEK_USHORT( p ) != 0xFFFFU ) 921 FT_INVALID_DATA; 922 } 923 924 { 925 FT_UInt start, end, offset, n; 926 FT_UInt last_start = 0, last_end = 0; 927 FT_Int delta; 928 FT_Byte* p_start = starts; 929 FT_Byte* p_end = ends; 930 FT_Byte* p_delta = deltas; 931 FT_Byte* p_offset = offsets; 932 933 934 for ( n = 0; n < num_segs; n++ ) 935 { 936 p = p_offset; 937 start = TT_NEXT_USHORT( p_start ); 938 end = TT_NEXT_USHORT( p_end ); 939 delta = TT_NEXT_SHORT( p_delta ); 940 offset = TT_NEXT_USHORT( p_offset ); 941 942 if ( start > end ) 943 FT_INVALID_DATA; 944 945 /* this test should be performed at default validation level; */ 946 /* unfortunately, some popular Asian fonts have overlapping */ 947 /* ranges in their charmaps */ 948 /* */ 949 if ( start <= last_end && n > 0 ) 950 { 951 if ( valid->level >= FT_VALIDATE_TIGHT ) 952 FT_INVALID_DATA; 953 else 954 { 955 /* allow overlapping segments, provided their start points */ 956 /* and end points, respectively, are in ascending order */ 957 /* */ 958 if ( last_start > start || last_end > end ) 959 error |= TT_CMAP_FLAG_UNSORTED; 960 else 961 error |= TT_CMAP_FLAG_OVERLAPPING; 962 } 963 } 964 965 if ( offset && offset != 0xFFFFU ) 966 { 967 p += offset; /* start of glyph ID array */ 968 969 /* check that we point within the glyph IDs table only */ 970 if ( valid->level >= FT_VALIDATE_TIGHT ) 971 { 972 if ( p < glyph_ids || 973 p + ( end - start + 1 ) * 2 > table + length ) 974 FT_INVALID_DATA; 975 } 976 /* Some fonts handle the last segment incorrectly. In */ 977 /* theory, 0xFFFF might point to an ordinary glyph -- */ 978 /* a cmap 4 is versatile and could be used for any */ 979 /* encoding, not only Unicode. However, reality shows */ 980 /* that far too many fonts are sloppy and incorrectly */ 981 /* set all fields but `start' and `end' for the last */ 982 /* segment if it contains only a single character. */ 983 /* */ 984 /* We thus omit the test here, delaying it to the */ 985 /* routines that actually access the cmap. */ 986 else if ( n != num_segs - 1 || 987 !( start == 0xFFFFU && end == 0xFFFFU ) ) 988 { 989 if ( p < glyph_ids || 990 p + ( end - start + 1 ) * 2 > valid->limit ) 991 FT_INVALID_DATA; 992 } 993 994 /* check glyph indices within the segment range */ 995 if ( valid->level >= FT_VALIDATE_TIGHT ) 996 { 997 FT_UInt i, idx; 998 999 1000 for ( i = start; i < end; i++ ) 1001 { 1002 idx = FT_NEXT_USHORT( p ); 1003 if ( idx != 0 ) 1004 { 1005 idx = (FT_UInt)( (FT_Int)idx + delta ) & 0xFFFFU; 1006 1007 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) 1008 FT_INVALID_GLYPH_ID; 1009 } 1010 } 1011 } 1012 } 1013 else if ( offset == 0xFFFFU ) 1014 { 1015 /* some fonts (erroneously?) use a range offset of 0xFFFF */ 1016 /* to mean missing glyph in cmap table */ 1017 /* */ 1018 if ( valid->level >= FT_VALIDATE_PARANOID || 1019 n != num_segs - 1 || 1020 !( start == 0xFFFFU && end == 0xFFFFU ) ) 1021 FT_INVALID_DATA; 1022 } 1023 1024 last_start = start; 1025 last_end = end; 1026 } 1027 } 1028 1029 return error; 1030 } 1031 1032 1033 static FT_UInt tt_cmap4_char_map_linear(TT_CMap cmap,FT_UInt32 * pcharcode,FT_Bool next)1034 tt_cmap4_char_map_linear( TT_CMap cmap, 1035 FT_UInt32* pcharcode, 1036 FT_Bool next ) 1037 { 1038 TT_Face face = (TT_Face)cmap->cmap.charmap.face; 1039 FT_Byte* limit = face->cmap_table + face->cmap_size; 1040 1041 1042 FT_UInt num_segs2, start, end, offset; 1043 FT_Int delta; 1044 FT_UInt i, num_segs; 1045 FT_UInt32 charcode = *pcharcode; 1046 FT_UInt gindex = 0; 1047 FT_Byte* p; 1048 FT_Byte* q; 1049 1050 1051 p = cmap->data + 6; 1052 num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); 1053 1054 num_segs = num_segs2 >> 1; 1055 1056 if ( !num_segs ) 1057 return 0; 1058 1059 if ( next ) 1060 charcode++; 1061 1062 if ( charcode > 0xFFFFU ) 1063 return 0; 1064 1065 /* linear search */ 1066 p = cmap->data + 14; /* ends table */ 1067 q = cmap->data + 16 + num_segs2; /* starts table */ 1068 1069 for ( i = 0; i < num_segs; i++ ) 1070 { 1071 end = TT_NEXT_USHORT( p ); 1072 start = TT_NEXT_USHORT( q ); 1073 1074 if ( charcode < start ) 1075 { 1076 if ( next ) 1077 charcode = start; 1078 else 1079 break; 1080 } 1081 1082 Again: 1083 if ( charcode <= end ) 1084 { 1085 FT_Byte* r; 1086 1087 1088 r = q - 2 + num_segs2; 1089 delta = TT_PEEK_SHORT( r ); 1090 r += num_segs2; 1091 offset = TT_PEEK_USHORT( r ); 1092 1093 /* some fonts have an incorrect last segment; */ 1094 /* we have to catch it */ 1095 if ( i >= num_segs - 1 && 1096 start == 0xFFFFU && end == 0xFFFFU ) 1097 { 1098 if ( offset && r + offset + 2 > limit ) 1099 { 1100 delta = 1; 1101 offset = 0; 1102 } 1103 } 1104 1105 if ( offset == 0xFFFFU ) 1106 continue; 1107 1108 if ( offset ) 1109 { 1110 r += offset + ( charcode - start ) * 2; 1111 1112 /* if r > limit, the whole segment is invalid */ 1113 if ( next && r > limit ) 1114 continue; 1115 1116 gindex = TT_PEEK_USHORT( r ); 1117 if ( gindex ) 1118 { 1119 gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU; 1120 if ( gindex >= (FT_UInt)face->root.num_glyphs ) 1121 gindex = 0; 1122 } 1123 } 1124 else 1125 { 1126 gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU; 1127 1128 if ( next && gindex >= (FT_UInt)face->root.num_glyphs ) 1129 { 1130 /* we have an invalid glyph index; if there is an overflow, */ 1131 /* we can adjust `charcode', otherwise the whole segment is */ 1132 /* invalid */ 1133 gindex = 0; 1134 1135 if ( (FT_Int)charcode + delta < 0 && 1136 (FT_Int)end + delta >= 0 ) 1137 charcode = (FT_UInt)( -delta ); 1138 1139 else if ( (FT_Int)charcode + delta < 0x10000L && 1140 (FT_Int)end + delta >= 0x10000L ) 1141 charcode = (FT_UInt)( 0x10000L - delta ); 1142 1143 else 1144 continue; 1145 } 1146 } 1147 1148 if ( next && !gindex ) 1149 { 1150 if ( charcode >= 0xFFFFU ) 1151 break; 1152 1153 charcode++; 1154 goto Again; 1155 } 1156 1157 break; 1158 } 1159 } 1160 1161 if ( next ) 1162 *pcharcode = charcode; 1163 1164 return gindex; 1165 } 1166 1167 1168 static FT_UInt tt_cmap4_char_map_binary(TT_CMap cmap,FT_UInt32 * pcharcode,FT_Bool next)1169 tt_cmap4_char_map_binary( TT_CMap cmap, 1170 FT_UInt32* pcharcode, 1171 FT_Bool next ) 1172 { 1173 FT_UInt num_segs2, start, end, offset; 1174 FT_Int delta; 1175 FT_UInt max, min, mid, num_segs; 1176 FT_UInt charcode = (FT_UInt)*pcharcode; 1177 FT_UInt gindex = 0; 1178 FT_Byte* p; 1179 1180 1181 p = cmap->data + 6; 1182 num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); 1183 1184 if ( !num_segs2 ) 1185 return 0; 1186 1187 num_segs = num_segs2 >> 1; 1188 1189 /* make compiler happy */ 1190 mid = num_segs; 1191 end = 0xFFFFU; 1192 1193 if ( next ) 1194 charcode++; 1195 1196 min = 0; 1197 max = num_segs; 1198 1199 /* binary search */ 1200 while ( min < max ) 1201 { 1202 mid = ( min + max ) >> 1; 1203 p = cmap->data + 14 + mid * 2; 1204 end = TT_PEEK_USHORT( p ); 1205 p += 2 + num_segs2; 1206 start = TT_PEEK_USHORT( p ); 1207 1208 if ( charcode < start ) 1209 max = mid; 1210 else if ( charcode > end ) 1211 min = mid + 1; 1212 else 1213 { 1214 p += num_segs2; 1215 delta = TT_PEEK_SHORT( p ); 1216 p += num_segs2; 1217 offset = TT_PEEK_USHORT( p ); 1218 1219 /* some fonts have an incorrect last segment; */ 1220 /* we have to catch it */ 1221 if ( mid >= num_segs - 1 && 1222 start == 0xFFFFU && end == 0xFFFFU ) 1223 { 1224 TT_Face face = (TT_Face)cmap->cmap.charmap.face; 1225 FT_Byte* limit = face->cmap_table + face->cmap_size; 1226 1227 1228 if ( offset && p + offset + 2 > limit ) 1229 { 1230 delta = 1; 1231 offset = 0; 1232 } 1233 } 1234 1235 /* search the first segment containing `charcode' */ 1236 if ( cmap->flags & TT_CMAP_FLAG_OVERLAPPING ) 1237 { 1238 FT_UInt i; 1239 1240 1241 /* call the current segment `max' */ 1242 max = mid; 1243 1244 if ( offset == 0xFFFFU ) 1245 mid = max + 1; 1246 1247 /* search in segments before the current segment */ 1248 for ( i = max; i > 0; i-- ) 1249 { 1250 FT_UInt prev_end; 1251 FT_Byte* old_p; 1252 1253 1254 old_p = p; 1255 p = cmap->data + 14 + ( i - 1 ) * 2; 1256 prev_end = TT_PEEK_USHORT( p ); 1257 1258 if ( charcode > prev_end ) 1259 { 1260 p = old_p; 1261 break; 1262 } 1263 1264 end = prev_end; 1265 p += 2 + num_segs2; 1266 start = TT_PEEK_USHORT( p ); 1267 p += num_segs2; 1268 delta = TT_PEEK_SHORT( p ); 1269 p += num_segs2; 1270 offset = TT_PEEK_USHORT( p ); 1271 1272 if ( offset != 0xFFFFU ) 1273 mid = i - 1; 1274 } 1275 1276 /* no luck */ 1277 if ( mid == max + 1 ) 1278 { 1279 if ( i != max ) 1280 { 1281 p = cmap->data + 14 + max * 2; 1282 end = TT_PEEK_USHORT( p ); 1283 p += 2 + num_segs2; 1284 start = TT_PEEK_USHORT( p ); 1285 p += num_segs2; 1286 delta = TT_PEEK_SHORT( p ); 1287 p += num_segs2; 1288 offset = TT_PEEK_USHORT( p ); 1289 } 1290 1291 mid = max; 1292 1293 /* search in segments after the current segment */ 1294 for ( i = max + 1; i < num_segs; i++ ) 1295 { 1296 FT_UInt next_end, next_start; 1297 1298 1299 p = cmap->data + 14 + i * 2; 1300 next_end = TT_PEEK_USHORT( p ); 1301 p += 2 + num_segs2; 1302 next_start = TT_PEEK_USHORT( p ); 1303 1304 if ( charcode < next_start ) 1305 break; 1306 1307 end = next_end; 1308 start = next_start; 1309 p += num_segs2; 1310 delta = TT_PEEK_SHORT( p ); 1311 p += num_segs2; 1312 offset = TT_PEEK_USHORT( p ); 1313 1314 if ( offset != 0xFFFFU ) 1315 mid = i; 1316 } 1317 i--; 1318 1319 /* still no luck */ 1320 if ( mid == max ) 1321 { 1322 mid = i; 1323 1324 break; 1325 } 1326 } 1327 1328 /* end, start, delta, and offset are for the i'th segment */ 1329 if ( mid != i ) 1330 { 1331 p = cmap->data + 14 + mid * 2; 1332 end = TT_PEEK_USHORT( p ); 1333 p += 2 + num_segs2; 1334 start = TT_PEEK_USHORT( p ); 1335 p += num_segs2; 1336 delta = TT_PEEK_SHORT( p ); 1337 p += num_segs2; 1338 offset = TT_PEEK_USHORT( p ); 1339 } 1340 } 1341 else 1342 { 1343 if ( offset == 0xFFFFU ) 1344 break; 1345 } 1346 1347 if ( offset ) 1348 { 1349 p += offset + ( charcode - start ) * 2; 1350 gindex = TT_PEEK_USHORT( p ); 1351 if ( gindex != 0 ) 1352 gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU; 1353 } 1354 else 1355 gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU; 1356 1357 break; 1358 } 1359 } 1360 1361 if ( next ) 1362 { 1363 TT_CMap4 cmap4 = (TT_CMap4)cmap; 1364 1365 1366 /* if `charcode' is not in any segment, then `mid' is */ 1367 /* the segment nearest to `charcode' */ 1368 1369 if ( charcode > end ) 1370 { 1371 mid++; 1372 if ( mid == num_segs ) 1373 return 0; 1374 } 1375 1376 if ( tt_cmap4_set_range( cmap4, mid ) ) 1377 { 1378 if ( gindex ) 1379 *pcharcode = charcode; 1380 } 1381 else 1382 { 1383 cmap4->cur_charcode = charcode; 1384 1385 if ( gindex ) 1386 cmap4->cur_gindex = gindex; 1387 else 1388 { 1389 cmap4->cur_charcode = charcode; 1390 tt_cmap4_next( cmap4 ); 1391 gindex = cmap4->cur_gindex; 1392 } 1393 1394 if ( gindex ) 1395 *pcharcode = cmap4->cur_charcode; 1396 } 1397 } 1398 1399 return gindex; 1400 } 1401 1402 1403 FT_CALLBACK_DEF( FT_UInt ) tt_cmap4_char_index(TT_CMap cmap,FT_UInt32 char_code)1404 tt_cmap4_char_index( TT_CMap cmap, 1405 FT_UInt32 char_code ) 1406 { 1407 if ( char_code >= 0x10000UL ) 1408 return 0; 1409 1410 if ( cmap->flags & TT_CMAP_FLAG_UNSORTED ) 1411 return tt_cmap4_char_map_linear( cmap, &char_code, 0 ); 1412 else 1413 return tt_cmap4_char_map_binary( cmap, &char_code, 0 ); 1414 } 1415 1416 1417 FT_CALLBACK_DEF( FT_UInt32 ) tt_cmap4_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)1418 tt_cmap4_char_next( TT_CMap cmap, 1419 FT_UInt32 *pchar_code ) 1420 { 1421 FT_UInt gindex; 1422 1423 1424 if ( *pchar_code >= 0xFFFFU ) 1425 return 0; 1426 1427 if ( cmap->flags & TT_CMAP_FLAG_UNSORTED ) 1428 gindex = tt_cmap4_char_map_linear( cmap, pchar_code, 1 ); 1429 else 1430 { 1431 TT_CMap4 cmap4 = (TT_CMap4)cmap; 1432 1433 1434 /* no need to search */ 1435 if ( *pchar_code == cmap4->cur_charcode ) 1436 { 1437 tt_cmap4_next( cmap4 ); 1438 gindex = cmap4->cur_gindex; 1439 if ( gindex ) 1440 *pchar_code = cmap4->cur_charcode; 1441 } 1442 else 1443 gindex = tt_cmap4_char_map_binary( cmap, pchar_code, 1 ); 1444 } 1445 1446 return gindex; 1447 } 1448 1449 1450 FT_CALLBACK_DEF( FT_Error ) tt_cmap4_get_info(TT_CMap cmap,TT_CMapInfo * cmap_info)1451 tt_cmap4_get_info( TT_CMap cmap, 1452 TT_CMapInfo *cmap_info ) 1453 { 1454 FT_Byte* p = cmap->data + 4; 1455 1456 1457 cmap_info->format = 4; 1458 cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); 1459 1460 return FT_Err_Ok; 1461 } 1462 1463 1464 FT_DEFINE_TT_CMAP( 1465 tt_cmap4_class_rec, 1466 sizeof ( TT_CMap4Rec ), 1467 (FT_CMap_InitFunc) tt_cmap4_init, 1468 (FT_CMap_DoneFunc) NULL, 1469 (FT_CMap_CharIndexFunc)tt_cmap4_char_index, 1470 (FT_CMap_CharNextFunc) tt_cmap4_char_next, 1471 1472 NULL, 1473 NULL, 1474 NULL, 1475 NULL, 1476 NULL, 1477 1478 4, 1479 (TT_CMap_ValidateFunc)tt_cmap4_validate, 1480 (TT_CMap_Info_GetFunc)tt_cmap4_get_info ) 1481 1482 #endif /* TT_CONFIG_CMAP_FORMAT_4 */ 1483 1484 1485 /*************************************************************************/ 1486 /*************************************************************************/ 1487 /***** *****/ 1488 /***** FORMAT 6 *****/ 1489 /***** *****/ 1490 /*************************************************************************/ 1491 /*************************************************************************/ 1492 1493 /*************************************************************************/ 1494 /* */ 1495 /* TABLE OVERVIEW */ 1496 /* -------------- */ 1497 /* */ 1498 /* NAME OFFSET TYPE DESCRIPTION */ 1499 /* */ 1500 /* format 0 USHORT must be 6 */ 1501 /* length 2 USHORT table length in bytes */ 1502 /* language 4 USHORT Mac language code */ 1503 /* */ 1504 /* first 6 USHORT first segment code */ 1505 /* count 8 USHORT segment size in chars */ 1506 /* glyphIds 10 USHORT[count] glyph IDs */ 1507 /* */ 1508 /* A very simplified segment mapping. */ 1509 /* */ 1510 1511 #ifdef TT_CONFIG_CMAP_FORMAT_6 1512 FT_CALLBACK_DEF(FT_Error)1513 FT_CALLBACK_DEF( FT_Error ) 1514 tt_cmap6_validate( FT_Byte* table, 1515 FT_Validator valid ) 1516 { 1517 FT_Byte* p; 1518 FT_UInt length, count; 1519 1520 1521 if ( table + 10 > valid->limit ) 1522 FT_INVALID_TOO_SHORT; 1523 1524 p = table + 2; 1525 length = TT_NEXT_USHORT( p ); 1526 1527 p = table + 8; /* skip language and start index */ 1528 count = TT_NEXT_USHORT( p ); 1529 1530 if ( table + length > valid->limit || length < 10 + count * 2 ) 1531 FT_INVALID_TOO_SHORT; 1532 1533 /* check glyph indices */ 1534 if ( valid->level >= FT_VALIDATE_TIGHT ) 1535 { 1536 FT_UInt gindex; 1537 1538 1539 for ( ; count > 0; count-- ) 1540 { 1541 gindex = TT_NEXT_USHORT( p ); 1542 if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) ) 1543 FT_INVALID_GLYPH_ID; 1544 } 1545 } 1546 1547 return FT_Err_Ok; 1548 } 1549 1550 1551 FT_CALLBACK_DEF( FT_UInt ) tt_cmap6_char_index(TT_CMap cmap,FT_UInt32 char_code)1552 tt_cmap6_char_index( TT_CMap cmap, 1553 FT_UInt32 char_code ) 1554 { 1555 FT_Byte* table = cmap->data; 1556 FT_UInt result = 0; 1557 FT_Byte* p = table + 6; 1558 FT_UInt start = TT_NEXT_USHORT( p ); 1559 FT_UInt count = TT_NEXT_USHORT( p ); 1560 FT_UInt idx = (FT_UInt)( char_code - start ); 1561 1562 1563 if ( idx < count ) 1564 { 1565 p += 2 * idx; 1566 result = TT_PEEK_USHORT( p ); 1567 } 1568 1569 return result; 1570 } 1571 1572 1573 FT_CALLBACK_DEF( FT_UInt32 ) tt_cmap6_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)1574 tt_cmap6_char_next( TT_CMap cmap, 1575 FT_UInt32 *pchar_code ) 1576 { 1577 FT_Byte* table = cmap->data; 1578 FT_UInt32 result = 0; 1579 FT_UInt32 char_code = *pchar_code + 1; 1580 FT_UInt gindex = 0; 1581 1582 FT_Byte* p = table + 6; 1583 FT_UInt start = TT_NEXT_USHORT( p ); 1584 FT_UInt count = TT_NEXT_USHORT( p ); 1585 FT_UInt idx; 1586 1587 1588 if ( char_code >= 0x10000UL ) 1589 return 0; 1590 1591 if ( char_code < start ) 1592 char_code = start; 1593 1594 idx = (FT_UInt)( char_code - start ); 1595 p += 2 * idx; 1596 1597 for ( ; idx < count; idx++ ) 1598 { 1599 gindex = TT_NEXT_USHORT( p ); 1600 if ( gindex != 0 ) 1601 { 1602 result = char_code; 1603 break; 1604 } 1605 1606 if ( char_code >= 0xFFFFU ) 1607 return 0; 1608 1609 char_code++; 1610 } 1611 1612 *pchar_code = result; 1613 return gindex; 1614 } 1615 1616 1617 FT_CALLBACK_DEF( FT_Error ) tt_cmap6_get_info(TT_CMap cmap,TT_CMapInfo * cmap_info)1618 tt_cmap6_get_info( TT_CMap cmap, 1619 TT_CMapInfo *cmap_info ) 1620 { 1621 FT_Byte* p = cmap->data + 4; 1622 1623 1624 cmap_info->format = 6; 1625 cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); 1626 1627 return FT_Err_Ok; 1628 } 1629 1630 1631 FT_DEFINE_TT_CMAP( 1632 tt_cmap6_class_rec, 1633 sizeof ( TT_CMapRec ), 1634 1635 (FT_CMap_InitFunc) tt_cmap_init, 1636 (FT_CMap_DoneFunc) NULL, 1637 (FT_CMap_CharIndexFunc)tt_cmap6_char_index, 1638 (FT_CMap_CharNextFunc) tt_cmap6_char_next, 1639 1640 NULL, 1641 NULL, 1642 NULL, 1643 NULL, 1644 NULL, 1645 1646 6, 1647 (TT_CMap_ValidateFunc)tt_cmap6_validate, 1648 (TT_CMap_Info_GetFunc)tt_cmap6_get_info ) 1649 1650 #endif /* TT_CONFIG_CMAP_FORMAT_6 */ 1651 1652 1653 /*************************************************************************/ 1654 /*************************************************************************/ 1655 /***** *****/ 1656 /***** FORMAT 8 *****/ 1657 /***** *****/ 1658 /***** It is hard to completely understand what the OpenType spec *****/ 1659 /***** says about this format, but here is my conclusion. *****/ 1660 /***** *****/ 1661 /***** The purpose of this format is to easily map UTF-16 text to *****/ 1662 /***** glyph indices. Basically, the `char_code' must be in one of *****/ 1663 /***** the following formats. *****/ 1664 /***** *****/ 1665 /***** - A 16-bit value that isn't part of the Unicode Surrogates *****/ 1666 /***** Area (i.e. U+D800-U+DFFF). *****/ 1667 /***** *****/ 1668 /***** - A 32-bit value, made of two surrogate values, i.e.. if *****/ 1669 /***** `char_code = (char_hi << 16) | char_lo', then both *****/ 1670 /***** `char_hi' and `char_lo' must be in the Surrogates Area. *****/ 1671 /***** Area. *****/ 1672 /***** *****/ 1673 /***** The `is32' table embedded in the charmap indicates whether a *****/ 1674 /***** given 16-bit value is in the surrogates area or not. *****/ 1675 /***** *****/ 1676 /***** So, for any given `char_code', we can assert the following. *****/ 1677 /***** *****/ 1678 /***** If `char_hi == 0' then we must have `is32[char_lo] == 0'. *****/ 1679 /***** *****/ 1680 /***** If `char_hi != 0' then we must have both *****/ 1681 /***** `is32[char_hi] != 0' and `is32[char_lo] != 0'. *****/ 1682 /***** *****/ 1683 /*************************************************************************/ 1684 /*************************************************************************/ 1685 1686 /*************************************************************************/ 1687 /* */ 1688 /* TABLE OVERVIEW */ 1689 /* -------------- */ 1690 /* */ 1691 /* NAME OFFSET TYPE DESCRIPTION */ 1692 /* */ 1693 /* format 0 USHORT must be 8 */ 1694 /* reserved 2 USHORT reserved */ 1695 /* length 4 ULONG length in bytes */ 1696 /* language 8 ULONG Mac language code */ 1697 /* is32 12 BYTE[8192] 32-bitness bitmap */ 1698 /* count 8204 ULONG number of groups */ 1699 /* */ 1700 /* This header is followed by `count' groups of the following format: */ 1701 /* */ 1702 /* start 0 ULONG first charcode */ 1703 /* end 4 ULONG last charcode */ 1704 /* startId 8 ULONG start glyph ID for the group */ 1705 /* */ 1706 1707 #ifdef TT_CONFIG_CMAP_FORMAT_8 1708 FT_CALLBACK_DEF(FT_Error)1709 FT_CALLBACK_DEF( FT_Error ) 1710 tt_cmap8_validate( FT_Byte* table, 1711 FT_Validator valid ) 1712 { 1713 FT_Byte* p = table + 4; 1714 FT_Byte* is32; 1715 FT_UInt32 length; 1716 FT_UInt32 num_groups; 1717 1718 1719 if ( table + 16 + 8192 > valid->limit ) 1720 FT_INVALID_TOO_SHORT; 1721 1722 length = TT_NEXT_ULONG( p ); 1723 if ( length > (FT_UInt32)( valid->limit - table ) || length < 8192 + 16 ) 1724 FT_INVALID_TOO_SHORT; 1725 1726 is32 = table + 12; 1727 p = is32 + 8192; /* skip `is32' array */ 1728 num_groups = TT_NEXT_ULONG( p ); 1729 1730 /* p + num_groups * 12 > valid->limit ? */ 1731 if ( num_groups > (FT_UInt32)( valid->limit - p ) / 12 ) 1732 FT_INVALID_TOO_SHORT; 1733 1734 /* check groups, they must be in increasing order */ 1735 { 1736 FT_UInt32 n, start, end, start_id, count, last = 0; 1737 1738 1739 for ( n = 0; n < num_groups; n++ ) 1740 { 1741 FT_UInt hi, lo; 1742 1743 1744 start = TT_NEXT_ULONG( p ); 1745 end = TT_NEXT_ULONG( p ); 1746 start_id = TT_NEXT_ULONG( p ); 1747 1748 if ( start > end ) 1749 FT_INVALID_DATA; 1750 1751 if ( n > 0 && start <= last ) 1752 FT_INVALID_DATA; 1753 1754 if ( valid->level >= FT_VALIDATE_TIGHT ) 1755 { 1756 FT_UInt32 d = end - start; 1757 1758 1759 /* start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ? */ 1760 if ( d > TT_VALID_GLYPH_COUNT( valid ) || 1761 start_id >= TT_VALID_GLYPH_COUNT( valid ) - d ) 1762 FT_INVALID_GLYPH_ID; 1763 1764 count = (FT_UInt32)( end - start + 1 ); 1765 1766 if ( start & ~0xFFFFU ) 1767 { 1768 /* start_hi != 0; check that is32[i] is 1 for each i in */ 1769 /* the `hi' and `lo' of the range [start..end] */ 1770 for ( ; count > 0; count--, start++ ) 1771 { 1772 hi = (FT_UInt)( start >> 16 ); 1773 lo = (FT_UInt)( start & 0xFFFFU ); 1774 1775 if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 ) 1776 FT_INVALID_DATA; 1777 1778 if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 ) 1779 FT_INVALID_DATA; 1780 } 1781 } 1782 else 1783 { 1784 /* start_hi == 0; check that is32[i] is 0 for each i in */ 1785 /* the range [start..end] */ 1786 1787 /* end_hi cannot be != 0! */ 1788 if ( end & ~0xFFFFU ) 1789 FT_INVALID_DATA; 1790 1791 for ( ; count > 0; count--, start++ ) 1792 { 1793 lo = (FT_UInt)( start & 0xFFFFU ); 1794 1795 if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 ) 1796 FT_INVALID_DATA; 1797 } 1798 } 1799 } 1800 1801 last = end; 1802 } 1803 } 1804 1805 return FT_Err_Ok; 1806 } 1807 1808 1809 FT_CALLBACK_DEF( FT_UInt ) tt_cmap8_char_index(TT_CMap cmap,FT_UInt32 char_code)1810 tt_cmap8_char_index( TT_CMap cmap, 1811 FT_UInt32 char_code ) 1812 { 1813 FT_Byte* table = cmap->data; 1814 FT_UInt result = 0; 1815 FT_Byte* p = table + 8204; 1816 FT_UInt32 num_groups = TT_NEXT_ULONG( p ); 1817 FT_UInt32 start, end, start_id; 1818 1819 1820 for ( ; num_groups > 0; num_groups-- ) 1821 { 1822 start = TT_NEXT_ULONG( p ); 1823 end = TT_NEXT_ULONG( p ); 1824 start_id = TT_NEXT_ULONG( p ); 1825 1826 if ( char_code < start ) 1827 break; 1828 1829 if ( char_code <= end ) 1830 { 1831 if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) ) 1832 return 0; 1833 1834 result = (FT_UInt)( start_id + ( char_code - start ) ); 1835 break; 1836 } 1837 } 1838 return result; 1839 } 1840 1841 1842 FT_CALLBACK_DEF( FT_UInt32 ) tt_cmap8_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)1843 tt_cmap8_char_next( TT_CMap cmap, 1844 FT_UInt32 *pchar_code ) 1845 { 1846 FT_Face face = cmap->cmap.charmap.face; 1847 FT_UInt32 result = 0; 1848 FT_UInt32 char_code; 1849 FT_UInt gindex = 0; 1850 FT_Byte* table = cmap->data; 1851 FT_Byte* p = table + 8204; 1852 FT_UInt32 num_groups = TT_NEXT_ULONG( p ); 1853 FT_UInt32 start, end, start_id; 1854 1855 1856 if ( *pchar_code >= 0xFFFFFFFFUL ) 1857 return 0; 1858 1859 char_code = *pchar_code + 1; 1860 1861 p = table + 8208; 1862 1863 for ( ; num_groups > 0; num_groups-- ) 1864 { 1865 start = TT_NEXT_ULONG( p ); 1866 end = TT_NEXT_ULONG( p ); 1867 start_id = TT_NEXT_ULONG( p ); 1868 1869 if ( char_code < start ) 1870 char_code = start; 1871 1872 Again: 1873 if ( char_code <= end ) 1874 { 1875 /* ignore invalid group */ 1876 if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) ) 1877 continue; 1878 1879 gindex = (FT_UInt)( start_id + ( char_code - start ) ); 1880 1881 /* does first element of group point to `.notdef' glyph? */ 1882 if ( gindex == 0 ) 1883 { 1884 if ( char_code >= 0xFFFFFFFFUL ) 1885 break; 1886 1887 char_code++; 1888 goto Again; 1889 } 1890 1891 /* if `gindex' is invalid, the remaining values */ 1892 /* in this group are invalid, too */ 1893 if ( gindex >= (FT_UInt)face->num_glyphs ) 1894 { 1895 gindex = 0; 1896 continue; 1897 } 1898 1899 result = char_code; 1900 break; 1901 } 1902 } 1903 1904 *pchar_code = result; 1905 return gindex; 1906 } 1907 1908 1909 FT_CALLBACK_DEF( FT_Error ) tt_cmap8_get_info(TT_CMap cmap,TT_CMapInfo * cmap_info)1910 tt_cmap8_get_info( TT_CMap cmap, 1911 TT_CMapInfo *cmap_info ) 1912 { 1913 FT_Byte* p = cmap->data + 8; 1914 1915 1916 cmap_info->format = 8; 1917 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); 1918 1919 return FT_Err_Ok; 1920 } 1921 1922 1923 FT_DEFINE_TT_CMAP( 1924 tt_cmap8_class_rec, 1925 sizeof ( TT_CMapRec ), 1926 1927 (FT_CMap_InitFunc) tt_cmap_init, 1928 (FT_CMap_DoneFunc) NULL, 1929 (FT_CMap_CharIndexFunc)tt_cmap8_char_index, 1930 (FT_CMap_CharNextFunc) tt_cmap8_char_next, 1931 1932 NULL, 1933 NULL, 1934 NULL, 1935 NULL, 1936 NULL, 1937 1938 8, 1939 (TT_CMap_ValidateFunc)tt_cmap8_validate, 1940 (TT_CMap_Info_GetFunc)tt_cmap8_get_info ) 1941 1942 #endif /* TT_CONFIG_CMAP_FORMAT_8 */ 1943 1944 1945 /*************************************************************************/ 1946 /*************************************************************************/ 1947 /***** *****/ 1948 /***** FORMAT 10 *****/ 1949 /***** *****/ 1950 /*************************************************************************/ 1951 /*************************************************************************/ 1952 1953 /*************************************************************************/ 1954 /* */ 1955 /* TABLE OVERVIEW */ 1956 /* -------------- */ 1957 /* */ 1958 /* NAME OFFSET TYPE DESCRIPTION */ 1959 /* */ 1960 /* format 0 USHORT must be 10 */ 1961 /* reserved 2 USHORT reserved */ 1962 /* length 4 ULONG length in bytes */ 1963 /* language 8 ULONG Mac language code */ 1964 /* */ 1965 /* start 12 ULONG first char in range */ 1966 /* count 16 ULONG number of chars in range */ 1967 /* glyphIds 20 USHORT[count] glyph indices covered */ 1968 /* */ 1969 1970 #ifdef TT_CONFIG_CMAP_FORMAT_10 1971 FT_CALLBACK_DEF(FT_Error)1972 FT_CALLBACK_DEF( FT_Error ) 1973 tt_cmap10_validate( FT_Byte* table, 1974 FT_Validator valid ) 1975 { 1976 FT_Byte* p = table + 4; 1977 FT_ULong length, count; 1978 1979 1980 if ( table + 20 > valid->limit ) 1981 FT_INVALID_TOO_SHORT; 1982 1983 length = TT_NEXT_ULONG( p ); 1984 p = table + 16; 1985 count = TT_NEXT_ULONG( p ); 1986 1987 if ( length > (FT_ULong)( valid->limit - table ) || 1988 /* length < 20 + count * 2 ? */ 1989 length < 20 || 1990 ( length - 20 ) / 2 < count ) 1991 FT_INVALID_TOO_SHORT; 1992 1993 /* check glyph indices */ 1994 if ( valid->level >= FT_VALIDATE_TIGHT ) 1995 { 1996 FT_UInt gindex; 1997 1998 1999 for ( ; count > 0; count-- ) 2000 { 2001 gindex = TT_NEXT_USHORT( p ); 2002 if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) ) 2003 FT_INVALID_GLYPH_ID; 2004 } 2005 } 2006 2007 return FT_Err_Ok; 2008 } 2009 2010 2011 FT_CALLBACK_DEF( FT_UInt ) tt_cmap10_char_index(TT_CMap cmap,FT_UInt32 char_code)2012 tt_cmap10_char_index( TT_CMap cmap, 2013 FT_UInt32 char_code ) 2014 { 2015 FT_Byte* table = cmap->data; 2016 FT_UInt result = 0; 2017 FT_Byte* p = table + 12; 2018 FT_UInt32 start = TT_NEXT_ULONG( p ); 2019 FT_UInt32 count = TT_NEXT_ULONG( p ); 2020 FT_UInt32 idx; 2021 2022 2023 if ( char_code < start ) 2024 return 0; 2025 2026 idx = char_code - start; 2027 2028 if ( idx < count ) 2029 { 2030 p += 2 * idx; 2031 result = TT_PEEK_USHORT( p ); 2032 } 2033 2034 return result; 2035 } 2036 2037 2038 FT_CALLBACK_DEF( FT_UInt32 ) tt_cmap10_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)2039 tt_cmap10_char_next( TT_CMap cmap, 2040 FT_UInt32 *pchar_code ) 2041 { 2042 FT_Byte* table = cmap->data; 2043 FT_UInt32 char_code; 2044 FT_UInt gindex = 0; 2045 FT_Byte* p = table + 12; 2046 FT_UInt32 start = TT_NEXT_ULONG( p ); 2047 FT_UInt32 count = TT_NEXT_ULONG( p ); 2048 FT_UInt32 idx; 2049 2050 2051 if ( *pchar_code >= 0xFFFFFFFFUL ) 2052 return 0; 2053 2054 char_code = *pchar_code + 1; 2055 2056 if ( char_code < start ) 2057 char_code = start; 2058 2059 idx = char_code - start; 2060 p += 2 * idx; 2061 2062 for ( ; idx < count; idx++ ) 2063 { 2064 gindex = TT_NEXT_USHORT( p ); 2065 if ( gindex != 0 ) 2066 break; 2067 2068 if ( char_code >= 0xFFFFFFFFUL ) 2069 return 0; 2070 2071 char_code++; 2072 } 2073 2074 *pchar_code = char_code; 2075 return gindex; 2076 } 2077 2078 2079 FT_CALLBACK_DEF( FT_Error ) tt_cmap10_get_info(TT_CMap cmap,TT_CMapInfo * cmap_info)2080 tt_cmap10_get_info( TT_CMap cmap, 2081 TT_CMapInfo *cmap_info ) 2082 { 2083 FT_Byte* p = cmap->data + 8; 2084 2085 2086 cmap_info->format = 10; 2087 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); 2088 2089 return FT_Err_Ok; 2090 } 2091 2092 2093 FT_DEFINE_TT_CMAP( 2094 tt_cmap10_class_rec, 2095 sizeof ( TT_CMapRec ), 2096 2097 (FT_CMap_InitFunc) tt_cmap_init, 2098 (FT_CMap_DoneFunc) NULL, 2099 (FT_CMap_CharIndexFunc)tt_cmap10_char_index, 2100 (FT_CMap_CharNextFunc) tt_cmap10_char_next, 2101 2102 NULL, 2103 NULL, 2104 NULL, 2105 NULL, 2106 NULL, 2107 2108 10, 2109 (TT_CMap_ValidateFunc)tt_cmap10_validate, 2110 (TT_CMap_Info_GetFunc)tt_cmap10_get_info ) 2111 2112 #endif /* TT_CONFIG_CMAP_FORMAT_10 */ 2113 2114 2115 /*************************************************************************/ 2116 /*************************************************************************/ 2117 /***** *****/ 2118 /***** FORMAT 12 *****/ 2119 /***** *****/ 2120 /*************************************************************************/ 2121 /*************************************************************************/ 2122 2123 /*************************************************************************/ 2124 /* */ 2125 /* TABLE OVERVIEW */ 2126 /* -------------- */ 2127 /* */ 2128 /* NAME OFFSET TYPE DESCRIPTION */ 2129 /* */ 2130 /* format 0 USHORT must be 12 */ 2131 /* reserved 2 USHORT reserved */ 2132 /* length 4 ULONG length in bytes */ 2133 /* language 8 ULONG Mac language code */ 2134 /* count 12 ULONG number of groups */ 2135 /* 16 */ 2136 /* */ 2137 /* This header is followed by `count' groups of the following format: */ 2138 /* */ 2139 /* start 0 ULONG first charcode */ 2140 /* end 4 ULONG last charcode */ 2141 /* startId 8 ULONG start glyph ID for the group */ 2142 /* */ 2143 2144 #ifdef TT_CONFIG_CMAP_FORMAT_12 2145 2146 typedef struct TT_CMap12Rec_ 2147 { 2148 TT_CMapRec cmap; 2149 FT_Bool valid; 2150 FT_ULong cur_charcode; 2151 FT_UInt cur_gindex; 2152 FT_ULong cur_group; 2153 FT_ULong num_groups; 2154 2155 } TT_CMap12Rec, *TT_CMap12; 2156 2157 2158 FT_CALLBACK_DEF( FT_Error ) tt_cmap12_init(TT_CMap12 cmap,FT_Byte * table)2159 tt_cmap12_init( TT_CMap12 cmap, 2160 FT_Byte* table ) 2161 { 2162 cmap->cmap.data = table; 2163 2164 table += 12; 2165 cmap->num_groups = FT_PEEK_ULONG( table ); 2166 2167 cmap->valid = 0; 2168 2169 return FT_Err_Ok; 2170 } 2171 2172 2173 FT_CALLBACK_DEF( FT_Error ) tt_cmap12_validate(FT_Byte * table,FT_Validator valid)2174 tt_cmap12_validate( FT_Byte* table, 2175 FT_Validator valid ) 2176 { 2177 FT_Byte* p; 2178 FT_ULong length; 2179 FT_ULong num_groups; 2180 2181 2182 if ( table + 16 > valid->limit ) 2183 FT_INVALID_TOO_SHORT; 2184 2185 p = table + 4; 2186 length = TT_NEXT_ULONG( p ); 2187 2188 p = table + 12; 2189 num_groups = TT_NEXT_ULONG( p ); 2190 2191 if ( length > (FT_ULong)( valid->limit - table ) || 2192 /* length < 16 + 12 * num_groups ? */ 2193 length < 16 || 2194 ( length - 16 ) / 12 < num_groups ) 2195 FT_INVALID_TOO_SHORT; 2196 2197 /* check groups, they must be in increasing order */ 2198 { 2199 FT_ULong n, start, end, start_id, last = 0; 2200 2201 2202 for ( n = 0; n < num_groups; n++ ) 2203 { 2204 start = TT_NEXT_ULONG( p ); 2205 end = TT_NEXT_ULONG( p ); 2206 start_id = TT_NEXT_ULONG( p ); 2207 2208 if ( start > end ) 2209 FT_INVALID_DATA; 2210 2211 if ( n > 0 && start <= last ) 2212 FT_INVALID_DATA; 2213 2214 if ( valid->level >= FT_VALIDATE_TIGHT ) 2215 { 2216 FT_UInt32 d = end - start; 2217 2218 2219 /* start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ? */ 2220 if ( d > TT_VALID_GLYPH_COUNT( valid ) || 2221 start_id >= TT_VALID_GLYPH_COUNT( valid ) - d ) 2222 FT_INVALID_GLYPH_ID; 2223 } 2224 2225 last = end; 2226 } 2227 } 2228 2229 return FT_Err_Ok; 2230 } 2231 2232 2233 /* search the index of the charcode next to cmap->cur_charcode */ 2234 /* cmap->cur_group should be set up properly by caller */ 2235 /* */ 2236 static void tt_cmap12_next(TT_CMap12 cmap)2237 tt_cmap12_next( TT_CMap12 cmap ) 2238 { 2239 FT_Face face = cmap->cmap.cmap.charmap.face; 2240 FT_Byte* p; 2241 FT_ULong start, end, start_id, char_code; 2242 FT_ULong n; 2243 FT_UInt gindex; 2244 2245 2246 if ( cmap->cur_charcode >= 0xFFFFFFFFUL ) 2247 goto Fail; 2248 2249 char_code = cmap->cur_charcode + 1; 2250 2251 for ( n = cmap->cur_group; n < cmap->num_groups; n++ ) 2252 { 2253 p = cmap->cmap.data + 16 + 12 * n; 2254 start = TT_NEXT_ULONG( p ); 2255 end = TT_NEXT_ULONG( p ); 2256 start_id = TT_PEEK_ULONG( p ); 2257 2258 if ( char_code < start ) 2259 char_code = start; 2260 2261 Again: 2262 if ( char_code <= end ) 2263 { 2264 /* ignore invalid group */ 2265 if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) ) 2266 continue; 2267 2268 gindex = (FT_UInt)( start_id + ( char_code - start ) ); 2269 2270 /* does first element of group point to `.notdef' glyph? */ 2271 if ( gindex == 0 ) 2272 { 2273 if ( char_code >= 0xFFFFFFFFUL ) 2274 goto Fail; 2275 2276 char_code++; 2277 goto Again; 2278 } 2279 2280 /* if `gindex' is invalid, the remaining values */ 2281 /* in this group are invalid, too */ 2282 if ( gindex >= (FT_UInt)face->num_glyphs ) 2283 { 2284 gindex = 0; 2285 continue; 2286 } 2287 2288 cmap->cur_charcode = char_code; 2289 cmap->cur_gindex = gindex; 2290 cmap->cur_group = n; 2291 2292 return; 2293 } 2294 } 2295 2296 Fail: 2297 cmap->valid = 0; 2298 } 2299 2300 2301 static FT_UInt tt_cmap12_char_map_binary(TT_CMap cmap,FT_UInt32 * pchar_code,FT_Bool next)2302 tt_cmap12_char_map_binary( TT_CMap cmap, 2303 FT_UInt32* pchar_code, 2304 FT_Bool next ) 2305 { 2306 FT_UInt gindex = 0; 2307 FT_Byte* p = cmap->data + 12; 2308 FT_UInt32 num_groups = TT_PEEK_ULONG( p ); 2309 FT_UInt32 char_code = *pchar_code; 2310 FT_UInt32 start, end, start_id; 2311 FT_UInt32 max, min, mid; 2312 2313 2314 if ( !num_groups ) 2315 return 0; 2316 2317 /* make compiler happy */ 2318 mid = num_groups; 2319 end = 0xFFFFFFFFUL; 2320 2321 if ( next ) 2322 { 2323 if ( char_code >= 0xFFFFFFFFUL ) 2324 return 0; 2325 2326 char_code++; 2327 } 2328 2329 min = 0; 2330 max = num_groups; 2331 2332 /* binary search */ 2333 while ( min < max ) 2334 { 2335 mid = ( min + max ) >> 1; 2336 p = cmap->data + 16 + 12 * mid; 2337 2338 start = TT_NEXT_ULONG( p ); 2339 end = TT_NEXT_ULONG( p ); 2340 2341 if ( char_code < start ) 2342 max = mid; 2343 else if ( char_code > end ) 2344 min = mid + 1; 2345 else 2346 { 2347 start_id = TT_PEEK_ULONG( p ); 2348 2349 /* reject invalid glyph index */ 2350 if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) ) 2351 gindex = 0; 2352 else 2353 gindex = (FT_UInt)( start_id + ( char_code - start ) ); 2354 break; 2355 } 2356 } 2357 2358 if ( next ) 2359 { 2360 FT_Face face = cmap->cmap.charmap.face; 2361 TT_CMap12 cmap12 = (TT_CMap12)cmap; 2362 2363 2364 /* if `char_code' is not in any group, then `mid' is */ 2365 /* the group nearest to `char_code' */ 2366 2367 if ( char_code > end ) 2368 { 2369 mid++; 2370 if ( mid == num_groups ) 2371 return 0; 2372 } 2373 2374 cmap12->valid = 1; 2375 cmap12->cur_charcode = char_code; 2376 cmap12->cur_group = mid; 2377 2378 if ( gindex >= (FT_UInt)face->num_glyphs ) 2379 gindex = 0; 2380 2381 if ( !gindex ) 2382 { 2383 tt_cmap12_next( cmap12 ); 2384 2385 if ( cmap12->valid ) 2386 gindex = cmap12->cur_gindex; 2387 } 2388 else 2389 cmap12->cur_gindex = gindex; 2390 2391 *pchar_code = cmap12->cur_charcode; 2392 } 2393 2394 return gindex; 2395 } 2396 2397 2398 FT_CALLBACK_DEF( FT_UInt ) tt_cmap12_char_index(TT_CMap cmap,FT_UInt32 char_code)2399 tt_cmap12_char_index( TT_CMap cmap, 2400 FT_UInt32 char_code ) 2401 { 2402 return tt_cmap12_char_map_binary( cmap, &char_code, 0 ); 2403 } 2404 2405 2406 FT_CALLBACK_DEF( FT_UInt32 ) tt_cmap12_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)2407 tt_cmap12_char_next( TT_CMap cmap, 2408 FT_UInt32 *pchar_code ) 2409 { 2410 TT_CMap12 cmap12 = (TT_CMap12)cmap; 2411 FT_UInt gindex; 2412 2413 2414 /* no need to search */ 2415 if ( cmap12->valid && cmap12->cur_charcode == *pchar_code ) 2416 { 2417 tt_cmap12_next( cmap12 ); 2418 if ( cmap12->valid ) 2419 { 2420 gindex = cmap12->cur_gindex; 2421 *pchar_code = (FT_UInt32)cmap12->cur_charcode; 2422 } 2423 else 2424 gindex = 0; 2425 } 2426 else 2427 gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 ); 2428 2429 return gindex; 2430 } 2431 2432 2433 FT_CALLBACK_DEF( FT_Error ) tt_cmap12_get_info(TT_CMap cmap,TT_CMapInfo * cmap_info)2434 tt_cmap12_get_info( TT_CMap cmap, 2435 TT_CMapInfo *cmap_info ) 2436 { 2437 FT_Byte* p = cmap->data + 8; 2438 2439 2440 cmap_info->format = 12; 2441 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); 2442 2443 return FT_Err_Ok; 2444 } 2445 2446 2447 FT_DEFINE_TT_CMAP( 2448 tt_cmap12_class_rec, 2449 sizeof ( TT_CMap12Rec ), 2450 2451 (FT_CMap_InitFunc) tt_cmap12_init, 2452 (FT_CMap_DoneFunc) NULL, 2453 (FT_CMap_CharIndexFunc)tt_cmap12_char_index, 2454 (FT_CMap_CharNextFunc) tt_cmap12_char_next, 2455 2456 NULL, 2457 NULL, 2458 NULL, 2459 NULL, 2460 NULL, 2461 2462 12, 2463 (TT_CMap_ValidateFunc)tt_cmap12_validate, 2464 (TT_CMap_Info_GetFunc)tt_cmap12_get_info ) 2465 2466 #endif /* TT_CONFIG_CMAP_FORMAT_12 */ 2467 2468 2469 /*************************************************************************/ 2470 /*************************************************************************/ 2471 /***** *****/ 2472 /***** FORMAT 13 *****/ 2473 /***** *****/ 2474 /*************************************************************************/ 2475 /*************************************************************************/ 2476 2477 /*************************************************************************/ 2478 /* */ 2479 /* TABLE OVERVIEW */ 2480 /* -------------- */ 2481 /* */ 2482 /* NAME OFFSET TYPE DESCRIPTION */ 2483 /* */ 2484 /* format 0 USHORT must be 13 */ 2485 /* reserved 2 USHORT reserved */ 2486 /* length 4 ULONG length in bytes */ 2487 /* language 8 ULONG Mac language code */ 2488 /* count 12 ULONG number of groups */ 2489 /* 16 */ 2490 /* */ 2491 /* This header is followed by `count' groups of the following format: */ 2492 /* */ 2493 /* start 0 ULONG first charcode */ 2494 /* end 4 ULONG last charcode */ 2495 /* glyphId 8 ULONG glyph ID for the whole group */ 2496 /* */ 2497 2498 #ifdef TT_CONFIG_CMAP_FORMAT_13 2499 2500 typedef struct TT_CMap13Rec_ 2501 { 2502 TT_CMapRec cmap; 2503 FT_Bool valid; 2504 FT_ULong cur_charcode; 2505 FT_UInt cur_gindex; 2506 FT_ULong cur_group; 2507 FT_ULong num_groups; 2508 2509 } TT_CMap13Rec, *TT_CMap13; 2510 2511 2512 FT_CALLBACK_DEF( FT_Error ) tt_cmap13_init(TT_CMap13 cmap,FT_Byte * table)2513 tt_cmap13_init( TT_CMap13 cmap, 2514 FT_Byte* table ) 2515 { 2516 cmap->cmap.data = table; 2517 2518 table += 12; 2519 cmap->num_groups = FT_PEEK_ULONG( table ); 2520 2521 cmap->valid = 0; 2522 2523 return FT_Err_Ok; 2524 } 2525 2526 2527 FT_CALLBACK_DEF( FT_Error ) tt_cmap13_validate(FT_Byte * table,FT_Validator valid)2528 tt_cmap13_validate( FT_Byte* table, 2529 FT_Validator valid ) 2530 { 2531 FT_Byte* p; 2532 FT_ULong length; 2533 FT_ULong num_groups; 2534 2535 2536 if ( table + 16 > valid->limit ) 2537 FT_INVALID_TOO_SHORT; 2538 2539 p = table + 4; 2540 length = TT_NEXT_ULONG( p ); 2541 2542 p = table + 12; 2543 num_groups = TT_NEXT_ULONG( p ); 2544 2545 if ( length > (FT_ULong)( valid->limit - table ) || 2546 /* length < 16 + 12 * num_groups ? */ 2547 length < 16 || 2548 ( length - 16 ) / 12 < num_groups ) 2549 FT_INVALID_TOO_SHORT; 2550 2551 /* check groups, they must be in increasing order */ 2552 { 2553 FT_ULong n, start, end, glyph_id, last = 0; 2554 2555 2556 for ( n = 0; n < num_groups; n++ ) 2557 { 2558 start = TT_NEXT_ULONG( p ); 2559 end = TT_NEXT_ULONG( p ); 2560 glyph_id = TT_NEXT_ULONG( p ); 2561 2562 if ( start > end ) 2563 FT_INVALID_DATA; 2564 2565 if ( n > 0 && start <= last ) 2566 FT_INVALID_DATA; 2567 2568 if ( valid->level >= FT_VALIDATE_TIGHT ) 2569 { 2570 if ( glyph_id >= TT_VALID_GLYPH_COUNT( valid ) ) 2571 FT_INVALID_GLYPH_ID; 2572 } 2573 2574 last = end; 2575 } 2576 } 2577 2578 return FT_Err_Ok; 2579 } 2580 2581 2582 /* search the index of the charcode next to cmap->cur_charcode */ 2583 /* cmap->cur_group should be set up properly by caller */ 2584 /* */ 2585 static void tt_cmap13_next(TT_CMap13 cmap)2586 tt_cmap13_next( TT_CMap13 cmap ) 2587 { 2588 FT_Face face = cmap->cmap.cmap.charmap.face; 2589 FT_Byte* p; 2590 FT_ULong start, end, glyph_id, char_code; 2591 FT_ULong n; 2592 FT_UInt gindex; 2593 2594 2595 if ( cmap->cur_charcode >= 0xFFFFFFFFUL ) 2596 goto Fail; 2597 2598 char_code = cmap->cur_charcode + 1; 2599 2600 for ( n = cmap->cur_group; n < cmap->num_groups; n++ ) 2601 { 2602 p = cmap->cmap.data + 16 + 12 * n; 2603 start = TT_NEXT_ULONG( p ); 2604 end = TT_NEXT_ULONG( p ); 2605 glyph_id = TT_PEEK_ULONG( p ); 2606 2607 if ( char_code < start ) 2608 char_code = start; 2609 2610 if ( char_code <= end ) 2611 { 2612 gindex = (FT_UInt)glyph_id; 2613 2614 if ( gindex && gindex < (FT_UInt)face->num_glyphs ) 2615 { 2616 cmap->cur_charcode = char_code; 2617 cmap->cur_gindex = gindex; 2618 cmap->cur_group = n; 2619 2620 return; 2621 } 2622 } 2623 } 2624 2625 Fail: 2626 cmap->valid = 0; 2627 } 2628 2629 2630 static FT_UInt tt_cmap13_char_map_binary(TT_CMap cmap,FT_UInt32 * pchar_code,FT_Bool next)2631 tt_cmap13_char_map_binary( TT_CMap cmap, 2632 FT_UInt32* pchar_code, 2633 FT_Bool next ) 2634 { 2635 FT_UInt gindex = 0; 2636 FT_Byte* p = cmap->data + 12; 2637 FT_UInt32 num_groups = TT_PEEK_ULONG( p ); 2638 FT_UInt32 char_code = *pchar_code; 2639 FT_UInt32 start, end; 2640 FT_UInt32 max, min, mid; 2641 2642 2643 if ( !num_groups ) 2644 return 0; 2645 2646 /* make compiler happy */ 2647 mid = num_groups; 2648 end = 0xFFFFFFFFUL; 2649 2650 if ( next ) 2651 { 2652 if ( char_code >= 0xFFFFFFFFUL ) 2653 return 0; 2654 2655 char_code++; 2656 } 2657 2658 min = 0; 2659 max = num_groups; 2660 2661 /* binary search */ 2662 while ( min < max ) 2663 { 2664 mid = ( min + max ) >> 1; 2665 p = cmap->data + 16 + 12 * mid; 2666 2667 start = TT_NEXT_ULONG( p ); 2668 end = TT_NEXT_ULONG( p ); 2669 2670 if ( char_code < start ) 2671 max = mid; 2672 else if ( char_code > end ) 2673 min = mid + 1; 2674 else 2675 { 2676 gindex = (FT_UInt)TT_PEEK_ULONG( p ); 2677 2678 break; 2679 } 2680 } 2681 2682 if ( next ) 2683 { 2684 FT_Face face = cmap->cmap.charmap.face; 2685 TT_CMap13 cmap13 = (TT_CMap13)cmap; 2686 2687 2688 /* if `char_code' is not in any group, then `mid' is */ 2689 /* the group nearest to `char_code' */ 2690 2691 if ( char_code > end ) 2692 { 2693 mid++; 2694 if ( mid == num_groups ) 2695 return 0; 2696 } 2697 2698 cmap13->valid = 1; 2699 cmap13->cur_charcode = char_code; 2700 cmap13->cur_group = mid; 2701 2702 if ( gindex >= (FT_UInt)face->num_glyphs ) 2703 gindex = 0; 2704 2705 if ( !gindex ) 2706 { 2707 tt_cmap13_next( cmap13 ); 2708 2709 if ( cmap13->valid ) 2710 gindex = cmap13->cur_gindex; 2711 } 2712 else 2713 cmap13->cur_gindex = gindex; 2714 2715 *pchar_code = cmap13->cur_charcode; 2716 } 2717 2718 return gindex; 2719 } 2720 2721 2722 FT_CALLBACK_DEF( FT_UInt ) tt_cmap13_char_index(TT_CMap cmap,FT_UInt32 char_code)2723 tt_cmap13_char_index( TT_CMap cmap, 2724 FT_UInt32 char_code ) 2725 { 2726 return tt_cmap13_char_map_binary( cmap, &char_code, 0 ); 2727 } 2728 2729 2730 FT_CALLBACK_DEF( FT_UInt32 ) tt_cmap13_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)2731 tt_cmap13_char_next( TT_CMap cmap, 2732 FT_UInt32 *pchar_code ) 2733 { 2734 TT_CMap13 cmap13 = (TT_CMap13)cmap; 2735 FT_UInt gindex; 2736 2737 2738 /* no need to search */ 2739 if ( cmap13->valid && cmap13->cur_charcode == *pchar_code ) 2740 { 2741 tt_cmap13_next( cmap13 ); 2742 if ( cmap13->valid ) 2743 { 2744 gindex = cmap13->cur_gindex; 2745 *pchar_code = cmap13->cur_charcode; 2746 } 2747 else 2748 gindex = 0; 2749 } 2750 else 2751 gindex = tt_cmap13_char_map_binary( cmap, pchar_code, 1 ); 2752 2753 return gindex; 2754 } 2755 2756 2757 FT_CALLBACK_DEF( FT_Error ) tt_cmap13_get_info(TT_CMap cmap,TT_CMapInfo * cmap_info)2758 tt_cmap13_get_info( TT_CMap cmap, 2759 TT_CMapInfo *cmap_info ) 2760 { 2761 FT_Byte* p = cmap->data + 8; 2762 2763 2764 cmap_info->format = 13; 2765 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); 2766 2767 return FT_Err_Ok; 2768 } 2769 2770 2771 FT_DEFINE_TT_CMAP( 2772 tt_cmap13_class_rec, 2773 sizeof ( TT_CMap13Rec ), 2774 2775 (FT_CMap_InitFunc) tt_cmap13_init, 2776 (FT_CMap_DoneFunc) NULL, 2777 (FT_CMap_CharIndexFunc)tt_cmap13_char_index, 2778 (FT_CMap_CharNextFunc) tt_cmap13_char_next, 2779 2780 NULL, 2781 NULL, 2782 NULL, 2783 NULL, 2784 NULL, 2785 2786 13, 2787 (TT_CMap_ValidateFunc)tt_cmap13_validate, 2788 (TT_CMap_Info_GetFunc)tt_cmap13_get_info ) 2789 2790 #endif /* TT_CONFIG_CMAP_FORMAT_13 */ 2791 2792 2793 /*************************************************************************/ 2794 /*************************************************************************/ 2795 /***** *****/ 2796 /***** FORMAT 14 *****/ 2797 /***** *****/ 2798 /*************************************************************************/ 2799 /*************************************************************************/ 2800 2801 /*************************************************************************/ 2802 /* */ 2803 /* TABLE OVERVIEW */ 2804 /* -------------- */ 2805 /* */ 2806 /* NAME OFFSET TYPE DESCRIPTION */ 2807 /* */ 2808 /* format 0 USHORT must be 14 */ 2809 /* length 2 ULONG table length in bytes */ 2810 /* numSelector 6 ULONG number of variation sel. records */ 2811 /* */ 2812 /* Followed by numSelector records, each of which looks like */ 2813 /* */ 2814 /* varSelector 0 UINT24 Unicode codepoint of sel. */ 2815 /* defaultOff 3 ULONG offset to a default UVS table */ 2816 /* describing any variants to be found in */ 2817 /* the normal Unicode subtable. */ 2818 /* nonDefOff 7 ULONG offset to a non-default UVS table */ 2819 /* describing any variants not in the */ 2820 /* standard cmap, with GIDs here */ 2821 /* (either offset may be 0 NULL) */ 2822 /* */ 2823 /* Selectors are sorted by code point. */ 2824 /* */ 2825 /* A default Unicode Variation Selector (UVS) subtable is just a list of */ 2826 /* ranges of code points which are to be found in the standard cmap. No */ 2827 /* glyph IDs (GIDs) here. */ 2828 /* */ 2829 /* numRanges 0 ULONG number of ranges following */ 2830 /* */ 2831 /* A range looks like */ 2832 /* */ 2833 /* uniStart 0 UINT24 code point of the first character in */ 2834 /* this range */ 2835 /* additionalCnt 3 UBYTE count of additional characters in this */ 2836 /* range (zero means a range of a single */ 2837 /* character) */ 2838 /* */ 2839 /* Ranges are sorted by `uniStart'. */ 2840 /* */ 2841 /* A non-default Unicode Variation Selector (UVS) subtable is a list of */ 2842 /* mappings from codepoint to GID. */ 2843 /* */ 2844 /* numMappings 0 ULONG number of mappings */ 2845 /* */ 2846 /* A range looks like */ 2847 /* */ 2848 /* uniStart 0 UINT24 code point of the first character in */ 2849 /* this range */ 2850 /* GID 3 USHORT and its GID */ 2851 /* */ 2852 /* Ranges are sorted by `uniStart'. */ 2853 2854 #ifdef TT_CONFIG_CMAP_FORMAT_14 2855 2856 typedef struct TT_CMap14Rec_ 2857 { 2858 TT_CMapRec cmap; 2859 FT_ULong num_selectors; 2860 2861 /* This array is used to store the results of various 2862 * cmap 14 query functions. The data is overwritten 2863 * on each call to these functions. 2864 */ 2865 FT_UInt32 max_results; 2866 FT_UInt32* results; 2867 FT_Memory memory; 2868 2869 } TT_CMap14Rec, *TT_CMap14; 2870 2871 2872 FT_CALLBACK_DEF( void ) tt_cmap14_done(TT_CMap14 cmap)2873 tt_cmap14_done( TT_CMap14 cmap ) 2874 { 2875 FT_Memory memory = cmap->memory; 2876 2877 2878 cmap->max_results = 0; 2879 if ( memory != NULL && cmap->results != NULL ) 2880 FT_FREE( cmap->results ); 2881 } 2882 2883 2884 static FT_Error tt_cmap14_ensure(TT_CMap14 cmap,FT_UInt32 num_results,FT_Memory memory)2885 tt_cmap14_ensure( TT_CMap14 cmap, 2886 FT_UInt32 num_results, 2887 FT_Memory memory ) 2888 { 2889 FT_UInt32 old_max = cmap->max_results; 2890 FT_Error error = FT_Err_Ok; 2891 2892 2893 if ( num_results > cmap->max_results ) 2894 { 2895 cmap->memory = memory; 2896 2897 if ( FT_QRENEW_ARRAY( cmap->results, old_max, num_results ) ) 2898 return error; 2899 2900 cmap->max_results = num_results; 2901 } 2902 2903 return error; 2904 } 2905 2906 2907 FT_CALLBACK_DEF( FT_Error ) tt_cmap14_init(TT_CMap14 cmap,FT_Byte * table)2908 tt_cmap14_init( TT_CMap14 cmap, 2909 FT_Byte* table ) 2910 { 2911 cmap->cmap.data = table; 2912 2913 table += 6; 2914 cmap->num_selectors = FT_PEEK_ULONG( table ); 2915 cmap->max_results = 0; 2916 cmap->results = NULL; 2917 2918 return FT_Err_Ok; 2919 } 2920 2921 2922 FT_CALLBACK_DEF( FT_Error ) tt_cmap14_validate(FT_Byte * table,FT_Validator valid)2923 tt_cmap14_validate( FT_Byte* table, 2924 FT_Validator valid ) 2925 { 2926 FT_Byte* p; 2927 FT_ULong length; 2928 FT_ULong num_selectors; 2929 2930 2931 if ( table + 2 + 4 + 4 > valid->limit ) 2932 FT_INVALID_TOO_SHORT; 2933 2934 p = table + 2; 2935 length = TT_NEXT_ULONG( p ); 2936 num_selectors = TT_NEXT_ULONG( p ); 2937 2938 if ( length > (FT_ULong)( valid->limit - table ) || 2939 /* length < 10 + 11 * num_selectors ? */ 2940 length < 10 || 2941 ( length - 10 ) / 11 < num_selectors ) 2942 FT_INVALID_TOO_SHORT; 2943 2944 /* check selectors, they must be in increasing order */ 2945 { 2946 /* we start lastVarSel at 1 because a variant selector value of 0 2947 * isn't valid. 2948 */ 2949 FT_ULong n, lastVarSel = 1; 2950 2951 2952 for ( n = 0; n < num_selectors; n++ ) 2953 { 2954 FT_ULong varSel = TT_NEXT_UINT24( p ); 2955 FT_ULong defOff = TT_NEXT_ULONG( p ); 2956 FT_ULong nondefOff = TT_NEXT_ULONG( p ); 2957 2958 2959 if ( defOff >= length || nondefOff >= length ) 2960 FT_INVALID_TOO_SHORT; 2961 2962 if ( varSel < lastVarSel ) 2963 FT_INVALID_DATA; 2964 2965 lastVarSel = varSel + 1; 2966 2967 /* check the default table (these glyphs should be reached */ 2968 /* through the normal Unicode cmap, no GIDs, just check order) */ 2969 if ( defOff != 0 ) 2970 { 2971 FT_Byte* defp = table + defOff; 2972 FT_ULong numRanges; 2973 FT_ULong i; 2974 FT_ULong lastBase = 0; 2975 2976 2977 if ( defp + 4 > valid->limit ) 2978 FT_INVALID_TOO_SHORT; 2979 2980 numRanges = TT_NEXT_ULONG( defp ); 2981 2982 /* defp + numRanges * 4 > valid->limit ? */ 2983 if ( numRanges > (FT_ULong)( valid->limit - defp ) / 4 ) 2984 FT_INVALID_TOO_SHORT; 2985 2986 for ( i = 0; i < numRanges; ++i ) 2987 { 2988 FT_ULong base = TT_NEXT_UINT24( defp ); 2989 FT_ULong cnt = FT_NEXT_BYTE( defp ); 2990 2991 2992 if ( base + cnt >= 0x110000UL ) /* end of Unicode */ 2993 FT_INVALID_DATA; 2994 2995 if ( base < lastBase ) 2996 FT_INVALID_DATA; 2997 2998 lastBase = base + cnt + 1U; 2999 } 3000 } 3001 3002 /* and the non-default table (these glyphs are specified here) */ 3003 if ( nondefOff != 0 ) 3004 { 3005 FT_Byte* ndp = table + nondefOff; 3006 FT_ULong numMappings; 3007 FT_ULong i, lastUni = 0; 3008 3009 3010 if ( ndp + 4 > valid->limit ) 3011 FT_INVALID_TOO_SHORT; 3012 3013 numMappings = TT_NEXT_ULONG( ndp ); 3014 3015 /* numMappings * 5 > (FT_ULong)( valid->limit - ndp ) ? */ 3016 if ( numMappings > ( (FT_ULong)( valid->limit - ndp ) ) / 5 ) 3017 FT_INVALID_TOO_SHORT; 3018 3019 for ( i = 0; i < numMappings; ++i ) 3020 { 3021 FT_ULong uni = TT_NEXT_UINT24( ndp ); 3022 FT_ULong gid = TT_NEXT_USHORT( ndp ); 3023 3024 3025 if ( uni >= 0x110000UL ) /* end of Unicode */ 3026 FT_INVALID_DATA; 3027 3028 if ( uni < lastUni ) 3029 FT_INVALID_DATA; 3030 3031 lastUni = uni + 1U; 3032 3033 if ( valid->level >= FT_VALIDATE_TIGHT && 3034 gid >= TT_VALID_GLYPH_COUNT( valid ) ) 3035 FT_INVALID_GLYPH_ID; 3036 } 3037 } 3038 } 3039 } 3040 3041 return FT_Err_Ok; 3042 } 3043 3044 3045 FT_CALLBACK_DEF( FT_UInt ) tt_cmap14_char_index(TT_CMap cmap,FT_UInt32 char_code)3046 tt_cmap14_char_index( TT_CMap cmap, 3047 FT_UInt32 char_code ) 3048 { 3049 FT_UNUSED( cmap ); 3050 FT_UNUSED( char_code ); 3051 3052 /* This can't happen */ 3053 return 0; 3054 } 3055 3056 3057 FT_CALLBACK_DEF( FT_UInt32 ) tt_cmap14_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)3058 tt_cmap14_char_next( TT_CMap cmap, 3059 FT_UInt32 *pchar_code ) 3060 { 3061 FT_UNUSED( cmap ); 3062 3063 /* This can't happen */ 3064 *pchar_code = 0; 3065 return 0; 3066 } 3067 3068 3069 FT_CALLBACK_DEF( FT_Error ) tt_cmap14_get_info(TT_CMap cmap,TT_CMapInfo * cmap_info)3070 tt_cmap14_get_info( TT_CMap cmap, 3071 TT_CMapInfo *cmap_info ) 3072 { 3073 FT_UNUSED( cmap ); 3074 3075 cmap_info->format = 14; 3076 /* subtable 14 does not define a language field */ 3077 cmap_info->language = 0xFFFFFFFFUL; 3078 3079 return FT_Err_Ok; 3080 } 3081 3082 3083 static FT_UInt tt_cmap14_char_map_def_binary(FT_Byte * base,FT_UInt32 char_code)3084 tt_cmap14_char_map_def_binary( FT_Byte *base, 3085 FT_UInt32 char_code ) 3086 { 3087 FT_UInt32 numRanges = TT_PEEK_ULONG( base ); 3088 FT_UInt32 max, min; 3089 3090 3091 min = 0; 3092 max = numRanges; 3093 3094 base += 4; 3095 3096 /* binary search */ 3097 while ( min < max ) 3098 { 3099 FT_UInt32 mid = ( min + max ) >> 1; 3100 FT_Byte* p = base + 4 * mid; 3101 FT_ULong start = TT_NEXT_UINT24( p ); 3102 FT_UInt cnt = FT_NEXT_BYTE( p ); 3103 3104 3105 if ( char_code < start ) 3106 max = mid; 3107 else if ( char_code > start + cnt ) 3108 min = mid + 1; 3109 else 3110 return TRUE; 3111 } 3112 3113 return FALSE; 3114 } 3115 3116 3117 static FT_UInt tt_cmap14_char_map_nondef_binary(FT_Byte * base,FT_UInt32 char_code)3118 tt_cmap14_char_map_nondef_binary( FT_Byte *base, 3119 FT_UInt32 char_code ) 3120 { 3121 FT_UInt32 numMappings = TT_PEEK_ULONG( base ); 3122 FT_UInt32 max, min; 3123 3124 3125 min = 0; 3126 max = numMappings; 3127 3128 base += 4; 3129 3130 /* binary search */ 3131 while ( min < max ) 3132 { 3133 FT_UInt32 mid = ( min + max ) >> 1; 3134 FT_Byte* p = base + 5 * mid; 3135 FT_UInt32 uni = (FT_UInt32)TT_NEXT_UINT24( p ); 3136 3137 3138 if ( char_code < uni ) 3139 max = mid; 3140 else if ( char_code > uni ) 3141 min = mid + 1; 3142 else 3143 return TT_PEEK_USHORT( p ); 3144 } 3145 3146 return 0; 3147 } 3148 3149 3150 static FT_Byte* tt_cmap14_find_variant(FT_Byte * base,FT_UInt32 variantCode)3151 tt_cmap14_find_variant( FT_Byte *base, 3152 FT_UInt32 variantCode ) 3153 { 3154 FT_UInt32 numVar = TT_PEEK_ULONG( base ); 3155 FT_UInt32 max, min; 3156 3157 3158 min = 0; 3159 max = numVar; 3160 3161 base += 4; 3162 3163 /* binary search */ 3164 while ( min < max ) 3165 { 3166 FT_UInt32 mid = ( min + max ) >> 1; 3167 FT_Byte* p = base + 11 * mid; 3168 FT_ULong varSel = TT_NEXT_UINT24( p ); 3169 3170 3171 if ( variantCode < varSel ) 3172 max = mid; 3173 else if ( variantCode > varSel ) 3174 min = mid + 1; 3175 else 3176 return p; 3177 } 3178 3179 return NULL; 3180 } 3181 3182 3183 FT_CALLBACK_DEF( FT_UInt ) tt_cmap14_char_var_index(TT_CMap cmap,TT_CMap ucmap,FT_UInt32 charcode,FT_UInt32 variantSelector)3184 tt_cmap14_char_var_index( TT_CMap cmap, 3185 TT_CMap ucmap, 3186 FT_UInt32 charcode, 3187 FT_UInt32 variantSelector ) 3188 { 3189 FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector ); 3190 FT_ULong defOff; 3191 FT_ULong nondefOff; 3192 3193 3194 if ( !p ) 3195 return 0; 3196 3197 defOff = TT_NEXT_ULONG( p ); 3198 nondefOff = TT_PEEK_ULONG( p ); 3199 3200 if ( defOff != 0 && 3201 tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) ) 3202 { 3203 /* This is the default variant of this charcode. GID not stored */ 3204 /* here; stored in the normal Unicode charmap instead. */ 3205 return ucmap->cmap.clazz->char_index( &ucmap->cmap, charcode ); 3206 } 3207 3208 if ( nondefOff != 0 ) 3209 return tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, 3210 charcode ); 3211 3212 return 0; 3213 } 3214 3215 3216 FT_CALLBACK_DEF( FT_Int ) tt_cmap14_char_var_isdefault(TT_CMap cmap,FT_UInt32 charcode,FT_UInt32 variantSelector)3217 tt_cmap14_char_var_isdefault( TT_CMap cmap, 3218 FT_UInt32 charcode, 3219 FT_UInt32 variantSelector ) 3220 { 3221 FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector ); 3222 FT_ULong defOff; 3223 FT_ULong nondefOff; 3224 3225 3226 if ( !p ) 3227 return -1; 3228 3229 defOff = TT_NEXT_ULONG( p ); 3230 nondefOff = TT_NEXT_ULONG( p ); 3231 3232 if ( defOff != 0 && 3233 tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) ) 3234 return 1; 3235 3236 if ( nondefOff != 0 && 3237 tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, 3238 charcode ) != 0 ) 3239 return 0; 3240 3241 return -1; 3242 } 3243 3244 3245 FT_CALLBACK_DEF( FT_UInt32* ) tt_cmap14_variants(TT_CMap cmap,FT_Memory memory)3246 tt_cmap14_variants( TT_CMap cmap, 3247 FT_Memory memory ) 3248 { 3249 TT_CMap14 cmap14 = (TT_CMap14)cmap; 3250 FT_UInt32 count = cmap14->num_selectors; 3251 FT_Byte* p = cmap->data + 10; 3252 FT_UInt32* result; 3253 FT_UInt32 i; 3254 3255 3256 if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) ) 3257 return NULL; 3258 3259 result = cmap14->results; 3260 for ( i = 0; i < count; ++i ) 3261 { 3262 result[i] = (FT_UInt32)TT_NEXT_UINT24( p ); 3263 p += 8; 3264 } 3265 result[i] = 0; 3266 3267 return result; 3268 } 3269 3270 3271 FT_CALLBACK_DEF( FT_UInt32 * ) tt_cmap14_char_variants(TT_CMap cmap,FT_Memory memory,FT_UInt32 charCode)3272 tt_cmap14_char_variants( TT_CMap cmap, 3273 FT_Memory memory, 3274 FT_UInt32 charCode ) 3275 { 3276 TT_CMap14 cmap14 = (TT_CMap14) cmap; 3277 FT_UInt32 count = cmap14->num_selectors; 3278 FT_Byte* p = cmap->data + 10; 3279 FT_UInt32* q; 3280 3281 3282 if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) ) 3283 return NULL; 3284 3285 for ( q = cmap14->results; count > 0; --count ) 3286 { 3287 FT_UInt32 varSel = TT_NEXT_UINT24( p ); 3288 FT_ULong defOff = TT_NEXT_ULONG( p ); 3289 FT_ULong nondefOff = TT_NEXT_ULONG( p ); 3290 3291 3292 if ( ( defOff != 0 && 3293 tt_cmap14_char_map_def_binary( cmap->data + defOff, 3294 charCode ) ) || 3295 ( nondefOff != 0 && 3296 tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, 3297 charCode ) != 0 ) ) 3298 { 3299 q[0] = varSel; 3300 q++; 3301 } 3302 } 3303 q[0] = 0; 3304 3305 return cmap14->results; 3306 } 3307 3308 3309 static FT_UInt tt_cmap14_def_char_count(FT_Byte * p)3310 tt_cmap14_def_char_count( FT_Byte *p ) 3311 { 3312 FT_UInt32 numRanges = (FT_UInt32)TT_NEXT_ULONG( p ); 3313 FT_UInt tot = 0; 3314 3315 3316 p += 3; /* point to the first `cnt' field */ 3317 for ( ; numRanges > 0; numRanges-- ) 3318 { 3319 tot += 1 + p[0]; 3320 p += 4; 3321 } 3322 3323 return tot; 3324 } 3325 3326 3327 static FT_UInt32* tt_cmap14_get_def_chars(TT_CMap cmap,FT_Byte * p,FT_Memory memory)3328 tt_cmap14_get_def_chars( TT_CMap cmap, 3329 FT_Byte* p, 3330 FT_Memory memory ) 3331 { 3332 TT_CMap14 cmap14 = (TT_CMap14) cmap; 3333 FT_UInt32 numRanges; 3334 FT_UInt cnt; 3335 FT_UInt32* q; 3336 3337 3338 cnt = tt_cmap14_def_char_count( p ); 3339 numRanges = (FT_UInt32)TT_NEXT_ULONG( p ); 3340 3341 if ( tt_cmap14_ensure( cmap14, ( cnt + 1 ), memory ) ) 3342 return NULL; 3343 3344 for ( q = cmap14->results; numRanges > 0; --numRanges ) 3345 { 3346 FT_UInt32 uni = (FT_UInt32)TT_NEXT_UINT24( p ); 3347 3348 3349 cnt = FT_NEXT_BYTE( p ) + 1; 3350 do 3351 { 3352 q[0] = uni; 3353 uni += 1; 3354 q += 1; 3355 3356 } while ( --cnt != 0 ); 3357 } 3358 q[0] = 0; 3359 3360 return cmap14->results; 3361 } 3362 3363 3364 static FT_UInt32* tt_cmap14_get_nondef_chars(TT_CMap cmap,FT_Byte * p,FT_Memory memory)3365 tt_cmap14_get_nondef_chars( TT_CMap cmap, 3366 FT_Byte *p, 3367 FT_Memory memory ) 3368 { 3369 TT_CMap14 cmap14 = (TT_CMap14) cmap; 3370 FT_UInt32 numMappings; 3371 FT_UInt i; 3372 FT_UInt32 *ret; 3373 3374 3375 numMappings = (FT_UInt32)TT_NEXT_ULONG( p ); 3376 3377 if ( tt_cmap14_ensure( cmap14, ( numMappings + 1 ), memory ) ) 3378 return NULL; 3379 3380 ret = cmap14->results; 3381 for ( i = 0; i < numMappings; ++i ) 3382 { 3383 ret[i] = (FT_UInt32)TT_NEXT_UINT24( p ); 3384 p += 2; 3385 } 3386 ret[i] = 0; 3387 3388 return ret; 3389 } 3390 3391 3392 FT_CALLBACK_DEF( FT_UInt32 * ) tt_cmap14_variant_chars(TT_CMap cmap,FT_Memory memory,FT_UInt32 variantSelector)3393 tt_cmap14_variant_chars( TT_CMap cmap, 3394 FT_Memory memory, 3395 FT_UInt32 variantSelector ) 3396 { 3397 FT_Byte *p = tt_cmap14_find_variant( cmap->data + 6, 3398 variantSelector ); 3399 FT_Int i; 3400 FT_ULong defOff; 3401 FT_ULong nondefOff; 3402 3403 3404 if ( !p ) 3405 return NULL; 3406 3407 defOff = TT_NEXT_ULONG( p ); 3408 nondefOff = TT_NEXT_ULONG( p ); 3409 3410 if ( defOff == 0 && nondefOff == 0 ) 3411 return NULL; 3412 3413 if ( defOff == 0 ) 3414 return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff, 3415 memory ); 3416 else if ( nondefOff == 0 ) 3417 return tt_cmap14_get_def_chars( cmap, cmap->data + defOff, 3418 memory ); 3419 else 3420 { 3421 /* Both a default and a non-default glyph set? That's probably not */ 3422 /* good font design, but the spec allows for it... */ 3423 TT_CMap14 cmap14 = (TT_CMap14) cmap; 3424 FT_UInt32 numRanges; 3425 FT_UInt32 numMappings; 3426 FT_UInt32 duni; 3427 FT_UInt32 dcnt; 3428 FT_UInt32 nuni; 3429 FT_Byte* dp; 3430 FT_UInt di, ni, k; 3431 3432 FT_UInt32 *ret; 3433 3434 3435 p = cmap->data + nondefOff; 3436 dp = cmap->data + defOff; 3437 3438 numMappings = (FT_UInt32)TT_NEXT_ULONG( p ); 3439 dcnt = tt_cmap14_def_char_count( dp ); 3440 numRanges = (FT_UInt32)TT_NEXT_ULONG( dp ); 3441 3442 if ( numMappings == 0 ) 3443 return tt_cmap14_get_def_chars( cmap, cmap->data + defOff, 3444 memory ); 3445 if ( dcnt == 0 ) 3446 return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff, 3447 memory ); 3448 3449 if ( tt_cmap14_ensure( cmap14, ( dcnt + numMappings + 1 ), memory ) ) 3450 return NULL; 3451 3452 ret = cmap14->results; 3453 duni = (FT_UInt32)TT_NEXT_UINT24( dp ); 3454 dcnt = FT_NEXT_BYTE( dp ); 3455 di = 1; 3456 nuni = (FT_UInt32)TT_NEXT_UINT24( p ); 3457 p += 2; 3458 ni = 1; 3459 i = 0; 3460 3461 for (;;) 3462 { 3463 if ( nuni > duni + dcnt ) 3464 { 3465 for ( k = 0; k <= dcnt; ++k ) 3466 ret[i++] = duni + k; 3467 3468 ++di; 3469 3470 if ( di > numRanges ) 3471 break; 3472 3473 duni = (FT_UInt32)TT_NEXT_UINT24( dp ); 3474 dcnt = FT_NEXT_BYTE( dp ); 3475 } 3476 else 3477 { 3478 if ( nuni < duni ) 3479 ret[i++] = nuni; 3480 /* If it is within the default range then ignore it -- */ 3481 /* that should not have happened */ 3482 ++ni; 3483 if ( ni > numMappings ) 3484 break; 3485 3486 nuni = (FT_UInt32)TT_NEXT_UINT24( p ); 3487 p += 2; 3488 } 3489 } 3490 3491 if ( ni <= numMappings ) 3492 { 3493 /* If we get here then we have run out of all default ranges. */ 3494 /* We have read one non-default mapping which we haven't stored */ 3495 /* and there may be others that need to be read. */ 3496 ret[i++] = nuni; 3497 while ( ni < numMappings ) 3498 { 3499 ret[i++] = (FT_UInt32)TT_NEXT_UINT24( p ); 3500 p += 2; 3501 ++ni; 3502 } 3503 } 3504 else if ( di <= numRanges ) 3505 { 3506 /* If we get here then we have run out of all non-default */ 3507 /* mappings. We have read one default range which we haven't */ 3508 /* stored and there may be others that need to be read. */ 3509 for ( k = 0; k <= dcnt; ++k ) 3510 ret[i++] = duni + k; 3511 3512 while ( di < numRanges ) 3513 { 3514 duni = (FT_UInt32)TT_NEXT_UINT24( dp ); 3515 dcnt = FT_NEXT_BYTE( dp ); 3516 3517 for ( k = 0; k <= dcnt; ++k ) 3518 ret[i++] = duni + k; 3519 ++di; 3520 } 3521 } 3522 3523 ret[i] = 0; 3524 3525 return ret; 3526 } 3527 } 3528 3529 3530 FT_DEFINE_TT_CMAP( 3531 tt_cmap14_class_rec, 3532 sizeof ( TT_CMap14Rec ), 3533 3534 (FT_CMap_InitFunc) tt_cmap14_init, 3535 (FT_CMap_DoneFunc) tt_cmap14_done, 3536 (FT_CMap_CharIndexFunc)tt_cmap14_char_index, 3537 (FT_CMap_CharNextFunc) tt_cmap14_char_next, 3538 3539 /* Format 14 extension functions */ 3540 (FT_CMap_CharVarIndexFunc) tt_cmap14_char_var_index, 3541 (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault, 3542 (FT_CMap_VariantListFunc) tt_cmap14_variants, 3543 (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants, 3544 (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars, 3545 3546 14, 3547 (TT_CMap_ValidateFunc)tt_cmap14_validate, 3548 (TT_CMap_Info_GetFunc)tt_cmap14_get_info ) 3549 3550 #endif /* TT_CONFIG_CMAP_FORMAT_14 */ 3551 3552 3553 #ifndef FT_CONFIG_OPTION_PIC 3554 3555 static const TT_CMap_Class tt_cmap_classes[] = 3556 { 3557 #define TTCMAPCITEM( a ) &a, 3558 #include "ttcmapc.h" 3559 NULL, 3560 }; 3561 3562 #else /*FT_CONFIG_OPTION_PIC*/ 3563 3564 void 3565 FT_Destroy_Class_tt_cmap_classes( FT_Library library, 3566 TT_CMap_Class* clazz ) 3567 { 3568 FT_Memory memory = library->memory; 3569 3570 3571 if ( clazz ) 3572 FT_FREE( clazz ); 3573 } 3574 3575 3576 FT_Error 3577 FT_Create_Class_tt_cmap_classes( FT_Library library, 3578 TT_CMap_Class** output_class ) 3579 { 3580 TT_CMap_Class* clazz = NULL; 3581 TT_CMap_ClassRec* recs; 3582 FT_Error error; 3583 FT_Memory memory = library->memory; 3584 3585 int i = 0; 3586 3587 3588 #define TTCMAPCITEM( a ) i++; 3589 #include "ttcmapc.h" 3590 3591 /* allocate enough space for both the pointers */ 3592 /* plus terminator and the class instances */ 3593 if ( FT_ALLOC( clazz, sizeof ( *clazz ) * ( i + 1 ) + 3594 sizeof ( TT_CMap_ClassRec ) * i ) ) 3595 return error; 3596 3597 /* the location of the class instances follows the array of pointers */ 3598 recs = (TT_CMap_ClassRec*)( (char*)clazz + 3599 sizeof ( *clazz ) * ( i + 1 ) ); 3600 i = 0; 3601 3602 #undef TTCMAPCITEM 3603 #define TTCMAPCITEM( a ) \ 3604 FT_Init_Class_ ## a( &recs[i] ); \ 3605 clazz[i] = &recs[i]; \ 3606 i++; 3607 #include "ttcmapc.h" 3608 3609 clazz[i] = NULL; 3610 3611 *output_class = clazz; 3612 return FT_Err_Ok; 3613 } 3614 3615 #endif /*FT_CONFIG_OPTION_PIC*/ 3616 3617 3618 /* parse the `cmap' table and build the corresponding TT_CMap objects */ 3619 /* in the current face */ 3620 /* */ 3621 FT_LOCAL_DEF( FT_Error ) tt_face_build_cmaps(TT_Face face)3622 tt_face_build_cmaps( TT_Face face ) 3623 { 3624 FT_Byte* table = face->cmap_table; 3625 FT_Byte* limit = table + face->cmap_size; 3626 FT_UInt volatile num_cmaps; 3627 FT_Byte* volatile p = table; 3628 FT_Library library = FT_FACE_LIBRARY( face ); 3629 3630 FT_UNUSED( library ); 3631 3632 3633 if ( !p || p + 4 > limit ) 3634 return FT_THROW( Invalid_Table ); 3635 3636 /* only recognize format 0 */ 3637 if ( TT_NEXT_USHORT( p ) != 0 ) 3638 { 3639 FT_ERROR(( "tt_face_build_cmaps:" 3640 " unsupported `cmap' table format = %d\n", 3641 TT_PEEK_USHORT( p - 2 ) )); 3642 return FT_THROW( Invalid_Table ); 3643 } 3644 3645 num_cmaps = TT_NEXT_USHORT( p ); 3646 3647 for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- ) 3648 { 3649 FT_CharMapRec charmap; 3650 FT_UInt32 offset; 3651 3652 3653 charmap.platform_id = TT_NEXT_USHORT( p ); 3654 charmap.encoding_id = TT_NEXT_USHORT( p ); 3655 charmap.face = FT_FACE( face ); 3656 charmap.encoding = FT_ENCODING_NONE; /* will be filled later */ 3657 offset = TT_NEXT_ULONG( p ); 3658 3659 if ( offset && offset <= face->cmap_size - 2 ) 3660 { 3661 FT_Byte* volatile cmap = table + offset; 3662 volatile FT_UInt format = TT_PEEK_USHORT( cmap ); 3663 const TT_CMap_Class* volatile pclazz = TT_CMAP_CLASSES_GET; 3664 TT_CMap_Class volatile clazz; 3665 3666 3667 for ( ; *pclazz; pclazz++ ) 3668 { 3669 clazz = *pclazz; 3670 if ( clazz->format == format ) 3671 { 3672 volatile TT_ValidatorRec valid; 3673 volatile FT_Error error = FT_Err_Ok; 3674 3675 3676 ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit, 3677 FT_VALIDATE_DEFAULT ); 3678 3679 valid.num_glyphs = (FT_UInt)face->max_profile.numGlyphs; 3680 3681 if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer) == 0 ) 3682 { 3683 /* validate this cmap sub-table */ 3684 error = clazz->validate( cmap, FT_VALIDATOR( &valid ) ); 3685 } 3686 3687 if ( valid.validator.error == 0 ) 3688 { 3689 FT_CMap ttcmap; 3690 3691 3692 /* It might make sense to store the single variation */ 3693 /* selector cmap somewhere special. But it would have to be */ 3694 /* in the public FT_FaceRec, and we can't change that. */ 3695 3696 if ( !FT_CMap_New( (FT_CMap_Class)clazz, 3697 cmap, &charmap, &ttcmap ) ) 3698 { 3699 /* it is simpler to directly set `flags' than adding */ 3700 /* a parameter to FT_CMap_New */ 3701 ((TT_CMap)ttcmap)->flags = (FT_Int)error; 3702 } 3703 } 3704 else 3705 { 3706 FT_TRACE0(( "tt_face_build_cmaps:" 3707 " broken cmap sub-table ignored\n" )); 3708 } 3709 break; 3710 } 3711 } 3712 3713 if ( *pclazz == NULL ) 3714 { 3715 FT_TRACE0(( "tt_face_build_cmaps:" 3716 " unsupported cmap sub-table ignored\n" )); 3717 } 3718 } 3719 } 3720 3721 return FT_Err_Ok; 3722 } 3723 3724 3725 FT_LOCAL( FT_Error ) tt_get_cmap_info(FT_CharMap charmap,TT_CMapInfo * cmap_info)3726 tt_get_cmap_info( FT_CharMap charmap, 3727 TT_CMapInfo *cmap_info ) 3728 { 3729 FT_CMap cmap = (FT_CMap)charmap; 3730 TT_CMap_Class clazz = (TT_CMap_Class)cmap->clazz; 3731 3732 3733 return clazz->get_cmap_info( charmap, cmap_info ); 3734 } 3735 3736 3737 /* END */ 3738