optimization of linear charmap scanning for Format 4

This commit is contained in:
David Turner 2005-02-28 17:17:47 +00:00
parent fa0eb0c95f
commit 150c0dc616
1 changed files with 197 additions and 3 deletions

View File

@ -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