From 92460940337d14caf45c902ab47b8863ca41a9ae Mon Sep 17 00:00:00 2001 From: Kleis Auke Wolthuizen Date: Tue, 30 Jun 2020 12:10:30 +0200 Subject: [PATCH] Fix function pointer cast issues It is undefined behavior in C and C++ to cast a function pointer to another type and call it that way. This does work in most native platforms, however, despite it being UB, but in WASM it can fail. See: https://emscripten.org/docs/porting/guidelines/function_pointer_issues.html --- libvips/colour/profile_load.c | 2 +- libvips/conversion/extract.c | 24 +++++++++++++++++++++++ libvips/conversion/tilecache.c | 2 +- libvips/convolution/canny.c | 2 +- libvips/deprecated/package.c | 2 +- libvips/deprecated/rename.c | 10 ++++++++++ libvips/foreign/analyze2vips.c | 10 +++++----- libvips/foreign/dzsave.c | 4 ++-- libvips/foreign/exif.c | 4 ++-- libvips/foreign/foreign.c | 10 +++++----- libvips/foreign/jpeg2vips.c | 4 ++-- libvips/foreign/magicksave.c | 4 +--- libvips/foreign/matlab.c | 2 +- libvips/foreign/openexr2vips.c | 2 +- libvips/foreign/radiance.c | 6 +++--- libvips/foreign/tiff2vips.c | 4 ++-- libvips/foreign/tiffsave.c | 5 +---- libvips/foreign/vips2tiff.c | 8 ++++---- libvips/include/vips/almostdeprecated.h | 4 ++++ libvips/include/vips/image.h | 12 ++++++------ libvips/include/vips/memory.h | 1 - libvips/include/vips/object.h | 2 +- libvips/include/vips/type.h | 1 + libvips/iofuncs/buffer.c | 2 +- libvips/iofuncs/cache.c | 4 ++-- libvips/iofuncs/gate.c | 8 +++++--- libvips/iofuncs/generate.c | 19 +++++++++--------- libvips/iofuncs/header.c | 6 +++--- libvips/iofuncs/image.c | 22 ++++++++++----------- libvips/iofuncs/memory.c | 26 +++++-------------------- libvips/iofuncs/object.c | 14 ++++++------- libvips/iofuncs/rect.c | 2 +- libvips/iofuncs/region.c | 9 ++++----- libvips/iofuncs/sink.c | 2 +- libvips/iofuncs/sinkdisc.c | 2 +- libvips/iofuncs/sinkmemory.c | 2 +- libvips/iofuncs/sinkscreen.c | 14 ++++++------- libvips/iofuncs/source.c | 6 +++--- libvips/iofuncs/target.c | 2 +- libvips/iofuncs/type.c | 24 ++++++++++++++++------- libvips/iofuncs/util.c | 12 ++++++------ libvips/iofuncs/vips.c | 4 ++-- libvips/iofuncs/window.c | 4 ++-- 43 files changed, 167 insertions(+), 142 deletions(-) diff --git a/libvips/colour/profile_load.c b/libvips/colour/profile_load.c index c7fdb4a5a6..4966cb79ed 100644 --- a/libvips/colour/profile_load.c +++ b/libvips/colour/profile_load.c @@ -96,7 +96,7 @@ vips_profile_load_build( VipsObject *object ) else if( (data = vips__file_read_name( load->name, vips__icc_dir(), &length )) ) profile = vips_blob_new( - (VipsCallbackFn) g_free, data, length ); + (VipsCallbackFn) vips_area_free_cb, data, length ); else { vips_error( class->nickname, _( "unable to load profile \"%s\"" ), load->name ); diff --git a/libvips/conversion/extract.c b/libvips/conversion/extract.c index 7a60f877ad..e2c8ec7240 100644 --- a/libvips/conversion/extract.c +++ b/libvips/conversion/extract.c @@ -172,6 +172,14 @@ vips_extract_area_build( VipsObject *object ) return( 0 ); } +#ifdef __EMSCRIPTEN__ +static void +vips_crop_class_init_adapter( VipsExtractAreaClass *class, void *dummy ) +{ + vips_extract_area_class_init( class ); +} +#endif + static void vips_extract_area_class_init( VipsExtractAreaClass *class ) { @@ -226,6 +234,14 @@ vips_extract_area_class_init( VipsExtractAreaClass *class ) } +#ifdef __EMSCRIPTEN__ +static void +vips_crop_init_adapter( VipsExtractArea *extract, void *dummy ) +{ + vips_extract_area_init( extract ); +} +#endif + static void vips_extract_area_init( VipsExtractArea *extract ) { @@ -275,12 +291,20 @@ vips_crop_get_type( void ) sizeof( VipsExtractAreaClass ), NULL, /* base_init */ NULL, /* base_finalize */ +#ifdef __EMSCRIPTEN__ + (GClassInitFunc) vips_crop_class_init_adapter, +#else (GClassInitFunc) vips_extract_area_class_init, +#endif NULL, /* class_finalize */ NULL, /* class_data */ sizeof( VipsExtractArea ), 32, /* n_preallocs */ +#ifdef __EMSCRIPTEN__ + (GInstanceInitFunc) vips_crop_init_adapter, +#else (GInstanceInitFunc) vips_extract_area_init, +#endif }; type = g_type_register_static( VIPS_TYPE_CONVERSION, diff --git a/libvips/conversion/tilecache.c b/libvips/conversion/tilecache.c index c458254fea..e89853db96 100644 --- a/libvips/conversion/tilecache.c +++ b/libvips/conversion/tilecache.c @@ -473,7 +473,7 @@ vips_tile_destroy( VipsTile *tile ) VIPS_UNREF( tile->region ); - vips_free( tile ); + g_free( tile ); } static void diff --git a/libvips/convolution/canny.c b/libvips/convolution/canny.c index ca96f6b1fd..bd732c3711 100644 --- a/libvips/convolution/canny.c +++ b/libvips/convolution/canny.c @@ -225,7 +225,7 @@ vips_canny_polar( VipsImage **args, VipsImage **out ) { static GOnce once = G_ONCE_INIT; - g_once( &once, (GThreadFunc) vips_atan2_init, NULL ); + g_once( &once, vips_atan2_init, NULL ); *out = vips_image_new(); if( vips_image_pipeline_array( *out, diff --git a/libvips/deprecated/package.c b/libvips/deprecated/package.c index fb5b4dbc04..2549b2d0a2 100644 --- a/libvips/deprecated/package.c +++ b/libvips/deprecated/package.c @@ -910,7 +910,7 @@ im_free_vargv( im_function *fn, im_object *vargv ) /* If there is local storage, free it. */ if( fn->argv[i].desc->size != 0 ) - vips_free( vargv[i] ); + g_free( vargv[i] ); /* NULL out pointer. */ diff --git a/libvips/deprecated/rename.c b/libvips/deprecated/rename.c index ad3eaa226f..3c7761907b 100644 --- a/libvips/deprecated/rename.c +++ b/libvips/deprecated/rename.c @@ -813,3 +813,13 @@ vips_autorot_get_angle( VipsImage *im ) return( VIPS_ANGLE_D0 ); } +/* The old vips_free(), now replaced by g_free() and vips_area_free_cb(). + */ +int +vips_free( void *buf ) +{ + g_free( buf ); + + return( 0 ); +} + diff --git a/libvips/foreign/analyze2vips.c b/libvips/foreign/analyze2vips.c index c3802d8c89..9f17f1ff2b 100644 --- a/libvips/foreign/analyze2vips.c +++ b/libvips/foreign/analyze2vips.c @@ -309,7 +309,7 @@ read_header( const char *header ) if( len != sizeof( struct dsr ) ) { vips_error( "analyze2vips", "%s", _( "header file size incorrect" ) ); - vips_free( d ); + g_free( d ); return( NULL ); } @@ -354,7 +354,7 @@ read_header( const char *header ) if( (int) len != d->hk.sizeof_hdr ) { vips_error( "analyze2vips", "%s", _( "header size incorrect" ) ); - vips_free( d ); + g_free( d ); return( NULL ); } @@ -444,7 +444,7 @@ attach_meta( VipsImage *out, struct dsr *d ) int i; vips_image_set_blob( out, "dsr", - (VipsCallbackFn) vips_free, d, d->hk.sizeof_hdr ); + (VipsCallbackFn) vips_area_free_cb, d, d->hk.sizeof_hdr ); for( i = 0; i < VIPS_NUMBER( dsr_header ); i++ ) { switch( dsr_header[i].type ) { @@ -514,7 +514,7 @@ vips__isanalyze( const char *filename ) result = get_vips_properties( d, &width, &height, &bands, &fmt ); vips_error_thaw(); - vips_free( d ); + g_free( d ); return( result == 0 ); } @@ -538,7 +538,7 @@ vips__analyze_read_header( const char *filename, VipsImage *out ) #endif /*DEBUG*/ if( get_vips_properties( d, &width, &height, &bands, &fmt ) ) { - vips_free( d ); + g_free( d ); return( -1 ); } diff --git a/libvips/foreign/dzsave.c b/libvips/foreign/dzsave.c index d0e2a98ac7..c793668e15 100644 --- a/libvips/foreign/dzsave.c +++ b/libvips/foreign/dzsave.c @@ -275,7 +275,7 @@ vips_gsf_tree_new( GsfOutput *out, gint deflate_level ) } static void * -vips_gsf_child_by_name_sub( VipsGsfDirectory *dir, const char *name ) +vips_gsf_child_by_name_sub( VipsGsfDirectory *dir, const char *name, void *b ) { if( strcmp( dir->name, name ) == 0 ) return( dir ); @@ -2692,7 +2692,7 @@ vips_foreign_save_dz_buffer_build( VipsObject *object ) gsf_output_memory_get_bytes( GSF_OUTPUT_MEMORY( dz->out ) ), olen ); - blob = vips_blob_new( (VipsCallbackFn) g_free, obuf, olen ); + blob = vips_blob_new( (VipsCallbackFn) vips_area_free_cb, obuf, olen ); g_object_set( object, "buffer", blob, NULL ); vips_area_unref( VIPS_AREA( blob ) ); diff --git a/libvips/foreign/exif.c b/libvips/foreign/exif.c index 6e6c442d8a..3dc35ec510 100644 --- a/libvips/foreign/exif.c +++ b/libvips/foreign/exif.c @@ -1258,7 +1258,7 @@ vips_exif_exif_entry( ExifEntry *entry, VipsExifRemove *ve ) } static void * -vips_exif_exif_remove( ExifEntry *entry, VipsExifRemove *ve ) +vips_exif_exif_remove( ExifEntry *entry, VipsExifRemove *ve, void *b ) { #ifdef DEBUG { @@ -1405,7 +1405,7 @@ vips__exif_update( VipsImage *image ) #endif /*DEBUG*/ vips_image_set_blob( image, VIPS_META_EXIF_NAME, - (VipsCallbackFn) vips_free, data, length ); + (VipsCallbackFn) vips_area_free_cb, data, length ); exif_data_free( ed ); diff --git a/libvips/foreign/foreign.c b/libvips/foreign/foreign.c index f7fdd49637..0459c47fb4 100644 --- a/libvips/foreign/foreign.c +++ b/libvips/foreign/foreign.c @@ -390,7 +390,7 @@ file_add_class( VipsForeignClass *class, GSList **files ) } static gint -file_compare( VipsForeignClass *a, VipsForeignClass *b ) +file_compare( VipsForeignClass *a, VipsForeignClass *b, void *user_data ) { return( b->priority - a->priority ); } @@ -479,7 +479,7 @@ vips_foreign_load_summary_class( VipsObjectClass *object_class, VipsBuf *buf ) */ static void * vips_foreign_find_load_sub( VipsForeignLoadClass *load_class, - const char *filename ) + const char *filename, void *b ) { VipsObjectClass *object_class = VIPS_OBJECT_CLASS( load_class ); VipsForeignClass *class = VIPS_FOREIGN_CLASS( load_class ); @@ -1763,7 +1763,7 @@ vips_foreign_save_init( VipsForeignSave *save ) */ static void * vips_foreign_find_save_sub( VipsForeignSaveClass *save_class, - const char *filename ) + const char *filename, void *b ) { VipsObjectClass *object_class = VIPS_OBJECT_CLASS( save_class ); VipsForeignClass *class = VIPS_FOREIGN_CLASS( save_class ); @@ -1919,7 +1919,7 @@ vips_foreign_save( VipsImage *in, const char *name, ... ) */ static void * vips_foreign_find_save_target_sub( VipsForeignSaveClass *save_class, - const char *suffix ) + const char *suffix, void *b ) { VipsObjectClass *object_class = VIPS_OBJECT_CLASS( save_class ); VipsForeignClass *class = VIPS_FOREIGN_CLASS( save_class ); @@ -1977,7 +1977,7 @@ vips_foreign_find_save_target( const char *name ) */ static void * vips_foreign_find_save_buffer_sub( VipsForeignSaveClass *save_class, - const char *suffix ) + const char *suffix, void *b ) { VipsObjectClass *object_class = VIPS_OBJECT_CLASS( save_class ); VipsForeignClass *class = VIPS_FOREIGN_CLASS( save_class ); diff --git a/libvips/foreign/jpeg2vips.c b/libvips/foreign/jpeg2vips.c index 26accc4091..c1e87fd580 100644 --- a/libvips/foreign/jpeg2vips.c +++ b/libvips/foreign/jpeg2vips.c @@ -334,7 +334,7 @@ readjpeg_free( ReadJpeg *jpeg ) } static void -readjpeg_close_cb( VipsObject *object, ReadJpeg *jpeg ) +readjpeg_close_cb( VipsImage *image, ReadJpeg *jpeg ) { (void) readjpeg_free( jpeg ); } @@ -728,7 +728,7 @@ read_jpeg_header( ReadJpeg *jpeg, VipsImage *out ) } vips_image_set_blob( out, VIPS_META_ICC_NAME, - (VipsCallbackFn) vips_free, data, data_length ); + (VipsCallbackFn) vips_area_free_cb, data, data_length ); } return( 0 ); diff --git a/libvips/foreign/magicksave.c b/libvips/foreign/magicksave.c index 102252d960..bc1d39872a 100644 --- a/libvips/foreign/magicksave.c +++ b/libvips/foreign/magicksave.c @@ -593,9 +593,7 @@ vips_foreign_save_magick_buffer_build( VipsObject *object ) return( -1 ); } - /* obuf is a g_free() buffer, not vips_free(). - */ - blob = vips_blob_new( (VipsCallbackFn) g_free, obuf, olen ); + blob = vips_blob_new( (VipsCallbackFn) vips_area_free_cb, obuf, olen ); g_object_set( buffer, "buffer", blob, NULL ); vips_area_unref( VIPS_AREA( blob ) ); diff --git a/libvips/foreign/matlab.c b/libvips/foreign/matlab.c index 5335647b11..dde57f2e47 100644 --- a/libvips/foreign/matlab.c +++ b/libvips/foreign/matlab.c @@ -92,7 +92,7 @@ read_destroy( Read *read ) VIPS_FREEF( Mat_VarFree, read->var ); VIPS_FREEF( Mat_Close, read->mat ); - vips_free( read ); + g_free( read ); } static Read * diff --git a/libvips/foreign/openexr2vips.c b/libvips/foreign/openexr2vips.c index e36b477e01..523b72b576 100644 --- a/libvips/foreign/openexr2vips.c +++ b/libvips/foreign/openexr2vips.c @@ -139,7 +139,7 @@ read_destroy( VipsImage *out, Read *read ) read_close( read ); - vips_free( read ); + g_free( read ); } static Read * diff --git a/libvips/foreign/radiance.c b/libvips/foreign/radiance.c index d5ba070b81..c9889b148e 100644 --- a/libvips/foreign/radiance.c +++ b/libvips/foreign/radiance.c @@ -739,13 +739,13 @@ vips__rad_israd( VipsSource *source ) } static void -read_destroy( VipsObject *object, Read *read ) +read_destroy( VipsImage *image, Read *read ) { VIPS_UNREF( read->sbuf ); } static void -read_minimise_cb( VipsObject *object, Read *read ) +read_minimise_cb( VipsImage *image, Read *read ) { if( read->sbuf ) vips_source_minimise( read->sbuf->source ); @@ -994,7 +994,7 @@ write_destroy( Write *write ) VIPS_FREE( write->line ); VIPS_UNREF( write->target ); - vips_free( write ); + g_free( write ); } static Write * diff --git a/libvips/foreign/tiff2vips.c b/libvips/foreign/tiff2vips.c index 6bde6f31ed..cac7139638 100644 --- a/libvips/foreign/tiff2vips.c +++ b/libvips/foreign/tiff2vips.c @@ -522,7 +522,7 @@ rtiff_free( Rtiff *rtiff ) } static void -rtiff_close_cb( VipsObject *object, Rtiff *rtiff ) +rtiff_close_cb( VipsImage *image, Rtiff *rtiff ) { rtiff_free( rtiff ); } @@ -1926,7 +1926,7 @@ rtiff_fill_region( VipsRegion *out, static int rtiff_seq_stop( void *seq, void *a, void *b ) { - vips_free( seq ); + g_free( seq ); return( 0 ); } diff --git a/libvips/foreign/tiffsave.c b/libvips/foreign/tiffsave.c index 83d9fd94ed..33bc65ea61 100644 --- a/libvips/foreign/tiffsave.c +++ b/libvips/foreign/tiffsave.c @@ -503,10 +503,7 @@ vips_foreign_save_tiff_buffer_build( VipsObject *object ) tiff->subifd ) ) return( -1 ); - /* vips__tiff_write_buf() makes a buffer that needs g_free(), not - * vips_free(). - */ - blob = vips_blob_new( (VipsCallbackFn) g_free, obuf, olen ); + blob = vips_blob_new( (VipsCallbackFn) vips_area_free_cb, obuf, olen ); g_object_set( object, "buffer", blob, NULL ); vips_area_unref( VIPS_AREA( blob ) ); diff --git a/libvips/foreign/vips2tiff.c b/libvips/foreign/vips2tiff.c index 5ff5834dc4..9a6244a9e0 100644 --- a/libvips/foreign/vips2tiff.c +++ b/libvips/foreign/vips2tiff.c @@ -979,9 +979,9 @@ wtiff_free( Wtiff *wtiff ) wtiff_delete_temps( wtiff ); VIPS_UNREF( wtiff->ready ); - VIPS_FREEF( vips_free, wtiff->tbuf ); + VIPS_FREE( wtiff->tbuf ); VIPS_FREEF( layer_free_all, wtiff->layer ); - VIPS_FREEF( vips_free, wtiff->icc_profile ); + VIPS_FREE( wtiff->icc_profile ); VIPS_FREE( wtiff->filename ); VIPS_FREE( wtiff ); } @@ -1888,11 +1888,11 @@ wtiff_copy_tiff( Wtiff *wtiff, TIFF *out, TIFF *in ) len = TIFFReadEncodedTile( in, tile, buf, -1 ); if( len < 0 || TIFFWriteEncodedTile( out, tile, buf, len ) < 0 ) { - vips_free( buf ); + g_free( buf ); return( -1 ); } } - vips_free( buf ); + g_free( buf ); return( 0 ); } diff --git a/libvips/include/vips/almostdeprecated.h b/libvips/include/vips/almostdeprecated.h index 1bde7c8482..e397c27f62 100644 --- a/libvips/include/vips/almostdeprecated.h +++ b/libvips/include/vips/almostdeprecated.h @@ -294,6 +294,10 @@ void vips_vinfo( const char *domain, const char *fmt, va_list ap ); VipsAngle vips_autorot_get_angle( VipsImage *image ); +/* iofuncs + */ +int vips_free( void *buf ); + #ifdef __cplusplus } #endif /*__cplusplus*/ diff --git a/libvips/include/vips/image.h b/libvips/include/vips/image.h index d400ffc4a4..01b5996889 100644 --- a/libvips/include/vips/image.h +++ b/libvips/include/vips/image.h @@ -319,27 +319,27 @@ typedef struct _VipsImageClass { /* Evaluation is starting. */ - void (*preeval)( VipsImage *image, VipsProgress *progress ); + void (*preeval)( VipsImage *image, VipsProgress *progress, void *data ); /* Evaluation progress. */ - void (*eval)( VipsImage *image, VipsProgress *progress ); + void (*eval)( VipsImage *image, VipsProgress *progress, void *data ); /* Evaluation is ending. */ - void (*posteval)( VipsImage *image, VipsProgress *progress ); + void (*posteval)( VipsImage *image, VipsProgress *progress, void *data ); /* An image has been written to. * Used by eg. vips_image_new_mode("x.jpg", "w") to do the * final write to jpeg. * Set *result to non-zero to indicate an error on write. */ - void (*written)( VipsImage *image, int *result ); + void (*written)( VipsImage *image, int *result, void *data ); /* An image has been modified in some way and all caches * need dropping. */ - void (*invalidate)( VipsImage *image ); + void (*invalidate)( VipsImage *image, void *data ); /* Minimise this pipeline. * @@ -349,7 +349,7 @@ typedef struct _VipsImageClass { * * See vips_tilecache(). */ - void (*minimise)( VipsImage *image ); + void (*minimise)( VipsImage *image, void *data ); } VipsImageClass; diff --git a/libvips/include/vips/memory.h b/libvips/include/vips/memory.h index 99b26e8fef..6469db9fb5 100644 --- a/libvips/include/vips/memory.h +++ b/libvips/include/vips/memory.h @@ -66,7 +66,6 @@ G_STMT_START { \ void *vips_malloc( VipsObject *object, size_t size ); char *vips_strdup( VipsObject *object, const char *str ); -int vips_free( void *buf ); void vips_tracked_free( void *s ); void *vips_tracked_malloc( size_t size ); diff --git a/libvips/include/vips/object.h b/libvips/include/vips/object.h index ff500a61cc..f83ee46130 100644 --- a/libvips/include/vips/object.h +++ b/libvips/include/vips/object.h @@ -455,7 +455,7 @@ struct _VipsObjectClass { /* Just after build ... the object is fully ready for work. */ - int (*postbuild)( VipsObject *object ); + int (*postbuild)( VipsObject *object, void *data ); /* Try to print something about the class, handy for help displays. * Keep to one line. diff --git a/libvips/include/vips/type.h b/libvips/include/vips/type.h index ba7512ea1f..4f73d43e0b 100644 --- a/libvips/include/vips/type.h +++ b/libvips/include/vips/type.h @@ -92,6 +92,7 @@ typedef struct _VipsArea { } VipsArea; VipsArea *vips_area_copy( VipsArea *area ); +int vips_area_free_cb( void *mem, VipsArea *area ); void vips_area_unref( VipsArea *area ); VipsArea *vips_area_new( VipsCallbackFn free_fn, void *data ); diff --git a/libvips/iofuncs/buffer.c b/libvips/iofuncs/buffer.c index 87efa49f41..4462087b12 100644 --- a/libvips/iofuncs/buffer.c +++ b/libvips/iofuncs/buffer.c @@ -153,7 +153,7 @@ vips_buffer_dump( VipsBuffer *buffer, size_t *reserve, size_t *alive ) #ifdef DEBUG_CREATE static void * -vips_buffer_cache_dump( VipsBufferCache *cache ) +vips_buffer_cache_dump( VipsBufferCache *cache, void *a, void *b ) { printf( "VipsBufferCache: %p\n", cache ); printf( "\t%d buffers\n", g_slist_length( cache->buffers ) ); diff --git a/libvips/iofuncs/cache.c b/libvips/iofuncs/cache.c index 3ec4096680..339bbb92e1 100644 --- a/libvips/iofuncs/cache.c +++ b/libvips/iofuncs/cache.c @@ -453,7 +453,7 @@ vips_operation_equal( VipsOperation *a, VipsOperation *b ) } void * -vips__cache_once_init( void ) +vips__cache_once_init( void *data ) { vips_cache_lock = vips_g_mutex_new(); @@ -469,7 +469,7 @@ vips__cache_init( void ) { static GOnce once = G_ONCE_INIT; - VIPS_ONCE( &once, (GThreadFunc) vips__cache_once_init, NULL ); + VIPS_ONCE( &once, vips__cache_once_init, NULL ); } static void * diff --git a/libvips/iofuncs/gate.c b/libvips/iofuncs/gate.c index 0b45ec3eee..5e38d31536 100644 --- a/libvips/iofuncs/gate.c +++ b/libvips/iofuncs/gate.c @@ -210,8 +210,8 @@ vips__thread_profile_init_cb( VipsThreadProfile *profile ) vips_thread_profile_free( profile ); } -static void -vips__thread_profile_init( void ) +static void * +vips__thread_profile_init( void *data ) { #ifdef HAVE_PRIVATE_INIT static GPrivate private = @@ -223,6 +223,8 @@ vips__thread_profile_init( void ) vips_thread_profile_key = g_private_new( (GDestroyNotify) vips__thread_profile_init_cb ); #endif + + return( NULL ); } static VipsThreadGate * @@ -245,7 +247,7 @@ vips__thread_profile_attach( const char *thread_name ) VipsThreadProfile *profile; - VIPS_ONCE( &once, (GThreadFunc) vips__thread_profile_init, NULL ); + VIPS_ONCE( &once, vips__thread_profile_init, NULL ); VIPS_DEBUG_MSG( "vips__thread_profile_attach: %s\n", thread_name ); diff --git a/libvips/iofuncs/generate.c b/libvips/iofuncs/generate.c index 65be8d9cf1..8e8e53a484 100644 --- a/libvips/iofuncs/generate.c +++ b/libvips/iofuncs/generate.c @@ -148,7 +148,7 @@ vips__link_make( VipsImage *image_up, VipsImage *image_down ) } static void * -vips__link_break( VipsImage *image_up, VipsImage *image_down ) +vips__link_break( VipsImage *image_up, VipsImage *image_down, void *b ) { g_assert( image_up ); g_assert( image_down ); @@ -171,9 +171,9 @@ vips__link_break( VipsImage *image_up, VipsImage *image_down ) } static void * -vips__link_break_rev( VipsImage *image_down, VipsImage *image_up ) +vips__link_break_rev( VipsImage *image_down, VipsImage *image_up, void *b ) { - return( vips__link_break( image_up, image_down ) ); + return( vips__link_break( image_up, image_down, b ) ); } /* A VipsImage is going ... break all links. @@ -203,7 +203,7 @@ typedef struct _LinkMap { } LinkMap; static void * -vips__link_mapp( VipsImage *image, LinkMap *map ) +vips__link_mapp( VipsImage *image, LinkMap *map, void *b ) { void *res; @@ -222,7 +222,7 @@ vips__link_mapp( VipsImage *image, LinkMap *map ) } static void * -vips__link_map_cb( VipsImage *image, GSList **images ) +vips__link_map_cb( VipsImage *image, GSList **images, void *b ) { *images = g_slist_prepend( *images, image ); @@ -265,7 +265,7 @@ vips__link_map( VipsImage *image, gboolean upstream, serial += 1; map.serial = serial; - vips__link_mapp( image, &map ); + vips__link_mapp( image, &map, NULL ); for( p = images; p; p = p->next ) g_object_ref( p->data ); @@ -494,7 +494,7 @@ vips_stop_many( void *seq, void *a, void *b ) for( i = 0; ar[i]; i++ ) g_object_unref( ar[i] ); - vips_free( (char *) ar ); + g_free( (char *) ar ); } return( 0 ); @@ -630,7 +630,7 @@ vips_allocate_input_array( VipsImage *out, ... ) /* A write function for VIPS images. Just write() the pixel data. */ static int -write_vips( VipsRegion *region, VipsRect *area, void *a, void *b ) +write_vips( VipsRegion *region, VipsRect *area, void *a ) { size_t nwritten, count; void *buf; @@ -753,8 +753,7 @@ vips_image_generate( VipsImage *image, return( -1 ); if( image->dtype == VIPS_IMAGE_OPENOUT ) - res = vips_sink_disc( image, - (VipsRegionWrite) write_vips, NULL ); + res = vips_sink_disc( image, write_vips, NULL ); else res = vips_sink_memory( image ); diff --git a/libvips/iofuncs/header.c b/libvips/iofuncs/header.c index 4109b5d483..b10235b322 100644 --- a/libvips/iofuncs/header.c +++ b/libvips/iofuncs/header.c @@ -235,7 +235,7 @@ vips_format_sizeof_unsafe( VipsBandFormat format ) /* Check that this meta is on the hash table. */ static void * -meta_sanity_on_hash( VipsMeta *meta, VipsImage *im ) +meta_sanity_on_hash( VipsMeta *meta, VipsImage *im, void *b ) { VipsMeta *found; @@ -970,7 +970,7 @@ vips_image_init_fields( VipsImage *image, } static void * -meta_cp_field( VipsMeta *meta, VipsImage *dst ) +meta_cp_field( VipsMeta *meta, VipsImage *dst, void *b ) { #ifdef DEBUG { @@ -1569,7 +1569,7 @@ vips_image_set_blob_copy( VipsImage *image, ((unsigned char *) data_copy)[length] = '\0'; vips_image_set_blob( image, - name, (VipsCallbackFn) vips_free, data_copy, length ); + name, (VipsCallbackFn) vips_area_free_cb, data_copy, length ); } /** diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c index c5d51b23a3..f2acf931dc 100644 --- a/libvips/iofuncs/image.c +++ b/libvips/iofuncs/image.c @@ -651,7 +651,7 @@ vips_image_summary( VipsObject *object, VipsBuf *buf ) } static void * -vips_image_sanity_upstream( VipsImage *up, VipsImage *down ) +vips_image_sanity_upstream( VipsImage *up, VipsImage *down, void *b ) { if( !g_slist_find( up->downstream, down ) || !g_slist_find( down->upstream, up ) ) @@ -661,9 +661,9 @@ vips_image_sanity_upstream( VipsImage *up, VipsImage *down ) } static void * -vips_image_sanity_downstream( VipsImage *down, VipsImage *up ) +vips_image_sanity_downstream( VipsImage *down, VipsImage *up, void *b ) { - return( vips_image_sanity_upstream( up, down ) ); + return( vips_image_sanity_upstream( up, down, b ) ); } static void @@ -738,7 +738,7 @@ vips_image_rewind( VipsObject *object ) /* From "written" callback: save to image->filename using VipsForeign. */ static void -vips_image_save_cb( VipsImage *image, int *result ) +vips_image_save_cb( VipsImage *image, int *result, void *data ) { if( vips_foreign_save( image, image->filename, NULL ) ) *result = -1; @@ -786,7 +786,7 @@ vips_image_eval_cb( VipsImage *image, VipsProgress *progress, int *last ) } static void -vips_image_posteval_cb( VipsImage *image, VipsProgress *progress ) +vips_image_posteval_cb( VipsImage *image, VipsProgress *progress, void *data ) { /* Spaces at end help to erase the %complete message we overwrite. */ @@ -1016,7 +1016,7 @@ vips_image_build( VipsObject *object ) } static void * -vips_image_real_invalidate_cb( VipsRegion *reg ) +vips_image_real_invalidate_cb( VipsRegion *reg, void *a, void *b ) { vips_region_invalidate( reg ); @@ -1024,7 +1024,7 @@ vips_image_real_invalidate_cb( VipsRegion *reg ) } static void -vips_image_real_invalidate( VipsImage *image ) +vips_image_real_invalidate( VipsImage *image, void *data ) { VIPS_DEBUG_MSG( "vips_image_real_invalidate: %p\n", image ); @@ -1041,13 +1041,13 @@ vips_image_real_invalidate( VipsImage *image ) } static void -vips_image_real_minimise( VipsImage *image ) +vips_image_real_minimise( VipsImage *image, void *data ) { VIPS_DEBUG_MSG( "vips_image_real_minimise: %p\n", image ); } static void -vips_image_real_written( VipsImage *image, int *result ) +vips_image_real_written( VipsImage *image, int *result, void *data ) { VIPS_DEBUG_MSG( "vips_image_real_written: %p\n", image ); @@ -1390,7 +1390,7 @@ vips_image_invalidate( VipsImage *image ) } static void * -vips_image_invalidate_all_cb( VipsImage *image ) +vips_image_invalidate_all_cb( VipsImage *image, void *a, void *b ) { vips_image_invalidate( image ); @@ -1430,7 +1430,7 @@ vips_image_minimise( VipsImage *image ) } static void * -vips_image_minimise_all_cb( VipsImage *image ) +vips_image_minimise_all_cb( VipsImage *image, void *a, void *b ) { vips_image_minimise( image ); diff --git a/libvips/iofuncs/memory.c b/libvips/iofuncs/memory.c index 2233b17b83..b2fa30aa84 100644 --- a/libvips/iofuncs/memory.c +++ b/libvips/iofuncs/memory.c @@ -215,24 +215,6 @@ vips_strdup( VipsObject *object, const char *str ) return( str_dup ); } -/** - * vips_free: - * @buf: memory to free - * - * Frees memory with g_free() and returns 0. Handy for callbacks. - * - * See also: vips_malloc(). - * - * Returns: 0 - */ -int -vips_free( void *buf ) -{ - g_free( buf ); - - return( 0 ); -} - /** * vips_tracked_free: * @s: (transfer full): memory to free @@ -273,10 +255,12 @@ vips_tracked_free( void *s ) VIPS_GATE_FREE( size ); } -static void -vips_tracked_init_mutex( void ) +static void * +vips_tracked_init_mutex( void *data ) { vips_tracked_mutex = vips_g_mutex_new(); + + return( NULL ); } static void @@ -285,7 +269,7 @@ vips_tracked_init( void ) static GOnce vips_tracked_once = G_ONCE_INIT; VIPS_ONCE( &vips_tracked_once, - (GThreadFunc) vips_tracked_init_mutex, NULL ); + vips_tracked_init_mutex, NULL ); } /** diff --git a/libvips/iofuncs/object.c b/libvips/iofuncs/object.c index bbb6ac3c16..36cccdf338 100644 --- a/libvips/iofuncs/object.c +++ b/libvips/iofuncs/object.c @@ -1460,7 +1460,7 @@ vips_object_real_build( VipsObject *object ) } static int -vips_object_real_postbuild( VipsObject *object ) +vips_object_real_postbuild( VipsObject *object, void *data ) { #ifdef DEBUG printf( "vips_object_real_postbuild: " ); @@ -1701,7 +1701,7 @@ traverse_find_required_priority( void *data, void *a, void *b ) } static gint -traverse_sort( gconstpointer a, gconstpointer b ) +traverse_sort( gconstpointer a, gconstpointer b, void *user_data ) { VipsArgumentClass *class1 = (VipsArgumentClass *) a; VipsArgumentClass *class2 = (VipsArgumentClass *) b; @@ -1803,7 +1803,7 @@ vips_object_class_install_argument( VipsObjectClass *object_class, argument_table_traverse = g_slist_prepend( argument_table_traverse, argument_class ); argument_table_traverse = g_slist_sort( - argument_table_traverse, traverse_sort ); + argument_table_traverse, (GCompareFunc) traverse_sort ); VIPS_SWAP( GSList *, argument_table_traverse, object_class->argument_table_traverse ); @@ -3045,7 +3045,7 @@ typedef struct { } VipsObjectLocal; static void -vips_object_local_array_cb( GObject *parent, VipsObjectLocal *local ) +vips_object_local_array_cb( VipsObject *parent, VipsObjectLocal *local ) { int i; @@ -3111,7 +3111,7 @@ vips_object_set_static( VipsObject *object, gboolean static_object ) } static void * -vips_object_n_static_cb( VipsObject *object, int *n ) +vips_object_n_static_cb( VipsObject *object, int *n, void *b ) { if( object->static_object ) *n += 1; @@ -3132,7 +3132,7 @@ vips_object_n_static( void ) } static void * -vips_object_print_all_cb( VipsObject *object, int *n ) +vips_object_print_all_cb( VipsObject *object, int *n, void *b ) { VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object ); @@ -3176,7 +3176,7 @@ vips_object_print_all( void ) } static void * -vips_object_sanity_all_cb( VipsObject *object ) +vips_object_sanity_all_cb( VipsObject *object, void *a, void *b ) { (void) vips_object_sanity( object ); diff --git a/libvips/iofuncs/rect.c b/libvips/iofuncs/rect.c index 8e5dd5acb6..79ae69f764 100644 --- a/libvips/iofuncs/rect.c +++ b/libvips/iofuncs/rect.c @@ -225,7 +225,7 @@ vips_rect_unionrect( const VipsRect *r1, const VipsRect *r2, VipsRect *out ) * vips_rect_dup: (skip) * @r: rectangle to duplicate * - * Duplicate a rect to the heap. You need to free the result with vips_free(). + * Duplicate a rect to the heap. You need to free the result with g_free(). * * Returns: (transfer full): a pointer to copy of @r allocated on the heap. */ diff --git a/libvips/iofuncs/region.c b/libvips/iofuncs/region.c index 50b4dc8381..89d215ab0e 100644 --- a/libvips/iofuncs/region.c +++ b/libvips/iofuncs/region.c @@ -1576,7 +1576,7 @@ vips_region_shrink( VipsRegion *from, VipsRegion *to, const VipsRect *target ) /* Generate into a region. */ static int -vips_region_generate( VipsRegion *reg ) +vips_region_generate( VipsRegion *reg, void *a ) { VipsImage *im = reg->im; @@ -1659,8 +1659,7 @@ vips_region_prepare( VipsRegion *reg, const VipsRect *r ) switch( im->dtype ) { case VIPS_IMAGE_PARTIAL: - if( vips_region_fill( reg, r, - (VipsRegionFillFn) vips_region_generate, NULL ) ) + if( vips_region_fill( reg, r, vips_region_generate, NULL ) ) return( -1 ); break; @@ -1716,7 +1715,7 @@ vips_region_prepare_to_generate( VipsRegion *reg, /* Run sequence into reg. */ - if( vips_region_generate( reg ) ) + if( vips_region_generate( reg, NULL ) ) return( -1 ); /* The generate function may not have actually made any pixels ... it @@ -2007,7 +2006,7 @@ vips_region_invalidate( VipsRegion *reg ) #ifdef VIPS_DEBUG static void * -vips_region_dump_all_cb( VipsRegion *region, size_t *alive ) +vips_region_dump_all_cb( VipsRegion *region, size_t *alive, void *b ) { char str[2048]; VipsBuf buf = VIPS_BUF_STATIC( str ); diff --git a/libvips/iofuncs/sink.c b/libvips/iofuncs/sink.c index d8cad9b343..17454eda36 100644 --- a/libvips/iofuncs/sink.c +++ b/libvips/iofuncs/sink.c @@ -120,7 +120,7 @@ static void sink_area_free( SinkArea *area ) { vips_semaphore_destroy( &area->n_thread ); - vips_free( area ); + g_free( area ); } static SinkArea * diff --git a/libvips/iofuncs/sinkdisc.c b/libvips/iofuncs/sinkdisc.c index 33647b6360..8cd62be6b9 100644 --- a/libvips/iofuncs/sinkdisc.c +++ b/libvips/iofuncs/sinkdisc.c @@ -157,7 +157,7 @@ wbuffer_free( WriteBuffer *wbuffer ) vips_semaphore_destroy( &wbuffer->go ); vips_semaphore_destroy( &wbuffer->nwrite ); vips_semaphore_destroy( &wbuffer->done ); - vips_free( wbuffer ); + g_free( wbuffer ); } static void diff --git a/libvips/iofuncs/sinkmemory.c b/libvips/iofuncs/sinkmemory.c index bde9ac0981..0441312f89 100644 --- a/libvips/iofuncs/sinkmemory.c +++ b/libvips/iofuncs/sinkmemory.c @@ -126,7 +126,7 @@ static void sink_memory_area_free( SinkMemoryArea *area ) { vips_semaphore_destroy( &area->nwrite ); - vips_free( area ); + g_free( area ); } static SinkMemoryArea * diff --git a/libvips/iofuncs/sinkscreen.c b/libvips/iofuncs/sinkscreen.c index e36644a31b..9c216e59d2 100644 --- a/libvips/iofuncs/sinkscreen.c +++ b/libvips/iofuncs/sinkscreen.c @@ -206,12 +206,12 @@ render_thread_state_new( VipsImage *im, void *a ) } static void * -tile_free( Tile *tile ) +tile_free( Tile *tile, void *a, void *b ) { VIPS_DEBUG_MSG_AMBER( "tile_free\n" ); VIPS_UNREF( tile->region ); - vips_free( tile ); + g_free( tile ); return( NULL ); } @@ -245,7 +245,7 @@ render_free( Render *render ) VIPS_UNREF( render->in ); - vips_free( render ); + g_free( render ); #ifdef VIPS_DEBUG_AMBER render_num_renders -= 1; @@ -454,7 +454,7 @@ vips__render_shutdown( void ) } static int -render_dirty_sort( Render *a, Render *b ) +render_dirty_sort( Render *a, Render *b, void *user_data ) { return( b->priority - a->priority ); } @@ -504,7 +504,7 @@ tile_equal( gconstpointer a, gconstpointer b ) rect1->top == rect2->top ); } -static int +static void render_close_cb( VipsImage *image, Render *render ) { VIPS_DEBUG_MSG_AMBER( "render_close_cb\n" ); @@ -523,8 +523,6 @@ render_close_cb( VipsImage *image, Render *render ) */ VIPS_DEBUG_MSG_GREEN( "render_close_cb: reschedule\n" ); render_reschedule = TRUE; - - return( 0 ); } static Render * @@ -617,7 +615,7 @@ tile_new( Render *render ) tile->ticks = render->ticks; if( !(tile->region = vips_region_new( render->in )) ) { - (void) tile_free( tile ); + (void) tile_free( tile, NULL, NULL ); return( NULL ); } diff --git a/libvips/iofuncs/source.c b/libvips/iofuncs/source.c index b20c5b580c..a8d59261d6 100644 --- a/libvips/iofuncs/source.c +++ b/libvips/iofuncs/source.c @@ -1000,9 +1000,8 @@ vips_source_map( VipsSource *source, size_t *length_out ) } static int -vips_source_map_cb( void *a, void *b ) +vips_source_map_cb( void *a, VipsArea *area ) { - VipsArea *area = VIPS_AREA( b ); GObject *gobject = G_OBJECT( area->client ); VIPS_UNREF( gobject ); @@ -1027,7 +1026,8 @@ vips_source_map_blob( VipsSource *source ) VipsBlob *blob; if( !(buf = vips_source_map( source, &len )) || - !(blob = vips_blob_new( vips_source_map_cb, buf, len )) ) + !(blob = vips_blob_new( (VipsCallbackFn) vips_source_map_cb, + buf, len )) ) return( NULL ); /* The source must stay alive until the blob is done. diff --git a/libvips/iofuncs/target.c b/libvips/iofuncs/target.c index 11ca2fc688..1ca378357e 100644 --- a/libvips/iofuncs/target.c +++ b/libvips/iofuncs/target.c @@ -413,7 +413,7 @@ vips_target_finish( VipsTarget *target ) data = g_byte_array_free( target->memory_buffer, FALSE ); target->memory_buffer = NULL; vips_blob_set( target->blob, - (VipsCallbackFn) g_free, data, length ); + (VipsCallbackFn) vips_area_free_cb, data, length ); } else class->finish( target ); diff --git a/libvips/iofuncs/type.c b/libvips/iofuncs/type.c index 120a71dab0..f706655c02 100644 --- a/libvips/iofuncs/type.c +++ b/libvips/iofuncs/type.c @@ -171,6 +171,14 @@ vips_area_copy( VipsArea *area ) return( area ); } +int +vips_area_free_cb( void *mem, VipsArea *area ) +{ + g_free( mem ); + + return( 0 ); +} + void vips_area_free( VipsArea *area ) { @@ -314,7 +322,7 @@ vips_area_new_array( GType type, size_t sizeof_type, int n ) void *array; array = g_malloc( n * sizeof_type ); - area = vips_area_new( (VipsCallbackFn) g_free, array ); + area = vips_area_new( (VipsCallbackFn) vips_area_free_cb, array ); area->n = n; area->length = n * sizeof_type; area->type = type; @@ -323,7 +331,7 @@ vips_area_new_array( GType type, size_t sizeof_type, int n ) return( area ); } -static void +static int vips_area_free_array_object( GObject **array, VipsArea *area ) { int i; @@ -333,6 +341,8 @@ vips_area_free_array_object( GObject **array, VipsArea *area ) VIPS_FREE( array ); area->n = 0; + + return( 0 ); } /** @@ -556,7 +566,7 @@ vips_ref_string_new( const char *str ) if( !g_utf8_validate( str, -1, NULL ) ) str = ""; - area = vips_area_new( (VipsCallbackFn) g_free, g_strdup( str ) ); + area = vips_area_new( (VipsCallbackFn) vips_area_free_cb, g_strdup( str ) ); /* Handy place to cache this. */ @@ -655,7 +665,7 @@ vips_blob_copy( const void *data, size_t length ) data_copy = vips_malloc( NULL, length ); memcpy( data_copy, data, length ); - area = vips_area_new( (VipsCallbackFn) g_free, data_copy ); + area = vips_area_new( (VipsCallbackFn) vips_area_free_cb, data_copy ); area->length = length; return( (VipsBlob *) area ); @@ -737,7 +747,7 @@ transform_blob_save_string( const GValue *src_value, GValue *dest_value ) blob = vips_value_get_blob( src_value, &length ); if( (b64 = g_base64_encode( blob, length )) ) { vips_value_set_save_string( dest_value, b64 ); - vips_free( b64 ); + g_free( b64 ); } else /* No error return from transform, but we should set it to @@ -756,7 +766,7 @@ transform_save_string_blob( const GValue *src_value, GValue *dest_value ) b64 = vips_value_get_save_string( src_value ); if( (blob = g_base64_decode( b64, &length )) ) vips_value_set_blob( dest_value, - (VipsCallbackFn) vips_free, blob, length ); + (VipsCallbackFn) vips_area_free_cb, blob, length ); else /* No error return from transform, but we should set it to * something. @@ -1641,7 +1651,7 @@ vips_value_set_blob_free( GValue *value, void *data, size_t length ) g_assert( G_VALUE_TYPE( value ) == VIPS_TYPE_BLOB ); - blob = vips_blob_new( (VipsCallbackFn) g_free, data, length ); + blob = vips_blob_new( (VipsCallbackFn) vips_area_free_cb, data, length ); g_value_set_boxed( value, blob ); vips_area_unref( VIPS_AREA( blob ) ); } diff --git a/libvips/iofuncs/util.c b/libvips/iofuncs/util.c index f99deb81fb..0629adab79 100644 --- a/libvips/iofuncs/util.c +++ b/libvips/iofuncs/util.c @@ -222,10 +222,10 @@ vips_slist_filter( GSList *list, VipsSListMap2Fn fn, void *a, void *b ) static void vips_slist_free_all_cb( void * thing, void * dummy ) { - vips_free( thing ); + g_free( thing ); } -/* Free a g_slist of things which need vips_free()ing. +/* Free a g_slist of things which need g_free()ing. */ void vips_slist_free_all( GSList *list ) @@ -815,7 +815,7 @@ vips__file_read( FILE *fp, const char *filename, size_t *length_out ) rewind( fp ); read = fread( str, sizeof( char ), (size_t) len, fp ); if( read != (size_t) len ) { - vips_free( str ); + g_free( str ); vips_error( "vips__file_read", _( "error reading from file \"%s\"" ), filename ); @@ -944,7 +944,7 @@ vips__gvalue_copy( GValue *value ) } static void -vips__gvalue_free( GValue *value ) +vips__gvalue_free( GValue *value, void *user_data ) { g_value_unset( value ); g_free( value ); @@ -2031,7 +2031,7 @@ vips__icc_dir( void ) static GOnce once = G_ONCE_INIT; return( (const char *) g_once( &once, - (GThreadFunc) vips_icc_dir_once, NULL ) ); + vips_icc_dir_once, NULL ) ); } #ifdef OS_WIN32 @@ -2069,7 +2069,7 @@ vips__windows_prefix( void ) static GOnce once = G_ONCE_INIT; return( (const char *) g_once( &once, - (GThreadFunc) vips__windows_prefix_once, NULL ) ); + vips__windows_prefix_once, NULL ) ); } char * diff --git a/libvips/iofuncs/vips.c b/libvips/iofuncs/vips.c index 16e7475971..a1b61ab8aa 100644 --- a/libvips/iofuncs/vips.c +++ b/libvips/iofuncs/vips.c @@ -490,7 +490,7 @@ read_chunk( int fd, gint64 offset, size_t length ) if( !(buf = vips_malloc( NULL, length + 1 )) ) return( NULL ); if( read( fd, buf, length ) != (ssize_t) length ) { - vips_free( buf ); + g_free( buf ); vips_error( "VipsImage", "%s", _( "unable to read history" ) ); return( NULL ); } @@ -828,7 +828,7 @@ target_write_quotes( VipsTarget *target, const char *str ) } static void * -build_xml_meta( VipsMeta *meta, VipsTarget *target ) +build_xml_meta( VipsMeta *meta, VipsTarget *target, void *b ) { GType type = G_VALUE_TYPE( &meta->value ); diff --git a/libvips/iofuncs/window.c b/libvips/iofuncs/window.c index 8b98683d2f..875c895ef2 100644 --- a/libvips/iofuncs/window.c +++ b/libvips/iofuncs/window.c @@ -129,7 +129,7 @@ vips_window_free( VipsWindow *window ) window->im = NULL; - vips_free( window ); + g_free( window ); return( 0 ); } @@ -307,7 +307,7 @@ typedef struct { } request_t; static void * -vips_window_fits( VipsWindow *window, request_t *req ) +vips_window_fits( VipsWindow *window, request_t *req, void *b ) { if( window->top <= req->top && window->top + window->height >= req->top + req->height )