📄 ttcmap.c
字号:
length = (FT_UInt)( valid->limit - table ); } p = table + 6; num_segs = TT_NEXT_USHORT( p ); /* read segCountX2 */ if ( valid->level >= FT_VALIDATE_PARANOID ) { /* check that we have an even value here */ if ( num_segs & 1 ) FT_INVALID_DATA; } num_segs /= 2; /* check the search parameters - even though we never use them */ /* */ if ( valid->level >= FT_VALIDATE_PARANOID ) { /* check the values of 'searchRange', 'entrySelector', 'rangeShift' */ FT_UInt search_range = TT_NEXT_USHORT( p ); FT_UInt entry_selector = TT_NEXT_USHORT( p ); FT_UInt range_shift = TT_NEXT_USHORT( p ); if ( ( search_range | range_shift ) & 1 ) /* must be even values */ FT_INVALID_DATA; search_range /= 2; range_shift /= 2; /* `search range' is the greatest power of 2 that is <= num_segs */ if ( search_range > num_segs || search_range * 2 < num_segs || search_range + range_shift != num_segs || search_range != ( 1U << entry_selector ) ) FT_INVALID_DATA; } ends = table + 14; starts = table + 16 + num_segs * 2; deltas = starts + num_segs * 2; offsets = deltas + num_segs * 2; glyph_ids = offsets + num_segs * 2; if ( glyph_ids > table + length ) FT_INVALID_TOO_SHORT; /* check last segment, its end count must be FFFF */ if ( valid->level >= FT_VALIDATE_PARANOID ) { p = ends + ( num_segs - 1 ) * 2; if ( TT_PEEK_USHORT( p ) != 0xFFFFU ) FT_INVALID_DATA; } /* check that segments are sorted in increasing order and do not */ /* overlap; check also the offsets */ { FT_UInt start, end, last = 0, offset, n; FT_Int delta; for ( n = 0; n < num_segs; n++ ) { p = starts + n * 2; start = TT_PEEK_USHORT( p ); p = ends + n * 2; end = TT_PEEK_USHORT( p ); p = deltas + n * 2; delta = TT_PEEK_SHORT( p ); p = offsets + n * 2; offset = TT_PEEK_USHORT( p ); if ( start > end ) FT_INVALID_DATA; /* this test should be performed at default validation level; */ /* unfortunately, some popular Asian fonts present overlapping */ /* ranges in their charmaps */ /* */ if ( n > 0 && start <= last ) { if ( valid->level >= FT_VALIDATE_TIGHT ) FT_INVALID_DATA; else error = SFNT_Err_Invalid_CharMap_Format; } if ( offset && offset != 0xFFFFU ) { p += offset; /* start of glyph id array */ /* check that we point within the glyph ids table only */ if ( valid->level >= FT_VALIDATE_TIGHT ) { if ( p < glyph_ids || p + ( end - start + 1 ) * 2 > table + length ) FT_INVALID_DATA; } else { if ( p < glyph_ids || p + ( end - start + 1 ) * 2 > valid->limit ) FT_INVALID_DATA; } /* check glyph indices within the segment range */ if ( valid->level >= FT_VALIDATE_TIGHT ) { FT_UInt i, idx; for ( i = start; i < end; i++ ) { idx = FT_NEXT_USHORT( p ); if ( idx != 0 ) { idx = (FT_UInt)( idx + delta ) & 0xFFFFU; if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) FT_INVALID_GLYPH_ID; } } } } else if ( offset == 0xFFFFU ) { /* Some fonts (erroneously?) use a range offset of 0xFFFF */ /* to mean missing glyph in cmap table */ /* */ if ( valid->level >= FT_VALIDATE_PARANOID || n != num_segs - 1 || !( start == 0xFFFFU && end == 0xFFFFU && delta == 0x1U ) ) FT_INVALID_DATA; } last = end; } } return error; } FT_CALLBACK_DEF( FT_UInt ) tt_cmap4_char_index( TT_CMap cmap, FT_UInt32 char_code ) { FT_Byte* table = cmap->data; FT_UInt result = 0; if ( char_code < 0x10000UL ) { FT_UInt idx, num_segs2; FT_Int delta; FT_UInt code = (FT_UInt)char_code; FT_Byte* p; p = table + 6; num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); /* be paranoid! */ if ( !cmap->unsorted ) { /* Some fonts have more than 170 segments in their charmaps! */ /* We changed this function to use a more efficient binary */ /* search for improving performance */ FT_UInt min = 0; FT_UInt max = num_segs2 >> 1; FT_UInt mid, start, end, offset; while ( min < max ) { mid = ( min + max ) >> 1; p = table + 14 + mid * 2; end = TT_NEXT_USHORT( p ); p += num_segs2; start = TT_PEEK_USHORT( p); if ( code < start ) max = mid; else if ( code > end ) min = mid + 1; else { /* we found the segment */ idx = code; p += num_segs2; delta = TT_PEEK_SHORT( p ); p += num_segs2; offset = TT_PEEK_USHORT( p ); if ( offset == 0xFFFFU ) goto Exit; if ( offset != 0 ) { p += offset + 2 * ( idx - start ); idx = TT_PEEK_USHORT( p ); } if ( idx != 0 ) result = (FT_UInt)( idx + delta ) & 0xFFFFU; goto Exit; } } } else { FT_UInt n; FT_Byte* q; p = table + 14; /* ends table */ q = table + 16 + num_segs2; /* starts table */ for ( n = 0; n < num_segs2; n += 2 ) { FT_UInt end = TT_NEXT_USHORT( p ); FT_UInt start = TT_NEXT_USHORT( q ); FT_UInt offset; if ( code < start ) break; if ( code <= end ) { idx = code; p = q + num_segs2 - 2; delta = TT_PEEK_SHORT( p ); p += num_segs2; offset = TT_PEEK_USHORT( p ); if ( offset == 0xFFFFU ) goto Exit; if ( offset != 0 ) { p += offset + 2 * ( idx - start ); idx = TT_PEEK_USHORT( p ); } if ( idx != 0 ) result = (FT_UInt)( idx + delta ) & 0xFFFFU; } } } } Exit: return result; } FT_CALLBACK_DEF( FT_UInt ) tt_cmap4_char_next( TT_CMap cmap, FT_UInt32 *pchar_code ) { FT_Byte* table = cmap->data; FT_UInt32 result = 0; FT_UInt gindex = 0; FT_UInt32 char_code = *pchar_code; FT_Byte* p; FT_UInt code, num_segs2; if ( char_code >= 0xFFFFUL ) goto Exit;#ifdef OPT_CMAP4 { TT_CMap4 cmap4 = (TT_CMap4)cmap; if ( char_code == cmap4->old_charcode ) { result = cmap4->cur_charcode; gindex = cmap4->cur_gindex; if ( result != 0 ) { tt_cmap4_next( cmap4 ); goto Exit; } } }#endif /* OPT_CMAP4 */ code = (FT_UInt)char_code + 1; p = table + 6; num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); /* ensure even-ness */ if ( !cmap->unsorted ) { for (;;) { /* Some fonts have more than 170 segments in their charmaps! */ /* We changed this function to use a more efficient binary */ /* search */ FT_UInt offset; FT_Int delta; FT_UInt min = 0; FT_UInt max = num_segs2 >> 1; FT_UInt mid, start, end; FT_UInt hi; /* we begin by finding the segment which end is closer to our code point */ hi = max + 1; while ( min < max ) { mid = ( min + max ) >> 1; p = table + 14 + mid * 2; end = TT_PEEK_USHORT( p ); if ( end < code ) min = mid + 1; else { hi = mid; max = mid; } } if ( hi > max ) { /* the point is behind the last segment; we will exit right now */ goto Exit; } p = table + 14 + hi * 2; end = TT_PEEK_USHORT( p ); p += 2 + num_segs2; start = TT_PEEK_USHORT( p ); if ( code < start ) code = start; p += num_segs2; delta = TT_PEEK_USHORT( p ); p += num_segs2; offset = TT_PEEK_USHORT( p ); if ( offset != 0 && offset != 0xFFFFU ) { /* parse the glyph ids array for non-zero index */ p += offset + ( code - start ) * 2; while ( code <= end ) { gindex = TT_NEXT_USHORT( p ); if ( gindex != 0 ) { gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU; if ( gindex != 0 ) { result = code;#ifdef OPT_CMAP4 tt_cmap4_reset( (TT_CMap4)cmap, code, hi );#endif goto Exit; } } code++; } } else if ( offset == 0xFFFFU ) { /* an offset of 0xFFFF means an empty segment in certain fonts! */ code = end + 1; } else /* offset == 0 */ { gindex = (FT_UInt)( code + delta ) & 0xFFFFU; if ( gindex != 0 ) { result = code;#ifdef OPT_CMAP4 tt_cmap4_reset( (TT_CMap4)cmap, code, hi );#endif goto Exit; } code++; } } } else { for ( ;; ) { FT_UInt offset, n; FT_Int delta; FT_Byte* q; p = table + 14; /* ends table */ q = table + 16 + num_segs2; /* starts table */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -