diff --git a/ChangeLog b/ChangeLog index 882c0b7c..e7c73f44 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,9 @@ 20/8/11 started 7.27.0 - version bump for new dev cycle -- im_subtract(), im_avg() redone as classes +- im_subtract(), im_avg(), im_min(), im_minpos() redone as classes - added VIPS_ARGUMENT_APPEND to help control arg ordering - generate has a 'stop' param to signal successful early termination +- added optional output args, eg. x/y for min 10/8/11 started 7.26.3 - don't use G_VALUE_COLLECT_INIT(), many platforms do not have a glib this diff --git a/TODO b/TODO index bcdbab03..497af5f9 100644 --- a/TODO +++ b/TODO @@ -1,16 +1,30 @@ -- optional output args are broken +- cmd line interface needs to print optional output args, if requested + + eg. + + $ vips min fred.v + 12 + $ vips min -x fred.v + 12 + 300 + + the switch is there, but breaks an assert: + + $ vips min -x babe.jpg + VIPS:ERROR:object.c:1178:vips_object_set_argument_from_string: assertion + failed: (argument_class->flags & VIPS_ARGUMENT_INPUT) + Aborted + + + + +- C interface needs to look for optional output args in final psss, eg. vips_min( im, &min, "x", &xpos, "y", &ypos, NULL ); - tries to set "x" and "y" during vips_operation_set_valist_optional(), - instead it should read them during output arg readout phase - - - - diff --git a/libvips/iofuncs/object.c b/libvips/iofuncs/object.c index d6df050b..027e67f0 100644 --- a/libvips/iofuncs/object.c +++ b/libvips/iofuncs/object.c @@ -702,7 +702,6 @@ vips_object_set_property( GObject *gobject, } #ifdef DEBUG -#endif /*DEBUG*/ { char *str_value; @@ -712,6 +711,7 @@ vips_object_set_property( GObject *gobject, printf( ".%s = %s\n", g_param_spec_get_name( pspec ), str_value ); g_free( str_value ); } +#endif /*DEBUG*/ g_assert( ((VipsArgument *) argument_class)->pspec == pspec ); g_assert( ((VipsArgument *) argument_instance)->pspec == pspec ); diff --git a/libvips/iofuncs/operation.c b/libvips/iofuncs/operation.c index 9d21ffe5..b64194e4 100644 --- a/libvips/iofuncs/operation.c +++ b/libvips/iofuncs/operation.c @@ -302,10 +302,54 @@ vips_operation_set_valist_required( VipsOperation *operation, va_list ap ) static int vips_operation_set_valist_optional( VipsOperation *operation, va_list ap ) { - char *first_property_name; + VipsOperationClass *class = + VIPS_OPERATION_GET_CLASS( operation ); + VipsArgumentTable *argument_table = + VIPS_OBJECT_CLASS( class )->argument_table; - first_property_name = va_arg( ap, char * ); - g_object_set_valist( G_OBJECT (operation), first_property_name, ap ); + char *name; + + name = va_arg( ap, char * ); + + while( name ) { + GValue value = { 0, }; + GParamSpec *pspec; + gchar *error = NULL; + VipsArgumentClass *argument_class; + + if( !(pspec = g_object_class_find_property( + G_OBJECT_CLASS( class ), name )) ) { + vips_error( VIPS_OBJECT_CLASS( class )->description, + _( "class `%s' has no property named `%s'\n" ), + G_OBJECT_TYPE_NAME( operation ), name ); + return( -1 ); + } + + g_value_init( &value, G_PARAM_SPEC_VALUE_TYPE( pspec ) ); + G_VALUE_COLLECT( &value, ap, 0, &error ); + if( error ) { + vips_error( VIPS_OBJECT_CLASS( class )->description, + "%s", _( error ) ); + g_value_unset( &value ); + g_free( error ); + + return( -1 ); + } + + /* Only set input args, Output args are read from the + * finished object after build. + */ + argument_class = (VipsArgumentClass *) + vips__argument_table_lookup( argument_table, pspec ); + if( argument_class && + (argument_class->flags & VIPS_ARGUMENT_INPUT) ) + g_object_set_property( G_OBJECT( operation ), + name, &value ); + + g_value_unset( &value ); + + name = va_arg( ap, char * ); + } return( 0 ); }