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