* src/sfnt/ttcmap.c (struct TT_CMap12Rec_, tt_cmap12_init,

tt_cmap12_next): New struct/function for fast "next char".
(tt_cmap12_char_map_binary): New function to do "charcode => glyph
index" by binary search.
(tt_cmap12_char_index, tt_cmap12_char_next): Use
tt_cmap12_char_map_binary.
(tt_face_build_cmaps): Check table and offset correctly (equality is
missing).
This commit is contained in:
Wu, Chia-I (吳佳一) 2005-11-29 11:27:51 +00:00
parent df1598e316
commit 569ec4ee2a
2 changed files with 188 additions and 53 deletions

View File

@ -1,3 +1,14 @@
2005-11-29 Chia-I Wu <b90201047@ntu.edu.tw>
* src/sfnt/ttcmap.c (struct TT_CMap12Rec_, tt_cmap12_init,
tt_cmap12_next): New struct/function for fast "next char".
(tt_cmap12_char_map_binary): New function to do "charcode => glyph
index" by binary search.
(tt_cmap12_char_index, tt_cmap12_char_next): Use
tt_cmap12_char_map_binary.
(tt_face_build_cmaps): Check table and offset correctly (equality is
missing).
2005-11-15 Detlef Würkner <TetiSoft@apg.lahn.de>
* builds/amiga/smakefile: Adjusted the compiler options

View File

