forked from minhngoc25a/freetype2
[sfnt] Rewrite `tt_cmap4_char_map_linear' (#46078).
* src/sfnt/ttcmap.c (tt_cmap4_char_map_linear): Add code to better skip invalid segments. If searching the next character, provide a more efficient logic to speed up the code.
This commit is contained in:
parent
8651f37ad5
commit
2ff83a5c99
|
@ -1,3 +1,12 @@
|
|||
2015-09-30 Werner Lemberg <wl@gnu.org>
|
||||
|
||||
[sfnt] Rewrite `tt_cmap4_char_map_linear' (#46078).
|
||||
|
||||
* src/sfnt/ttcmap.c (tt_cmap4_char_map_linear): Add code to better
|
||||
skip invalid segments.
|
||||
If searching the next character, provide a more efficient logic to
|
||||
speed up the code.
|
||||
|
||||
2015-09-30 Werner Lemberg <wl@gnu.org>
|
||||
|
||||
[truetype] Adjust number of glyphs for malformed `loca' tables.
|
||||
|
|
|
@ -1035,12 +1035,17 @@
|
|||
FT_UInt32* pcharcode,
|
||||
FT_Bool next )
|
||||
{
|
||||
TT_Face face = (TT_Face)cmap->cmap.charmap.face;
|
||||
FT_Byte* limit = face->cmap_table + face->cmap_size;
|
||||
|
||||
|
||||
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;
|
||||
FT_Byte* q;
|
||||
|
||||
|
||||
p = cmap->data + 6;
|
||||
|
@ -1054,65 +1059,104 @@
|
|||
if ( next )
|
||||
charcode++;
|
||||
|
||||
if ( charcode > 0xFFFFU )
|
||||
return 0;
|
||||
|
||||
/* linear search */
|
||||
for ( ; charcode <= 0xFFFFU; charcode++ )
|
||||
p = cmap->data + 14; /* ends table */
|
||||
q = cmap->data + 16 + num_segs2; /* starts table */
|
||||
|
||||
for ( i = 0; i < num_segs; i++ )
|
||||
{
|
||||
FT_Byte* q;
|
||||
end = TT_NEXT_USHORT( p );
|
||||
start = TT_NEXT_USHORT( q );
|
||||
|
||||
|
||||
p = cmap->data + 14; /* ends table */
|
||||
q = cmap->data + 16 + num_segs2; /* starts table */
|
||||
|
||||
for ( i = 0; i < num_segs; i++ )
|
||||
if ( charcode < start )
|
||||
{
|
||||
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 );
|
||||
|
||||
/* some fonts have an incorrect last segment; */
|
||||
/* we have to catch it */
|
||||
if ( i >= num_segs - 1 &&
|
||||
start == 0xFFFFU && end == 0xFFFFU )
|
||||
{
|
||||
TT_Face face = (TT_Face)cmap->cmap.charmap.face;
|
||||
FT_Byte* limit = face->cmap_table + face->cmap_size;
|
||||
|
||||
|
||||
if ( offset && p + offset + 2 > limit )
|
||||
{
|
||||
delta = 1;
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ( offset == 0xFFFFU )
|
||||
continue;
|
||||
|
||||
if ( offset )
|
||||
{
|
||||
p += offset + ( charcode - start ) * 2;
|
||||
gindex = TT_PEEK_USHORT( p );
|
||||
if ( gindex != 0 )
|
||||
gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU;
|
||||
}
|
||||
else
|
||||
gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU;
|
||||
|
||||
if ( next )
|
||||
charcode = start;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !next || gindex )
|
||||
Again:
|
||||
if ( charcode <= end )
|
||||
{
|
||||
FT_Byte* r;
|
||||
|
||||
|
||||
r = q - 2 + num_segs2;
|
||||
delta = TT_PEEK_SHORT( r );
|
||||
r += num_segs2;
|
||||
offset = TT_PEEK_USHORT( r );
|
||||
|
||||
/* some fonts have an incorrect last segment; */
|
||||
/* we have to catch it */
|
||||
if ( i >= num_segs - 1 &&
|
||||
start == 0xFFFFU && end == 0xFFFFU )
|
||||
{
|
||||
if ( offset && r + offset + 2 > limit )
|
||||
{
|
||||
delta = 1;
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ( offset == 0xFFFFU )
|
||||
continue;
|
||||
|
||||
if ( offset )
|
||||
{
|
||||
r += offset + ( charcode - start ) * 2;
|
||||
|
||||
/* if r > limit, the whole segment is invalid */
|
||||
if ( next && r > limit )
|
||||
continue;
|
||||
|
||||
gindex = TT_PEEK_USHORT( r );
|
||||
if ( gindex )
|
||||
gindex = (FT_UInt)( (FT_Int)gindex + delta ) & 0xFFFFU;
|
||||
}
|
||||
else
|
||||
{
|
||||
gindex = (FT_UInt)( (FT_Int)charcode + delta ) & 0xFFFFU;
|
||||
|
||||
if ( next && gindex >= (FT_UInt)face->root.num_glyphs )
|
||||
{
|
||||
/* we have an invalid glyph index; if there is an overflow, */
|
||||
/* we can adjust `charcode', otherwise the whole segment is */
|
||||
/* invalid */
|
||||
if ( (FT_Int)charcode + delta < 0 &&
|
||||
(FT_Int)end + delta >= 0 )
|
||||
{
|
||||
charcode = (FT_UInt)( -delta );
|
||||
gindex = 0;
|
||||
}
|
||||
else if ( (FT_Int)charcode + delta < 0x10000L &&
|
||||
(FT_Int)end + delta >= 0x10000L )
|
||||
{
|
||||
charcode = (FT_UInt)( 0x10000L - delta );
|
||||
gindex = 0;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ( next && !gindex )
|
||||
{
|
||||
if ( charcode >= 0xFFFFU )
|
||||
break;
|
||||
|
||||
charcode++;
|
||||
goto Again;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( next && gindex )
|
||||
if ( next )
|
||||
*pcharcode = charcode;
|
||||
|
||||
return gindex;
|
||||
|
|
Loading…
Reference in New Issue