📄 ttcmap0.c
字号:
FT_UInt32 result = 0; FT_UInt32 charcode = *pcharcode + 1; FT_Byte* subheader; while ( charcode < 0x10000UL ) { subheader = tt_cmap2_get_subheader( table, charcode ); if ( subheader ) { FT_Byte* p = subheader; FT_UInt start = TT_NEXT_USHORT( p ); FT_UInt count = TT_NEXT_USHORT( p ); FT_Int delta = TT_NEXT_SHORT ( p ); FT_UInt offset = TT_PEEK_USHORT( p ); FT_UInt char_lo = (FT_UInt)( charcode & 0xFF ); FT_UInt pos, idx; if ( offset == 0 ) goto Next_SubHeader; if ( char_lo < start ) { char_lo = start; pos = 0; } else pos = (FT_UInt)( char_lo - start ); p += offset + pos * 2; charcode = ( charcode & -256 ) + char_lo; for ( ; pos < count; pos++, charcode++ ) { idx = TT_NEXT_USHORT( p ); if ( idx != 0 ) { gindex = ( idx + delta ) & 0xFFFFU; if ( gindex != 0 ) { result = charcode; goto Exit; } } } } /* jump to next sub-header, i.e. higher byte value */ Next_SubHeader: charcode = ( charcode & -256 ) + 256; } Exit: *pcharcode = result; return gindex; } FT_CALLBACK_TABLE_DEF const TT_CMap_ClassRec tt_cmap2_class_rec = { { sizeof( TT_CMapRec ), (FT_CMap_InitFunc) tt_cmap_init, (FT_CMap_DoneFunc) NULL, (FT_CMap_CharIndexFunc)tt_cmap2_char_index, (FT_CMap_CharNextFunc) tt_cmap2_char_next }, 2, (TT_CMap_ValidateFunc) tt_cmap2_validate };#endif /* TT_CONFIG_CMAP_FORMAT_2 */ /*************************************************************************/ /*************************************************************************/ /***** *****/ /***** FORMAT 4 *****/ /***** *****/ /*************************************************************************/ /*************************************************************************/ /*************************************************************************/ /* */ /* TABLE OVERVIEW */ /* -------------- */ /* */ /* NAME OFFSET TYPE DESCRIPTION */ /* */ /* format 0 USHORT must be 4 */ /* length 2 USHORT table length */ /* in bytes */ /* language 4 USHORT Mac language code */ /* */ /* segCountX2 6 USHORT 2*NUM_SEGS */ /* searchRange 8 USHORT 2*(1 << LOG_SEGS) */ /* entrySelector 10 USHORT LOG_SEGS */ /* rangeShift 12 USHORT segCountX2 - */ /* searchRange */ /* */ /* endCount 14 USHORT[NUM_SEGS] end charcode for */ /* each segment; last */ /* is 0xFFFF */ /* */ /* pad 14+NUM_SEGS*2 USHORT padding */ /* */ /* startCount 16+NUM_SEGS*2 USHORT[NUM_SEGS] first charcode for */ /* each segment */ /* */ /* idDelta 16+NUM_SEGS*4 SHORT[NUM_SEGS] delta for each */ /* segment */ /* idOffset 16+NUM_SEGS*6 SHORT[NUM_SEGS] range offset for */ /* each segment; can be */ /* zero */ /* */ /* glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph id */ /* ranges */ /* */ /* Character codes are modelled by a series of ordered (increasing) */ /* intervals called segments. Each segment has start and end codes, */ /* provided by the `startCount' and `endCount' arrays. Segments must */ /* not be overlapping and the last segment should always contain the */ /* `0xFFFF' endCount. */ /* */ /* The fields `searchRange', `entrySelector' and `rangeShift' are better */ /* ignored (they are traces of over-engineering in the TrueType */ /* specification). */ /* */ /* Each segment also has a signed `delta', as well as an optional offset */ /* within the `glyphIds' table. */ /* */ /* If a segment's idOffset is 0, the glyph index corresponding to any */ /* charcode within the segment is obtained by adding the value of */ /* `idDelta' directly to the charcode, modulo 65536. */ /* */ /* Otherwise, a glyph index is taken from the glyph ids sub-array for */ /* the segment, and the value of `idDelta' is added to it. */ /* */#ifdef TT_CONFIG_CMAP_FORMAT_4 FT_CALLBACK_DEF( void ) tt_cmap4_validate( FT_Byte* table, FT_Validator valid ) { FT_Byte* p = table + 2; /* skip format */ FT_UInt length = TT_NEXT_USHORT( p ); FT_Byte *ends, *starts, *offsets, *deltas, *glyph_ids; FT_UInt num_segs; if ( table + length > valid->limit || length < 16 ) FT_INVALID_TOO_SHORT; 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 ( valid->level >= FT_VALIDATE_TIGHT ) { if ( n > 0 && start <= last ) FT_INVALID_DATA; } if ( offset ) { p += offset; /* start of glyph id array */ /* check that we point within the glyph ids table only */ if ( p < glyph_ids || p + ( end - start + 1 ) * 2 > table + length ) FT_INVALID_DATA; /* check glyph indices within the segment range */ if ( valid->level >= FT_VALIDATE_TIGHT ) { FT_UInt idx; for ( ; start < end; ) { 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; } } } } last = end; } } } 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 = TT_PEEK_USHORT( p ) & -2; /* be paranoid! */#if 1 /* 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 != 0 ) { p += offset + 2 * ( idx - start ); idx = TT_PEEK_USHORT( p ); } if ( idx != 0 ) result = (FT_UInt)( idx + delta ) & 0xFFFFU; goto Exit; } } }#else /* 0 - old code */ { 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 != 0 ) { p += offset + 2 * ( idx - start ); idx = TT_PEEK_USHORT( p ); } if ( idx != 0 ) result = (FT_UInt)( idx + delta ) & 0xFFFFU; } } }#endif /* 0 */ } 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_UInt32 char_code = *pchar_code + 1; FT_UInt gindex = 0; FT_Byte* p; FT_Byte* q; FT_UInt code, num_segs2; if ( char_code >= 0x10000UL ) goto Exit; code = (FT_UInt)char_code; p = table + 6; num_segs2 = TT_PEEK_USHORT(p) & -2; /* ensure even-ness */ for (;;) { FT_UInt offset, n; FT_Int delta; 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 ); if ( code < start ) code = start; if ( code <= end ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -