📄 ttcmap.c
字号:
/* indicates that it's really a valid one-byte value */
/* Otherwise, return 0 */
/* */
p += char_lo * 2;
if ( TT_PEEK_USHORT( p ) != 0 )
goto Exit;
}
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 SFNT_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
typedef struct TT_CMap4Rec_
{
TT_CMapRec cmap;
FT_UInt32 cur_charcode; /* current charcode */
FT_UInt cur_gindex; /* current glyph index */
FT_UInt num_ranges;
FT_UInt cur_range;
FT_UInt cur_start;
FT_UInt cur_end;
FT_Int cur_delta;
FT_Byte* cur_values;
} TT_CMap4Rec, *TT_CMap4;
FT_CALLBACK_DEF( FT_Error )
tt_cmap4_init( TT_CMap4 cmap,
FT_Byte* table )
{
FT_Byte* p;
cmap->cmap.data = table;
p = table + 6;
cmap->num_ranges = FT_PEEK_USHORT( p ) >> 1;
cmap->cur_charcode = 0xFFFFFFFFUL;
cmap->cur_gindex = 0;
return SFNT_Err_Ok;
}
static FT_Int
tt_cmap4_set_range( TT_CMap4 cmap,
FT_UInt range_index )
{
FT_Byte* table = cmap->cmap.data;
FT_Byte* p;
FT_UInt num_ranges = cmap->num_ranges;
while ( range_index < num_ranges )
{
FT_UInt offset;
p = table + 14 + range_index * 2;
cmap->cur_end = FT_PEEK_USHORT( p );
p += 2 + num_ranges * 2;
cmap->cur_start = FT_PEEK_USHORT( p );
p += num_ranges * 2;
cmap->cur_delta = FT_PEEK_SHORT( p );
p += num_ranges * 2;
offset = FT_PEEK_USHORT( p );
if ( offset != 0xFFFFU )
{
cmap->cur_values = offset ? p + offset : NULL;
cmap->cur_range = range_index;
return 0;
}
/* we skip empty segments */
range_index++;
}
return -1;
}
/* search the index of the charcode next to cmap->cur_charcode; */
/* caller should call tt_cmap4_set_range with proper range */
/* before calling this function */
/* */
static void
tt_cmap4_next( TT_CMap4 cmap )
{
FT_UInt charcode;
if ( cmap->cur_charcode >= 0xFFFFUL )
goto Fail;
charcode = cmap->cur_charcode + 1;
if ( charcode < cmap->cur_start )
charcode = cmap->cur_start;
for ( ;; )
{
FT_Byte* values = cmap->cur_values;
FT_UInt end = cmap->cur_end;
FT_Int delta = cmap->cur_delta;
if ( charcode <= end )
{
if ( values )
{
FT_Byte* p = values + 2 * ( charcode - cmap->cur_start );
do
{
FT_UInt gindex = FT_NEXT_USHORT( p );
if ( gindex != 0 )
{
gindex = (FT_UInt)( ( gindex + delta ) & 0xFFFFU );
if ( gindex != 0 )
{
cmap->cur_charcode = charcode;
cmap->cur_gindex = gindex;
return;
}
}
} while ( ++charcode <= end );
}
else
{
do
{
FT_UInt gindex = (FT_UInt)( ( charcode + delta ) & 0xFFFFU );
if ( gindex != 0 )
{
cmap->cur_charcode = charcode;
cmap->cur_gindex = gindex;
return;
}
} while ( ++charcode <= end );
}
}
/* we need to find another range */
if ( tt_cmap4_set_range( cmap, cmap->cur_range + 1 ) < 0 )
break;
if ( charcode < cmap->cur_start )
charcode = cmap->cur_start;
}
Fail:
cmap->cur_charcode = 0xFFFFFFFFUL;
cmap->cur_gindex = 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -