diff --git a/TODO b/TODO index ad3d3c91..628095a3 100644 --- a/TODO +++ b/TODO @@ -1,15 +1,7 @@ -- rewind is not removing arg instance flags +- on rewind, we junk filename, argh - VIPS-WARNING **: object.c:567: VipsImage can only assign 'nickname' once + I guess we need to save and restore it - VipsArgumentInstance *argument_instance = - vips__argument_get_instance( argument_class, object ); - - how do we find and junk these? - - vips_object_dispose_argument( - - runs, but perhaps does not trash instance storage? where is this released? diff --git a/libvips/include/vips/image.h b/libvips/include/vips/image.h index 86431fe9..54dceff8 100644 --- a/libvips/include/vips/image.h +++ b/libvips/include/vips/image.h @@ -349,6 +349,8 @@ double vips_image_get_xres( VipsImage *image ); double vips_image_get_yres( VipsImage *image ); int vips_image_get_xoffset( VipsImage *image ); int vips_image_get_yoffset( VipsImage *image ); +const char *vips_image_get_filename( VipsImage *image ); +const char *vips_image_get_mode( VipsImage *image ); size_t vips_image_size( VipsImage *image ); void vips_image_written( VipsImage *image ); diff --git a/libvips/include/vips/object.h b/libvips/include/vips/object.h index 940de6ce..e67583a2 100644 --- a/libvips/include/vips/object.h +++ b/libvips/include/vips/object.h @@ -217,6 +217,11 @@ struct _VipsObjectClass { */ void (*sanity)( VipsObject *, VipsBuf * ); + /* Rewind. Save and restore any stuff that needs to survive a + * dispose(). + */ + void (*rewind)( VipsObject * ); + /* Just before close, everything is still alive. */ void (*preclose)( VipsObject * ); diff --git a/libvips/iofuncs/image.c b/libvips/iofuncs/image.c index 40ed606f..ba1c1c2d 100644 --- a/libvips/iofuncs/image.c +++ b/libvips/iofuncs/image.c @@ -506,6 +506,27 @@ vips_image_sanity( VipsObject *object, VipsBuf *buf ) VIPS_OBJECT_CLASS( vips_image_parent_class )->sanity( object, buf ); } +static void +vips_image_rewind( VipsObject *object ) +{ + VipsImage *image = VIPS_IMAGE( object ); + char *filename; + char *mode; + + /* The old values for filename and mode become the new defaults. + */ + filename = g_strdup( vips_image_get_filename( image ) ); + mode = g_strdup( vips_image_get_mode( image ) ); + + VIPS_OBJECT_CLASS( vips_image_parent_class )->rewind( object ); + + g_assert( image->filename == NULL ); + g_assert( image->mode == NULL ); + + image->filename = filename; + image->mode = mode; +} + static gboolean vips_format_is_vips( VipsFormatClass *format ) { @@ -1042,6 +1063,7 @@ vips_image_class_init( VipsImageClass *class ) vobject_class->print = vips_image_print; vobject_class->sanity = vips_image_sanity; + vobject_class->rewind = vips_image_rewind; vobject_class->build = vips_image_build; class->invalidate = vips_image_real_invalidate; @@ -1261,6 +1283,12 @@ vips_image_get_yoffset( VipsImage *image ) return( image->Yoffset ); } +const char * +vips_image_get_filename( VipsImage *image ) +{ + return( image->filename ); +} + size_t vips_image_size( VipsImage *image ) { diff --git a/libvips/iofuncs/object.c b/libvips/iofuncs/object.c index dc765b5b..7baffcc5 100644 --- a/libvips/iofuncs/object.c +++ b/libvips/iofuncs/object.c @@ -172,6 +172,20 @@ vips_object_sanity( VipsObject *object ) return( TRUE ); } +/* On a rewind, we dispose the old contents of the object and + * reconstruct. This is used in things like im_pincheck() where a "w" + * image has to be rewound and become a "p" image. + * + * Override in subclasses if you want to preserve some fields, see image.c. + */ +void +vips_object_rewind( VipsObject *object ) +{ + VipsObjectClass *class = VIPS_OBJECT_GET_CLASS( object ); + + class->rewind( object ); +} + /* Extra stuff we track for properties to do our argument handling. */ @@ -180,6 +194,8 @@ vips_object_sanity( VipsObject *object ) static void vips_argument_instance_free( VipsArgumentInstance *argument_instance ) { + printf( "vips_argument_instance_free\n" ); + if( argument_instance->destroy_id ) { g_signal_handler_disconnect( argument_instance->object, argument_instance->destroy_id ); @@ -368,10 +384,10 @@ vips_object_dispose_argument( VipsObject *object, GParamSpec *pspec, void *a, void *b ) { #ifdef DEBUG +#endif /*DEBUG*/ printf( "vips_object_dispose_argument: " ); vips_object_print( object ); printf( ".%s\n", pspec->name ); -#endif /*DEBUG*/ g_assert( ((VipsArgument *) argument_class)->pspec == pspec ); g_assert( ((VipsArgument *) argument_instance)->pspec == pspec ); @@ -404,9 +420,9 @@ vips_object_dispose( GObject *gobject ) VipsObject *object = VIPS_OBJECT( gobject ); #ifdef DEBUG +#endif /*DEBUG*/ printf( "vips_object_dispose: " ); vips_object_print( object ); -#endif /*DEBUG*/ /* Our subclasses should have already called this. Run it again, just * in case. @@ -423,6 +439,7 @@ vips_object_dispose( GObject *gobject ) /* Clear all our arguments: they may be holding refs we should drop. */ vips_argument_map( object, vips_object_dispose_argument, NULL, NULL ); + VIPS_FREEF( vips_argument_table_destroy, object->argument_table ); G_OBJECT_CLASS( vips_object_parent_class )->dispose( gobject ); } @@ -440,7 +457,6 @@ vips_object_finalize( GObject *gobject ) vips_object_close( object ); g_hash_table_remove( vips_object_all, object ); - VIPS_FREEF( vips_argument_table_destroy, object->argument_table ); G_OBJECT_CLASS( vips_object_parent_class )->finalize( gobject ); @@ -792,6 +808,22 @@ vips_object_real_sanity( VipsObject *object, VipsBuf *buf ) { } +static void +vips_object_real_rewind( VipsObject *object ) +{ +#ifdef DEBUG +#endif /*DEBUG*/ + printf( "vips_object_rewind\n" ); + vips_object_print( object ); + + g_object_run_dispose( G_OBJECT( object ) ); + + object->constructed = FALSE; + object->preclose = FALSE; + object->close = FALSE; + object->postclose = FALSE; +} + static void transform_string_double( const GValue *src_value, GValue *dest_value ) { @@ -819,6 +851,7 @@ vips_object_class_init( VipsObjectClass *class ) class->print_class = vips_object_real_print_class; class->print = vips_object_real_print; class->sanity = vips_object_real_sanity; + class->rewind = vips_object_real_rewind; class->nickname = "object"; class->description = _( "VIPS base class" ); @@ -1244,18 +1277,3 @@ vips_object_sanity_all( void ) { vips_object_map( (VSListMap2Fn) vips_object_sanity_all_cb, NULL, NULL ); } - -/* On a rewind, we dispose the old contents of the object and - * reconstruct. This is used in things like im_pincheck() where a "w" - * image has to be rewound and become a "p" image. - */ -void -vips_object_rewind( VipsObject *object ) -{ - g_object_run_dispose( G_OBJECT( object ) ); - - object->constructed = FALSE; - object->preclose = FALSE; - object->close = FALSE; - object->postclose = FALSE; -}