diff --git a/ChangeLog b/ChangeLog index 303b640b6..16e464e7f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2008-09-19 suzuki toshiya + + * src/base/ftmac.c: Import sfnt-wrapped Type1 and sfnt-wrapped + CID-keyed font support. + * builds/mac/ftmac.c: Ditto. + 2008-09-19 suzuki toshiya * src/base/ftobjs.c (Mac_Read_sfnt_Resource): Fix double free bug diff --git a/builds/mac/ftmac.c b/builds/mac/ftmac.c index ef45dca90..24844344d 100644 --- a/builds/mac/ftmac.c +++ b/builds/mac/ftmac.c @@ -1208,6 +1208,59 @@ typedef short ResourceIndex; } + /* Look up `TYP1' or `CID ' table from sfnt table directory. */ + /* offset & length must exclude the binary header in tables. */ + + /* For proper support, PS Type1 and CID-keyed font drivers */ + /* should recognize sfnt-wrapped format. Here, yet TrueType */ + /* font driver is not loaded, we must parse by ourselves. */ + /* We only care the name of table and offset. */ + + static FT_Error + ft_lookup_PS_in_sfnt( FT_Byte* sfnt, + FT_ULong* offset, + FT_ULong* length, + FT_Bool* is_sfnt_cid ) + { + FT_Byte* p = sfnt + 4; /* skip version `typ1' */ + FT_UShort numTables = FT_NEXT_USHORT( p ); + + + p += ( 2 * 3 ); /* skip binary search header */ + for ( ; numTables > 0 ; numTables -- ) + { + FT_ULong tag = FT_NEXT_ULONG( p ); + + + p += 4; /* skip checkSum */ + *offset = FT_NEXT_ULONG( p ); + *length = FT_NEXT_ULONG( p ); + + /* see Adobe TN# 5180 for binary header in CID table */ + if ( tag == FT_MAKE_TAG( 'C', 'I', 'D', ' ' ) ) + { + *offset += 22; + *length -= 22; + *is_sfnt_cid = TRUE; + return FT_Err_Ok; + } + + /* see Apple "The Type 1 GX Font Format" */ + if ( tag == FT_MAKE_TAG( 'T', 'Y', 'P', '1' ) ) + { + *offset += 24; + *length -= 24; + *is_sfnt_cid = FALSE; + return FT_Err_Ok; + } + } + + *offset = 0; + *length = 0; + return FT_Err_Invalid_Table; + } + + /* Create a new FT_Face from an SFNT resource, specified by res ID. */ static FT_Error FT_New_Face_From_SFNT( FT_Library library, @@ -1220,7 +1273,7 @@ typedef short ResourceIndex; size_t sfnt_size; FT_Error error = FT_Err_Ok; FT_Memory memory = library->memory; - int is_cff; + int is_cff, is_sfnt_ps; sfnt = GetResource( FT_MAKE_TAG( 's', 'f', 'n', 't' ), sfnt_id ); @@ -1239,17 +1292,49 @@ typedef short ResourceIndex; HUnlock( sfnt ); ReleaseResource( sfnt ); - is_cff = sfnt_size > 4 && sfnt_data[0] == 'O' && - sfnt_data[1] == 'T' && - sfnt_data[2] == 'T' && - sfnt_data[3] == 'O'; + is_cff = sfnt_size > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 ); + is_sfnt_ps = sfnt_size > 4 && !ft_memcmp( sfnt_data, "typ1", 4 ); - return open_face_from_buffer( library, - sfnt_data, - sfnt_size, - face_index, - is_cff ? "cff" : "truetype", - aface ); + if ( is_sfnt_ps ) + { + FT_ULong offset, length; + FT_Bool is_sfnt_cid; + FT_Byte* sfnt_ps; + + + error = ft_lookup_PS_in_sfnt( sfnt_data, + &offset, + &length, + &is_sfnt_cid ); + if ( error ) + goto Try_OpenType; + + + if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) ) + return error; + ft_memcpy( sfnt_ps, sfnt_data + offset, length ); + + error = open_face_from_buffer( library, + sfnt_ps, + length, + face_index, + is_sfnt_cid ? "cid" : "type1", + aface ); + if ( !error ) + { + FT_FREE( sfnt_data ); + goto Exit; + } + } + Try_OpenType: + error = open_face_from_buffer( library, + sfnt_data, + sfnt_size, + face_index, + is_cff ? "cff" : "truetype", + aface ); + Exit: + return error; } diff --git a/src/base/ftmac.c b/src/base/ftmac.c index a799817b7..4a52d76d0 100644 --- a/src/base/ftmac.c +++ b/src/base/ftmac.c @@ -829,6 +829,59 @@ } + /* Look up `TYP1' or `CID ' table from sfnt table directory. */ + /* offset & length must exclude the binary header in tables. */ + + /* For proper support, PS Type1 and CID-keyed font drivers */ + /* should recognize sfnt-wrapped format. Here, yet TrueType */ + /* font driver is not loaded, we must parse by ourselves. */ + /* We only care the name of table and offset. */ + + static FT_Error + ft_lookup_PS_in_sfnt( FT_Byte* sfnt, + FT_ULong* offset, + FT_ULong* length, + FT_Bool* is_sfnt_cid ) + { + FT_Byte* p = sfnt + 4; /* skip version `typ1' */ + FT_UShort numTables = FT_NEXT_USHORT( p ); + + + p += ( 2 * 3 ); /* skip binary search header */ + for ( ; numTables > 0 ; numTables -- ) + { + FT_ULong tag = FT_NEXT_ULONG( p ); + + + p += 4; /* skip checkSum */ + *offset = FT_NEXT_ULONG( p ); + *length = FT_NEXT_ULONG( p ); + + /* see Adobe TN# 5180 for binary header in CID table */ + if ( tag == FT_MAKE_TAG( 'C', 'I', 'D', ' ' ) ) + { + *offset += 22; + *length -= 22; + *is_sfnt_cid = TRUE; + return FT_Err_Ok; + } + + /* see Apple "The Type 1 GX Font Format" */ + if ( tag == FT_MAKE_TAG( 'T', 'Y', 'P', '1' ) ) + { + *offset += 24; + *length -= 24; + *is_sfnt_cid = FALSE; + return FT_Err_Ok; + } + } + + *offset = 0; + *length = 0; + return FT_Err_Invalid_Table; + } + + /* Create a new FT_Face from an SFNT resource, specified by res ID. */ static FT_Error FT_New_Face_From_SFNT( FT_Library library, @@ -841,7 +894,7 @@ size_t sfnt_size; FT_Error error = FT_Err_Ok; FT_Memory memory = library->memory; - int is_cff; + int is_cff, is_sfnt_ps; sfnt = GetResource( FT_MAKE_TAG( 's', 'f', 'n', 't' ), sfnt_id ); @@ -858,17 +911,49 @@ ft_memcpy( sfnt_data, *sfnt, sfnt_size ); ReleaseResource( sfnt ); - is_cff = sfnt_size > 4 && sfnt_data[0] == 'O' && - sfnt_data[1] == 'T' && - sfnt_data[2] == 'T' && - sfnt_data[3] == 'O'; + is_cff = sfnt_size > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 ); + is_sfnt_ps = sfnt_size > 4 && !ft_memcmp( sfnt_data, "typ1", 4 ); - return open_face_from_buffer( library, - sfnt_data, - sfnt_size, - face_index, - is_cff ? "cff" : "truetype", - aface ); + if ( is_sfnt_ps ) + { + FT_ULong offset, length; + FT_Bool is_sfnt_cid; + FT_Byte* sfnt_ps; + + + error = ft_lookup_PS_in_sfnt( sfnt_data, + &offset, + &length, + &is_sfnt_cid ); + if ( error ) + goto Try_OpenType; + + + if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) ) + return error; + ft_memcpy( sfnt_ps, sfnt_data + offset, length ); + + error = open_face_from_buffer( library, + sfnt_ps, + length, + face_index, + is_sfnt_cid ? "cid" : "type1", + aface ); + if ( !error ) + { + FT_FREE( sfnt_data ); + goto Exit; + } + } + Try_OpenType: + error = open_face_from_buffer( library, + sfnt_data, + sfnt_size, + face_index, + is_cff ? "cff" : "truetype", + aface ); + Exit: + return error; }