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