diff --git a/ChangeLog b/ChangeLog index 62400f4c0..664d51a46 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2021-02-12 Alexei Podtelezhnikov + + Decorate qsort callbacks with cdecl. + + * include/freetype/internal/compiler-macros.h (FT_COMPARE_DEF): + Add new macro. + * src/base/ftrfork.c, src/bdf/bdflib.c, src/gxvalid/gxvcommn.c, + src/psaux/afmparse.c, src/psnames/psmodule.c, src/type1/t1afm.c, + src/sfnt/sfwoff.c, src/sfnt/sfwoff2.c: Update qsort callbacks. + + Fixes #1026 when compiling FreeType with an unusual calling convention + while the C library qsort still expects cdecl. + 2021-02-10 Dominik Röttsches [sfnt] Implement 'COLR' v1 sweep gradients. diff --git a/include/freetype/internal/compiler-macros.h b/include/freetype/internal/compiler-macros.h index 570949ade..869d1d1af 100644 --- a/include/freetype/internal/compiler-macros.h +++ b/include/freetype/internal/compiler-macros.h @@ -267,7 +267,8 @@ FT_BEGIN_HEADER /* */ /* FT_CALLBACK_DEF is used to _define_ a callback function, */ /* located in the same source code file as the structure that uses */ - /* it. */ + /* it. FT_COMPARE_DEF, in addition, ensures the cdecl calling */ + /* convention on x86, required by the C library qsort. */ /* */ /* FT_BASE_CALLBACK and FT_BASE_CALLBACK_DEF are used to declare */ /* and define a callback function, respectively, in a similar way */ @@ -289,6 +290,14 @@ FT_BEGIN_HEADER #define FT_CALLBACK_DEF( x ) static x #endif +#if defined( __i386__ ) +#define FT_COMPARE_DEF( x ) FT_CALLBACK_DEF( x ) __attribute__(( cdecl )) +#elif defined( _M_IX86 ) +#define FT_COMPARE_DEF( x ) FT_CALLBACK_DEF( x ) __cdecl +#else +#define FT_COMPARE_DEF( x ) FT_CALLBACK_DEF( x ) +#endif + #define FT_BASE_CALLBACK( x ) FT_FUNCTION_DECLARATION( x ) #define FT_BASE_CALLBACK_DEF( x ) FT_FUNCTION_DEFINITION( x ) diff --git a/src/base/ftrfork.c b/src/base/ftrfork.c index 07481724f..b558437dd 100644 --- a/src/base/ftrfork.c +++ b/src/base/ftrfork.c @@ -167,16 +167,11 @@ } - static int - ft_raccess_sort_ref_by_id( FT_RFork_Ref* a, - FT_RFork_Ref* b ) + FT_COMPARE_DEF( int ) + ft_raccess_sort_ref_by_id( const void* a, + const void* b ) { - if ( a->res_id < b->res_id ) - return -1; - else if ( a->res_id > b->res_id ) - return 1; - else - return 0; + return ( (FT_RFork_Ref*)a )->res_id - ( (FT_RFork_Ref*)b )->res_id; } @@ -294,8 +289,7 @@ ft_qsort( ref, (size_t)*count, sizeof ( FT_RFork_Ref ), - ( int(*)(const void*, - const void*) )ft_raccess_sort_ref_by_id ); + ft_raccess_sort_ref_by_id ); FT_TRACE3(( " -- sort resources by their ids --\n" )); diff --git a/src/bdf/bdflib.c b/src/bdf/bdflib.c index b494a0913..e62f09a23 100644 --- a/src/bdf/bdflib.c +++ b/src/bdf/bdflib.c @@ -807,7 +807,7 @@ /* Routine to compare two glyphs by encoding so they can be sorted. */ - static int + FT_COMPARE_DEF( int ) by_encoding( const void* a, const void* b ) { diff --git a/src/gxvalid/gxvcommn.c b/src/gxvalid/gxvcommn.c index 57b8845ca..f96d57bdb 100644 --- a/src/gxvalid/gxvcommn.c +++ b/src/gxvalid/gxvcommn.c @@ -46,16 +46,11 @@ /*************************************************************************/ /*************************************************************************/ - static int - gxv_compare_ushort_offset( FT_UShort* a, - FT_UShort* b ) + FT_COMPARE_DEF( int ) + gxv_compare_ushort_offset( const void* a, + const void* b ) { - if ( *a < *b ) - return -1; - else if ( *a > *b ) - return 1; - else - return 0; + return *(FT_UShort*)a - *(FT_UShort*)b; } @@ -78,7 +73,7 @@ buff[nmemb] = limit; ft_qsort( buff, ( nmemb + 1 ), sizeof ( FT_UShort ), - ( int(*)(const void*, const void*) )gxv_compare_ushort_offset ); + gxv_compare_ushort_offset ); if ( buff[nmemb] > limit ) FT_INVALID_OFFSET; @@ -111,13 +106,17 @@ /*************************************************************************/ /*************************************************************************/ - static int - gxv_compare_ulong_offset( FT_ULong* a, - FT_ULong* b ) + FT_COMPARE_DEF( int ) + gxv_compare_ulong_offset( const void* a, + const void* b ) { - if ( *a < *b ) + FT_ULong a_ = *(FT_ULong*)a; + FT_ULong b_ = *(FT_ULong*)b; + + + if ( a_ < b_ ) return -1; - else if ( *a > *b ) + else if ( a_ > b_ ) return 1; else return 0; @@ -143,7 +142,7 @@ buff[nmemb] = limit; ft_qsort( buff, ( nmemb + 1 ), sizeof ( FT_ULong ), - ( int(*)(const void*, const void*) )gxv_compare_ulong_offset ); + gxv_compare_ulong_offset ); if ( buff[nmemb] > limit ) FT_INVALID_OFFSET; diff --git a/src/psaux/afmparse.c b/src/psaux/afmparse.c index 79587e1ae..a778cde6d 100644 --- a/src/psaux/afmparse.c +++ b/src/psaux/afmparse.c @@ -667,7 +667,7 @@ /* compare two kerning pairs */ - FT_CALLBACK_DEF( int ) + FT_COMPARE_DEF( int ) afm_compare_kern_pairs( const void* a, const void* b ) { diff --git a/src/psnames/psmodule.c b/src/psnames/psmodule.c index 89dd2536a..913ca98c4 100644 --- a/src/psnames/psmodule.c +++ b/src/psnames/psmodule.c @@ -179,7 +179,7 @@ /* ft_qsort callback to sort the unicode map */ - FT_CALLBACK_DEF( int ) + FT_COMPARE_DEF( int ) compare_uni_maps( const void* a, const void* b ) { diff --git a/src/sfnt/sfwoff.c b/src/sfnt/sfwoff.c index be102aa53..481179c3d 100644 --- a/src/sfnt/sfwoff.c +++ b/src/sfnt/sfwoff.c @@ -66,7 +66,7 @@ } - FT_CALLBACK_DEF( int ) + FT_COMPARE_DEF( int ) compare_offsets( const void* a, const void* b ) { diff --git a/src/sfnt/sfwoff2.c b/src/sfnt/sfwoff2.c index 8809ec591..2fe7f4728 100644 --- a/src/sfnt/sfwoff2.c +++ b/src/sfnt/sfwoff2.c @@ -101,7 +101,7 @@ } - FT_CALLBACK_DEF( int ) + FT_COMPARE_DEF( int ) compare_tags( const void* a, const void* b ) { diff --git a/src/type1/t1afm.c b/src/type1/t1afm.c index f39068d1a..4c18ed195 100644 --- a/src/type1/t1afm.c +++ b/src/type1/t1afm.c @@ -83,7 +83,7 @@ /* compare two kerning pairs */ - FT_CALLBACK_DEF( int ) + FT_COMPARE_DEF( int ) compare_kern_pairs( const void* a, const void* b ) {