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
|
#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 )
|
FT_CALLBACK_DEF( void )
|
||||||
tt_cmap4_validate( FT_Byte* table,
|
tt_cmap4_validate( FT_Byte* table,
|
||||||
FT_Validator valid )
|
FT_Validator valid )
|
||||||
|
@ -798,7 +966,6 @@
|
||||||
FT_UInt code = (FT_UInt)char_code;
|
FT_UInt code = (FT_UInt)char_code;
|
||||||
FT_Byte* p;
|
FT_Byte* p;
|
||||||
|
|
||||||
|
|
||||||
p = table + 6;
|
p = table + 6;
|
||||||
num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); /* be paranoid! */
|
num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); /* be paranoid! */
|
||||||
|
|
||||||
|
@ -921,6 +1088,23 @@
|
||||||
if ( char_code >= 0xFFFFUL )
|
if ( char_code >= 0xFFFFUL )
|
||||||
goto Exit;
|
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;
|
code = (FT_UInt)char_code + 1;
|
||||||
p = table + 6;
|
p = table + 6;
|
||||||
num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT(p), 2 ); /* ensure even-ness */
|
num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT(p), 2 ); /* ensure even-ness */
|
||||||
|
@ -993,6 +1177,9 @@
|
||||||
if ( gindex != 0 )
|
if ( gindex != 0 )
|
||||||
{
|
{
|
||||||
result = code;
|
result = code;
|
||||||
|
#ifdef OPT_CMAP4
|
||||||
|
tt_cmap4_reset( (TT_CMap4)cmap, code, hi );
|
||||||
|
#endif
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1001,7 +1188,7 @@
|
||||||
}
|
}
|
||||||
else if ( offset == 0xFFFFU )
|
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;
|
code = end + 1;
|
||||||
}
|
}
|
||||||
else /* offset == 0 */
|
else /* offset == 0 */
|
||||||
|
@ -1010,6 +1197,9 @@
|
||||||
if ( gindex != 0 )
|
if ( gindex != 0 )
|
||||||
{
|
{
|
||||||
result = code;
|
result = code;
|
||||||
|
#ifdef OPT_CMAP4
|
||||||
|
tt_cmap4_reset( (TT_CMap4)cmap, code, hi );
|
||||||
|
#endif
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
code++;
|
code++;
|
||||||
|
@ -1108,9 +1298,13 @@
|
||||||
const TT_CMap_ClassRec tt_cmap4_class_rec =
|
const TT_CMap_ClassRec tt_cmap4_class_rec =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
#ifdef OPT_CMAP4
|
||||||
|
sizeof ( TT_CMap4Rec ),
|
||||||
|
(FT_CMap_InitFunc) tt_cmap4_init,
|
||||||
|
#else
|
||||||
sizeof ( TT_CMapRec ),
|
sizeof ( TT_CMapRec ),
|
||||||
|
|
||||||
(FT_CMap_InitFunc) tt_cmap_init,
|
(FT_CMap_InitFunc) tt_cmap_init,
|
||||||
|
#endif
|
||||||
(FT_CMap_DoneFunc) NULL,
|
(FT_CMap_DoneFunc) NULL,
|
||||||
(FT_CMap_CharIndexFunc)tt_cmap4_char_index,
|
(FT_CMap_CharIndexFunc)tt_cmap4_char_index,
|
||||||
(FT_CMap_CharNextFunc) tt_cmap4_char_next
|
(FT_CMap_CharNextFunc) tt_cmap4_char_next
|
||||||
|
|
Loading…
Reference in New Issue