optimization of linear charmap scanning for Format 4
This commit is contained in:
parent
fa0eb0c95f
commit
150c0dc616
@ -621,6 +621,174 @@
|
||||
|
||||
#ifdef TT_CONFIG_CMAP_FORMAT_4
|
||||
|
||||
#define OPT_CMAP4
|
||||
|
||||
#ifdef OPT_CMAP4
|
||||
|
||||
typedef struct TT_CMap4Rec_
|
||||
{
|
||||
TT_CMapRec cmap;
|
||||
FT_UInt32 old_charcode; /* old charcode */
|
||||
FT_UInt32 cur_charcode; /* current charcode */
|
||||
FT_UInt cur_gindex; /* current glyph index */
|
||||
|
||||
FT_UInt table_length;
|
||||
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 + 2;
|
||||
cmap->table_length = FT_PEEK_USHORT(p);
|
||||
|
||||
p = table + 6;
|
||||
cmap->num_ranges = FT_PEEK_USHORT(p) >> 1;
|
||||
cmap->cur_range = cmap->num_ranges;
|
||||
cmap->old_charcode = 0xFFFFFFFFUL;
|
||||
cmap->cur_charcode = 0;
|
||||
cmap->cur_gindex = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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_SHORT(p);
|
||||
|
||||
if ( offset != 0xFFFF )
|
||||
{
|
||||
cmap->cur_values = offset ? p + offset : NULL;
|
||||
cmap->cur_range = range_index;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* we skip empty segments */
|
||||
range_index++;
|
||||
}
|
||||
|
||||
cmap->old_charcode = 0xFFFFFFFFUL;
|
||||
cmap->cur_charcode = 0;
|
||||
cmap->cur_gindex = 0;
|
||||
cmap->cur_range = num_ranges;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
tt_cmap4_next( TT_CMap4 cmap )
|
||||
{
|
||||
FT_UInt num_ranges = cmap->num_ranges;
|
||||
FT_UInt charcode = cmap->cur_charcode + 1;
|
||||
|
||||
cmap->old_charcode = cmap->cur_charcode;
|
||||
|
||||
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) & 0xFFFF);
|
||||
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;
|
||||
|
||||
charcode = cmap->cur_start;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
tt_cmap4_reset( TT_CMap4 cmap,
|
||||
FT_UInt code,
|
||||
FT_UInt range_index )
|
||||
{
|
||||
if ( tt_cmap4_set_range( cmap, range_index ) >= 0 )
|
||||
{
|
||||
cmap->cur_charcode = code;
|
||||
tt_cmap4_next( cmap );
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OPT_CMAP4 */
|
||||
|
||||
|
||||
|
||||
FT_CALLBACK_DEF( void )
|
||||
tt_cmap4_validate( FT_Byte* table,
|
||||
FT_Validator valid )
|
||||
@ -798,7 +966,6 @@
|
||||
FT_UInt code = (FT_UInt)char_code;
|
||||
FT_Byte* p;
|
||||
|
||||
|
||||
p = table + 6;
|
||||
num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); /* be paranoid! */
|
||||
|
||||
@ -921,6 +1088,23 @@
|
||||
if ( char_code >= 0xFFFFUL )
|
||||
goto Exit;
|
||||
|
||||
#ifdef OPT_CMAP4
|
||||
{
|
||||
TT_CMap4 cmap4 = (TT_CMap4)cmap;
|
||||
|
||||
if ( char_code == cmap4->old_charcode )
|
||||
{
|
||||
result = cmap4->cur_charcode;
|
||||
gindex = cmap4->cur_gindex;
|
||||
if ( result != 0 )
|
||||
{
|
||||
tt_cmap4_next( cmap4 );
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* OPT_CMAP4 */
|
||||
|
||||
code = (FT_UInt)char_code + 1;
|
||||
p = table + 6;
|
||||
num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT(p), 2 ); /* ensure even-ness */
|
||||
@ -993,6 +1177,9 @@
|
||||
if ( gindex != 0 )
|
||||
{
|
||||
result = code;
|
||||
#ifdef OPT_CMAP4
|
||||
tt_cmap4_reset( (TT_CMap4)cmap, code, hi );
|
||||
#endif
|
||||
goto Exit;
|
||||
}
|
||||
}
|
||||
@ -1001,7 +1188,7 @@
|
||||
}
|
||||
else if ( offset == 0xFFFFU )
|
||||
{
|
||||
/* an offset of 0xFFFF means an empty glyph in certain fonts! */
|
||||
/* an offset of 0xFFFF means an empty segment in certain fonts! */
|
||||
code = end + 1;
|
||||
}
|
||||
else /* offset == 0 */
|
||||
@ -1010,6 +1197,9 @@
|
||||
if ( gindex != 0 )
|
||||
{
|
||||
result = code;
|
||||
#ifdef OPT_CMAP4
|
||||
tt_cmap4_reset( (TT_CMap4)cmap, code, hi );
|
||||
#endif
|
||||
goto Exit;
|
||||
}
|
||||
code++;
|
||||
@ -1108,9 +1298,13 @@
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user