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