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