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