@ -1916,6 +1916,33 @@
#ifdef TT_CONFIG_CMAP_FORMAT_12
typedef struct TT_CMap12Rec_
{
TT_CMapRec cmap;
FT_Bool valid;
FT_ULong cur_charcode;
FT_UInt cur_gindex;
FT_ULong cur_group;
FT_ULong num_groups;
} TT_CMap12Rec, *TT_CMap12;
FT_CALLBACK_DEF( FT_Error )
tt_cmap12_init( TT_CMap12 cmap,
FT_Byte* table )
{
cmap->cmap.data = table;
table += 12;
cmap->num_groups = FT_PEEK_ULONG( table );
cmap->valid = 0;
return SFNT_Err_Ok;
}
FT_CALLBACK_DEF( FT_Error )
tt_cmap12_validate( FT_Byte* table,
FT_Validator valid )
@ -1968,33 +1995,142 @@
}
/* find the index of the charcode next to cmap->cur_charcode */
/* cmap->cur_group should be set up properly by caller */
/* */
static void
tt_cmap12_next( TT_CMap12 cmap )
{
FT_Byte* p;
FT_ULong start, end, start_id, char_code;
FT_ULong n;
FT_UInt gindex;
if ( cmap->cur_charcode >= 0xFFFFFFFFUL )
goto Fail;
char_code = cmap->cur_charcode + 1;
n = cmap->cur_group;
for ( n = cmap->cur_group; n < cmap->num_groups; n++ )
{
p = cmap->cmap.data + 16 + 12 * n;
start = TT_NEXT_ULONG( p );
end = TT_NEXT_ULONG( p );
start_id = TT_PEEK_ULONG( p );
if ( char_code < start )
char_code = start;
for ( ; char_code <= end; char_code++ )
{
gindex = (FT_UInt)( start_id + char_code - start );
if ( gindex )
{
cmap->cur_charcode = char_code;;
cmap->cur_gindex = gindex;
cmap->cur_group = n;
return;
}
}
}
Fail:
cmap->valid = 0;
}
static FT_UInt
tt_cmap12_char_map_binary( TT_CMap cmap,
FT_UInt32* pchar_code,
FT_Bool next )
{
FT_UInt gindex = 0;
FT_Byte* p = cmap->data + 12;
FT_UInt32 num_groups = TT_PEEK_ULONG( p );
FT_UInt32 char_code = *pchar_code;
FT_UInt32 start, end, start_id;
FT_UInt32 max, min, mid;
if ( !num_groups )
return 0;
if ( next )
char_code++;
min = 0;
max = num_groups;
/* binary search */
while ( min < max )
{
mid = ( min + max ) >> 1;
p = cmap->data + 16 + 12 * mid;
start = TT_NEXT_ULONG( p );
end = TT_NEXT_ULONG( p );
if ( char_code < start )
max = mid;
else if ( char_code > end )
min = mid + 1;
else
{
start_id = TT_PEEK_ULONG( p );
gindex = (FT_UInt)( start_id + char_code - start );
break;
}
}
if ( next )
{
TT_CMap12 cmap12 = (TT_CMap12)cmap;
/* if `char_code' is not in any group, then `mid' is */
/* the group nearest to `char_code' */
/* */
if ( char_code > end )
{
mid++;
if ( mid == num_groups )
return 0;
}
cmap12->valid = 1;
cmap12->cur_charcode = char_code;
cmap12->cur_group = mid;
if ( !gindex )
{
tt_cmap12_next( cmap12 );
if ( cmap12->valid )
gindex = cmap12->cur_gindex;
}
else
cmap12->cur_gindex = gindex;
if ( gindex )
*pchar_code = cmap12->cur_charcode;
}
return gindex;
}
FT_CALLBACK_DEF( FT_UInt )
tt_cmap12_char_index( TT_CMap cmap,
FT_UInt32 char_code )
{
FT_UInt result = 0;
FT_Byte* table = cmap->data;
FT_Byte* p = table + 12;
FT_UInt32 num_groups = TT_NEXT_ULONG( p );
FT_UInt32 start, end, start_id;
for ( ; num_groups > 0; num_groups-- )
{
start = TT_NEXT_ULONG( p );
end = TT_NEXT_ULONG( p );
start_id = TT_NEXT_ULONG( p );
if ( char_code < start )
break;
if ( char_code <= end )
{
result = (FT_UInt)( start_id + char_code - start );
break;
}
}
return result;
return tt_cmap12_char_map_binary( cmap, &char_code, 0 );
}
@ -2002,39 +2138,29 @@
tt_cmap12_char_next( TT_CMap cmap,
FT_UInt32 *pchar_code )
{
FT_Byte* table = cmap->data;
FT_UInt32 result = 0;
FT_UInt32 char_code = *pchar_code + 1;
FT_UInt gindex = 0;
FT_Byte* p = table + 12;
FT_UInt32 num_groups = TT_NEXT_ULONG( p );
FT_UInt32 start, end, start_id;
TT_CMap12 cmap12 = (TT_CMap12)cmap;
FT_ULong gindex;
p = table + 16;
if ( cmap12->cur_charcode >= 0xFFFFFFFFUL )
return 0;
for ( ; num_groups > 0; num_groups-- )
/* no need to search */
if ( cmap12->valid && cmap12->cur_charcode == *pchar_code )
{
start = TT_NEXT_ULONG( p );
end = TT_NEXT_ULONG( p );
start_id = TT_NEXT_ULONG( p );
if ( char_code < start )
char_code = start;
if ( char_code <= end )
tt_cmap12_next( cmap12 );
if ( cmap12->valid )
{
gindex = (FT_UInt)(char_code - start + start_id);
if ( gindex != 0 )
{
result = char_code;
goto Exit;
}
gindex = cmap12->cur_gindex;
if ( gindex )
*pchar_code = cmap12->cur_charcode;
}
else
gindex = 0;
}
else
gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 );
Exit:
*pchar_code = result;
return gindex;
}
@ -2056,9 +2182,9 @@
const TT_CMap_ClassRec tt_cmap12_class_rec =
{
{
sizeof ( TT_CMapRec ),
sizeof ( TT_CMap12Rec ),
(FT_CMap_InitFunc) tt_cmap_init,
(FT_CMap_InitFunc) tt_cmap12_init,
(FT_CMap_DoneFunc) NULL,
(FT_CMap_CharIndexFunc)tt_cmap12_char_index,
(FT_CMap_CharNextFunc) tt_cmap12_char_next
@ -2144,9 +2270,7 @@
charmap.encoding = FT_ENCODING_NONE; /* will be filled later */
offset = TT_NEXT_ULONG( p );
if ( offset &&
table + offset + 2 < limit &&
table + offset >= table )
if ( offset && table + offset + 2 <= limit )
{
FT_Byte* cmap = table + offset;
volatile FT_UInt format = TT_PEEK_USHORT( cmap );