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