diff --git a/ChangeLog b/ChangeLog index ab0f4c16a..2f0f31c19 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2007-12-21 suzuki toshiya + + Improvement of POSIX resource-fork accessor to load unsorted + references in a resource. In HelveLTMM (resource-fork + PostScript Type1 font bundled to Mac OS X since 10.3.x), + the appearance order of PFB chunks is not sorted. + Sorting the chunks by reference IDs is required. + + * include/freetype/internal/ftrfork.h (FT_RFork_Ref): + New structure type to store a pair of reference ID and offset + to the chunk. + + * src/base/ftrfork.c (ft_raccess_sort_ref_by_id): + New function to sort FT_RFork_Ref by their reference ID. + + (FT_Raccess_Get_DataOffsets): Returns an array of offsets + that is sorted by reference ID. + 2007-12-14 Werner Lemberg * src/cff/cffparse.c (cff_parse_real): Don't apply `power_ten' diff --git a/include/freetype/internal/ftrfork.h b/include/freetype/internal/ftrfork.h index a4ddedc5b..7f1a3f47d 100644 --- a/include/freetype/internal/ftrfork.h +++ b/include/freetype/internal/ftrfork.h @@ -36,6 +36,13 @@ FT_BEGIN_HEADER /* Don't forget to increment the number if you add a new guessing rule. */ #define FT_RACCESS_N_RULES 9 + /* Structure to describe a reference in resource, by its resource id */ + /* and internal offset. `POST' resource expects to be concatenated by */ + /* the order of resource id, instead of its appearance in the file. */ + typedef struct FT_RFork_Ref_ { + FT_UShort res_id; + FT_ULong offset; + } FT_RFork_Ref; /*************************************************************************/ /* */ diff --git a/src/base/ftrfork.c b/src/base/ftrfork.c index 4e32fba5f..ac6602f29 100644 --- a/src/base/ftrfork.c +++ b/src/base/ftrfork.c @@ -132,6 +132,19 @@ } + static int + ft_raccess_sort_ref_by_id( FT_RFork_Ref* a, + FT_RFork_Ref* b ) + { + if ( a->res_id < b->res_id ) + return ( -1 ); + else if ( a->res_id > b->res_id ) + return ( 1 ); + else + return ( 0 ); + } + + FT_BASE_DEF( FT_Error ) FT_Raccess_Get_DataOffsets( FT_Library library, FT_Stream stream, @@ -147,6 +160,7 @@ FT_Memory memory = library->memory; FT_Long temp; FT_Long *offsets_internal; + FT_RFork_Ref *ref; error = FT_Stream_Seek( stream, map_offset ); @@ -179,28 +193,42 @@ if ( error ) return error; - if ( FT_NEW_ARRAY( offsets_internal, *count ) ) + if ( FT_NEW_ARRAY( ref, *count ) ) return error; for ( j = 0; j < *count; ++j ) { - (void)FT_STREAM_SKIP( 2 ); /* resource id */ - (void)FT_STREAM_SKIP( 2 ); /* rsource name */ - + if ( FT_READ_USHORT( ref[j].res_id ) ) + goto Exit; + if ( FT_STREAM_SKIP( 2 ) ) /* resource name */ + goto Exit; if ( FT_READ_LONG( temp ) ) - { - FT_FREE( offsets_internal ); - return error; - } + goto Exit; + if ( FT_STREAM_SKIP( 4 ) ) /* mbz */ + goto Exit; - offsets_internal[j] = rdata_pos + ( temp & 0xFFFFFFL ); - - (void)FT_STREAM_SKIP( 4 ); /* mbz */ + ref[j].offset = temp & 0xFFFFFFL; } - *offsets = offsets_internal; + ft_qsort( ref, *count, sizeof( FT_RFork_Ref ), + ( int(*)(const void*, const void*) ) + ft_raccess_sort_ref_by_id ); - return FT_Err_Ok; + if ( FT_NEW_ARRAY( offsets_internal, *count ) ) + goto Exit; + + /* XXX: duplicated reference ID, + * gap between reference IDs are acceptable? + * further investigation on Apple implementation is needed. + */ + for ( j = 0; j < *count; ++j ) + offsets_internal[j] = rdata_pos + ref[j].offset; + + *offsets = offsets_internal; + error = FT_Err_Ok; +Exit: + FT_FREE( ref ); + return error; } }