|
|
|
@ -4,7 +4,7 @@ |
|
|
|
|
/* */ |
|
|
|
|
/* CFF character mapping table (cmap) support (body). */ |
|
|
|
|
/* */ |
|
|
|
|
/* Copyright 2002, 2003, 2004, 2005 by */ |
|
|
|
|
/* Copyright 2002, 2003, 2004, 2005, 2006 by */ |
|
|
|
|
/* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
|
|
|
|
/* */ |
|
|
|
|
/* This file is part of the FreeType project, and may only be used, */ |
|
|
|
@ -119,30 +119,23 @@ |
|
|
|
|
/*************************************************************************/ |
|
|
|
|
/*************************************************************************/ |
|
|
|
|
|
|
|
|
|
FT_CALLBACK_DEF( FT_Int ) |
|
|
|
|
cff_cmap_uni_pair_compare( const void* pair1, |
|
|
|
|
const void* pair2 ) |
|
|
|
|
const char * |
|
|
|
|
cff_sid_to_glyph_name( CFF_Font cff, |
|
|
|
|
FT_UInt idx ) |
|
|
|
|
{ |
|
|
|
|
FT_UInt32 u1 = ((CFF_CMapUniPair)pair1)->unicode; |
|
|
|
|
FT_UInt32 u2 = ((CFF_CMapUniPair)pair2)->unicode; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( u1 < u2 ) |
|
|
|
|
return -1; |
|
|
|
|
CFF_Charset charset = &cff->charset; |
|
|
|
|
FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; |
|
|
|
|
FT_UInt sid = charset->sids[idx]; |
|
|
|
|
|
|
|
|
|
if ( u1 > u2 ) |
|
|
|
|
return +1; |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
return cff_index_get_sid_string( &cff->string_index, sid, psnames ); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FT_CALLBACK_DEF( FT_Error ) |
|
|
|
|
cff_cmap_unicode_init( CFF_CMapUnicode cmap ) |
|
|
|
|
cff_cmap_unicode_init( PS_Unicodes unicodes ) |
|
|
|
|
{ |
|
|
|
|
FT_Error error; |
|
|
|
|
FT_UInt count; |
|
|
|
|
TT_Face face = (TT_Face)FT_CMAP_FACE( cmap ); |
|
|
|
|
TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); |
|
|
|
|
FT_Memory memory = FT_FACE_MEMORY( face ); |
|
|
|
|
CFF_Font cff = (CFF_Font)face->extra.data; |
|
|
|
|
CFF_Charset charset = &cff->charset; |
|
|
|
@ -151,178 +144,58 @@ |
|
|
|
|
|
|
|
|
|
/* can't build Unicode map for CID-keyed font */ |
|
|
|
|
if ( !charset->sids ) |
|
|
|
|
{ |
|
|
|
|
error = CFF_Err_Invalid_Argument; |
|
|
|
|
goto Exit; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
cmap->num_pairs = 0; |
|
|
|
|
cmap->pairs = NULL; |
|
|
|
|
|
|
|
|
|
count = cff->num_glyphs; |
|
|
|
|
|
|
|
|
|
if ( !FT_NEW_ARRAY( cmap->pairs, count ) ) |
|
|
|
|
{ |
|
|
|
|
FT_UInt n, new_count; |
|
|
|
|
CFF_CMapUniPair pair; |
|
|
|
|
FT_UInt32 uni_code; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pair = cmap->pairs; |
|
|
|
|
for ( n = 0; n < count; n++ ) |
|
|
|
|
{ |
|
|
|
|
FT_UInt sid = charset->sids[n]; |
|
|
|
|
const char* gname; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gname = cff_index_get_sid_string( &cff->string_index, sid, psnames ); |
|
|
|
|
|
|
|
|
|
/* build unsorted pair table by matching glyph names */ |
|
|
|
|
if ( gname ) |
|
|
|
|
{ |
|
|
|
|
uni_code = psnames->unicode_value( gname ); |
|
|
|
|
|
|
|
|
|
if ( uni_code != 0 ) |
|
|
|
|
{ |
|
|
|
|
pair->unicode = uni_code; |
|
|
|
|
pair->gindex = n; |
|
|
|
|
pair++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
FT_FREE( gname ); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
new_count = (FT_UInt)( pair - cmap->pairs ); |
|
|
|
|
if ( new_count == 0 ) |
|
|
|
|
{ |
|
|
|
|
/* there are no unicode characters in here! */ |
|
|
|
|
FT_FREE( cmap->pairs ); |
|
|
|
|
error = CFF_Err_Invalid_Argument; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
/* re-allocate if the new array is much smaller than the original */ |
|
|
|
|
/* one */ |
|
|
|
|
if ( new_count != count && new_count < count / 2 ) |
|
|
|
|
{ |
|
|
|
|
(void)FT_RENEW_ARRAY( cmap->pairs, count, new_count ); |
|
|
|
|
error = CFF_Err_Ok; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* sort the pairs table to allow efficient binary searches */ |
|
|
|
|
ft_qsort( cmap->pairs, |
|
|
|
|
new_count, |
|
|
|
|
sizeof ( CFF_CMapUniPairRec ), |
|
|
|
|
cff_cmap_uni_pair_compare ); |
|
|
|
|
|
|
|
|
|
cmap->num_pairs = new_count; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return CFF_Err_Invalid_Argument; |
|
|
|
|
|
|
|
|
|
Exit: |
|
|
|
|
return error; |
|
|
|
|
return psnames->unicodes_init( memory, |
|
|
|
|
unicodes, |
|
|
|
|
cff->num_glyphs, |
|
|
|
|
(PS_Glyph_NameFunc)&cff_sid_to_glyph_name, |
|
|
|
|
(FT_Pointer)cff ); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FT_CALLBACK_DEF( void ) |
|
|
|
|
cff_cmap_unicode_done( CFF_CMapUnicode cmap ) |
|
|
|
|
cff_cmap_unicode_done( PS_Unicodes unicodes ) |
|
|
|
|
{ |
|
|
|
|
FT_Face face = FT_CMAP_FACE( cmap ); |
|
|
|
|
FT_Face face = FT_CMAP_FACE( unicodes ); |
|
|
|
|
FT_Memory memory = FT_FACE_MEMORY( face ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FT_FREE( cmap->pairs ); |
|
|
|
|
cmap->num_pairs = 0; |
|
|
|
|
FT_FREE( unicodes->maps ); |
|
|
|
|
unicodes->num_maps = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FT_CALLBACK_DEF( FT_UInt ) |
|
|
|
|
cff_cmap_unicode_char_index( CFF_CMapUnicode cmap, |
|
|
|
|
FT_UInt32 char_code ) |
|
|
|
|
cff_cmap_unicode_char_index( PS_Unicodes unicodes, |
|
|
|
|
FT_UInt32 char_code ) |
|
|
|
|
{ |
|
|
|
|
FT_UInt min = 0; |
|
|
|
|
FT_UInt max = cmap->num_pairs; |
|
|
|
|
FT_UInt mid; |
|
|
|
|
CFF_CMapUniPair pair; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while ( min < max ) |
|
|
|
|
{ |
|
|
|
|
mid = min + ( max - min ) / 2; |
|
|
|
|
pair = cmap->pairs + mid; |
|
|
|
|
TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); |
|
|
|
|
CFF_Font cff = (CFF_Font)face->extra.data; |
|
|
|
|
FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; |
|
|
|
|
|
|
|
|
|
if ( pair->unicode == char_code ) |
|
|
|
|
return pair->gindex; |
|
|
|
|
|
|
|
|
|
if ( pair->unicode < char_code ) |
|
|
|
|
min = mid + 1; |
|
|
|
|
else |
|
|
|
|
max = mid; |
|
|
|
|
} |
|
|
|
|
return 0; |
|
|
|
|
return psnames->unicodes_char_index( unicodes, char_code ); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FT_CALLBACK_DEF( FT_UInt ) |
|
|
|
|
cff_cmap_unicode_char_next( CFF_CMapUnicode cmap, |
|
|
|
|
FT_UInt32 *pchar_code ) |
|
|
|
|
cff_cmap_unicode_char_next( PS_Unicodes unicodes, |
|
|
|
|
FT_UInt32 *pchar_code ) |
|
|
|
|
{ |
|
|
|
|
FT_UInt result = 0; |
|
|
|
|
FT_UInt32 char_code = *pchar_code + 1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Restart: |
|
|
|
|
{ |
|
|
|
|
FT_UInt min = 0; |
|
|
|
|
FT_UInt max = cmap->num_pairs; |
|
|
|
|
FT_UInt mid; |
|
|
|
|
CFF_CMapUniPair pair; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
while ( min < max ) |
|
|
|
|
{ |
|
|
|
|
mid = min + ( ( max - min ) >> 1 ); |
|
|
|
|
pair = cmap->pairs + mid; |
|
|
|
|
|
|
|
|
|
if ( pair->unicode == char_code ) |
|
|
|
|
{ |
|
|
|
|
result = pair->gindex; |
|
|
|
|
if ( result != 0 ) |
|
|
|
|
goto Exit; |
|
|
|
|
|
|
|
|
|
char_code++; |
|
|
|
|
goto Restart; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ( pair->unicode < char_code ) |
|
|
|
|
min = mid+1; |
|
|
|
|
else |
|
|
|
|
max = mid; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* we didn't find it, but we have a pair just above it */ |
|
|
|
|
char_code = 0; |
|
|
|
|
TT_Face face = (TT_Face)FT_CMAP_FACE( unicodes ); |
|
|
|
|
CFF_Font cff = (CFF_Font)face->extra.data; |
|
|
|
|
FT_Service_PsCMaps psnames = (FT_Service_PsCMaps)cff->psnames; |
|
|
|
|
|
|
|
|
|
if ( min < cmap->num_pairs ) |
|
|
|
|
{ |
|
|
|
|
pair = cmap->pairs + min; |
|
|
|
|
result = pair->gindex; |
|
|
|
|
if ( result != 0 ) |
|
|
|
|
char_code = pair->unicode; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Exit: |
|
|
|
|
*pchar_code = char_code; |
|
|
|
|
return result; |
|
|
|
|
return psnames->unicodes_char_next( unicodes, pchar_code ); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FT_CALLBACK_TABLE_DEF const FT_CMap_ClassRec |
|
|
|
|
cff_cmap_unicode_class_rec = |
|
|
|
|
{ |
|
|
|
|
sizeof ( CFF_CMapUnicodeRec ), |
|
|
|
|
sizeof ( PS_UnicodesRec ), |
|
|
|
|
|
|
|
|
|
(FT_CMap_InitFunc) cff_cmap_unicode_init, |
|
|
|
|
(FT_CMap_DoneFunc) cff_cmap_unicode_done, |
|
|
|
|