From 1137d04f85079ff3b96b148ebcfed39690fdb09e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Suzuki=2C=20Toshiya=20=28=E9=88=B4=E6=9C=A8=E4=BF=8A?= =?UTF-8?q?=E5=93=89=29?= Date: Sat, 4 Oct 2008 07:11:58 +0000 Subject: [PATCH] * New function `open_face_PS_from_sfnt_stream' to check and open a Type1 PS or CID-keyed font in an sfnt stream. --- ChangeLog | 16 ++++ builds/mac/ftmac.c | 32 +++----- src/base/ftbase.h | 16 ++-- src/base/ftmac.c | 33 +++----- src/base/ftobjs.c | 189 +++++++++++++++++++++++++++------------------ 5 files changed, 163 insertions(+), 123 deletions(-) diff --git a/ChangeLog b/ChangeLog index d78485600..ff89f6877 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2008-10-04 suzuki toshiya + + * src/base/ftobjs.c (ft_lookup_PS_in_sfnt): Replaced by... + (ft_lookup_PS_in_sfnt_stream): This. + (open_face_PS_from_sfnt_stream): New function. It checks + whether the stream is sfnt-wrapped Type1 PS font or sfnt- + wrapped CID-keyed font, then try to open a face for given + face_index. + (Mac_Read_sfnt_Resource): Replace the combination of + `ft_lookup_PS_in_sfnt' and `open_face_from_buffer' by + `open_face_PS_from_sfnt_stream'. + * src/base/ftmac.c (FT_New_Face_From_SFNT): Ditto. + * builds/mac/ftmac.c (FT_New_Face_From_SFNT): Ditto. + * src/base/ftbase.h: Remove `ft_lookup_PS_in_sfnt' and add + `open_face_PS_from_sfnt_stream'. + 2008-10-03 suzuki toshiya * src/base/ftobjs.c (ft_lookup_PS_in_sfnt): Set *is_sfnt_cid diff --git a/builds/mac/ftmac.c b/builds/mac/ftmac.c index 77f025e20..b2d56b884 100644 --- a/builds/mac/ftmac.c +++ b/builds/mac/ftmac.c @@ -1142,34 +1142,26 @@ typedef short ResourceIndex; if ( is_sfnt_ps ) { - FT_ULong offset, length; - FT_Bool is_sfnt_cid; - FT_Byte* sfnt_ps; + FT_Stream stream; - error = ft_lookup_PS_in_sfnt( sfnt_data, - &offset, - &length, - &is_sfnt_cid ); - if ( error ) + if ( FT_NEW( stream ) ) 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_Stream_OpenMemory( stream, sfnt_data, sfnt_size ); + if ( !open_face_PS_from_sfnt_stream( library, + stream, + face_index, + 0, NULL, + aface ) ) { + FT_Stream_Close( stream ); + FT_FREE( stream ); FT_FREE( sfnt_data ); goto Exit; } + + FT_FREE( stream ); } Try_OpenType: error = open_face_from_buffer( library, diff --git a/src/base/ftbase.h b/src/base/ftbase.h index a20158363..d8c18abaa 100644 --- a/src/base/ftbase.h +++ b/src/base/ftbase.h @@ -27,14 +27,16 @@ FT_BEGIN_HEADER - /* Check whether the sfnt image in the buffer is sfnt-wrapped PS Type1 */ - /* or sfnt-wrapped CID-keyed font. */ + /* Assume the stream is sfnt-wrapped PS Type1 or sfnt-wrapped CID-keyed */ + /* font, and try to load a face specified by the face_index. */ FT_LOCAL_DEF( FT_Error ) - ft_lookup_PS_in_sfnt( FT_Byte* sfnt, - FT_ULong* offset, - FT_ULong* length, - FT_Bool* is_sfnt_cid ); - + open_face_PS_from_sfnt_stream( FT_Library library, + FT_Stream stream, + FT_Long face_index, + FT_Int num_params, + FT_Parameter *params, + FT_Face *aface ); + /* Create a new FT_Face given a buffer and a driver name. */ /* From ftmac.c. */ diff --git a/src/base/ftmac.c b/src/base/ftmac.c index 4c471386f..b9d11ae53 100644 --- a/src/base/ftmac.c +++ b/src/base/ftmac.c @@ -761,36 +761,27 @@ if ( is_sfnt_ps ) { - FT_ULong offset, length; - FT_Bool is_sfnt_cid; - FT_Byte* sfnt_ps; + FT_Stream stream; - error = ft_lookup_PS_in_sfnt( sfnt_data, - &offset, - &length, - &is_sfnt_cid ); - if ( error ) + if ( FT_NEW( stream ) ) 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_Stream_OpenMemory( stream, sfnt_data, sfnt_size ); + if ( !open_face_PS_from_sfnt_stream( library, + stream, + face_index, + 0, NULL, + aface ) ) { + FT_Stream_Close( stream ); + FT_FREE( stream ); FT_FREE( sfnt_data ); goto Exit; } - } + FT_FREE( stream ); + } Try_OpenType: error = open_face_from_buffer( library, sfnt_data, diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c index b799a31c4..a8fe744f0 100644 --- a/src/base/ftobjs.c +++ b/src/base/ftobjs.c @@ -1323,50 +1323,117 @@ /* ourselves. We are only interested in the name of the table and */ /* the offset. */ - FT_LOCAL_DEF( FT_Error ) - ft_lookup_PS_in_sfnt( FT_Byte* sfnt, - FT_ULong* offset, - FT_ULong* length, - FT_Bool* is_sfnt_cid ) + static FT_Error + ft_lookup_PS_in_sfnt_stream( FT_Stream stream, + FT_Long face_index, + 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 ); + FT_Error error; + FT_UShort numTables; + FT_Long pstable_index; + FT_ULong tag; + int i; - 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's `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; + *is_sfnt_cid = TRUE; + /* TODO: support for sfnt-wrapped PS/CID in TTC format */ *is_sfnt_cid = FALSE; - return FT_Err_Invalid_Table; + + /* version check for 'typ1' (should be ignored?) */ + if ( FT_READ_ULONG( tag ) ) + return error; + if ( tag != FT_MAKE_TAG( 't', 'y', 'p', '1' ) ) + return FT_Err_Unknown_File_Format; + + + if ( FT_READ_USHORT( numTables ) ) + return error; + if ( FT_STREAM_SKIP( 2 * 3 ) ) /* skip binary search header */ + return error; + + + pstable_index = -1; + *is_sfnt_cid = FALSE; + for ( i = 0; i < numTables; i ++ ) + { + if ( FT_READ_ULONG( tag ) || FT_STREAM_SKIP( 4 ) || + FT_READ_ULONG( *offset ) || FT_READ_ULONG( *length ) ) + return error; + + if ( tag == FT_MAKE_TAG( 'C', 'I', 'D', ' ' ) ) + { + pstable_index ++; + *offset += 22; + *length -= 22; + *is_sfnt_cid = TRUE; + if ( face_index < 0 ) + return FT_Err_Ok; + } + else if ( tag == FT_MAKE_TAG( 'T', 'Y', 'P', '1' ) ) + { + pstable_index ++; + *offset += 24; + *length -= 24; + *is_sfnt_cid = FALSE; + if ( face_index < 0 ) + return FT_Err_Ok; + } + if ( face_index >= 0 && pstable_index == face_index ) + return FT_Err_Ok; + } + return FT_Err_Table_Missing; + } + + + FT_LOCAL_DEF( FT_Error ) + open_face_PS_from_sfnt_stream( FT_Library library, + FT_Stream stream, + FT_Long face_index, + FT_Int num_params, + FT_Parameter *params, + FT_Face *aface ) + { + FT_Error error; + FT_Memory memory = library->memory; + FT_ULong offset, length; + FT_Long pos; + FT_Bool is_sfnt_cid; + FT_Byte* sfnt_ps; + + + pos = FT_Stream_Pos( stream ); + + error = ft_lookup_PS_in_sfnt_stream( stream, + face_index, + &offset, + &length, + &is_sfnt_cid ); + if ( error ) + return error; + + if ( FT_Stream_Seek( stream, pos + offset ) ) + goto Exit; + + if ( FT_ALLOC( sfnt_ps, (FT_Long)length ) ) + goto Exit; + + error = FT_Stream_Read( stream, (FT_Byte *)sfnt_ps, length ); + if ( error ) + goto Exit; + + error = open_face_from_buffer( library, + sfnt_ps, + length, + face_index < 0 ? face_index : 0, + is_sfnt_cid ? "cid" : "type1", + aface ); + Exit: + FT_Stream_Seek( stream, pos ); + return error; } @@ -1508,7 +1575,6 @@ FT_Long flag_offset; FT_Long rlen; int is_cff; - int is_sfnt_ps; FT_Long face_index_in_resource = 0; @@ -1527,48 +1593,21 @@ if ( rlen == -1 ) return FT_Err_Cannot_Open_Resource; + error = open_face_PS_from_sfnt_stream( library, + stream, + face_index, + 0, NULL, + aface ); + if ( !error ) + goto Exit; + if ( FT_ALLOC( sfnt_data, (FT_Long)rlen ) ) return error; error = FT_Stream_Read( stream, (FT_Byte *)sfnt_data, rlen ); if ( error ) goto Exit; - is_cff = rlen > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 ); - is_sfnt_ps = rlen > 4 && !ft_memcmp( sfnt_data, "typ1", 4 ); - - 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_in_resource, - is_sfnt_cid ? "cid" : "type1", - aface ); - if ( !error ) - { - FT_FREE( sfnt_data ); - goto Exit; - } - } - - Try_OpenType: + is_cff = rlen > 4 && !ft_memcmp( sfnt_data, "OTTO", 4 ); error = open_face_from_buffer( library, sfnt_data, rlen,