1 /**************************************************************************** 2 * 3 * ttcmap.c 4 * 5 * TrueType character mapping table (cmap) support (body). 6 * 7 * Copyright (C) 2002-2019 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 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 continue; 2372 2373 cmap->cur_charcode = char_code; 2374 cmap->cur_gindex = gindex; 2375 cmap->cur_group = n; 2376 2377 return; 2378 } 2379 } 2380 2381 Fail: 2382 cmap->valid = 0; 2383 } 2384 2385 2386 static FT_UInt tt_cmap12_char_map_binary(TT_CMap cmap,FT_UInt32 * pchar_code,FT_Bool next)2387 tt_cmap12_char_map_binary( TT_CMap cmap, 2388 FT_UInt32* pchar_code, 2389 FT_Bool next ) 2390 { 2391 FT_UInt gindex = 0; 2392 FT_Byte* p = cmap->data + 12; 2393 FT_UInt32 num_groups = TT_PEEK_ULONG( p ); 2394 FT_UInt32 char_code = *pchar_code; 2395 FT_UInt32 start, end, start_id; 2396 FT_UInt32 max, min, mid; 2397 2398 2399 if ( !num_groups ) 2400 return 0; 2401 2402 /* make compiler happy */ 2403 mid = num_groups; 2404 end = 0xFFFFFFFFUL; 2405 2406 if ( next ) 2407 { 2408 if ( char_code >= 0xFFFFFFFFUL ) 2409 return 0; 2410 2411 char_code++; 2412 } 2413 2414 min = 0; 2415 max = num_groups; 2416 2417 /* binary search */ 2418 while ( min < max ) 2419 { 2420 mid = ( min + max ) >> 1; 2421 p = cmap->data + 16 + 12 * mid; 2422 2423 start = TT_NEXT_ULONG( p ); 2424 end = TT_NEXT_ULONG( p ); 2425 2426 if ( char_code < start ) 2427 max = mid; 2428 else if ( char_code > end ) 2429 min = mid + 1; 2430 else 2431 { 2432 start_id = TT_PEEK_ULONG( p ); 2433 2434 /* reject invalid glyph index */ 2435 if ( start_id > 0xFFFFFFFFUL - ( char_code - start ) ) 2436 gindex = 0; 2437 else 2438 gindex = (FT_UInt)( start_id + ( char_code - start ) ); 2439 break; 2440 } 2441 } 2442 2443 if ( next ) 2444 { 2445 FT_Face face = cmap->cmap.charmap.face; 2446 TT_CMap12 cmap12 = (TT_CMap12)cmap; 2447 2448 2449 /* if `char_code' is not in any group, then `mid' is */ 2450 /* the group nearest to `char_code' */ 2451 2452 if ( char_code > end ) 2453 { 2454 mid++; 2455 if ( mid == num_groups ) 2456 return 0; 2457 } 2458 2459 cmap12->valid = 1; 2460 cmap12->cur_charcode = char_code; 2461 cmap12->cur_group = mid; 2462 2463 if ( gindex >= (FT_UInt)face->num_glyphs ) 2464 gindex = 0; 2465 2466 if ( !gindex ) 2467 { 2468 tt_cmap12_next( cmap12 ); 2469 2470 if ( cmap12->valid ) 2471 gindex = cmap12->cur_gindex; 2472 } 2473 else 2474 cmap12->cur_gindex = gindex; 2475 2476 *pchar_code = cmap12->cur_charcode; 2477 } 2478 2479 return gindex; 2480 } 2481 2482 2483 FT_CALLBACK_DEF( FT_UInt ) tt_cmap12_char_index(TT_CMap cmap,FT_UInt32 char_code)2484 tt_cmap12_char_index( TT_CMap cmap, 2485 FT_UInt32 char_code ) 2486 { 2487 return tt_cmap12_char_map_binary( cmap, &char_code, 0 ); 2488 } 2489 2490 2491 FT_CALLBACK_DEF( FT_UInt32 ) tt_cmap12_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)2492 tt_cmap12_char_next( TT_CMap cmap, 2493 FT_UInt32 *pchar_code ) 2494 { 2495 TT_CMap12 cmap12 = (TT_CMap12)cmap; 2496 FT_UInt gindex; 2497 2498 2499 /* no need to search */ 2500 if ( cmap12->valid && cmap12->cur_charcode == *pchar_code ) 2501 { 2502 tt_cmap12_next( cmap12 ); 2503 if ( cmap12->valid ) 2504 { 2505 gindex = cmap12->cur_gindex; 2506 *pchar_code = (FT_UInt32)cmap12->cur_charcode; 2507 } 2508 else 2509 gindex = 0; 2510 } 2511 else 2512 gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 ); 2513 2514 return gindex; 2515 } 2516 2517 2518 FT_CALLBACK_DEF( FT_Error ) tt_cmap12_get_info(TT_CMap cmap,TT_CMapInfo * cmap_info)2519 tt_cmap12_get_info( TT_CMap cmap, 2520 TT_CMapInfo *cmap_info ) 2521 { 2522 FT_Byte* p = cmap->data + 8; 2523 2524 2525 cmap_info->format = 12; 2526 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); 2527 2528 return FT_Err_Ok; 2529 } 2530 2531 2532 FT_DEFINE_TT_CMAP( 2533 tt_cmap12_class_rec, 2534 2535 sizeof ( TT_CMap12Rec ), 2536 2537 (FT_CMap_InitFunc) tt_cmap12_init, /* init */ 2538 (FT_CMap_DoneFunc) NULL, /* done */ 2539 (FT_CMap_CharIndexFunc)tt_cmap12_char_index, /* char_index */ 2540 (FT_CMap_CharNextFunc) tt_cmap12_char_next, /* char_next */ 2541 2542 (FT_CMap_CharVarIndexFunc) NULL, /* char_var_index */ 2543 (FT_CMap_CharVarIsDefaultFunc)NULL, /* char_var_default */ 2544 (FT_CMap_VariantListFunc) NULL, /* variant_list */ 2545 (FT_CMap_CharVariantListFunc) NULL, /* charvariant_list */ 2546 (FT_CMap_VariantCharListFunc) NULL, /* variantchar_list */ 2547 2548 12, 2549 (TT_CMap_ValidateFunc)tt_cmap12_validate, /* validate */ 2550 (TT_CMap_Info_GetFunc)tt_cmap12_get_info /* get_cmap_info */ 2551 ) 2552 2553 #endif /* TT_CONFIG_CMAP_FORMAT_12 */ 2554 2555 2556 /*************************************************************************/ 2557 /*************************************************************************/ 2558 /***** *****/ 2559 /***** FORMAT 13 *****/ 2560 /***** *****/ 2561 /*************************************************************************/ 2562 /*************************************************************************/ 2563 2564 /************************************************************************** 2565 * 2566 * TABLE OVERVIEW 2567 * -------------- 2568 * 2569 * NAME OFFSET TYPE DESCRIPTION 2570 * 2571 * format 0 USHORT must be 13 2572 * reserved 2 USHORT reserved 2573 * length 4 ULONG length in bytes 2574 * language 8 ULONG Mac language code 2575 * count 12 ULONG number of groups 2576 * 16 2577 * 2578 * This header is followed by `count' groups of the following format: 2579 * 2580 * start 0 ULONG first charcode 2581 * end 4 ULONG last charcode 2582 * glyphId 8 ULONG glyph ID for the whole group 2583 */ 2584 2585 #ifdef TT_CONFIG_CMAP_FORMAT_13 2586 2587 typedef struct TT_CMap13Rec_ 2588 { 2589 TT_CMapRec cmap; 2590 FT_Bool valid; 2591 FT_ULong cur_charcode; 2592 FT_UInt cur_gindex; 2593 FT_ULong cur_group; 2594 FT_ULong num_groups; 2595 2596 } TT_CMap13Rec, *TT_CMap13; 2597 2598 2599 FT_CALLBACK_DEF( FT_Error ) tt_cmap13_init(TT_CMap13 cmap,FT_Byte * table)2600 tt_cmap13_init( TT_CMap13 cmap, 2601 FT_Byte* table ) 2602 { 2603 cmap->cmap.data = table; 2604 2605 table += 12; 2606 cmap->num_groups = FT_PEEK_ULONG( table ); 2607 2608 cmap->valid = 0; 2609 2610 return FT_Err_Ok; 2611 } 2612 2613 2614 FT_CALLBACK_DEF( FT_Error ) tt_cmap13_validate(FT_Byte * table,FT_Validator valid)2615 tt_cmap13_validate( FT_Byte* table, 2616 FT_Validator valid ) 2617 { 2618 FT_Byte* p; 2619 FT_ULong length; 2620 FT_ULong num_groups; 2621 2622 2623 if ( table + 16 > valid->limit ) 2624 FT_INVALID_TOO_SHORT; 2625 2626 p = table + 4; 2627 length = TT_NEXT_ULONG( p ); 2628 2629 p = table + 12; 2630 num_groups = TT_NEXT_ULONG( p ); 2631 2632 if ( length > (FT_ULong)( valid->limit - table ) || 2633 /* length < 16 + 12 * num_groups ? */ 2634 length < 16 || 2635 ( length - 16 ) / 12 < num_groups ) 2636 FT_INVALID_TOO_SHORT; 2637 2638 /* check groups, they must be in increasing order */ 2639 { 2640 FT_ULong n, start, end, glyph_id, last = 0; 2641 2642 2643 for ( n = 0; n < num_groups; n++ ) 2644 { 2645 start = TT_NEXT_ULONG( p ); 2646 end = TT_NEXT_ULONG( p ); 2647 glyph_id = TT_NEXT_ULONG( p ); 2648 2649 if ( start > end ) 2650 FT_INVALID_DATA; 2651 2652 if ( n > 0 && start <= last ) 2653 FT_INVALID_DATA; 2654 2655 if ( valid->level >= FT_VALIDATE_TIGHT ) 2656 { 2657 if ( glyph_id >= TT_VALID_GLYPH_COUNT( valid ) ) 2658 FT_INVALID_GLYPH_ID; 2659 } 2660 2661 last = end; 2662 } 2663 } 2664 2665 return FT_Err_Ok; 2666 } 2667 2668 2669 /* search the index of the charcode next to cmap->cur_charcode */ 2670 /* cmap->cur_group should be set up properly by caller */ 2671 /* */ 2672 static void tt_cmap13_next(TT_CMap13 cmap)2673 tt_cmap13_next( TT_CMap13 cmap ) 2674 { 2675 FT_Face face = cmap->cmap.cmap.charmap.face; 2676 FT_Byte* p; 2677 FT_ULong start, end, glyph_id, char_code; 2678 FT_ULong n; 2679 FT_UInt gindex; 2680 2681 2682 if ( cmap->cur_charcode >= 0xFFFFFFFFUL ) 2683 goto Fail; 2684 2685 char_code = cmap->cur_charcode + 1; 2686 2687 for ( n = cmap->cur_group; n < cmap->num_groups; n++ ) 2688 { 2689 p = cmap->cmap.data + 16 + 12 * n; 2690 start = TT_NEXT_ULONG( p ); 2691 end = TT_NEXT_ULONG( p ); 2692 glyph_id = TT_PEEK_ULONG( p ); 2693 2694 if ( char_code < start ) 2695 char_code = start; 2696 2697 if ( char_code <= end ) 2698 { 2699 gindex = (FT_UInt)glyph_id; 2700 2701 if ( gindex && gindex < (FT_UInt)face->num_glyphs ) 2702 { 2703 cmap->cur_charcode = char_code; 2704 cmap->cur_gindex = gindex; 2705 cmap->cur_group = n; 2706 2707 return; 2708 } 2709 } 2710 } 2711 2712 Fail: 2713 cmap->valid = 0; 2714 } 2715 2716 2717 static FT_UInt tt_cmap13_char_map_binary(TT_CMap cmap,FT_UInt32 * pchar_code,FT_Bool next)2718 tt_cmap13_char_map_binary( TT_CMap cmap, 2719 FT_UInt32* pchar_code, 2720 FT_Bool next ) 2721 { 2722 FT_UInt gindex = 0; 2723 FT_Byte* p = cmap->data + 12; 2724 FT_UInt32 num_groups = TT_PEEK_ULONG( p ); 2725 FT_UInt32 char_code = *pchar_code; 2726 FT_UInt32 start, end; 2727 FT_UInt32 max, min, mid; 2728 2729 2730 if ( !num_groups ) 2731 return 0; 2732 2733 /* make compiler happy */ 2734 mid = num_groups; 2735 end = 0xFFFFFFFFUL; 2736 2737 if ( next ) 2738 { 2739 if ( char_code >= 0xFFFFFFFFUL ) 2740 return 0; 2741 2742 char_code++; 2743 } 2744 2745 min = 0; 2746 max = num_groups; 2747 2748 /* binary search */ 2749 while ( min < max ) 2750 { 2751 mid = ( min + max ) >> 1; 2752 p = cmap->data + 16 + 12 * mid; 2753 2754 start = TT_NEXT_ULONG( p ); 2755 end = TT_NEXT_ULONG( p ); 2756 2757 if ( char_code < start ) 2758 max = mid; 2759 else if ( char_code > end ) 2760 min = mid + 1; 2761 else 2762 { 2763 gindex = (FT_UInt)TT_PEEK_ULONG( p ); 2764 2765 break; 2766 } 2767 } 2768 2769 if ( next ) 2770 { 2771 FT_Face face = cmap->cmap.charmap.face; 2772 TT_CMap13 cmap13 = (TT_CMap13)cmap; 2773 2774 2775 /* if `char_code' is not in any group, then `mid' is */ 2776 /* the group nearest to `char_code' */ 2777 2778 if ( char_code > end ) 2779 { 2780 mid++; 2781 if ( mid == num_groups ) 2782 return 0; 2783 } 2784 2785 cmap13->valid = 1; 2786 cmap13->cur_charcode = char_code; 2787 cmap13->cur_group = mid; 2788 2789 if ( gindex >= (FT_UInt)face->num_glyphs ) 2790 gindex = 0; 2791 2792 if ( !gindex ) 2793 { 2794 tt_cmap13_next( cmap13 ); 2795 2796 if ( cmap13->valid ) 2797 gindex = cmap13->cur_gindex; 2798 } 2799 else 2800 cmap13->cur_gindex = gindex; 2801 2802 *pchar_code = cmap13->cur_charcode; 2803 } 2804 2805 return gindex; 2806 } 2807 2808 2809 FT_CALLBACK_DEF( FT_UInt ) tt_cmap13_char_index(TT_CMap cmap,FT_UInt32 char_code)2810 tt_cmap13_char_index( TT_CMap cmap, 2811 FT_UInt32 char_code ) 2812 { 2813 return tt_cmap13_char_map_binary( cmap, &char_code, 0 ); 2814 } 2815 2816 2817 FT_CALLBACK_DEF( FT_UInt32 ) tt_cmap13_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)2818 tt_cmap13_char_next( TT_CMap cmap, 2819 FT_UInt32 *pchar_code ) 2820 { 2821 TT_CMap13 cmap13 = (TT_CMap13)cmap; 2822 FT_UInt gindex; 2823 2824 2825 /* no need to search */ 2826 if ( cmap13->valid && cmap13->cur_charcode == *pchar_code ) 2827 { 2828 tt_cmap13_next( cmap13 ); 2829 if ( cmap13->valid ) 2830 { 2831 gindex = cmap13->cur_gindex; 2832 *pchar_code = cmap13->cur_charcode; 2833 } 2834 else 2835 gindex = 0; 2836 } 2837 else 2838 gindex = tt_cmap13_char_map_binary( cmap, pchar_code, 1 ); 2839 2840 return gindex; 2841 } 2842 2843 2844 FT_CALLBACK_DEF( FT_Error ) tt_cmap13_get_info(TT_CMap cmap,TT_CMapInfo * cmap_info)2845 tt_cmap13_get_info( TT_CMap cmap, 2846 TT_CMapInfo *cmap_info ) 2847 { 2848 FT_Byte* p = cmap->data + 8; 2849 2850 2851 cmap_info->format = 13; 2852 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); 2853 2854 return FT_Err_Ok; 2855 } 2856 2857 2858 FT_DEFINE_TT_CMAP( 2859 tt_cmap13_class_rec, 2860 2861 sizeof ( TT_CMap13Rec ), 2862 2863 (FT_CMap_InitFunc) tt_cmap13_init, /* init */ 2864 (FT_CMap_DoneFunc) NULL, /* done */ 2865 (FT_CMap_CharIndexFunc)tt_cmap13_char_index, /* char_index */ 2866 (FT_CMap_CharNextFunc) tt_cmap13_char_next, /* char_next */ 2867 2868 (FT_CMap_CharVarIndexFunc) NULL, /* char_var_index */ 2869 (FT_CMap_CharVarIsDefaultFunc)NULL, /* char_var_default */ 2870 (FT_CMap_VariantListFunc) NULL, /* variant_list */ 2871 (FT_CMap_CharVariantListFunc) NULL, /* charvariant_list */ 2872 (FT_CMap_VariantCharListFunc) NULL, /* variantchar_list */ 2873 2874 13, 2875 (TT_CMap_ValidateFunc)tt_cmap13_validate, /* validate */ 2876 (TT_CMap_Info_GetFunc)tt_cmap13_get_info /* get_cmap_info */ 2877 ) 2878 2879 #endif /* TT_CONFIG_CMAP_FORMAT_13 */ 2880 2881 2882 /*************************************************************************/ 2883 /*************************************************************************/ 2884 /***** *****/ 2885 /***** FORMAT 14 *****/ 2886 /***** *****/ 2887 /*************************************************************************/ 2888 /*************************************************************************/ 2889 2890 /************************************************************************** 2891 * 2892 * TABLE OVERVIEW 2893 * -------------- 2894 * 2895 * NAME OFFSET TYPE DESCRIPTION 2896 * 2897 * format 0 USHORT must be 14 2898 * length 2 ULONG table length in bytes 2899 * numSelector 6 ULONG number of variation sel. records 2900 * 2901 * Followed by numSelector records, each of which looks like 2902 * 2903 * varSelector 0 UINT24 Unicode codepoint of sel. 2904 * defaultOff 3 ULONG offset to a default UVS table 2905 * describing any variants to be found in 2906 * the normal Unicode subtable. 2907 * nonDefOff 7 ULONG offset to a non-default UVS table 2908 * describing any variants not in the 2909 * standard cmap, with GIDs here 2910 * (either offset may be 0 NULL) 2911 * 2912 * Selectors are sorted by code point. 2913 * 2914 * A default Unicode Variation Selector (UVS) subtable is just a list of 2915 * ranges of code points which are to be found in the standard cmap. No 2916 * glyph IDs (GIDs) here. 2917 * 2918 * numRanges 0 ULONG number of ranges following 2919 * 2920 * A range looks like 2921 * 2922 * uniStart 0 UINT24 code point of the first character in 2923 * this range 2924 * additionalCnt 3 UBYTE count of additional characters in this 2925 * range (zero means a range of a single 2926 * character) 2927 * 2928 * Ranges are sorted by `uniStart'. 2929 * 2930 * A non-default Unicode Variation Selector (UVS) subtable is a list of 2931 * mappings from codepoint to GID. 2932 * 2933 * numMappings 0 ULONG number of mappings 2934 * 2935 * A range looks like 2936 * 2937 * uniStart 0 UINT24 code point of the first character in 2938 * this range 2939 * GID 3 USHORT and its GID 2940 * 2941 * Ranges are sorted by `uniStart'. 2942 */ 2943 2944 #ifdef TT_CONFIG_CMAP_FORMAT_14 2945 2946 typedef struct TT_CMap14Rec_ 2947 { 2948 TT_CMapRec cmap; 2949 FT_ULong num_selectors; 2950 2951 /* This array is used to store the results of various 2952 * cmap 14 query functions. The data is overwritten 2953 * on each call to these functions. 2954 */ 2955 FT_UInt32 max_results; 2956 FT_UInt32* results; 2957 FT_Memory memory; 2958 2959 } TT_CMap14Rec, *TT_CMap14; 2960 2961 2962 FT_CALLBACK_DEF( void ) tt_cmap14_done(TT_CMap14 cmap)2963 tt_cmap14_done( TT_CMap14 cmap ) 2964 { 2965 FT_Memory memory = cmap->memory; 2966 2967 2968 cmap->max_results = 0; 2969 if ( memory && cmap->results ) 2970 FT_FREE( cmap->results ); 2971 } 2972 2973 2974 static FT_Error tt_cmap14_ensure(TT_CMap14 cmap,FT_UInt32 num_results,FT_Memory memory)2975 tt_cmap14_ensure( TT_CMap14 cmap, 2976 FT_UInt32 num_results, 2977 FT_Memory memory ) 2978 { 2979 FT_UInt32 old_max = cmap->max_results; 2980 FT_Error error = FT_Err_Ok; 2981 2982 2983 if ( num_results > cmap->max_results ) 2984 { 2985 cmap->memory = memory; 2986 2987 if ( FT_QRENEW_ARRAY( cmap->results, old_max, num_results ) ) 2988 return error; 2989 2990 cmap->max_results = num_results; 2991 } 2992 2993 return error; 2994 } 2995 2996 2997 FT_CALLBACK_DEF( FT_Error ) tt_cmap14_init(TT_CMap14 cmap,FT_Byte * table)2998 tt_cmap14_init( TT_CMap14 cmap, 2999 FT_Byte* table ) 3000 { 3001 cmap->cmap.data = table; 3002 3003 table += 6; 3004 cmap->num_selectors = FT_PEEK_ULONG( table ); 3005 cmap->max_results = 0; 3006 cmap->results = NULL; 3007 3008 return FT_Err_Ok; 3009 } 3010 3011 3012 FT_CALLBACK_DEF( FT_Error ) tt_cmap14_validate(FT_Byte * table,FT_Validator valid)3013 tt_cmap14_validate( FT_Byte* table, 3014 FT_Validator valid ) 3015 { 3016 FT_Byte* p; 3017 FT_ULong length; 3018 FT_ULong num_selectors; 3019 3020 3021 if ( table + 2 + 4 + 4 > valid->limit ) 3022 FT_INVALID_TOO_SHORT; 3023 3024 p = table + 2; 3025 length = TT_NEXT_ULONG( p ); 3026 num_selectors = TT_NEXT_ULONG( p ); 3027 3028 if ( length > (FT_ULong)( valid->limit - table ) || 3029 /* length < 10 + 11 * num_selectors ? */ 3030 length < 10 || 3031 ( length - 10 ) / 11 < num_selectors ) 3032 FT_INVALID_TOO_SHORT; 3033 3034 /* check selectors, they must be in increasing order */ 3035 { 3036 /* we start lastVarSel at 1 because a variant selector value of 0 3037 * isn't valid. 3038 */ 3039 FT_ULong n, lastVarSel = 1; 3040 3041 3042 for ( n = 0; n < num_selectors; n++ ) 3043 { 3044 FT_ULong varSel = TT_NEXT_UINT24( p ); 3045 FT_ULong defOff = TT_NEXT_ULONG( p ); 3046 FT_ULong nondefOff = TT_NEXT_ULONG( p ); 3047 3048 3049 if ( defOff >= length || nondefOff >= length ) 3050 FT_INVALID_TOO_SHORT; 3051 3052 if ( varSel < lastVarSel ) 3053 FT_INVALID_DATA; 3054 3055 lastVarSel = varSel + 1; 3056 3057 /* check the default table (these glyphs should be reached */ 3058 /* through the normal Unicode cmap, no GIDs, just check order) */ 3059 if ( defOff != 0 ) 3060 { 3061 FT_Byte* defp = table + defOff; 3062 FT_ULong numRanges; 3063 FT_ULong i; 3064 FT_ULong lastBase = 0; 3065 3066 3067 if ( defp + 4 > valid->limit ) 3068 FT_INVALID_TOO_SHORT; 3069 3070 numRanges = TT_NEXT_ULONG( defp ); 3071 3072 /* defp + numRanges * 4 > valid->limit ? */ 3073 if ( numRanges > (FT_ULong)( valid->limit - defp ) / 4 ) 3074 FT_INVALID_TOO_SHORT; 3075 3076 for ( i = 0; i < numRanges; i++ ) 3077 { 3078 FT_ULong base = TT_NEXT_UINT24( defp ); 3079 FT_ULong cnt = FT_NEXT_BYTE( defp ); 3080 3081 3082 if ( base + cnt >= 0x110000UL ) /* end of Unicode */ 3083 FT_INVALID_DATA; 3084 3085 if ( base < lastBase ) 3086 FT_INVALID_DATA; 3087 3088 lastBase = base + cnt + 1U; 3089 } 3090 } 3091 3092 /* and the non-default table (these glyphs are specified here) */ 3093 if ( nondefOff != 0 ) 3094 { 3095 FT_Byte* ndp = table + nondefOff; 3096 FT_ULong numMappings; 3097 FT_ULong i, lastUni = 0; 3098 3099 3100 if ( ndp + 4 > valid->limit ) 3101 FT_INVALID_TOO_SHORT; 3102 3103 numMappings = TT_NEXT_ULONG( ndp ); 3104 3105 /* numMappings * 5 > (FT_ULong)( valid->limit - ndp ) ? */ 3106 if ( numMappings > ( (FT_ULong)( valid->limit - ndp ) ) / 5 ) 3107 FT_INVALID_TOO_SHORT; 3108 3109 for ( i = 0; i < numMappings; i++ ) 3110 { 3111 FT_ULong uni = TT_NEXT_UINT24( ndp ); 3112 FT_ULong gid = TT_NEXT_USHORT( ndp ); 3113 3114 3115 if ( uni >= 0x110000UL ) /* end of Unicode */ 3116 FT_INVALID_DATA; 3117 3118 if ( uni < lastUni ) 3119 FT_INVALID_DATA; 3120 3121 lastUni = uni + 1U; 3122 3123 if ( valid->level >= FT_VALIDATE_TIGHT && 3124 gid >= TT_VALID_GLYPH_COUNT( valid ) ) 3125 FT_INVALID_GLYPH_ID; 3126 } 3127 } 3128 } 3129 } 3130 3131 return FT_Err_Ok; 3132 } 3133 3134 3135 FT_CALLBACK_DEF( FT_UInt ) tt_cmap14_char_index(TT_CMap cmap,FT_UInt32 char_code)3136 tt_cmap14_char_index( TT_CMap cmap, 3137 FT_UInt32 char_code ) 3138 { 3139 FT_UNUSED( cmap ); 3140 FT_UNUSED( char_code ); 3141 3142 /* This can't happen */ 3143 return 0; 3144 } 3145 3146 3147 FT_CALLBACK_DEF( FT_UInt32 ) tt_cmap14_char_next(TT_CMap cmap,FT_UInt32 * pchar_code)3148 tt_cmap14_char_next( TT_CMap cmap, 3149 FT_UInt32 *pchar_code ) 3150 { 3151 FT_UNUSED( cmap ); 3152 3153 /* This can't happen */ 3154 *pchar_code = 0; 3155 return 0; 3156 } 3157 3158 3159 FT_CALLBACK_DEF( FT_Error ) tt_cmap14_get_info(TT_CMap cmap,TT_CMapInfo * cmap_info)3160 tt_cmap14_get_info( TT_CMap cmap, 3161 TT_CMapInfo *cmap_info ) 3162 { 3163 FT_UNUSED( cmap ); 3164 3165 cmap_info->format = 14; 3166 /* subtable 14 does not define a language field */ 3167 cmap_info->language = 0xFFFFFFFFUL; 3168 3169 return FT_Err_Ok; 3170 } 3171 3172 3173 static FT_UInt tt_cmap14_char_map_def_binary(FT_Byte * base,FT_UInt32 char_code)3174 tt_cmap14_char_map_def_binary( FT_Byte *base, 3175 FT_UInt32 char_code ) 3176 { 3177 FT_UInt32 numRanges = TT_PEEK_ULONG( base ); 3178 FT_UInt32 max, min; 3179 3180 3181 min = 0; 3182 max = numRanges; 3183 3184 base += 4; 3185 3186 /* binary search */ 3187 while ( min < max ) 3188 { 3189 FT_UInt32 mid = ( min + max ) >> 1; 3190 FT_Byte* p = base + 4 * mid; 3191 FT_ULong start = TT_NEXT_UINT24( p ); 3192 FT_UInt cnt = FT_NEXT_BYTE( p ); 3193 3194 3195 if ( char_code < start ) 3196 max = mid; 3197 else if ( char_code > start + cnt ) 3198 min = mid + 1; 3199 else 3200 return TRUE; 3201 } 3202 3203 return FALSE; 3204 } 3205 3206 3207 static FT_UInt tt_cmap14_char_map_nondef_binary(FT_Byte * base,FT_UInt32 char_code)3208 tt_cmap14_char_map_nondef_binary( FT_Byte *base, 3209 FT_UInt32 char_code ) 3210 { 3211 FT_UInt32 numMappings = TT_PEEK_ULONG( base ); 3212 FT_UInt32 max, min; 3213 3214 3215 min = 0; 3216 max = numMappings; 3217 3218 base += 4; 3219 3220 /* binary search */ 3221 while ( min < max ) 3222 { 3223 FT_UInt32 mid = ( min + max ) >> 1; 3224 FT_Byte* p = base + 5 * mid; 3225 FT_UInt32 uni = (FT_UInt32)TT_NEXT_UINT24( p ); 3226 3227 3228 if ( char_code < uni ) 3229 max = mid; 3230 else if ( char_code > uni ) 3231 min = mid + 1; 3232 else 3233 return TT_PEEK_USHORT( p ); 3234 } 3235 3236 return 0; 3237 } 3238 3239 3240 static FT_Byte* tt_cmap14_find_variant(FT_Byte * base,FT_UInt32 variantCode)3241 tt_cmap14_find_variant( FT_Byte *base, 3242 FT_UInt32 variantCode ) 3243 { 3244 FT_UInt32 numVar = TT_PEEK_ULONG( base ); 3245 FT_UInt32 max, min; 3246 3247 3248 min = 0; 3249 max = numVar; 3250 3251 base += 4; 3252 3253 /* binary search */ 3254 while ( min < max ) 3255 { 3256 FT_UInt32 mid = ( min + max ) >> 1; 3257 FT_Byte* p = base + 11 * mid; 3258 FT_ULong varSel = TT_NEXT_UINT24( p ); 3259 3260 3261 if ( variantCode < varSel ) 3262 max = mid; 3263 else if ( variantCode > varSel ) 3264 min = mid + 1; 3265 else 3266 return p; 3267 } 3268 3269 return NULL; 3270 } 3271 3272 3273 FT_CALLBACK_DEF( FT_UInt ) tt_cmap14_char_var_index(TT_CMap cmap,TT_CMap ucmap,FT_UInt32 charcode,FT_UInt32 variantSelector)3274 tt_cmap14_char_var_index( TT_CMap cmap, 3275 TT_CMap ucmap, 3276 FT_UInt32 charcode, 3277 FT_UInt32 variantSelector ) 3278 { 3279 FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector ); 3280 FT_ULong defOff; 3281 FT_ULong nondefOff; 3282 3283 3284 if ( !p ) 3285 return 0; 3286 3287 defOff = TT_NEXT_ULONG( p ); 3288 nondefOff = TT_PEEK_ULONG( p ); 3289 3290 if ( defOff != 0 && 3291 tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) ) 3292 { 3293 /* This is the default variant of this charcode. GID not stored */ 3294 /* here; stored in the normal Unicode charmap instead. */ 3295 return ucmap->cmap.clazz->char_index( &ucmap->cmap, charcode ); 3296 } 3297 3298 if ( nondefOff != 0 ) 3299 return tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, 3300 charcode ); 3301 3302 return 0; 3303 } 3304 3305 3306 FT_CALLBACK_DEF( FT_Int ) tt_cmap14_char_var_isdefault(TT_CMap cmap,FT_UInt32 charcode,FT_UInt32 variantSelector)3307 tt_cmap14_char_var_isdefault( TT_CMap cmap, 3308 FT_UInt32 charcode, 3309 FT_UInt32 variantSelector ) 3310 { 3311 FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector ); 3312 FT_ULong defOff; 3313 FT_ULong nondefOff; 3314 3315 3316 if ( !p ) 3317 return -1; 3318 3319 defOff = TT_NEXT_ULONG( p ); 3320 nondefOff = TT_NEXT_ULONG( p ); 3321 3322 if ( defOff != 0 && 3323 tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) ) 3324 return 1; 3325 3326 if ( nondefOff != 0 && 3327 tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, 3328 charcode ) != 0 ) 3329 return 0; 3330 3331 return -1; 3332 } 3333 3334 3335 FT_CALLBACK_DEF( FT_UInt32* ) tt_cmap14_variants(TT_CMap cmap,FT_Memory memory)3336 tt_cmap14_variants( TT_CMap cmap, 3337 FT_Memory memory ) 3338 { 3339 TT_CMap14 cmap14 = (TT_CMap14)cmap; 3340 FT_UInt32 count = cmap14->num_selectors; 3341 FT_Byte* p = cmap->data + 10; 3342 FT_UInt32* result; 3343 FT_UInt32 i; 3344 3345 3346 if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) ) 3347 return NULL; 3348 3349 result = cmap14->results; 3350 for ( i = 0; i < count; i++ ) 3351 { 3352 result[i] = (FT_UInt32)TT_NEXT_UINT24( p ); 3353 p += 8; 3354 } 3355 result[i] = 0; 3356 3357 return result; 3358 } 3359 3360 3361 FT_CALLBACK_DEF( FT_UInt32 * ) tt_cmap14_char_variants(TT_CMap cmap,FT_Memory memory,FT_UInt32 charCode)3362 tt_cmap14_char_variants( TT_CMap cmap, 3363 FT_Memory memory, 3364 FT_UInt32 charCode ) 3365 { 3366 TT_CMap14 cmap14 = (TT_CMap14) cmap; 3367 FT_UInt32 count = cmap14->num_selectors; 3368 FT_Byte* p = cmap->data + 10; 3369 FT_UInt32* q; 3370 3371 3372 if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) ) 3373 return NULL; 3374 3375 for ( q = cmap14->results; count > 0; count-- ) 3376 { 3377 FT_UInt32 varSel = TT_NEXT_UINT24( p ); 3378 FT_ULong defOff = TT_NEXT_ULONG( p ); 3379 FT_ULong nondefOff = TT_NEXT_ULONG( p ); 3380 3381 3382 if ( ( defOff != 0 && 3383 tt_cmap14_char_map_def_binary( cmap->data + defOff, 3384 charCode ) ) || 3385 ( nondefOff != 0 && 3386 tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, 3387 charCode ) != 0 ) ) 3388 { 3389 q[0] = varSel; 3390 q++; 3391 } 3392 } 3393 q[0] = 0; 3394 3395 return cmap14->results; 3396 } 3397 3398 3399 static FT_UInt tt_cmap14_def_char_count(FT_Byte * p)3400 tt_cmap14_def_char_count( FT_Byte *p ) 3401 { 3402 FT_UInt32 numRanges = (FT_UInt32)TT_NEXT_ULONG( p ); 3403 FT_UInt tot = 0; 3404 3405 3406 p += 3; /* point to the first `cnt' field */ 3407 for ( ; numRanges > 0; numRanges-- ) 3408 { 3409 tot += 1 + p[0]; 3410 p += 4; 3411 } 3412 3413 return tot; 3414 } 3415 3416 3417 static FT_UInt32* tt_cmap14_get_def_chars(TT_CMap cmap,FT_Byte * p,FT_Memory memory)3418 tt_cmap14_get_def_chars( TT_CMap cmap, 3419 FT_Byte* p, 3420 FT_Memory memory ) 3421 { 3422 TT_CMap14 cmap14 = (TT_CMap14) cmap; 3423 FT_UInt32 numRanges; 3424 FT_UInt cnt; 3425 FT_UInt32* q; 3426 3427 3428 cnt = tt_cmap14_def_char_count( p ); 3429 numRanges = (FT_UInt32)TT_NEXT_ULONG( p ); 3430 3431 if ( tt_cmap14_ensure( cmap14, ( cnt + 1 ), memory ) ) 3432 return NULL; 3433 3434 for ( q = cmap14->results; numRanges > 0; numRanges-- ) 3435 { 3436 FT_UInt32 uni = (FT_UInt32)TT_NEXT_UINT24( p ); 3437 3438 3439 cnt = FT_NEXT_BYTE( p ) + 1; 3440 do 3441 { 3442 q[0] = uni; 3443 uni += 1; 3444 q += 1; 3445 3446 } while ( --cnt != 0 ); 3447 } 3448 q[0] = 0; 3449 3450 return cmap14->results; 3451 } 3452 3453 3454 static FT_UInt32* tt_cmap14_get_nondef_chars(TT_CMap cmap,FT_Byte * p,FT_Memory memory)3455 tt_cmap14_get_nondef_chars( TT_CMap cmap, 3456 FT_Byte *p, 3457 FT_Memory memory ) 3458 { 3459 TT_CMap14 cmap14 = (TT_CMap14) cmap; 3460 FT_UInt32 numMappings; 3461 FT_UInt i; 3462 FT_UInt32 *ret; 3463 3464 3465 numMappings = (FT_UInt32)TT_NEXT_ULONG( p ); 3466 3467 if ( tt_cmap14_ensure( cmap14, ( numMappings + 1 ), memory ) ) 3468 return NULL; 3469 3470 ret = cmap14->results; 3471 for ( i = 0; i < numMappings; i++ ) 3472 { 3473 ret[i] = (FT_UInt32)TT_NEXT_UINT24( p ); 3474 p += 2; 3475 } 3476 ret[i] = 0; 3477 3478 return ret; 3479 } 3480 3481 3482 FT_CALLBACK_DEF( FT_UInt32 * ) tt_cmap14_variant_chars(TT_CMap cmap,FT_Memory memory,FT_UInt32 variantSelector)3483 tt_cmap14_variant_chars( TT_CMap cmap, 3484 FT_Memory memory, 3485 FT_UInt32 variantSelector ) 3486 { 3487 FT_Byte *p = tt_cmap14_find_variant( cmap->data + 6, 3488 variantSelector ); 3489 FT_Int i; 3490 FT_ULong defOff; 3491 FT_ULong nondefOff; 3492 3493 3494 if ( !p ) 3495 return NULL; 3496 3497 defOff = TT_NEXT_ULONG( p ); 3498 nondefOff = TT_NEXT_ULONG( p ); 3499 3500 if ( defOff == 0 && nondefOff == 0 ) 3501 return NULL; 3502 3503 if ( defOff == 0 ) 3504 return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff, 3505 memory ); 3506 else if ( nondefOff == 0 ) 3507 return tt_cmap14_get_def_chars( cmap, cmap->data + defOff, 3508 memory ); 3509 else 3510 { 3511 /* Both a default and a non-default glyph set? That's probably not */ 3512 /* good font design, but the spec allows for it... */ 3513 TT_CMap14 cmap14 = (TT_CMap14) cmap; 3514 FT_UInt32 numRanges; 3515 FT_UInt32 numMappings; 3516 FT_UInt32 duni; 3517 FT_UInt32 dcnt; 3518 FT_UInt32 nuni; 3519 FT_Byte* dp; 3520 FT_UInt di, ni, k; 3521 3522 FT_UInt32 *ret; 3523 3524 3525 p = cmap->data + nondefOff; 3526 dp = cmap->data + defOff; 3527 3528 numMappings = (FT_UInt32)TT_NEXT_ULONG( p ); 3529 dcnt = tt_cmap14_def_char_count( dp ); 3530 numRanges = (FT_UInt32)TT_NEXT_ULONG( dp ); 3531 3532 if ( numMappings == 0 ) 3533 return tt_cmap14_get_def_chars( cmap, cmap->data + defOff, 3534 memory ); 3535 if ( dcnt == 0 ) 3536 return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff, 3537 memory ); 3538 3539 if ( tt_cmap14_ensure( cmap14, ( dcnt + numMappings + 1 ), memory ) ) 3540 return NULL; 3541 3542 ret = cmap14->results; 3543 duni = (FT_UInt32)TT_NEXT_UINT24( dp ); 3544 dcnt = FT_NEXT_BYTE( dp ); 3545 di = 1; 3546 nuni = (FT_UInt32)TT_NEXT_UINT24( p ); 3547 p += 2; 3548 ni = 1; 3549 i = 0; 3550 3551 for (;;) 3552 { 3553 if ( nuni > duni + dcnt ) 3554 { 3555 for ( k = 0; k <= dcnt; k++ ) 3556 ret[i++] = duni + k; 3557 3558 di++; 3559 3560 if ( di > numRanges ) 3561 break; 3562 3563 duni = (FT_UInt32)TT_NEXT_UINT24( dp ); 3564 dcnt = FT_NEXT_BYTE( dp ); 3565 } 3566 else 3567 { 3568 if ( nuni < duni ) 3569 ret[i++] = nuni; 3570 /* If it is within the default range then ignore it -- */ 3571 /* that should not have happened */ 3572 ni++; 3573 if ( ni > numMappings ) 3574 break; 3575 3576 nuni = (FT_UInt32)TT_NEXT_UINT24( p ); 3577 p += 2; 3578 } 3579 } 3580 3581 if ( ni <= numMappings ) 3582 { 3583 /* If we get here then we have run out of all default ranges. */ 3584 /* We have read one non-default mapping which we haven't stored */ 3585 /* and there may be others that need to be read. */ 3586 ret[i++] = nuni; 3587 while ( ni < numMappings ) 3588 { 3589 ret[i++] = (FT_UInt32)TT_NEXT_UINT24( p ); 3590 p += 2; 3591 ni++; 3592 } 3593 } 3594 else if ( di <= numRanges ) 3595 { 3596 /* If we get here then we have run out of all non-default */ 3597 /* mappings. We have read one default range which we haven't */ 3598 /* stored and there may be others that need to be read. */ 3599 for ( k = 0; k <= dcnt; k++ ) 3600 ret[i++] = duni + k; 3601 3602 while ( di < numRanges ) 3603 { 3604 duni = (FT_UInt32)TT_NEXT_UINT24( dp ); 3605 dcnt = FT_NEXT_BYTE( dp ); 3606 3607 for ( k = 0; k <= dcnt; k++ ) 3608 ret[i++] = duni + k; 3609 di++; 3610 } 3611 } 3612 3613 ret[i] = 0; 3614 3615 return ret; 3616 } 3617 } 3618 3619 3620 FT_DEFINE_TT_CMAP( 3621 tt_cmap14_class_rec, 3622 3623 sizeof ( TT_CMap14Rec ), 3624 3625 (FT_CMap_InitFunc) tt_cmap14_init, /* init */ 3626 (FT_CMap_DoneFunc) tt_cmap14_done, /* done */ 3627 (FT_CMap_CharIndexFunc)tt_cmap14_char_index, /* char_index */ 3628 (FT_CMap_CharNextFunc) tt_cmap14_char_next, /* char_next */ 3629 3630 /* Format 14 extension functions */ 3631 (FT_CMap_CharVarIndexFunc) tt_cmap14_char_var_index, 3632 (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault, 3633 (FT_CMap_VariantListFunc) tt_cmap14_variants, 3634 (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants, 3635 (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars, 3636 3637 14, 3638 (TT_CMap_ValidateFunc)tt_cmap14_validate, /* validate */ 3639 (TT_CMap_Info_GetFunc)tt_cmap14_get_info /* get_cmap_info */ 3640 ) 3641 3642 #endif /* TT_CONFIG_CMAP_FORMAT_14 */ 3643 3644 3645 /*************************************************************************/ 3646 /*************************************************************************/ 3647 /***** *****/ 3648 /***** SYNTHETIC UNICODE *****/ 3649 /***** *****/ 3650 /*************************************************************************/ 3651 /*************************************************************************/ 3652 3653 /* This charmap is generated using postscript glyph names. */ 3654 3655 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES 3656 FT_CALLBACK_DEF(const char *)3657 FT_CALLBACK_DEF( const char * ) 3658 tt_get_glyph_name( TT_Face face, 3659 FT_UInt idx ) 3660 { 3661 FT_String* PSname = NULL; 3662 3663 3664 tt_face_get_ps_name( face, idx, &PSname ); 3665 3666 return PSname; 3667 } 3668 3669 3670 FT_CALLBACK_DEF( FT_Error ) tt_cmap_unicode_init(PS_Unicodes unicodes,FT_Pointer pointer)3671 tt_cmap_unicode_init( PS_Unicodes unicodes, 3672 FT_Pointer pointer ) 3673 { 3674 TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); 3675 FT_Memory memory = FT_FACE_MEMORY( face ); 3676 FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)face->psnames; 3677 3678 FT_UNUSED( pointer ); 3679 3680 3681 if ( !psnames->unicodes_init ) 3682 return FT_THROW( Unimplemented_Feature ); 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