ref: 150c0dc616b18922f8524d4902f408dcd8c54dda
parent: fa0eb0c95fa954a3097d62c440303c403f466942
author: David Turner <[email protected]>
date: Mon Feb 28 12:17:47 EST 2005
optimization of linear charmap scanning for Format 4
--- a/src/sfnt/ttcmap.c
+++ b/src/sfnt/ttcmap.c
@@ -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