00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <ft2build.h>
00020 #include FT_INTERNAL_DEBUG_H
00021
00022 #include "sferrors.h"
00023
00024 #include FT_INTERNAL_VALIDATE_H
00025 #include FT_INTERNAL_STREAM_H
00026 #include "ttload.h"
00027 #include "ttcmap.h"
00028 #include "sfntpic.h"
00029
00030
00031
00032
00033
00034
00035
00036
00037 #undef FT_COMPONENT
00038 #define FT_COMPONENT trace_ttcmap
00039
00040
00041 #define TT_PEEK_SHORT FT_PEEK_SHORT
00042 #define TT_PEEK_USHORT FT_PEEK_USHORT
00043 #define TT_PEEK_UINT24 FT_PEEK_UOFF3
00044 #define TT_PEEK_LONG FT_PEEK_LONG
00045 #define TT_PEEK_ULONG FT_PEEK_ULONG
00046
00047 #define TT_NEXT_SHORT FT_NEXT_SHORT
00048 #define TT_NEXT_USHORT FT_NEXT_USHORT
00049 #define TT_NEXT_UINT24 FT_NEXT_UOFF3
00050 #define TT_NEXT_LONG FT_NEXT_LONG
00051 #define TT_NEXT_ULONG FT_NEXT_ULONG
00052
00053
00054 FT_CALLBACK_DEF( FT_Error )
00055 tt_cmap_init( TT_CMap cmap,
00056 FT_Byte* table )
00057 {
00058 cmap->data = table;
00059 return SFNT_Err_Ok;
00060 }
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 #ifdef TT_CONFIG_CMAP_FORMAT_0
00086
00087 FT_CALLBACK_DEF( FT_Error )
00088 tt_cmap0_validate( FT_Byte* table,
00089 FT_Validator valid )
00090 {
00091 FT_Byte* p = table + 2;
00092 FT_UInt length = TT_NEXT_USHORT( p );
00093
00094
00095 if ( table + length > valid->limit || length < 262 )
00096 FT_INVALID_TOO_SHORT;
00097
00098
00099 if ( valid->level >= FT_VALIDATE_TIGHT )
00100 {
00101 FT_UInt n, idx;
00102
00103
00104 p = table + 6;
00105 for ( n = 0; n < 256; n++ )
00106 {
00107 idx = *p++;
00108 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
00109 FT_INVALID_GLYPH_ID;
00110 }
00111 }
00112
00113 return SFNT_Err_Ok;
00114 }
00115
00116
00117 FT_CALLBACK_DEF( FT_UInt )
00118 tt_cmap0_char_index( TT_CMap cmap,
00119 FT_UInt32 char_code )
00120 {
00121 FT_Byte* table = cmap->data;
00122
00123
00124 return char_code < 256 ? table[6 + char_code] : 0;
00125 }
00126
00127
00128 FT_CALLBACK_DEF( FT_UInt32 )
00129 tt_cmap0_char_next( TT_CMap cmap,
00130 FT_UInt32 *pchar_code )
00131 {
00132 FT_Byte* table = cmap->data;
00133 FT_UInt32 charcode = *pchar_code;
00134 FT_UInt32 result = 0;
00135 FT_UInt gindex = 0;
00136
00137
00138 table += 6;
00139 while ( ++charcode < 256 )
00140 {
00141 gindex = table[charcode];
00142 if ( gindex != 0 )
00143 {
00144 result = charcode;
00145 break;
00146 }
00147 }
00148
00149 *pchar_code = result;
00150 return gindex;
00151 }
00152
00153
00154 FT_CALLBACK_DEF( FT_Error )
00155 tt_cmap0_get_info( TT_CMap cmap,
00156 TT_CMapInfo *cmap_info )
00157 {
00158 FT_Byte* p = cmap->data + 4;
00159
00160
00161 cmap_info->format = 0;
00162 cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
00163
00164 return SFNT_Err_Ok;
00165 }
00166
00167
00168 FT_DEFINE_TT_CMAP(tt_cmap0_class_rec,
00169 sizeof ( TT_CMapRec ),
00170
00171 (FT_CMap_InitFunc) tt_cmap_init,
00172 (FT_CMap_DoneFunc) NULL,
00173 (FT_CMap_CharIndexFunc)tt_cmap0_char_index,
00174 (FT_CMap_CharNextFunc) tt_cmap0_char_next,
00175
00176 NULL, NULL, NULL, NULL, NULL
00177 ,
00178 0,
00179 (TT_CMap_ValidateFunc) tt_cmap0_validate,
00180 (TT_CMap_Info_GetFunc) tt_cmap0_get_info
00181 )
00182
00183 #endif
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272 #ifdef TT_CONFIG_CMAP_FORMAT_2
00273
00274 FT_CALLBACK_DEF( FT_Error )
00275 tt_cmap2_validate( FT_Byte* table,
00276 FT_Validator valid )
00277 {
00278 FT_Byte* p = table + 2;
00279 FT_UInt length = TT_PEEK_USHORT( p );
00280 FT_UInt n, max_subs;
00281 FT_Byte* keys;
00282 FT_Byte* subs;
00283 FT_Byte* glyph_ids;
00284
00285
00286 if ( table + length > valid->limit || length < 6 + 512 )
00287 FT_INVALID_TOO_SHORT;
00288
00289 keys = table + 6;
00290
00291
00292 p = keys;
00293 max_subs = 0;
00294 for ( n = 0; n < 256; n++ )
00295 {
00296 FT_UInt idx = TT_NEXT_USHORT( p );
00297
00298
00299
00300 if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 )
00301 FT_INVALID_DATA;
00302
00303 idx >>= 3;
00304
00305 if ( idx > max_subs )
00306 max_subs = idx;
00307 }
00308
00309 FT_ASSERT( p == table + 518 );
00310
00311 subs = p;
00312 glyph_ids = subs + (max_subs + 1) * 8;
00313 if ( glyph_ids > valid->limit )
00314 FT_INVALID_TOO_SHORT;
00315
00316
00317 for ( n = 0; n <= max_subs; n++ )
00318 {
00319 FT_UInt first_code, code_count, offset;
00320 FT_Int delta;
00321 FT_Byte* ids;
00322
00323
00324 first_code = TT_NEXT_USHORT( p );
00325 code_count = TT_NEXT_USHORT( p );
00326 delta = TT_NEXT_SHORT( p );
00327 offset = TT_NEXT_USHORT( p );
00328
00329
00330 if ( code_count == 0 )
00331 continue;
00332
00333
00334 if ( valid->level >= FT_VALIDATE_PARANOID )
00335 {
00336 if ( first_code >= 256 || first_code + code_count > 256 )
00337 FT_INVALID_DATA;
00338 }
00339
00340
00341 if ( offset != 0 )
00342 {
00343 ids = p - 2 + offset;
00344 if ( ids < glyph_ids || ids + code_count*2 > table + length )
00345 FT_INVALID_OFFSET;
00346
00347
00348 if ( valid->level >= FT_VALIDATE_TIGHT )
00349 {
00350 FT_Byte* limit = p + code_count * 2;
00351 FT_UInt idx;
00352
00353
00354 for ( ; p < limit; )
00355 {
00356 idx = TT_NEXT_USHORT( p );
00357 if ( idx != 0 )
00358 {
00359 idx = ( idx + delta ) & 0xFFFFU;
00360 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
00361 FT_INVALID_GLYPH_ID;
00362 }
00363 }
00364 }
00365 }
00366 }
00367
00368 return SFNT_Err_Ok;
00369 }
00370
00371
00372
00373
00374 static FT_Byte*
00375 tt_cmap2_get_subheader( FT_Byte* table,
00376 FT_UInt32 char_code )
00377 {
00378 FT_Byte* result = NULL;
00379
00380
00381 if ( char_code < 0x10000UL )
00382 {
00383 FT_UInt char_lo = (FT_UInt)( char_code & 0xFF );
00384 FT_UInt char_hi = (FT_UInt)( char_code >> 8 );
00385 FT_Byte* p = table + 6;
00386 FT_Byte* subs = table + 518;
00387 FT_Byte* sub;
00388
00389
00390 if ( char_hi == 0 )
00391 {
00392
00393
00394
00395 sub = subs;
00396
00397
00398
00399
00400
00401 p += char_lo * 2;
00402 if ( TT_PEEK_USHORT( p ) != 0 )
00403 goto Exit;
00404 }
00405 else
00406 {
00407
00408
00409
00410 p += char_hi * 2;
00411
00412 sub = subs + ( FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 8 ) );
00413
00414
00415 if ( sub == subs )
00416 goto Exit;
00417 }
00418 result = sub;
00419 }
00420 Exit:
00421 return result;
00422 }
00423
00424
00425 FT_CALLBACK_DEF( FT_UInt )
00426 tt_cmap2_char_index( TT_CMap cmap,
00427 FT_UInt32 char_code )
00428 {
00429 FT_Byte* table = cmap->data;
00430 FT_UInt result = 0;
00431 FT_Byte* subheader;
00432
00433
00434 subheader = tt_cmap2_get_subheader( table, char_code );
00435 if ( subheader )
00436 {
00437 FT_Byte* p = subheader;
00438 FT_UInt idx = (FT_UInt)(char_code & 0xFF);
00439 FT_UInt start, count;
00440 FT_Int delta;
00441 FT_UInt offset;
00442
00443
00444 start = TT_NEXT_USHORT( p );
00445 count = TT_NEXT_USHORT( p );
00446 delta = TT_NEXT_SHORT ( p );
00447 offset = TT_PEEK_USHORT( p );
00448
00449 idx -= start;
00450 if ( idx < count && offset != 0 )
00451 {
00452 p += offset + 2 * idx;
00453 idx = TT_PEEK_USHORT( p );
00454
00455 if ( idx != 0 )
00456 result = (FT_UInt)( idx + delta ) & 0xFFFFU;
00457 }
00458 }
00459 return result;
00460 }
00461
00462
00463 FT_CALLBACK_DEF( FT_UInt32 )
00464 tt_cmap2_char_next( TT_CMap cmap,
00465 FT_UInt32 *pcharcode )
00466 {
00467 FT_Byte* table = cmap->data;
00468 FT_UInt gindex = 0;
00469 FT_UInt32 result = 0;
00470 FT_UInt32 charcode = *pcharcode + 1;
00471 FT_Byte* subheader;
00472
00473
00474 while ( charcode < 0x10000UL )
00475 {
00476 subheader = tt_cmap2_get_subheader( table, charcode );
00477 if ( subheader )
00478 {
00479 FT_Byte* p = subheader;
00480 FT_UInt start = TT_NEXT_USHORT( p );
00481 FT_UInt count = TT_NEXT_USHORT( p );
00482 FT_Int delta = TT_NEXT_SHORT ( p );
00483 FT_UInt offset = TT_PEEK_USHORT( p );
00484 FT_UInt char_lo = (FT_UInt)( charcode & 0xFF );
00485 FT_UInt pos, idx;
00486
00487
00488 if ( offset == 0 )
00489 goto Next_SubHeader;
00490
00491 if ( char_lo < start )
00492 {
00493 char_lo = start;
00494 pos = 0;
00495 }
00496 else
00497 pos = (FT_UInt)( char_lo - start );
00498
00499 p += offset + pos * 2;
00500 charcode = FT_PAD_FLOOR( charcode, 256 ) + char_lo;
00501
00502 for ( ; pos < count; pos++, charcode++ )
00503 {
00504 idx = TT_NEXT_USHORT( p );
00505
00506 if ( idx != 0 )
00507 {
00508 gindex = ( idx + delta ) & 0xFFFFU;
00509 if ( gindex != 0 )
00510 {
00511 result = charcode;
00512 goto Exit;
00513 }
00514 }
00515 }
00516 }
00517
00518
00519 Next_SubHeader:
00520 charcode = FT_PAD_FLOOR( charcode, 256 ) + 256;
00521 }
00522
00523 Exit:
00524 *pcharcode = result;
00525
00526 return gindex;
00527 }
00528
00529
00530 FT_CALLBACK_DEF( FT_Error )
00531 tt_cmap2_get_info( TT_CMap cmap,
00532 TT_CMapInfo *cmap_info )
00533 {
00534 FT_Byte* p = cmap->data + 4;
00535
00536
00537 cmap_info->format = 2;
00538 cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
00539
00540 return SFNT_Err_Ok;
00541 }
00542
00543
00544 FT_DEFINE_TT_CMAP(tt_cmap2_class_rec,
00545 sizeof ( TT_CMapRec ),
00546
00547 (FT_CMap_InitFunc) tt_cmap_init,
00548 (FT_CMap_DoneFunc) NULL,
00549 (FT_CMap_CharIndexFunc)tt_cmap2_char_index,
00550 (FT_CMap_CharNextFunc) tt_cmap2_char_next,
00551
00552 NULL, NULL, NULL, NULL, NULL
00553 ,
00554 2,
00555 (TT_CMap_ValidateFunc) tt_cmap2_validate,
00556 (TT_CMap_Info_GetFunc) tt_cmap2_get_info
00557 )
00558
00559 #endif
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 #ifdef TT_CONFIG_CMAP_FORMAT_4
00634
00635 typedef struct TT_CMap4Rec_
00636 {
00637 TT_CMapRec cmap;
00638 FT_UInt32 cur_charcode;
00639 FT_UInt cur_gindex;
00640
00641 FT_UInt num_ranges;
00642 FT_UInt cur_range;
00643 FT_UInt cur_start;
00644 FT_UInt cur_end;
00645 FT_Int cur_delta;
00646 FT_Byte* cur_values;
00647
00648 } TT_CMap4Rec, *TT_CMap4;
00649
00650
00651 FT_CALLBACK_DEF( FT_Error )
00652 tt_cmap4_init( TT_CMap4 cmap,
00653 FT_Byte* table )
00654 {
00655 FT_Byte* p;
00656
00657
00658 cmap->cmap.data = table;
00659
00660 p = table + 6;
00661 cmap->num_ranges = FT_PEEK_USHORT( p ) >> 1;
00662 cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL;
00663 cmap->cur_gindex = 0;
00664
00665 return SFNT_Err_Ok;
00666 }
00667
00668
00669 static FT_Int
00670 tt_cmap4_set_range( TT_CMap4 cmap,
00671 FT_UInt range_index )
00672 {
00673 FT_Byte* table = cmap->cmap.data;
00674 FT_Byte* p;
00675 FT_UInt num_ranges = cmap->num_ranges;
00676
00677
00678 while ( range_index < num_ranges )
00679 {
00680 FT_UInt offset;
00681
00682
00683 p = table + 14 + range_index * 2;
00684 cmap->cur_end = FT_PEEK_USHORT( p );
00685
00686 p += 2 + num_ranges * 2;
00687 cmap->cur_start = FT_PEEK_USHORT( p );
00688
00689 p += num_ranges * 2;
00690 cmap->cur_delta = FT_PEEK_SHORT( p );
00691
00692 p += num_ranges * 2;
00693 offset = FT_PEEK_USHORT( p );
00694
00695
00696
00697 if ( range_index >= num_ranges - 1 &&
00698 cmap->cur_start == 0xFFFFU &&
00699 cmap->cur_end == 0xFFFFU )
00700 {
00701 TT_Face face = (TT_Face)cmap->cmap.cmap.charmap.face;
00702 FT_Byte* limit = face->cmap_table + face->cmap_size;
00703
00704
00705 if ( offset && p + offset + 2 > limit )
00706 {
00707 cmap->cur_delta = 1;
00708 offset = 0;
00709 }
00710 }
00711
00712 if ( offset != 0xFFFFU )
00713 {
00714 cmap->cur_values = offset ? p + offset : NULL;
00715 cmap->cur_range = range_index;
00716 return 0;
00717 }
00718
00719
00720 range_index++;
00721 }
00722
00723 return -1;
00724 }
00725
00726
00727
00728
00729
00730
00731 static void
00732 tt_cmap4_next( TT_CMap4 cmap )
00733 {
00734 FT_UInt charcode;
00735
00736
00737 if ( cmap->cur_charcode >= 0xFFFFUL )
00738 goto Fail;
00739
00740 charcode = (FT_UInt)cmap->cur_charcode + 1;
00741
00742 if ( charcode < cmap->cur_start )
00743 charcode = cmap->cur_start;
00744
00745 for ( ;; )
00746 {
00747 FT_Byte* values = cmap->cur_values;
00748 FT_UInt end = cmap->cur_end;
00749 FT_Int delta = cmap->cur_delta;
00750
00751
00752 if ( charcode <= end )
00753 {
00754 if ( values )
00755 {
00756 FT_Byte* p = values + 2 * ( charcode - cmap->cur_start );
00757
00758
00759 do
00760 {
00761 FT_UInt gindex = FT_NEXT_USHORT( p );
00762
00763
00764 if ( gindex != 0 )
00765 {
00766 gindex = (FT_UInt)( ( gindex + delta ) & 0xFFFFU );
00767 if ( gindex != 0 )
00768 {
00769 cmap->cur_charcode = charcode;
00770 cmap->cur_gindex = gindex;
00771 return;
00772 }
00773 }
00774 } while ( ++charcode <= end );
00775 }
00776 else
00777 {
00778 do
00779 {
00780 FT_UInt gindex = (FT_UInt)( ( charcode + delta ) & 0xFFFFU );
00781
00782
00783 if ( gindex != 0 )
00784 {
00785 cmap->cur_charcode = charcode;
00786 cmap->cur_gindex = gindex;
00787 return;
00788 }
00789 } while ( ++charcode <= end );
00790 }
00791 }
00792
00793
00794 if ( tt_cmap4_set_range( cmap, cmap->cur_range + 1 ) < 0 )
00795 break;
00796
00797 if ( charcode < cmap->cur_start )
00798 charcode = cmap->cur_start;
00799 }
00800
00801 Fail:
00802 cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL;
00803 cmap->cur_gindex = 0;
00804 }
00805
00806
00807 FT_CALLBACK_DEF( FT_Error )
00808 tt_cmap4_validate( FT_Byte* table,
00809 FT_Validator valid )
00810 {
00811 FT_Byte* p = table + 2;
00812 FT_UInt length = TT_NEXT_USHORT( p );
00813 FT_Byte *ends, *starts, *offsets, *deltas, *glyph_ids;
00814 FT_UInt num_segs;
00815 FT_Error error = SFNT_Err_Ok;
00816
00817
00818 if ( length < 16 )
00819 FT_INVALID_TOO_SHORT;
00820
00821
00822
00823 if ( table + length > valid->limit )
00824 {
00825 if ( valid->level >= FT_VALIDATE_TIGHT )
00826 FT_INVALID_TOO_SHORT;
00827
00828 length = (FT_UInt)( valid->limit - table );
00829 }
00830
00831 p = table + 6;
00832 num_segs = TT_NEXT_USHORT( p );
00833
00834 if ( valid->level >= FT_VALIDATE_PARANOID )
00835 {
00836
00837 if ( num_segs & 1 )
00838 FT_INVALID_DATA;
00839 }
00840
00841 num_segs /= 2;
00842
00843 if ( length < 16 + num_segs * 2 * 4 )
00844 FT_INVALID_TOO_SHORT;
00845
00846
00847
00848 if ( valid->level >= FT_VALIDATE_PARANOID )
00849 {
00850
00851 FT_UInt search_range = TT_NEXT_USHORT( p );
00852 FT_UInt entry_selector = TT_NEXT_USHORT( p );
00853 FT_UInt range_shift = TT_NEXT_USHORT( p );
00854
00855
00856 if ( ( search_range | range_shift ) & 1 )
00857 FT_INVALID_DATA;
00858
00859 search_range /= 2;
00860 range_shift /= 2;
00861
00862
00863
00864 if ( search_range > num_segs ||
00865 search_range * 2 < num_segs ||
00866 search_range + range_shift != num_segs ||
00867 search_range != ( 1U << entry_selector ) )
00868 FT_INVALID_DATA;
00869 }
00870
00871 ends = table + 14;
00872 starts = table + 16 + num_segs * 2;
00873 deltas = starts + num_segs * 2;
00874 offsets = deltas + num_segs * 2;
00875 glyph_ids = offsets + num_segs * 2;
00876
00877
00878 if ( valid->level >= FT_VALIDATE_PARANOID )
00879 {
00880 p = ends + ( num_segs - 1 ) * 2;
00881 if ( TT_PEEK_USHORT( p ) != 0xFFFFU )
00882 FT_INVALID_DATA;
00883 }
00884
00885 {
00886 FT_UInt start, end, offset, n;
00887 FT_UInt last_start = 0, last_end = 0;
00888 FT_Int delta;
00889 FT_Byte* p_start = starts;
00890 FT_Byte* p_end = ends;
00891 FT_Byte* p_delta = deltas;
00892 FT_Byte* p_offset = offsets;
00893
00894
00895 for ( n = 0; n < num_segs; n++ )
00896 {
00897 p = p_offset;
00898 start = TT_NEXT_USHORT( p_start );
00899 end = TT_NEXT_USHORT( p_end );
00900 delta = TT_NEXT_SHORT( p_delta );
00901 offset = TT_NEXT_USHORT( p_offset );
00902
00903 if ( start > end )
00904 FT_INVALID_DATA;
00905
00906
00907
00908
00909
00910 if ( start <= last_end && n > 0 )
00911 {
00912 if ( valid->level >= FT_VALIDATE_TIGHT )
00913 FT_INVALID_DATA;
00914 else
00915 {
00916
00917
00918
00919 if ( last_start > start || last_end > end )
00920 error |= TT_CMAP_FLAG_UNSORTED;
00921 else
00922 error |= TT_CMAP_FLAG_OVERLAPPING;
00923 }
00924 }
00925
00926 if ( offset && offset != 0xFFFFU )
00927 {
00928 p += offset;
00929
00930
00931 if ( valid->level >= FT_VALIDATE_TIGHT )
00932 {
00933 if ( p < glyph_ids ||
00934 p + ( end - start + 1 ) * 2 > table + length )
00935 FT_INVALID_DATA;
00936 }
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947 else if ( n != num_segs - 1 ||
00948 !( start == 0xFFFFU && end == 0xFFFFU ) )
00949 {
00950 if ( p < glyph_ids ||
00951 p + ( end - start + 1 ) * 2 > valid->limit )
00952 FT_INVALID_DATA;
00953 }
00954
00955
00956 if ( valid->level >= FT_VALIDATE_TIGHT )
00957 {
00958 FT_UInt i, idx;
00959
00960
00961 for ( i = start; i < end; i++ )
00962 {
00963 idx = FT_NEXT_USHORT( p );
00964 if ( idx != 0 )
00965 {
00966 idx = (FT_UInt)( idx + delta ) & 0xFFFFU;
00967
00968 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) )
00969 FT_INVALID_GLYPH_ID;
00970 }
00971 }
00972 }
00973 }
00974 else if ( offset == 0xFFFFU )
00975 {
00976
00977
00978
00979 if ( valid->level >= FT_VALIDATE_PARANOID ||
00980 n != num_segs - 1 ||
00981 !( start == 0xFFFFU && end == 0xFFFFU ) )
00982 FT_INVALID_DATA;
00983 }
00984
00985 last_start = start;
00986 last_end = end;
00987 }
00988 }
00989
00990 return error;
00991 }
00992
00993
00994 static FT_UInt
00995 tt_cmap4_char_map_linear( TT_CMap cmap,
00996 FT_UInt32* pcharcode,
00997 FT_Bool next )
00998 {
00999 FT_UInt num_segs2, start, end, offset;
01000 FT_Int delta;
01001 FT_UInt i, num_segs;
01002 FT_UInt32 charcode = *pcharcode;
01003 FT_UInt gindex = 0;
01004 FT_Byte* p;
01005
01006
01007 p = cmap->data + 6;
01008 num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );
01009
01010 num_segs = num_segs2 >> 1;
01011
01012 if ( !num_segs )
01013 return 0;
01014
01015 if ( next )
01016 charcode++;
01017
01018
01019 for ( ; charcode <= 0xFFFFU; charcode++ )
01020 {
01021 FT_Byte* q;
01022
01023
01024 p = cmap->data + 14;
01025 q = cmap->data + 16 + num_segs2;
01026
01027 for ( i = 0; i < num_segs; i++ )
01028 {
01029 end = TT_NEXT_USHORT( p );
01030 start = TT_NEXT_USHORT( q );
01031
01032 if ( charcode >= start && charcode <= end )
01033 {
01034 p = q - 2 + num_segs2;
01035 delta = TT_PEEK_SHORT( p );
01036 p += num_segs2;
01037 offset = TT_PEEK_USHORT( p );
01038
01039
01040
01041 if ( i >= num_segs - 1 &&
01042 start == 0xFFFFU && end == 0xFFFFU )
01043 {
01044 TT_Face face = (TT_Face)cmap->cmap.charmap.face;
01045 FT_Byte* limit = face->cmap_table + face->cmap_size;
01046
01047
01048 if ( offset && p + offset + 2 > limit )
01049 {
01050 delta = 1;
01051 offset = 0;
01052 }
01053 }
01054
01055 if ( offset == 0xFFFFU )
01056 continue;
01057
01058 if ( offset )
01059 {
01060 p += offset + ( charcode - start ) * 2;
01061 gindex = TT_PEEK_USHORT( p );
01062 if ( gindex != 0 )
01063 gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
01064 }
01065 else
01066 gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;
01067
01068 break;
01069 }
01070 }
01071
01072 if ( !next || gindex )
01073 break;
01074 }
01075
01076 if ( next && gindex )
01077 *pcharcode = charcode;
01078
01079 return gindex;
01080 }
01081
01082
01083 static FT_UInt
01084 tt_cmap4_char_map_binary( TT_CMap cmap,
01085 FT_UInt32* pcharcode,
01086 FT_Bool next )
01087 {
01088 FT_UInt num_segs2, start, end, offset;
01089 FT_Int delta;
01090 FT_UInt max, min, mid, num_segs;
01091 FT_UInt charcode = (FT_UInt)*pcharcode;
01092 FT_UInt gindex = 0;
01093 FT_Byte* p;
01094
01095
01096 p = cmap->data + 6;
01097 num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 );
01098
01099 if ( !num_segs2 )
01100 return 0;
01101
01102 num_segs = num_segs2 >> 1;
01103
01104
01105 mid = num_segs;
01106 end = 0xFFFFU;
01107
01108 if ( next )
01109 charcode++;
01110
01111 min = 0;
01112 max = num_segs;
01113
01114
01115 while ( min < max )
01116 {
01117 mid = ( min + max ) >> 1;
01118 p = cmap->data + 14 + mid * 2;
01119 end = TT_PEEK_USHORT( p );
01120 p += 2 + num_segs2;
01121 start = TT_PEEK_USHORT( p );
01122
01123 if ( charcode < start )
01124 max = mid;
01125 else if ( charcode > end )
01126 min = mid + 1;
01127 else
01128 {
01129 p += num_segs2;
01130 delta = TT_PEEK_SHORT( p );
01131 p += num_segs2;
01132 offset = TT_PEEK_USHORT( p );
01133
01134
01135
01136 if ( mid >= num_segs - 1 &&
01137 start == 0xFFFFU && end == 0xFFFFU )
01138 {
01139 TT_Face face = (TT_Face)cmap->cmap.charmap.face;
01140 FT_Byte* limit = face->cmap_table + face->cmap_size;
01141
01142
01143 if ( offset && p + offset + 2 > limit )
01144 {
01145 delta = 1;
01146 offset = 0;
01147 }
01148 }
01149
01150
01151 if ( cmap->flags & TT_CMAP_FLAG_OVERLAPPING )
01152 {
01153 FT_UInt i;
01154
01155
01156
01157 max = mid;
01158
01159 if ( offset == 0xFFFFU )
01160 mid = max + 1;
01161
01162
01163 for ( i = max ; i > 0; i-- )
01164 {
01165 FT_UInt prev_end;
01166 FT_Byte* old_p;
01167
01168
01169 old_p = p;
01170 p = cmap->data + 14 + ( i - 1 ) * 2;
01171 prev_end = TT_PEEK_USHORT( p );
01172
01173 if ( charcode > prev_end )
01174 {
01175 p = old_p;
01176 break;
01177 }
01178
01179 end = prev_end;
01180 p += 2 + num_segs2;
01181 start = TT_PEEK_USHORT( p );
01182 p += num_segs2;
01183 delta = TT_PEEK_SHORT( p );
01184 p += num_segs2;
01185 offset = TT_PEEK_USHORT( p );
01186
01187 if ( offset != 0xFFFFU )
01188 mid = i - 1;
01189 }
01190
01191
01192 if ( mid == max + 1 )
01193 {
01194 if ( i != max )
01195 {
01196 p = cmap->data + 14 + max * 2;
01197 end = TT_PEEK_USHORT( p );
01198 p += 2 + num_segs2;
01199 start = TT_PEEK_USHORT( p );
01200 p += num_segs2;
01201 delta = TT_PEEK_SHORT( p );
01202 p += num_segs2;
01203 offset = TT_PEEK_USHORT( p );
01204 }
01205
01206 mid = max;
01207
01208
01209 for ( i = max + 1; i < num_segs; i++ )
01210 {
01211 FT_UInt next_end, next_start;
01212
01213
01214 p = cmap->data + 14 + i * 2;
01215 next_end = TT_PEEK_USHORT( p );
01216 p += 2 + num_segs2;
01217 next_start = TT_PEEK_USHORT( p );
01218
01219 if ( charcode < next_start )
01220 break;
01221
01222 end = next_end;
01223 start = next_start;
01224 p += num_segs2;
01225 delta = TT_PEEK_SHORT( p );
01226 p += num_segs2;
01227 offset = TT_PEEK_USHORT( p );
01228
01229 if ( offset != 0xFFFFU )
01230 mid = i;
01231 }
01232 i--;
01233
01234
01235 if ( mid == max )
01236 {
01237 mid = i;
01238
01239 break;
01240 }
01241 }
01242
01243
01244 if ( mid != i )
01245 {
01246 p = cmap->data + 14 + mid * 2;
01247 end = TT_PEEK_USHORT( p );
01248 p += 2 + num_segs2;
01249 start = TT_PEEK_USHORT( p );
01250 p += num_segs2;
01251 delta = TT_PEEK_SHORT( p );
01252 p += num_segs2;
01253 offset = TT_PEEK_USHORT( p );
01254 }
01255 }
01256 else
01257 {
01258 if ( offset == 0xFFFFU )
01259 break;
01260 }
01261
01262 if ( offset )
01263 {
01264 p += offset + ( charcode - start ) * 2;
01265 gindex = TT_PEEK_USHORT( p );
01266 if ( gindex != 0 )
01267 gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU;
01268 }
01269 else
01270 gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU;
01271
01272 break;
01273 }
01274 }
01275
01276 if ( next )
01277 {
01278 TT_CMap4 cmap4 = (TT_CMap4)cmap;
01279
01280
01281
01282
01283
01284
01285 if ( charcode > end )
01286 {
01287 mid++;
01288 if ( mid == num_segs )
01289 return 0;
01290 }
01291
01292 if ( tt_cmap4_set_range( cmap4, mid ) )
01293 {
01294 if ( gindex )
01295 *pcharcode = charcode;
01296 }
01297 else
01298 {
01299 cmap4->cur_charcode = charcode;
01300
01301 if ( gindex )
01302 cmap4->cur_gindex = gindex;
01303 else
01304 {
01305 cmap4->cur_charcode = charcode;
01306 tt_cmap4_next( cmap4 );
01307 gindex = cmap4->cur_gindex;
01308 }
01309
01310 if ( gindex )
01311 *pcharcode = cmap4->cur_charcode;
01312 }
01313 }
01314
01315 return gindex;
01316 }
01317
01318
01319 FT_CALLBACK_DEF( FT_UInt )
01320 tt_cmap4_char_index( TT_CMap cmap,
01321 FT_UInt32 char_code )
01322 {
01323 if ( char_code >= 0x10000UL )
01324 return 0;
01325
01326 if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )
01327 return tt_cmap4_char_map_linear( cmap, &char_code, 0 );
01328 else
01329 return tt_cmap4_char_map_binary( cmap, &char_code, 0 );
01330 }
01331
01332
01333 FT_CALLBACK_DEF( FT_UInt32 )
01334 tt_cmap4_char_next( TT_CMap cmap,
01335 FT_UInt32 *pchar_code )
01336 {
01337 FT_UInt gindex;
01338
01339
01340 if ( *pchar_code >= 0xFFFFU )
01341 return 0;
01342
01343 if ( cmap->flags & TT_CMAP_FLAG_UNSORTED )
01344 gindex = tt_cmap4_char_map_linear( cmap, pchar_code, 1 );
01345 else
01346 {
01347 TT_CMap4 cmap4 = (TT_CMap4)cmap;
01348
01349
01350
01351 if ( *pchar_code == cmap4->cur_charcode )
01352 {
01353 tt_cmap4_next( cmap4 );
01354 gindex = cmap4->cur_gindex;
01355 if ( gindex )
01356 *pchar_code = cmap4->cur_charcode;
01357 }
01358 else
01359 gindex = tt_cmap4_char_map_binary( cmap, pchar_code, 1 );
01360 }
01361
01362 return gindex;
01363 }
01364
01365
01366 FT_CALLBACK_DEF( FT_Error )
01367 tt_cmap4_get_info( TT_CMap cmap,
01368 TT_CMapInfo *cmap_info )
01369 {
01370 FT_Byte* p = cmap->data + 4;
01371
01372
01373 cmap_info->format = 4;
01374 cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
01375
01376 return SFNT_Err_Ok;
01377 }
01378
01379
01380 FT_DEFINE_TT_CMAP(tt_cmap4_class_rec,
01381 sizeof ( TT_CMap4Rec ),
01382 (FT_CMap_InitFunc) tt_cmap4_init,
01383 (FT_CMap_DoneFunc) NULL,
01384 (FT_CMap_CharIndexFunc)tt_cmap4_char_index,
01385 (FT_CMap_CharNextFunc) tt_cmap4_char_next,
01386
01387 NULL, NULL, NULL, NULL, NULL
01388 ,
01389 4,
01390 (TT_CMap_ValidateFunc) tt_cmap4_validate,
01391 (TT_CMap_Info_GetFunc) tt_cmap4_get_info
01392 )
01393
01394 #endif
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423 #ifdef TT_CONFIG_CMAP_FORMAT_6
01424
01425 FT_CALLBACK_DEF( FT_Error )
01426 tt_cmap6_validate( FT_Byte* table,
01427 FT_Validator valid )
01428 {
01429 FT_Byte* p;
01430 FT_UInt length, count;
01431
01432
01433 if ( table + 10 > valid->limit )
01434 FT_INVALID_TOO_SHORT;
01435
01436 p = table + 2;
01437 length = TT_NEXT_USHORT( p );
01438
01439 p = table + 8;
01440 count = TT_NEXT_USHORT( p );
01441
01442 if ( table + length > valid->limit || length < 10 + count * 2 )
01443 FT_INVALID_TOO_SHORT;
01444
01445
01446 if ( valid->level >= FT_VALIDATE_TIGHT )
01447 {
01448 FT_UInt gindex;
01449
01450
01451 for ( ; count > 0; count-- )
01452 {
01453 gindex = TT_NEXT_USHORT( p );
01454 if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
01455 FT_INVALID_GLYPH_ID;
01456 }
01457 }
01458
01459 return SFNT_Err_Ok;
01460 }
01461
01462
01463 FT_CALLBACK_DEF( FT_UInt )
01464 tt_cmap6_char_index( TT_CMap cmap,
01465 FT_UInt32 char_code )
01466 {
01467 FT_Byte* table = cmap->data;
01468 FT_UInt result = 0;
01469 FT_Byte* p = table + 6;
01470 FT_UInt start = TT_NEXT_USHORT( p );
01471 FT_UInt count = TT_NEXT_USHORT( p );
01472 FT_UInt idx = (FT_UInt)( char_code - start );
01473
01474
01475 if ( idx < count )
01476 {
01477 p += 2 * idx;
01478 result = TT_PEEK_USHORT( p );
01479 }
01480 return result;
01481 }
01482
01483
01484 FT_CALLBACK_DEF( FT_UInt32 )
01485 tt_cmap6_char_next( TT_CMap cmap,
01486 FT_UInt32 *pchar_code )
01487 {
01488 FT_Byte* table = cmap->data;
01489 FT_UInt32 result = 0;
01490 FT_UInt32 char_code = *pchar_code + 1;
01491 FT_UInt gindex = 0;
01492
01493 FT_Byte* p = table + 6;
01494 FT_UInt start = TT_NEXT_USHORT( p );
01495 FT_UInt count = TT_NEXT_USHORT( p );
01496 FT_UInt idx;
01497
01498
01499 if ( char_code >= 0x10000UL )
01500 goto Exit;
01501
01502 if ( char_code < start )
01503 char_code = start;
01504
01505 idx = (FT_UInt)( char_code - start );
01506 p += 2 * idx;
01507
01508 for ( ; idx < count; idx++ )
01509 {
01510 gindex = TT_NEXT_USHORT( p );
01511 if ( gindex != 0 )
01512 {
01513 result = char_code;
01514 break;
01515 }
01516 char_code++;
01517 }
01518
01519 Exit:
01520 *pchar_code = result;
01521 return gindex;
01522 }
01523
01524
01525 FT_CALLBACK_DEF( FT_Error )
01526 tt_cmap6_get_info( TT_CMap cmap,
01527 TT_CMapInfo *cmap_info )
01528 {
01529 FT_Byte* p = cmap->data + 4;
01530
01531
01532 cmap_info->format = 6;
01533 cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
01534
01535 return SFNT_Err_Ok;
01536 }
01537
01538
01539 FT_DEFINE_TT_CMAP(tt_cmap6_class_rec,
01540 sizeof ( TT_CMapRec ),
01541
01542 (FT_CMap_InitFunc) tt_cmap_init,
01543 (FT_CMap_DoneFunc) NULL,
01544 (FT_CMap_CharIndexFunc)tt_cmap6_char_index,
01545 (FT_CMap_CharNextFunc) tt_cmap6_char_next,
01546
01547 NULL, NULL, NULL, NULL, NULL
01548 ,
01549 6,
01550 (TT_CMap_ValidateFunc) tt_cmap6_validate,
01551 (TT_CMap_Info_GetFunc) tt_cmap6_get_info
01552 )
01553
01554 #endif
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611 #ifdef TT_CONFIG_CMAP_FORMAT_8
01612
01613 FT_CALLBACK_DEF( FT_Error )
01614 tt_cmap8_validate( FT_Byte* table,
01615 FT_Validator valid )
01616 {
01617 FT_Byte* p = table + 4;
01618 FT_Byte* is32;
01619 FT_UInt32 length;
01620 FT_UInt32 num_groups;
01621
01622
01623 if ( table + 16 + 8192 > valid->limit )
01624 FT_INVALID_TOO_SHORT;
01625
01626 length = TT_NEXT_ULONG( p );
01627 if ( length > (FT_UInt32)( valid->limit - table ) || length < 8192 + 16 )
01628 FT_INVALID_TOO_SHORT;
01629
01630 is32 = table + 12;
01631 p = is32 + 8192;
01632 num_groups = TT_NEXT_ULONG( p );
01633
01634 if ( p + num_groups * 12 > valid->limit )
01635 FT_INVALID_TOO_SHORT;
01636
01637
01638 {
01639 FT_UInt32 n, start, end, start_id, count, last = 0;
01640
01641
01642 for ( n = 0; n < num_groups; n++ )
01643 {
01644 FT_UInt hi, lo;
01645
01646
01647 start = TT_NEXT_ULONG( p );
01648 end = TT_NEXT_ULONG( p );
01649 start_id = TT_NEXT_ULONG( p );
01650
01651 if ( start > end )
01652 FT_INVALID_DATA;
01653
01654 if ( n > 0 && start <= last )
01655 FT_INVALID_DATA;
01656
01657 if ( valid->level >= FT_VALIDATE_TIGHT )
01658 {
01659 if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
01660 FT_INVALID_GLYPH_ID;
01661
01662 count = (FT_UInt32)( end - start + 1 );
01663
01664 if ( start & ~0xFFFFU )
01665 {
01666
01667
01668 for ( ; count > 0; count--, start++ )
01669 {
01670 hi = (FT_UInt)( start >> 16 );
01671 lo = (FT_UInt)( start & 0xFFFFU );
01672
01673 if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 )
01674 FT_INVALID_DATA;
01675
01676 if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 )
01677 FT_INVALID_DATA;
01678 }
01679 }
01680 else
01681 {
01682
01683
01684
01685
01686 if ( end & ~0xFFFFU )
01687 FT_INVALID_DATA;
01688
01689 for ( ; count > 0; count--, start++ )
01690 {
01691 lo = (FT_UInt)( start & 0xFFFFU );
01692
01693 if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 )
01694 FT_INVALID_DATA;
01695 }
01696 }
01697 }
01698
01699 last = end;
01700 }
01701 }
01702
01703 return SFNT_Err_Ok;
01704 }
01705
01706
01707 FT_CALLBACK_DEF( FT_UInt )
01708 tt_cmap8_char_index( TT_CMap cmap,
01709 FT_UInt32 char_code )
01710 {
01711 FT_Byte* table = cmap->data;
01712 FT_UInt result = 0;
01713 FT_Byte* p = table + 8204;
01714 FT_UInt32 num_groups = TT_NEXT_ULONG( p );
01715 FT_UInt32 start, end, start_id;
01716
01717
01718 for ( ; num_groups > 0; num_groups-- )
01719 {
01720 start = TT_NEXT_ULONG( p );
01721 end = TT_NEXT_ULONG( p );
01722 start_id = TT_NEXT_ULONG( p );
01723
01724 if ( char_code < start )
01725 break;
01726
01727 if ( char_code <= end )
01728 {
01729 result = (FT_UInt)( start_id + char_code - start );
01730 break;
01731 }
01732 }
01733 return result;
01734 }
01735
01736
01737 FT_CALLBACK_DEF( FT_UInt32 )
01738 tt_cmap8_char_next( TT_CMap cmap,
01739 FT_UInt32 *pchar_code )
01740 {
01741 FT_UInt32 result = 0;
01742 FT_UInt32 char_code = *pchar_code + 1;
01743 FT_UInt gindex = 0;
01744 FT_Byte* table = cmap->data;
01745 FT_Byte* p = table + 8204;
01746 FT_UInt32 num_groups = TT_NEXT_ULONG( p );
01747 FT_UInt32 start, end, start_id;
01748
01749
01750 p = table + 8208;
01751
01752 for ( ; num_groups > 0; num_groups-- )
01753 {
01754 start = TT_NEXT_ULONG( p );
01755 end = TT_NEXT_ULONG( p );
01756 start_id = TT_NEXT_ULONG( p );
01757
01758 if ( char_code < start )
01759 char_code = start;
01760
01761 if ( char_code <= end )
01762 {
01763 gindex = (FT_UInt)( char_code - start + start_id );
01764 if ( gindex != 0 )
01765 {
01766 result = char_code;
01767 goto Exit;
01768 }
01769 }
01770 }
01771
01772 Exit:
01773 *pchar_code = result;
01774 return gindex;
01775 }
01776
01777
01778 FT_CALLBACK_DEF( FT_Error )
01779 tt_cmap8_get_info( TT_CMap cmap,
01780 TT_CMapInfo *cmap_info )
01781 {
01782 FT_Byte* p = cmap->data + 8;
01783
01784
01785 cmap_info->format = 8;
01786 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
01787
01788 return SFNT_Err_Ok;
01789 }
01790
01791
01792 FT_DEFINE_TT_CMAP(tt_cmap8_class_rec,
01793 sizeof ( TT_CMapRec ),
01794
01795 (FT_CMap_InitFunc) tt_cmap_init,
01796 (FT_CMap_DoneFunc) NULL,
01797 (FT_CMap_CharIndexFunc)tt_cmap8_char_index,
01798 (FT_CMap_CharNextFunc) tt_cmap8_char_next,
01799
01800 NULL, NULL, NULL, NULL, NULL
01801 ,
01802 8,
01803 (TT_CMap_ValidateFunc) tt_cmap8_validate,
01804 (TT_CMap_Info_GetFunc) tt_cmap8_get_info
01805 )
01806
01807 #endif
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835 #ifdef TT_CONFIG_CMAP_FORMAT_10
01836
01837 FT_CALLBACK_DEF( FT_Error )
01838 tt_cmap10_validate( FT_Byte* table,
01839 FT_Validator valid )
01840 {
01841 FT_Byte* p = table + 4;
01842 FT_ULong length, count;
01843
01844
01845 if ( table + 20 > valid->limit )
01846 FT_INVALID_TOO_SHORT;
01847
01848 length = TT_NEXT_ULONG( p );
01849 p = table + 16;
01850 count = TT_NEXT_ULONG( p );
01851
01852 if ( length > (FT_ULong)( valid->limit - table ) ||
01853 length < 20 + count * 2 )
01854 FT_INVALID_TOO_SHORT;
01855
01856
01857 if ( valid->level >= FT_VALIDATE_TIGHT )
01858 {
01859 FT_UInt gindex;
01860
01861
01862 for ( ; count > 0; count-- )
01863 {
01864 gindex = TT_NEXT_USHORT( p );
01865 if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
01866 FT_INVALID_GLYPH_ID;
01867 }
01868 }
01869
01870 return SFNT_Err_Ok;
01871 }
01872
01873
01874 FT_CALLBACK_DEF( FT_UInt )
01875 tt_cmap10_char_index( TT_CMap cmap,
01876 FT_UInt32 char_code )
01877 {
01878 FT_Byte* table = cmap->data;
01879 FT_UInt result = 0;
01880 FT_Byte* p = table + 12;
01881 FT_UInt32 start = TT_NEXT_ULONG( p );
01882 FT_UInt32 count = TT_NEXT_ULONG( p );
01883 FT_UInt32 idx = (FT_ULong)( char_code - start );
01884
01885
01886 if ( idx < count )
01887 {
01888 p += 2 * idx;
01889 result = TT_PEEK_USHORT( p );
01890 }
01891 return result;
01892 }
01893
01894
01895 FT_CALLBACK_DEF( FT_UInt32 )
01896 tt_cmap10_char_next( TT_CMap cmap,
01897 FT_UInt32 *pchar_code )
01898 {
01899 FT_Byte* table = cmap->data;
01900 FT_UInt32 char_code = *pchar_code + 1;
01901 FT_UInt gindex = 0;
01902 FT_Byte* p = table + 12;
01903 FT_UInt32 start = TT_NEXT_ULONG( p );
01904 FT_UInt32 count = TT_NEXT_ULONG( p );
01905 FT_UInt32 idx;
01906
01907
01908 if ( char_code < start )
01909 char_code = start;
01910
01911 idx = (FT_UInt32)( char_code - start );
01912 p += 2 * idx;
01913
01914 for ( ; idx < count; idx++ )
01915 {
01916 gindex = TT_NEXT_USHORT( p );
01917 if ( gindex != 0 )
01918 break;
01919 char_code++;
01920 }
01921
01922 *pchar_code = char_code;
01923 return gindex;
01924 }
01925
01926
01927 FT_CALLBACK_DEF( FT_Error )
01928 tt_cmap10_get_info( TT_CMap cmap,
01929 TT_CMapInfo *cmap_info )
01930 {
01931 FT_Byte* p = cmap->data + 8;
01932
01933
01934 cmap_info->format = 10;
01935 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
01936
01937 return SFNT_Err_Ok;
01938 }
01939
01940
01941 FT_DEFINE_TT_CMAP(tt_cmap10_class_rec,
01942 sizeof ( TT_CMapRec ),
01943
01944 (FT_CMap_InitFunc) tt_cmap_init,
01945 (FT_CMap_DoneFunc) NULL,
01946 (FT_CMap_CharIndexFunc)tt_cmap10_char_index,
01947 (FT_CMap_CharNextFunc) tt_cmap10_char_next,
01948
01949 NULL, NULL, NULL, NULL, NULL
01950 ,
01951 10,
01952 (TT_CMap_ValidateFunc) tt_cmap10_validate,
01953 (TT_CMap_Info_GetFunc) tt_cmap10_get_info
01954 )
01955
01956 #endif
01957
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988 #ifdef TT_CONFIG_CMAP_FORMAT_12
01989
01990 typedef struct TT_CMap12Rec_
01991 {
01992 TT_CMapRec cmap;
01993 FT_Bool valid;
01994 FT_ULong cur_charcode;
01995 FT_UInt cur_gindex;
01996 FT_ULong cur_group;
01997 FT_ULong num_groups;
01998
01999 } TT_CMap12Rec, *TT_CMap12;
02000
02001
02002 FT_CALLBACK_DEF( FT_Error )
02003 tt_cmap12_init( TT_CMap12 cmap,
02004 FT_Byte* table )
02005 {
02006 cmap->cmap.data = table;
02007
02008 table += 12;
02009 cmap->num_groups = FT_PEEK_ULONG( table );
02010
02011 cmap->valid = 0;
02012
02013 return SFNT_Err_Ok;
02014 }
02015
02016
02017 FT_CALLBACK_DEF( FT_Error )
02018 tt_cmap12_validate( FT_Byte* table,
02019 FT_Validator valid )
02020 {
02021 FT_Byte* p;
02022 FT_ULong length;
02023 FT_ULong num_groups;
02024
02025
02026 if ( table + 16 > valid->limit )
02027 FT_INVALID_TOO_SHORT;
02028
02029 p = table + 4;
02030 length = TT_NEXT_ULONG( p );
02031
02032 p = table + 12;
02033 num_groups = TT_NEXT_ULONG( p );
02034
02035 if ( length > (FT_ULong)( valid->limit - table ) ||
02036 length < 16 + 12 * num_groups )
02037 FT_INVALID_TOO_SHORT;
02038
02039
02040 {
02041 FT_ULong n, start, end, start_id, last = 0;
02042
02043
02044 for ( n = 0; n < num_groups; n++ )
02045 {
02046 start = TT_NEXT_ULONG( p );
02047 end = TT_NEXT_ULONG( p );
02048 start_id = TT_NEXT_ULONG( p );
02049
02050 if ( start > end )
02051 FT_INVALID_DATA;
02052
02053 if ( n > 0 && start <= last )
02054 FT_INVALID_DATA;
02055
02056 if ( valid->level >= FT_VALIDATE_TIGHT )
02057 {
02058 if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) )
02059 FT_INVALID_GLYPH_ID;
02060 }
02061
02062 last = end;
02063 }
02064 }
02065
02066 return SFNT_Err_Ok;
02067 }
02068
02069
02070
02071
02072
02073 static void
02074 tt_cmap12_next( TT_CMap12 cmap )
02075 {
02076 FT_Byte* p;
02077 FT_ULong start, end, start_id, char_code;
02078 FT_ULong n;
02079 FT_UInt gindex;
02080
02081
02082 if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
02083 goto Fail;
02084
02085 char_code = cmap->cur_charcode + 1;
02086
02087 n = cmap->cur_group;
02088
02089 for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
02090 {
02091 p = cmap->cmap.data + 16 + 12 * n;
02092 start = TT_NEXT_ULONG( p );
02093 end = TT_NEXT_ULONG( p );
02094 start_id = TT_PEEK_ULONG( p );
02095
02096 if ( char_code < start )
02097 char_code = start;
02098
02099 for ( ; char_code <= end; char_code++ )
02100 {
02101 gindex = (FT_UInt)( start_id + char_code - start );
02102
02103 if ( gindex )
02104 {
02105 cmap->cur_charcode = char_code;;
02106 cmap->cur_gindex = gindex;
02107 cmap->cur_group = n;
02108
02109 return;
02110 }
02111 }
02112 }
02113
02114 Fail:
02115 cmap->valid = 0;
02116 }
02117
02118
02119 static FT_UInt
02120 tt_cmap12_char_map_binary( TT_CMap cmap,
02121 FT_UInt32* pchar_code,
02122 FT_Bool next )
02123 {
02124 FT_UInt gindex = 0;
02125 FT_Byte* p = cmap->data + 12;
02126 FT_UInt32 num_groups = TT_PEEK_ULONG( p );
02127 FT_UInt32 char_code = *pchar_code;
02128 FT_UInt32 start, end, start_id;
02129 FT_UInt32 max, min, mid;
02130
02131
02132 if ( !num_groups )
02133 return 0;
02134
02135
02136 mid = num_groups;
02137 end = 0xFFFFFFFFUL;
02138
02139 if ( next )
02140 char_code++;
02141
02142 min = 0;
02143 max = num_groups;
02144
02145
02146 while ( min < max )
02147 {
02148 mid = ( min + max ) >> 1;
02149 p = cmap->data + 16 + 12 * mid;
02150
02151 start = TT_NEXT_ULONG( p );
02152 end = TT_NEXT_ULONG( p );
02153
02154 if ( char_code < start )
02155 max = mid;
02156 else if ( char_code > end )
02157 min = mid + 1;
02158 else
02159 {
02160 start_id = TT_PEEK_ULONG( p );
02161 gindex = (FT_UInt)( start_id + char_code - start );
02162
02163 break;
02164 }
02165 }
02166
02167 if ( next )
02168 {
02169 TT_CMap12 cmap12 = (TT_CMap12)cmap;
02170
02171
02172
02173
02174
02175
02176 if ( char_code > end )
02177 {
02178 mid++;
02179 if ( mid == num_groups )
02180 return 0;
02181 }
02182
02183 cmap12->valid = 1;
02184 cmap12->cur_charcode = char_code;
02185 cmap12->cur_group = mid;
02186
02187 if ( !gindex )
02188 {
02189 tt_cmap12_next( cmap12 );
02190
02191 if ( cmap12->valid )
02192 gindex = cmap12->cur_gindex;
02193 }
02194 else
02195 cmap12->cur_gindex = gindex;
02196
02197 if ( gindex )
02198 *pchar_code = cmap12->cur_charcode;
02199 }
02200
02201 return gindex;
02202 }
02203
02204
02205 FT_CALLBACK_DEF( FT_UInt )
02206 tt_cmap12_char_index( TT_CMap cmap,
02207 FT_UInt32 char_code )
02208 {
02209 return tt_cmap12_char_map_binary( cmap, &char_code, 0 );
02210 }
02211
02212
02213 FT_CALLBACK_DEF( FT_UInt32 )
02214 tt_cmap12_char_next( TT_CMap cmap,
02215 FT_UInt32 *pchar_code )
02216 {
02217 TT_CMap12 cmap12 = (TT_CMap12)cmap;
02218 FT_ULong gindex;
02219
02220
02221 if ( cmap12->cur_charcode >= 0xFFFFFFFFUL )
02222 return 0;
02223
02224
02225 if ( cmap12->valid && cmap12->cur_charcode == *pchar_code )
02226 {
02227 tt_cmap12_next( cmap12 );
02228 if ( cmap12->valid )
02229 {
02230 gindex = cmap12->cur_gindex;
02231
02232
02233 if ( gindex )
02234 *pchar_code = (FT_UInt32)cmap12->cur_charcode;
02235 }
02236 else
02237 gindex = 0;
02238 }
02239 else
02240 gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 );
02241
02242
02243 return (FT_UInt32)gindex;
02244 }
02245
02246
02247 FT_CALLBACK_DEF( FT_Error )
02248 tt_cmap12_get_info( TT_CMap cmap,
02249 TT_CMapInfo *cmap_info )
02250 {
02251 FT_Byte* p = cmap->data + 8;
02252
02253
02254 cmap_info->format = 12;
02255 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
02256
02257 return SFNT_Err_Ok;
02258 }
02259
02260
02261 FT_DEFINE_TT_CMAP(tt_cmap12_class_rec,
02262 sizeof ( TT_CMap12Rec ),
02263
02264 (FT_CMap_InitFunc) tt_cmap12_init,
02265 (FT_CMap_DoneFunc) NULL,
02266 (FT_CMap_CharIndexFunc)tt_cmap12_char_index,
02267 (FT_CMap_CharNextFunc) tt_cmap12_char_next,
02268
02269 NULL, NULL, NULL, NULL, NULL
02270 ,
02271 12,
02272 (TT_CMap_ValidateFunc) tt_cmap12_validate,
02273 (TT_CMap_Info_GetFunc) tt_cmap12_get_info
02274 )
02275
02276 #endif
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299
02300
02301
02302
02303
02304
02305
02306
02307
02308 #ifdef TT_CONFIG_CMAP_FORMAT_13
02309
02310 typedef struct TT_CMap13Rec_
02311 {
02312 TT_CMapRec cmap;
02313 FT_Bool valid;
02314 FT_ULong cur_charcode;
02315 FT_UInt cur_gindex;
02316 FT_ULong cur_group;
02317 FT_ULong num_groups;
02318
02319 } TT_CMap13Rec, *TT_CMap13;
02320
02321
02322 FT_CALLBACK_DEF( FT_Error )
02323 tt_cmap13_init( TT_CMap13 cmap,
02324 FT_Byte* table )
02325 {
02326 cmap->cmap.data = table;
02327
02328 table += 12;
02329 cmap->num_groups = FT_PEEK_ULONG( table );
02330
02331 cmap->valid = 0;
02332
02333 return SFNT_Err_Ok;
02334 }
02335
02336
02337 FT_CALLBACK_DEF( FT_Error )
02338 tt_cmap13_validate( FT_Byte* table,
02339 FT_Validator valid )
02340 {
02341 FT_Byte* p;
02342 FT_ULong length;
02343 FT_ULong num_groups;
02344
02345
02346 if ( table + 16 > valid->limit )
02347 FT_INVALID_TOO_SHORT;
02348
02349 p = table + 4;
02350 length = TT_NEXT_ULONG( p );
02351
02352 p = table + 12;
02353 num_groups = TT_NEXT_ULONG( p );
02354
02355 if ( length > (FT_ULong)( valid->limit - table ) ||
02356 length < 16 + 12 * num_groups )
02357 FT_INVALID_TOO_SHORT;
02358
02359
02360 {
02361 FT_ULong n, start, end, glyph_id, last = 0;
02362
02363
02364 for ( n = 0; n < num_groups; n++ )
02365 {
02366 start = TT_NEXT_ULONG( p );
02367 end = TT_NEXT_ULONG( p );
02368 glyph_id = TT_NEXT_ULONG( p );
02369
02370 if ( start > end )
02371 FT_INVALID_DATA;
02372
02373 if ( n > 0 && start <= last )
02374 FT_INVALID_DATA;
02375
02376 if ( valid->level >= FT_VALIDATE_TIGHT )
02377 {
02378 if ( glyph_id >= TT_VALID_GLYPH_COUNT( valid ) )
02379 FT_INVALID_GLYPH_ID;
02380 }
02381
02382 last = end;
02383 }
02384 }
02385
02386 return SFNT_Err_Ok;
02387 }
02388
02389
02390
02391
02392
02393 static void
02394 tt_cmap13_next( TT_CMap13 cmap )
02395 {
02396 FT_Byte* p;
02397 FT_ULong start, end, glyph_id, char_code;
02398 FT_ULong n;
02399 FT_UInt gindex;
02400
02401
02402 if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
02403 goto Fail;
02404
02405 char_code = cmap->cur_charcode + 1;
02406
02407 n = cmap->cur_group;
02408
02409 for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
02410 {
02411 p = cmap->cmap.data + 16 + 12 * n;
02412 start = TT_NEXT_ULONG( p );
02413 end = TT_NEXT_ULONG( p );
02414 glyph_id = TT_PEEK_ULONG( p );
02415
02416 if ( char_code < start )
02417 char_code = start;
02418
02419 if ( char_code <= end )
02420 {
02421 gindex = (FT_UInt)glyph_id;
02422
02423 if ( gindex )
02424 {
02425 cmap->cur_charcode = char_code;;
02426 cmap->cur_gindex = gindex;
02427 cmap->cur_group = n;
02428
02429 return;
02430 }
02431 }
02432 }
02433
02434 Fail:
02435 cmap->valid = 0;
02436 }
02437
02438
02439 static FT_UInt
02440 tt_cmap13_char_map_binary( TT_CMap cmap,
02441 FT_UInt32* pchar_code,
02442 FT_Bool next )
02443 {
02444 FT_UInt gindex = 0;
02445 FT_Byte* p = cmap->data + 12;
02446 FT_UInt32 num_groups = TT_PEEK_ULONG( p );
02447 FT_UInt32 char_code = *pchar_code;
02448 FT_UInt32 start, end;
02449 FT_UInt32 max, min, mid;
02450
02451
02452 if ( !num_groups )
02453 return 0;
02454
02455
02456 mid = num_groups;
02457 end = 0xFFFFFFFFUL;
02458
02459 if ( next )
02460 char_code++;
02461
02462 min = 0;
02463 max = num_groups;
02464
02465
02466 while ( min < max )
02467 {
02468 mid = ( min + max ) >> 1;
02469 p = cmap->data + 16 + 12 * mid;
02470
02471 start = TT_NEXT_ULONG( p );
02472 end = TT_NEXT_ULONG( p );
02473
02474 if ( char_code < start )
02475 max = mid;
02476 else if ( char_code > end )
02477 min = mid + 1;
02478 else
02479 {
02480 gindex = (FT_UInt)TT_PEEK_ULONG( p );
02481
02482 break;
02483 }
02484 }
02485
02486 if ( next )
02487 {
02488 TT_CMap13 cmap13 = (TT_CMap13)cmap;
02489
02490
02491
02492
02493
02494
02495 if ( char_code > end )
02496 {
02497 mid++;
02498 if ( mid == num_groups )
02499 return 0;
02500 }
02501
02502 cmap13->valid = 1;
02503 cmap13->cur_charcode = char_code;
02504 cmap13->cur_group = mid;
02505
02506 if ( !gindex )
02507 {
02508 tt_cmap13_next( cmap13 );
02509
02510 if ( cmap13->valid )
02511 gindex = cmap13->cur_gindex;
02512 }
02513 else
02514 cmap13->cur_gindex = gindex;
02515
02516 if ( gindex )
02517 *pchar_code = cmap13->cur_charcode;
02518 }
02519
02520 return gindex;
02521 }
02522
02523
02524 FT_CALLBACK_DEF( FT_UInt )
02525 tt_cmap13_char_index( TT_CMap cmap,
02526 FT_UInt32 char_code )
02527 {
02528 return tt_cmap13_char_map_binary( cmap, &char_code, 0 );
02529 }
02530
02531
02532 FT_CALLBACK_DEF( FT_UInt32 )
02533 tt_cmap13_char_next( TT_CMap cmap,
02534 FT_UInt32 *pchar_code )
02535 {
02536 TT_CMap13 cmap13 = (TT_CMap13)cmap;
02537 FT_UInt gindex;
02538
02539
02540 if ( cmap13->cur_charcode >= 0xFFFFFFFFUL )
02541 return 0;
02542
02543
02544 if ( cmap13->valid && cmap13->cur_charcode == *pchar_code )
02545 {
02546 tt_cmap13_next( cmap13 );
02547 if ( cmap13->valid )
02548 {
02549 gindex = cmap13->cur_gindex;
02550 if ( gindex )
02551 *pchar_code = cmap13->cur_charcode;
02552 }
02553 else
02554 gindex = 0;
02555 }
02556 else
02557 gindex = tt_cmap13_char_map_binary( cmap, pchar_code, 1 );
02558
02559 return gindex;
02560 }
02561
02562
02563 FT_CALLBACK_DEF( FT_Error )
02564 tt_cmap13_get_info( TT_CMap cmap,
02565 TT_CMapInfo *cmap_info )
02566 {
02567 FT_Byte* p = cmap->data + 8;
02568
02569
02570 cmap_info->format = 13;
02571 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
02572
02573 return SFNT_Err_Ok;
02574 }
02575
02576
02577 FT_DEFINE_TT_CMAP(tt_cmap13_class_rec,
02578 sizeof ( TT_CMap13Rec ),
02579
02580 (FT_CMap_InitFunc) tt_cmap13_init,
02581 (FT_CMap_DoneFunc) NULL,
02582 (FT_CMap_CharIndexFunc)tt_cmap13_char_index,
02583 (FT_CMap_CharNextFunc) tt_cmap13_char_next,
02584
02585 NULL, NULL, NULL, NULL, NULL
02586 ,
02587 13,
02588 (TT_CMap_ValidateFunc) tt_cmap13_validate,
02589 (TT_CMap_Info_GetFunc) tt_cmap13_get_info
02590 )
02591
02592 #endif
02593
02594
02595
02596
02597
02598
02599
02600
02601
02602
02603
02604
02605
02606
02607
02608
02609
02610
02611
02612
02613
02614
02615
02616
02617
02618
02619
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644
02645
02646
02647
02648
02649
02650
02651
02652
02653
02654
02655
02656 #ifdef TT_CONFIG_CMAP_FORMAT_14
02657
02658 typedef struct TT_CMap14Rec_
02659 {
02660 TT_CMapRec cmap;
02661 FT_ULong num_selectors;
02662
02663
02664
02665
02666
02667 FT_UInt32 max_results;
02668 FT_UInt32* results;
02669 FT_Memory memory;
02670
02671 } TT_CMap14Rec, *TT_CMap14;
02672
02673
02674 FT_CALLBACK_DEF( void )
02675 tt_cmap14_done( TT_CMap14 cmap )
02676 {
02677 FT_Memory memory = cmap->memory;
02678
02679
02680 cmap->max_results = 0;
02681 if ( memory != NULL && cmap->results != NULL )
02682 FT_FREE( cmap->results );
02683 }
02684
02685
02686 static FT_Error
02687 tt_cmap14_ensure( TT_CMap14 cmap,
02688 FT_UInt32 num_results,
02689 FT_Memory memory )
02690 {
02691 FT_UInt32 old_max = cmap->max_results;
02692 FT_Error error = 0;
02693
02694
02695 if ( num_results > cmap->max_results )
02696 {
02697 cmap->memory = memory;
02698
02699 if ( FT_QRENEW_ARRAY( cmap->results, old_max, num_results ) )
02700 return error;
02701
02702 cmap->max_results = num_results;
02703 }
02704
02705 return error;
02706 }
02707
02708
02709 FT_CALLBACK_DEF( FT_Error )
02710 tt_cmap14_init( TT_CMap14 cmap,
02711 FT_Byte* table )
02712 {
02713 cmap->cmap.data = table;
02714
02715 table += 6;
02716 cmap->num_selectors = FT_PEEK_ULONG( table );
02717 cmap->max_results = 0;
02718 cmap->results = NULL;
02719
02720 return SFNT_Err_Ok;
02721 }
02722
02723
02724 FT_CALLBACK_DEF( FT_Error )
02725 tt_cmap14_validate( FT_Byte* table,
02726 FT_Validator valid )
02727 {
02728 FT_Byte* p = table + 2;
02729 FT_ULong length = TT_NEXT_ULONG( p );
02730 FT_ULong num_selectors = TT_NEXT_ULONG( p );
02731
02732
02733 if ( length > (FT_ULong)( valid->limit - table ) ||
02734 length < 10 + 11 * num_selectors )
02735 FT_INVALID_TOO_SHORT;
02736
02737
02738 {
02739
02740
02741
02742 FT_ULong n, lastVarSel = 1;
02743
02744
02745 for ( n = 0; n < num_selectors; n++ )
02746 {
02747 FT_ULong varSel = TT_NEXT_UINT24( p );
02748 FT_ULong defOff = TT_NEXT_ULONG( p );
02749 FT_ULong nondefOff = TT_NEXT_ULONG( p );
02750
02751
02752 if ( defOff >= length || nondefOff >= length )
02753 FT_INVALID_TOO_SHORT;
02754
02755 if ( varSel < lastVarSel )
02756 FT_INVALID_DATA;
02757
02758 lastVarSel = varSel + 1;
02759
02760
02761
02762 if ( defOff != 0 )
02763 {
02764 FT_Byte* defp = table + defOff;
02765 FT_ULong numRanges = TT_NEXT_ULONG( defp );
02766 FT_ULong i;
02767 FT_ULong lastBase = 0;
02768
02769
02770 if ( defp + numRanges * 4 > valid->limit )
02771 FT_INVALID_TOO_SHORT;
02772
02773 for ( i = 0; i < numRanges; ++i )
02774 {
02775 FT_ULong base = TT_NEXT_UINT24( defp );
02776 FT_ULong cnt = FT_NEXT_BYTE( defp );
02777
02778
02779 if ( base + cnt >= 0x110000UL )
02780 FT_INVALID_DATA;
02781
02782 if ( base < lastBase )
02783 FT_INVALID_DATA;
02784
02785 lastBase = base + cnt + 1U;
02786 }
02787 }
02788
02789
02790 if ( nondefOff != 0 ) {
02791 FT_Byte* ndp = table + nondefOff;
02792 FT_ULong numMappings = TT_NEXT_ULONG( ndp );
02793 FT_ULong i, lastUni = 0;
02794
02795
02796 if ( numMappings * 4 > (FT_ULong)( valid->limit - ndp ) )
02797 FT_INVALID_TOO_SHORT;
02798
02799 for ( i = 0; i < numMappings; ++i )
02800 {
02801 FT_ULong uni = TT_NEXT_UINT24( ndp );
02802 FT_ULong gid = TT_NEXT_USHORT( ndp );
02803
02804
02805 if ( uni >= 0x110000UL )
02806 FT_INVALID_DATA;
02807
02808 if ( uni < lastUni )
02809 FT_INVALID_DATA;
02810
02811 lastUni = uni + 1U;
02812
02813 if ( valid->level >= FT_VALIDATE_TIGHT &&
02814 gid >= TT_VALID_GLYPH_COUNT( valid ) )
02815 FT_INVALID_GLYPH_ID;
02816 }
02817 }
02818 }
02819 }
02820
02821 return SFNT_Err_Ok;
02822 }
02823
02824
02825 FT_CALLBACK_DEF( FT_UInt )
02826 tt_cmap14_char_index( TT_CMap cmap,
02827 FT_UInt32 char_code )
02828 {
02829 FT_UNUSED( cmap );
02830 FT_UNUSED( char_code );
02831
02832
02833 return 0;
02834 }
02835
02836
02837 FT_CALLBACK_DEF( FT_UInt32 )
02838 tt_cmap14_char_next( TT_CMap cmap,
02839 FT_UInt32 *pchar_code )
02840 {
02841 FT_UNUSED( cmap );
02842
02843
02844 *pchar_code = 0;
02845 return 0;
02846 }
02847
02848
02849 FT_CALLBACK_DEF( FT_Error )
02850 tt_cmap14_get_info( TT_CMap cmap,
02851 TT_CMapInfo *cmap_info )
02852 {
02853 FT_UNUSED( cmap );
02854
02855 cmap_info->format = 14;
02856
02857 cmap_info->language = 0xFFFFFFFFUL;
02858
02859 return SFNT_Err_Ok;
02860 }
02861
02862
02863 static FT_UInt
02864 tt_cmap14_char_map_def_binary( FT_Byte *base,
02865 FT_UInt32 char_code )
02866 {
02867 FT_UInt32 numRanges = TT_PEEK_ULONG( base );
02868 FT_UInt32 max, min;
02869
02870
02871 min = 0;
02872 max = numRanges;
02873
02874 base += 4;
02875
02876
02877 while ( min < max )
02878 {
02879 FT_UInt32 mid = ( min + max ) >> 1;
02880 FT_Byte* p = base + 4 * mid;
02881 FT_ULong start = TT_NEXT_UINT24( p );
02882 FT_UInt cnt = FT_NEXT_BYTE( p );
02883
02884
02885 if ( char_code < start )
02886 max = mid;
02887 else if ( char_code > start+cnt )
02888 min = mid + 1;
02889 else
02890 return TRUE;
02891 }
02892
02893 return FALSE;
02894 }
02895
02896
02897 static FT_UInt
02898 tt_cmap14_char_map_nondef_binary( FT_Byte *base,
02899 FT_UInt32 char_code )
02900 {
02901 FT_UInt32 numMappings = TT_PEEK_ULONG( base );
02902 FT_UInt32 max, min;
02903
02904
02905 min = 0;
02906 max = numMappings;
02907
02908 base += 4;
02909
02910
02911 while ( min < max )
02912 {
02913 FT_UInt32 mid = ( min + max ) >> 1;
02914 FT_Byte* p = base + 5 * mid;
02915 FT_UInt32 uni = (FT_UInt32)TT_NEXT_UINT24( p );
02916
02917
02918 if ( char_code < uni )
02919 max = mid;
02920 else if ( char_code > uni )
02921 min = mid + 1;
02922 else
02923 return TT_PEEK_USHORT( p );
02924 }
02925
02926 return 0;
02927 }
02928
02929
02930 static FT_Byte*
02931 tt_cmap14_find_variant( FT_Byte *base,
02932 FT_UInt32 variantCode )
02933 {
02934 FT_UInt32 numVar = TT_PEEK_ULONG( base );
02935 FT_UInt32 max, min;
02936
02937
02938 min = 0;
02939 max = numVar;
02940
02941 base += 4;
02942
02943
02944 while ( min < max )
02945 {
02946 FT_UInt32 mid = ( min + max ) >> 1;
02947 FT_Byte* p = base + 11 * mid;
02948 FT_ULong varSel = TT_NEXT_UINT24( p );
02949
02950
02951 if ( variantCode < varSel )
02952 max = mid;
02953 else if ( variantCode > varSel )
02954 min = mid + 1;
02955 else
02956 return p;
02957 }
02958
02959 return NULL;
02960 }
02961
02962
02963 FT_CALLBACK_DEF( FT_UInt )
02964 tt_cmap14_char_var_index( TT_CMap cmap,
02965 TT_CMap ucmap,
02966 FT_UInt32 charcode,
02967 FT_UInt32 variantSelector)
02968 {
02969 FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
02970 FT_ULong defOff;
02971 FT_ULong nondefOff;
02972
02973
02974 if ( !p )
02975 return 0;
02976
02977 defOff = TT_NEXT_ULONG( p );
02978 nondefOff = TT_PEEK_ULONG( p );
02979
02980 if ( defOff != 0 &&
02981 tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
02982 {
02983
02984
02985 return ucmap->cmap.clazz->char_index( &ucmap->cmap, charcode );
02986 }
02987
02988 if ( nondefOff != 0 )
02989 return tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
02990 charcode );
02991
02992 return 0;
02993 }
02994
02995
02996 FT_CALLBACK_DEF( FT_Int )
02997 tt_cmap14_char_var_isdefault( TT_CMap cmap,
02998 FT_UInt32 charcode,
02999 FT_UInt32 variantSelector )
03000 {
03001 FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
03002 FT_ULong defOff;
03003 FT_ULong nondefOff;
03004
03005
03006 if ( !p )
03007 return -1;
03008
03009 defOff = TT_NEXT_ULONG( p );
03010 nondefOff = TT_NEXT_ULONG( p );
03011
03012 if ( defOff != 0 &&
03013 tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) )
03014 return 1;
03015
03016 if ( nondefOff != 0 &&
03017 tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
03018 charcode ) != 0 )
03019 return 0;
03020
03021 return -1;
03022 }
03023
03024
03025 FT_CALLBACK_DEF( FT_UInt32* )
03026 tt_cmap14_variants( TT_CMap cmap,
03027 FT_Memory memory )
03028 {
03029 TT_CMap14 cmap14 = (TT_CMap14)cmap;
03030 FT_UInt32 count = cmap14->num_selectors;
03031 FT_Byte* p = cmap->data + 10;
03032 FT_UInt32* result;
03033 FT_UInt32 i;
03034
03035
03036 if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
03037 return NULL;
03038
03039 result = cmap14->results;
03040 for ( i = 0; i < count; ++i )
03041 {
03042 result[i] = (FT_UInt32)TT_NEXT_UINT24( p );
03043 p += 8;
03044 }
03045 result[i] = 0;
03046
03047 return result;
03048 }
03049
03050
03051 FT_CALLBACK_DEF( FT_UInt32 * )
03052 tt_cmap14_char_variants( TT_CMap cmap,
03053 FT_Memory memory,
03054 FT_UInt32 charCode )
03055 {
03056 TT_CMap14 cmap14 = (TT_CMap14) cmap;
03057 FT_UInt32 count = cmap14->num_selectors;
03058 FT_Byte* p = cmap->data + 10;
03059 FT_UInt32* q;
03060
03061
03062 if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) )
03063 return NULL;
03064
03065 for ( q = cmap14->results; count > 0; --count )
03066 {
03067 FT_UInt32 varSel = TT_NEXT_UINT24( p );
03068 FT_ULong defOff = TT_NEXT_ULONG( p );
03069 FT_ULong nondefOff = TT_NEXT_ULONG( p );
03070
03071
03072 if ( ( defOff != 0 &&
03073 tt_cmap14_char_map_def_binary( cmap->data + defOff,
03074 charCode ) ) ||
03075 ( nondefOff != 0 &&
03076 tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff,
03077 charCode ) != 0 ) )
03078 {
03079 q[0] = varSel;
03080 q++;
03081 }
03082 }
03083 q[0] = 0;
03084
03085 return cmap14->results;
03086 }
03087
03088
03089 static FT_UInt
03090 tt_cmap14_def_char_count( FT_Byte *p )
03091 {
03092 FT_UInt32 numRanges = (FT_UInt32)TT_NEXT_ULONG( p );
03093 FT_UInt tot = 0;
03094
03095
03096 p += 3;
03097 for ( ; numRanges > 0; numRanges-- )
03098 {
03099 tot += 1 + p[0];
03100 p += 4;
03101 }
03102
03103 return tot;
03104 }
03105
03106
03107 static FT_UInt32*
03108 tt_cmap14_get_def_chars( TT_CMap cmap,
03109 FT_Byte* p,
03110 FT_Memory memory )
03111 {
03112 TT_CMap14 cmap14 = (TT_CMap14) cmap;
03113 FT_UInt32 numRanges;
03114 FT_UInt cnt;
03115 FT_UInt32* q;
03116
03117
03118 cnt = tt_cmap14_def_char_count( p );
03119 numRanges = (FT_UInt32)TT_NEXT_ULONG( p );
03120
03121 if ( tt_cmap14_ensure( cmap14, ( cnt + 1 ), memory ) )
03122 return NULL;
03123
03124 for ( q = cmap14->results; numRanges > 0; --numRanges )
03125 {
03126 FT_UInt32 uni = (FT_UInt32)TT_NEXT_UINT24( p );
03127
03128
03129 cnt = FT_NEXT_BYTE( p ) + 1;
03130 do
03131 {
03132 q[0] = uni;
03133 uni += 1;
03134 q += 1;
03135 } while ( --cnt != 0 );
03136 }
03137 q[0] = 0;
03138
03139 return cmap14->results;
03140 }
03141
03142
03143 static FT_UInt32*
03144 tt_cmap14_get_nondef_chars( TT_CMap cmap,
03145 FT_Byte *p,
03146 FT_Memory memory )
03147 {
03148 TT_CMap14 cmap14 = (TT_CMap14) cmap;
03149 FT_UInt32 numMappings;
03150 FT_UInt i;
03151 FT_UInt32 *ret;
03152
03153
03154 numMappings = (FT_UInt32)TT_NEXT_ULONG( p );
03155
03156 if ( tt_cmap14_ensure( cmap14, ( numMappings + 1 ), memory ) )
03157 return NULL;
03158
03159 ret = cmap14->results;
03160 for ( i = 0; i < numMappings; ++i )
03161 {
03162 ret[i] = (FT_UInt32)TT_NEXT_UINT24( p );
03163 p += 2;
03164 }
03165 ret[i] = 0;
03166
03167 return ret;
03168 }
03169
03170
03171 FT_CALLBACK_DEF( FT_UInt32 * )
03172 tt_cmap14_variant_chars( TT_CMap cmap,
03173 FT_Memory memory,
03174 FT_UInt32 variantSelector )
03175 {
03176 FT_Byte *p = tt_cmap14_find_variant( cmap->data + 6,
03177 variantSelector );
03178 FT_UInt32 *ret;
03179 FT_Int i;
03180 FT_ULong defOff;
03181 FT_ULong nondefOff;
03182
03183
03184 if ( !p )
03185 return NULL;
03186
03187 defOff = TT_NEXT_ULONG( p );
03188 nondefOff = TT_NEXT_ULONG( p );
03189
03190 if ( defOff == 0 && nondefOff == 0 )
03191 return NULL;
03192
03193 if ( defOff == 0 )
03194 return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
03195 memory );
03196 else if ( nondefOff == 0 )
03197 return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
03198 memory );
03199 else
03200 {
03201
03202
03203 TT_CMap14 cmap14 = (TT_CMap14) cmap;
03204 FT_UInt32 numRanges;
03205 FT_UInt32 numMappings;
03206 FT_UInt32 duni;
03207 FT_UInt32 dcnt;
03208 FT_UInt32 nuni;
03209 FT_Byte* dp;
03210 FT_UInt di, ni, k;
03211
03212
03213 p = cmap->data + nondefOff;
03214 dp = cmap->data + defOff;
03215
03216 numMappings = (FT_UInt32)TT_NEXT_ULONG( p );
03217 dcnt = tt_cmap14_def_char_count( dp );
03218 numRanges = (FT_UInt32)TT_NEXT_ULONG( dp );
03219
03220 if ( numMappings == 0 )
03221 return tt_cmap14_get_def_chars( cmap, cmap->data + defOff,
03222 memory );
03223 if ( dcnt == 0 )
03224 return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff,
03225 memory );
03226
03227 if ( tt_cmap14_ensure( cmap14, ( dcnt + numMappings + 1 ), memory ) )
03228 return NULL;
03229
03230 ret = cmap14->results;
03231 duni = (FT_UInt32)TT_NEXT_UINT24( dp );
03232 dcnt = FT_NEXT_BYTE( dp );
03233 di = 1;
03234 nuni = (FT_UInt32)TT_NEXT_UINT24( p );
03235 p += 2;
03236 ni = 1;
03237 i = 0;
03238
03239 for ( ;; )
03240 {
03241 if ( nuni > duni + dcnt )
03242 {
03243 for ( k = 0; k <= dcnt; ++k )
03244 ret[i++] = duni + k;
03245
03246 ++di;
03247
03248 if ( di > numRanges )
03249 break;
03250
03251 duni = (FT_UInt32)TT_NEXT_UINT24( dp );
03252 dcnt = FT_NEXT_BYTE( dp );
03253 }
03254 else
03255 {
03256 if ( nuni < duni )
03257 ret[i++] = nuni;
03258
03259
03260 ++ni;
03261 if ( ni > numMappings )
03262 break;
03263
03264 nuni = (FT_UInt32)TT_NEXT_UINT24( p );
03265 p += 2;
03266 }
03267 }
03268
03269 if ( ni <= numMappings )
03270 {
03271
03272
03273
03274 ret[i++] = nuni;
03275 while ( ni < numMappings )
03276 {
03277 ret[i++] = (FT_UInt32)TT_NEXT_UINT24( p );
03278 p += 2;
03279 ++ni;
03280 }
03281 }
03282 else if ( di <= numRanges )
03283 {
03284
03285
03286
03287 for ( k = 0; k <= dcnt; ++k )
03288 ret[i++] = duni + k;
03289
03290 while ( di < numRanges )
03291 {
03292 duni = (FT_UInt32)TT_NEXT_UINT24( dp );
03293 dcnt = FT_NEXT_BYTE( dp );
03294
03295 for ( k = 0; k <= dcnt; ++k )
03296 ret[i++] = duni + k;
03297 ++di;
03298 }
03299 }
03300
03301 ret[i] = 0;
03302
03303 return ret;
03304 }
03305 }
03306
03307
03308 FT_DEFINE_TT_CMAP(tt_cmap14_class_rec,
03309 sizeof ( TT_CMap14Rec ),
03310
03311 (FT_CMap_InitFunc) tt_cmap14_init,
03312 (FT_CMap_DoneFunc) tt_cmap14_done,
03313 (FT_CMap_CharIndexFunc)tt_cmap14_char_index,
03314 (FT_CMap_CharNextFunc) tt_cmap14_char_next,
03315
03316
03317 (FT_CMap_CharVarIndexFunc) tt_cmap14_char_var_index,
03318 (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault,
03319 (FT_CMap_VariantListFunc) tt_cmap14_variants,
03320 (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants,
03321 (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars
03322 ,
03323 14,
03324 (TT_CMap_ValidateFunc)tt_cmap14_validate,
03325 (TT_CMap_Info_GetFunc)tt_cmap14_get_info
03326 )
03327
03328 #endif
03329
03330
03331 #ifndef FT_CONFIG_OPTION_PIC
03332
03333 static const TT_CMap_Class tt_cmap_classes[] =
03334 {
03335 #define TTCMAPCITEM(a) &a,
03336 #include "ttcmapc.h"
03337 NULL,
03338 };
03339
03340 #else
03341
03342 void FT_Destroy_Class_tt_cmap_classes(FT_Library library, TT_CMap_Class* clazz)
03343 {
03344 FT_Memory memory = library->memory;
03345 if ( clazz )
03346 FT_FREE( clazz );
03347 }
03348
03349 FT_Error FT_Create_Class_tt_cmap_classes(FT_Library library, TT_CMap_Class** output_class)
03350 {
03351 TT_CMap_Class* clazz;
03352 TT_CMap_ClassRec* recs;
03353 FT_Error error;
03354 FT_Memory memory = library->memory;
03355 int i = 0;
03356
03357 #define TTCMAPCITEM(a) i++;
03358 #include "ttcmapc.h"
03359
03360
03361 if ( FT_ALLOC( clazz, sizeof(*clazz)*(i+1)+sizeof(TT_CMap_ClassRec)*i ) )
03362 return error;
03363
03364
03365 recs = (TT_CMap_ClassRec*) (((char*)clazz)+(sizeof(*clazz)*(i+1)));
03366 i=0;
03367
03368 #undef TTCMAPCITEM
03369 #define TTCMAPCITEM(a) \
03370 FT_Init_Class_##a(&recs[i]); \
03371 clazz[i] = &recs[i]; \
03372 i++;
03373 #include "ttcmapc.h"
03374
03375 clazz[i] = NULL;
03376
03377 *output_class = clazz;
03378 return FT_Err_Ok;
03379 }
03380
03381 #endif
03382
03383
03384
03385
03386
03387 FT_LOCAL_DEF( FT_Error )
03388 tt_face_build_cmaps( TT_Face face )
03389 {
03390 FT_Byte* table = face->cmap_table;
03391 FT_Byte* limit = table + face->cmap_size;
03392 FT_UInt volatile num_cmaps;
03393 FT_Byte* volatile p = table;
03394 FT_Library library = FT_FACE_LIBRARY(face);
03395 FT_UNUSED(library);
03396
03397
03398 if ( p + 4 > limit )
03399 return SFNT_Err_Invalid_Table;
03400
03401
03402 if ( TT_NEXT_USHORT( p ) != 0 )
03403 {
03404 p -= 2;
03405 FT_ERROR(( "tt_face_build_cmaps:"
03406 " unsupported `cmap' table format = %d\n",
03407 TT_PEEK_USHORT( p ) ));
03408 return SFNT_Err_Invalid_Table;
03409 }
03410
03411 num_cmaps = TT_NEXT_USHORT( p );
03412
03413 for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- )
03414 {
03415 FT_CharMapRec charmap;
03416 FT_UInt32 offset;
03417
03418
03419 charmap.platform_id = TT_NEXT_USHORT( p );
03420 charmap.encoding_id = TT_NEXT_USHORT( p );
03421 charmap.face = FT_FACE( face );
03422 charmap.encoding = FT_ENCODING_NONE;
03423 offset = TT_NEXT_ULONG( p );
03424
03425 if ( offset && offset <= face->cmap_size - 2 )
03426 {
03427 FT_Byte* volatile cmap = table + offset;
03428 volatile FT_UInt format = TT_PEEK_USHORT( cmap );
03429 const TT_CMap_Class* volatile pclazz = FT_TT_CMAP_CLASSES_GET;
03430 TT_CMap_Class volatile clazz;
03431
03432
03433 for ( ; *pclazz; pclazz++ )
03434 {
03435 clazz = *pclazz;
03436 if ( clazz->format == format )
03437 {
03438 volatile TT_ValidatorRec valid;
03439 volatile FT_Error error = SFNT_Err_Ok;
03440
03441
03442 ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit,
03443 FT_VALIDATE_DEFAULT );
03444
03445 valid.num_glyphs = (FT_UInt)face->max_profile.numGlyphs;
03446
03447 if ( ft_setjmp(
03448 *((ft_jmp_buf*)&FT_VALIDATOR( &valid )->jump_buffer) ) == 0 )
03449 {
03450
03451 error = clazz->validate( cmap, FT_VALIDATOR( &valid ) );
03452 }
03453
03454 if ( valid.validator.error == 0 )
03455 {
03456 FT_CMap ttcmap;
03457
03458
03459
03460
03461
03462
03463 if ( !FT_CMap_New( (FT_CMap_Class)clazz,
03464 cmap, &charmap, &ttcmap ) )
03465 {
03466
03467
03468 ((TT_CMap)ttcmap)->flags = (FT_Int)error;
03469 }
03470 }
03471 else
03472 {
03473 FT_TRACE0(( "tt_face_build_cmaps:"
03474 " broken cmap sub-table ignored\n" ));
03475 }
03476 break;
03477 }
03478 }
03479
03480 if ( *pclazz == NULL )
03481 {
03482 FT_TRACE0(( "tt_face_build_cmaps:"
03483 " unsupported cmap sub-table ignored\n" ));
03484 }
03485 }
03486 }
03487
03488 return SFNT_Err_Ok;
03489 }
03490
03491
03492 FT_LOCAL( FT_Error )
03493 tt_get_cmap_info( FT_CharMap charmap,
03494 TT_CMapInfo *cmap_info )
03495 {
03496 FT_CMap cmap = (FT_CMap)charmap;
03497 TT_CMap_Class clazz = (TT_CMap_Class)cmap->clazz;
03498
03499
03500 return clazz->get_cmap_info( charmap, cmap_info );
03501 }
03502
03503
03504