📄 ttcmap.c
字号:
} num_segs /= 2; if ( length < 16 + num_segs * 2 * 4 ) FT_INVALID_TOO_SHORT; /* 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; /* 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; } { FT_UInt start, end, offset, n; FT_UInt last_start = 0, last_end = 0; FT_Int delta; FT_Byte* p_start = starts; FT_Byte* p_end = ends; FT_Byte* p_delta = deltas; FT_Byte* p_offset = offsets; for ( n = 0; n < num_segs; n++ ) { p = p_offset; start = TT_NEXT_USHORT( p_start ); end = TT_NEXT_USHORT( p_end ); delta = TT_NEXT_SHORT( p_delta ); offset = TT_NEXT_USHORT( p_offset ); 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 ( start <= last_end && n > 0 ) { if ( valid->level >= FT_VALIDATE_TIGHT ) FT_INVALID_DATA; else { /* allow overlapping segments, provided their start points */ /* and end points, respectively, are in ascending order. */ /* */ if ( last_start > start || last_end > end ) error |= TT_CMAP_FLAG_UNSORTED; else error |= TT_CMAP_FLAG_OVERLAPPING; } } 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_start = start; last_end = end; } } return error; } static FT_UInt tt_cmap4_char_map_linear( TT_CMap cmap, FT_UInt* pcharcode, FT_Bool next ) { FT_UInt num_segs2, start, end, offset; FT_Int delta; FT_UInt i, num_segs; FT_UInt32 charcode = *pcharcode; FT_UInt gindex = 0; FT_Byte* p; p = cmap->data + 6; num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); num_segs = num_segs2 >> 1; if ( !num_segs ) return 0; if ( next ) charcode++; /* linear search */ for ( ; charcode <= 0xFFFFU; charcode++ ) { FT_Byte* q; p = cmap->data + 14; /* ends table */ q = cmap->data + 16 + num_segs2; /* starts table */ for ( i = 0; i < num_segs; i++ ) { end = TT_NEXT_USHORT( p ); start = TT_NEXT_USHORT( q ); if ( charcode >= start && charcode <= end ) { p = q - 2 + num_segs2; delta = TT_PEEK_SHORT( p ); p += num_segs2; offset = TT_PEEK_USHORT( p ); if ( offset == 0xFFFFU ) continue; if ( offset ) { p += offset + ( charcode - start ) * 2; gindex = TT_PEEK_USHORT( p ); if ( gindex != 0 ) gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU; } else gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU; break; } } if ( !next || gindex ) break; } if ( next && gindex ) *pcharcode = charcode; return gindex; } static FT_UInt tt_cmap4_char_map_binary( TT_CMap cmap, FT_UInt* pcharcode, FT_Bool next ) { FT_UInt num_segs2, start, end, offset; FT_Int delta; FT_UInt max, min, mid, num_segs; FT_UInt charcode = *pcharcode; FT_UInt gindex = 0; FT_Byte* p; p = cmap->data + 6; num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); if ( !num_segs2 ) return 0; num_segs = num_segs2 >> 1; /* make compiler happy */ mid = num_segs; end = 0xFFFFU; if ( next ) charcode++; min = 0; max = num_segs; /* binary search */ while ( min < max ) { mid = ( min + max ) >> 1; p = cmap->data + 14 + mid * 2; end = TT_PEEK_USHORT( p ); p += 2 + num_segs2; start = TT_PEEK_USHORT( p ); if ( charcode < start ) max = mid; else if ( charcode > end ) min = mid + 1; else { p += num_segs2; delta = TT_PEEK_SHORT( p ); p += num_segs2; offset = TT_PEEK_USHORT( p ); /* search the first segment containing `charcode' */ if ( cmap->flags & TT_CMAP_FLAG_OVERLAPPING ) { FT_UInt i; /* call the current segment `max' */ max = mid; if ( offset == 0xFFFFU ) mid = max + 1; /* search in segments before the current segment */ for ( i = max ; i > 0; i-- ) { FT_UInt prev_end; FT_Byte* old_p; old_p = p; p = cmap->data + 14 + ( i - 1 ) * 2; prev_end = TT_PEEK_USHORT( p ); if ( charcode > prev_end ) { p = old_p; break; } end = prev_end; p += 2 + num_segs2; start = TT_PEEK_USHORT( p ); p += num_segs2; delta = TT_PEEK_SHORT( p ); p += num_segs2; offset = TT_PEEK_USHORT( p ); if ( offset != 0xFFFFU ) mid = i - 1; } /* no luck */ if ( mid == max + 1 ) { if ( i != max ) { p = cmap->data + 14 + max * 2; end = TT_PEEK_USHORT( p ); p += 2 + num_segs2; start = TT_PEEK_USHORT( p ); p += num_segs2; delta = TT_PEEK_SHORT( p ); p += num_segs2; offset = TT_PEEK_USHORT( p ); } mid = max; /* search in segments after the current segment */ for ( i = max + 1; i < num_segs; i++ ) { FT_UInt next_end, next_start; p = cmap->data + 14 + i * 2; next_end = TT_PEEK_USHORT( p ); p += 2 + num_segs2; next_start = TT_PEEK_USHORT( p ); if ( charcode < next_start ) break; end = next_end; start = next_start; p += num_segs2; delta = TT_PEEK_SHORT( p ); p += num_segs2; offset = TT_PEEK_USHORT( p ); if ( offset != 0xFFFFU ) mid = i; } i--; /* still no luck */ if ( mid == max ) { mid = i; break; } } /* end, start, delta, and offset are for the i'th segment */ if ( mid != i ) { p = cmap->data + 14 + mid * 2; end = TT_PEEK_USHORT( p ); p += 2 + num_segs2; start = TT_PEEK_USHORT( p ); p += num_segs2; delta = TT_PEEK_SHORT( p ); p += num_segs2; offset = TT_PEEK_USHORT( p ); } } else { if ( offset == 0xFFFFU ) break; } if ( offset ) { p += offset + ( charcode - start ) * 2; gindex = TT_PEEK_USHORT( p ); if ( gindex != 0 ) gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU; } else gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU; break; } } if ( next ) { TT_CMap4 cmap4 = (TT_CMap4)cmap; /* if `charcode' is not in any segment, then `mid' is */ /* the segment nearest to `charcode' */ /* */ if ( charcode > end ) { mid++; if ( mid == num_segs )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -