📄 ttcmap.c
字号:
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 */
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 )
{
p = q + num_segs2 - 2;
delta = TT_PEEK_SHORT( p );
p += num_segs2;
offset = TT_PEEK_USHORT( p );
if ( offset != 0 && offset != 0xFFFFU )
{
/* parse the glyph ids array for non-0 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 )
break;
}
code++;
}
}
else if ( offset == 0xFFFFU )
{
/* an offset of 0xFFFF means an empty glyph in certain fonts! */
code = end;
break;
}
else
gindex = (FT_UInt)( code + delta ) & 0xFFFFU;
if ( gindex == 0 )
break;
result = code;
goto Exit;
}
}
/* loop to next trial charcode */
if ( code >= 0xFFFFU )
break;
code++;
}
}
Exit:
*pchar_code = result;
return gindex;
}
FT_CALLBACK_DEF( FT_Error )
tt_cmap4_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_cmap4_class_rec =
{
{
#ifdef OPT_CMAP4
sizeof ( TT_CMap4Rec ),
(FT_CMap_InitFunc) tt_cmap4_init,
#else
sizeof ( TT_CMapRec ),
(FT_CMap_InitFunc) tt_cmap_init,
#endif
(FT_CMap_DoneFunc) NULL,
(FT_CMap_CharIndexFunc)tt_cmap4_char_index,
(FT_CMap_CharNextFunc) tt_cmap4_char_next
},
4,
(TT_CMap_ValidateFunc) tt_cmap4_validate,
(TT_CMap_Info_GetFunc) tt_cmap4_get_info
};
#endif /* TT_CONFIG_CMAP_FORMAT_4 */
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** FORMAT 6 *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/* */
/* 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 */
/* */
/* first 6 USHORT first segment code */
/* count 8 USHORT segment size in chars */
/* glyphIds 10 USHORT[count] glyph ids */
/* */
/* A very simplified segment mapping. */
/* */
#ifdef TT_CONFIG_CMAP_FORMAT_6
FT_CALLBACK_DEF( FT_Error )
tt_cmap6_validate( FT_Byte* table,
FT_Validator valid )
{
FT_Byte* p;
FT_UInt length, count;
if ( table + 10 > valid->limit )
FT_INVALID_TOO_SHORT;
p = table + 2;
length = TT_NEXT_USHORT( p );
p = table + 8; /* skip language and start index */
count = TT_NEXT_USHORT( p );
if ( table + length > valid->limit || length < 10 + count * 2 )
FT_INVALID_TOO_SHORT;
/* check glyph indices */
if ( valid->level >= FT_VALIDATE_TIGHT )
{
FT_UInt gindex;
for ( ; count > 0; count-- )
{
gindex = TT_NEXT_USHORT( p );
if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) )
FT_INVALID_GLYPH_ID;
}
}
return SFNT_Err_Ok;
}
FT_CALLBACK_DEF( FT_UInt )
tt_cmap6_char_index( TT_CMap cmap,
FT_UInt32 char_code )
{
FT_Byte* table = cmap->data;
FT_UInt result = 0;
FT_Byte* p = table + 6;
FT_UInt start = TT_NEXT_USHORT( p );
FT_UInt count = TT_NEXT_USHORT( p );
FT_UInt idx = (FT_UInt)( char_code - start );
if ( idx < count )
{
p += 2 * idx;
result = TT_PEEK_USHORT( p );
}
return result;
}
FT_CALLBACK_DEF( FT_UInt )
tt_cmap6_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 = table + 6;
FT_UInt start = TT_NEXT_USHORT( p );
FT_UInt count = TT_NEXT_USHORT( p );
FT_UInt idx;
if ( char_code >= 0x10000UL )
goto Exit;
if ( char_code < start )
char_code = start;
idx = (FT_UInt)( char_code - start );
p += 2 * idx;
for ( ; idx < count; idx++ )
{
gindex = TT_NEXT_USHORT( p );
if ( gindex != 0 )
{
result = char_code;
break;
}
char_code++;
}
Exit:
*pchar_code = result;
return gindex;
}
FT_CALLBACK_DEF( FT_Error )
tt_cmap6_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_cmap6_class_rec =
{
{
sizeof ( TT_CMapRec ),
(FT_CMap_InitFunc) tt_cmap_init,
(FT_CMap_DoneFunc) NULL,
(FT_CMap_CharIndexFunc)tt_cmap6_char_index,
(FT_CMap_CharNextFunc) tt_cmap6_char_next
},
6,
(TT_CMap_ValidateFunc) tt_cmap6_validate,
(TT_CMap_Info_GetFunc) tt_cmap6_get_info
};
#endif /* TT_CONFIG_CMAP_FORMAT_6 */
/*************************************************************************/
/*************************************************************************/
/***** *****/
/***** FORMAT 8 *****/
/***** *****/
/***** It's hard to completely understand what the OpenType spec *****/
/***** says about this format, but here is my conclusion. *****/
/***** *****/
/***** The purpose of this format is to easily map UTF-16 text to *****/
/***** glyph indices. Basically, the `char_code' must be in one of *****/
/***** the following formats: *****/
/***** *****/
/***** - A 16-bit value that isn't part of the Unicode Surrogates *****/
/***** Area (i.e. U+D800-U+DFFF). *****/
/***** *****/
/***** - A 32-bit value, made of two surrogate values, i.e.. if *****/
/***** `char_code = (char_hi << 16) | char_lo', then both *****/
/***** `char_hi' and `char_lo' must be in the Surrogates Area. *****/
/***** Area. *****/
/***** *****/
/***** The 'is32' table embedded in the charmap indicates whether a *****/
/***** given 16-bit value is in the surrogates area or not. *****/
/***** *****/
/***** So, for any given `char_code', we can assert the following: *****/
/***** *****/
/***** If `char_hi == 0' then we must have `is32[char_lo] == 0'. *****/
/***** *****/
/***** If `char_hi != 0' then we must have both *****/
/***** `is32[char_hi] != 0' and `is32[char_lo] != 0'. *****/
/***** *****/
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
/* */
/* TABLE OVERVIEW */
/* -------------- */
/* */
/* NAME OFFSET TYPE DESCRIPTION */
/* */
/* format 0 USHORT must be 8 */
/* reseved 2 USHORT reserved */
/* length 4 ULONG length in bytes */
/* language 8 ULONG Mac language code */
/* is32 12 BYTE[8192] 32-bitness bitmap */
/* count 8204 ULONG number of groups */
/* */
/* This header is followed by 'count' groups of the following format: */
/* */
/* start 0 ULONG first charcode */
/* end 4 ULONG last charcode */
/* startId 8 ULONG start glyph id for the group */
/* */
#ifdef TT_CONFIG_CMAP_FORMAT_8
FT_CALLBACK_DEF( FT_Error )
tt_cmap8_validate( FT_Byte* table,
FT_Validator valid )
{
FT_Byte* p = table + 4;
FT_Byte* is32;
FT_UInt32 length;
FT_UInt32 num_groups;
if ( table + 16 + 8192 > valid->limit )
FT_INVALID_TOO_SHORT;
length = TT_NEXT_ULONG( p );
if ( table + length > valid->limit || length < 8208 )
FT_INVALID_TOO_SHORT;
is32 = table + 12;
p = is32 + 8192; /* skip `is32' array */
num_groups = TT_NEXT_ULONG( p );
if ( p + num_groups * 12 > valid->limit )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -