📄 ttcmap0.c
字号:
else
{
/* a 16-bit character code */
/* jump to key entry */
p += char_hi * 2;
/* jump to sub-header */
sub = subs + ( FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 8 ) );
/* check that the high byte isn't a valid one-byte value */
if ( sub == subs )
goto Exit;
}
result = sub;
}
Exit:
return result;
}
FT_CALLBACK_DEF( FT_UInt )
tt_cmap2_char_index( TT_CMap cmap,
FT_UInt32 char_code )
{
FT_Byte* table = cmap->data;
FT_UInt result = 0;
FT_Byte* subheader;
subheader = tt_cmap2_get_subheader( table, char_code );
if ( subheader )
{
FT_Byte* p = subheader;
FT_UInt idx = (FT_UInt)(char_code & 0xFF);
FT_UInt start, count;
FT_Int delta;
FT_UInt offset;
start = TT_NEXT_USHORT( p );
count = TT_NEXT_USHORT( p );
delta = TT_NEXT_SHORT ( p );
offset = TT_PEEK_USHORT( p );
idx -= start;
if ( idx < count && offset != 0 )
{
p += offset + 2 * idx;
idx = TT_PEEK_USHORT( p );
if ( idx != 0 )
result = (FT_UInt)( idx + delta ) & 0xFFFFU;
}
}
return result;
}
FT_CALLBACK_DEF( FT_UInt )
tt_cmap2_char_next( TT_CMap cmap,
FT_UInt32 *pcharcode )
{
FT_Byte* table = cmap->data;
FT_UInt gindex = 0;
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 = FT_PAD_FLOOR( 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 = FT_PAD_FLOOR( charcode, 256 ) + 256;
}
Exit:
*pcharcode = result;
return gindex;
}
FT_CALLBACK_DEF( FT_Error )
tt_cmap2_get_info( TT_CMap cmap,
TT_CMapInfo *cmap_info )
{
FT_Byte* p = cmap->data + 4;
cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
return FT_Err_Ok;
}
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,
(TT_CMap_Info_GetFunc) tt_cmap2_get_info
};
#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. */
/* */
/* */
/* Finally, note that certain fonts contain invalid charmaps that */
/* contain end=0xFFFF, start=0xFFFF, delta=0x0001, offset=0xFFFF at the */
/* of their charmaps (e.g. opens___.ttf which comes with OpenOffice.org) */
/* we need special code to deal with them correctly... */
/* */
#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;
/* in certain fonts, the `length' field is invalid and goes */
/* out of bound. We try to correct this here... */
if ( length < 16 )
FT_INVALID_TOO_SHORT;
if ( table + length > valid->limit )
{
if ( valid->level >= FT_VALIDATE_TIGHT )
FT_INVALID_TOO_SHORT;
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 ( valid->level >= FT_VALIDATE_TIGHT )
{
if ( n > 0 && start <= last )
FT_INVALID_DATA;
}
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;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -