add vips8 arg stuff
This commit is contained in:
parent
11352c8f1b
commit
534c05c567
@ -19,6 +19,7 @@
|
|||||||
- updated docs
|
- updated docs
|
||||||
- interpolators use type introspection
|
- interpolators use type introspection
|
||||||
- added vips --list classes, does formats too
|
- added vips --list classes, does formats too
|
||||||
|
- copy/pasted some vips8 arg stuff, needs much hacking
|
||||||
|
|
||||||
11/9/08 started 7.16.3
|
11/9/08 started 7.16.3
|
||||||
- oop typo in manpage for im_project()
|
- oop typo in manpage for im_project()
|
||||||
|
6
TODO
6
TODO
@ -6,8 +6,12 @@
|
|||||||
|
|
||||||
nickname, description etc need to be properties so nip2 can read them
|
nickname, description etc need to be properties so nip2 can read them
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
add a g_get_children( "classname" ) -> ["child1-name", ..] to nip2, see old
|
add a g_get_children( "classname" ) -> ["child1-name", ..] to nip2, see old
|
||||||
vips8.c cooe?
|
vips8.c code?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,6 +34,130 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif /*__cplusplus*/
|
#endif /*__cplusplus*/
|
||||||
|
|
||||||
|
typedef struct _VipsObject VipsObject;
|
||||||
|
typedef struct _VipsObjectClass VipsObjectClass;
|
||||||
|
|
||||||
|
/* Track extra stuff for arguments to objects
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Flags we associate with each argument.
|
||||||
|
*/
|
||||||
|
typedef enum _VipsArgumentFlags {
|
||||||
|
VIPS_ARGUMENT_NONE = 0,
|
||||||
|
|
||||||
|
/* Must be set before _build().
|
||||||
|
*/
|
||||||
|
VIPS_ARGUMENT_REQUIRED = 1,
|
||||||
|
|
||||||
|
/* Can only be set before _build().
|
||||||
|
*/
|
||||||
|
VIPS_ARGUMENT_CONSTRUCT = 2,
|
||||||
|
|
||||||
|
/* Can only be set once.
|
||||||
|
*/
|
||||||
|
VIPS_ARGUMENT_SET_ONCE = 4,
|
||||||
|
|
||||||
|
/* Have input & output flags. Both set is an error; neither set is OK.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Is an input argument (one we depend on) ... if it's a gobject, we
|
||||||
|
* should ref it. In our _dispose(), we should unref it.
|
||||||
|
*/
|
||||||
|
VIPS_ARGUMENT_INPUT = 8,
|
||||||
|
|
||||||
|
/* Is an output argument (one that depends on us) ... if it's a
|
||||||
|
* gobject, we should ref ourselves. We watch "destroy" on the
|
||||||
|
* argument: if it goes, we unref ourselves. If we dispose, we
|
||||||
|
* disconnect the signal.
|
||||||
|
*/
|
||||||
|
VIPS_ARGUMENT_OUTPUT = 16
|
||||||
|
} VipsArgumentFlags;
|
||||||
|
|
||||||
|
/* Useful flag combinations. User-visible ones are:
|
||||||
|
|
||||||
|
VIPS_ARGUMENT_REQURED_INPUT Eg. the "left" argument for an add operation
|
||||||
|
|
||||||
|
VIPS_ARGUMENT_OPTIONAL_INPUT Eg. the "caption" for an object
|
||||||
|
|
||||||
|
VIPS_ARGUMENT_REQURED_OUTPUT Eg. the "result" of an add operation
|
||||||
|
|
||||||
|
VIPS_ARGUMENT_OPTIONAL_OUTPUT Eg. the "width" of an image
|
||||||
|
|
||||||
|
Other combinations are used internally, eg. supplying the cast-table for an
|
||||||
|
arithmetic operation
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define VIPS_ARGUMENT_REQUIRED_INPUT \
|
||||||
|
(VIPS_ARGUMENT_INPUT | VIPS_ARGUMENT_REQUIRED | \
|
||||||
|
VIPS_ARGUMENT_CONSTRUCT | VIPS_ARGUMENT_SET_ONCE)
|
||||||
|
|
||||||
|
#define VIPS_ARGUMENT_OPTIONAL_INPUT \
|
||||||
|
(VIPS_ARGUMENT_INPUT | \
|
||||||
|
VIPS_ARGUMENT_CONSTRUCT | VIPS_ARGUMENT_SET_ONCE)
|
||||||
|
|
||||||
|
#define VIPS_ARGUMENT_REQUIRED_OUTPUT \
|
||||||
|
(VIPS_ARGUMENT_OUTPUT | VIPS_ARGUMENT_REQUIRED | \
|
||||||
|
VIPS_ARGUMENT_SET_ONCE)
|
||||||
|
|
||||||
|
#define VIPS_ARGUMENT_OPTIONAL_OUTPUT \
|
||||||
|
(VIPS_ARGUMENT_OUTPUT | \
|
||||||
|
VIPS_ARGUMENT_SET_ONCE)
|
||||||
|
|
||||||
|
/* Keep one of these for every argument.
|
||||||
|
*/
|
||||||
|
typedef struct _VipsArgument {
|
||||||
|
GParamSpec *pspec; /* pspec for this argument */
|
||||||
|
|
||||||
|
/* More stuff, see below */
|
||||||
|
} VipsArgument;
|
||||||
|
|
||||||
|
/* Keep one of these in the class struct for every argument.
|
||||||
|
*/
|
||||||
|
typedef struct _VipsArgumentClass {
|
||||||
|
VipsArgument parent;
|
||||||
|
|
||||||
|
/* The class of the object we are an arg for.
|
||||||
|
*/
|
||||||
|
VipsObjectClass *object_class;
|
||||||
|
|
||||||
|
VipsArgumentFlags flags;
|
||||||
|
guint offset; /* G_STRUCT_OFFSET of member in object */
|
||||||
|
} VipsArgumentClass;
|
||||||
|
|
||||||
|
/* Keep one of these in the object struct for every argument instance.
|
||||||
|
*/
|
||||||
|
typedef struct _VipsArgumentInstance {
|
||||||
|
VipsArgument parent;
|
||||||
|
|
||||||
|
/* The object we are attached to.
|
||||||
|
*/
|
||||||
|
VipsObject *object;
|
||||||
|
|
||||||
|
/* Has been set.
|
||||||
|
*/
|
||||||
|
gboolean assigned;
|
||||||
|
|
||||||
|
/* If this is an output argument, keep the id of our "destroy" handler
|
||||||
|
* here.
|
||||||
|
*/
|
||||||
|
gulong destroy_id;
|
||||||
|
} VipsArgumentInstance;
|
||||||
|
|
||||||
|
/* Need to look up our VipsArgument structs from a pspec. Just hash the
|
||||||
|
* pointer (ie. we assume pspecs are never shared, is this correct?)
|
||||||
|
*/
|
||||||
|
typedef GHashTable VipsArgumentTable;
|
||||||
|
|
||||||
|
VipsArgumentInstance *vips__argument_get_instance( VipsArgumentClass *,
|
||||||
|
VipsObject *);
|
||||||
|
VipsArgument *vips__argument_table_lookup( VipsArgumentTable *,
|
||||||
|
GParamSpec *);
|
||||||
|
typedef void *(*VipsArgumentMapFn)( VipsObject *, GParamSpec *,
|
||||||
|
VipsArgumentClass *, VipsArgumentInstance *, void *a, void *b );
|
||||||
|
void *vips__argument_map( VipsObject *object,
|
||||||
|
VipsArgumentMapFn fn, void *a, void *b );
|
||||||
|
|
||||||
#define VIPS_TYPE_OBJECT (vips_object_get_type())
|
#define VIPS_TYPE_OBJECT (vips_object_get_type())
|
||||||
#define VIPS_OBJECT( obj ) \
|
#define VIPS_OBJECT( obj ) \
|
||||||
(G_TYPE_CHECK_INSTANCE_CAST( (obj), VIPS_TYPE_OBJECT, VipsObject ))
|
(G_TYPE_CHECK_INSTANCE_CAST( (obj), VIPS_TYPE_OBJECT, VipsObject ))
|
||||||
@ -46,15 +170,17 @@ extern "C" {
|
|||||||
#define VIPS_OBJECT_GET_CLASS( obj ) \
|
#define VIPS_OBJECT_GET_CLASS( obj ) \
|
||||||
(G_TYPE_INSTANCE_GET_CLASS( (obj), VIPS_TYPE_OBJECT, VipsObjectClass ))
|
(G_TYPE_INSTANCE_GET_CLASS( (obj), VIPS_TYPE_OBJECT, VipsObjectClass ))
|
||||||
|
|
||||||
typedef struct _VipsObject {
|
struct _VipsObject {
|
||||||
GObject parent_object;
|
GObject parent_object;
|
||||||
|
|
||||||
/* Optional instance name.
|
char *name; /* Optional instance name */
|
||||||
*/
|
|
||||||
char *name;
|
|
||||||
} VipsObject;
|
|
||||||
|
|
||||||
typedef struct _VipsObjectClass {
|
/* Table of argument instances for this class and any derived classes.
|
||||||
|
*/
|
||||||
|
VipsArgumentTable *argument_table;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _VipsObjectClass {
|
||||||
GObjectClass parent_class;
|
GObjectClass parent_class;
|
||||||
|
|
||||||
/* Something about the object has changed. Should use glib's properties
|
/* Something about the object has changed. Should use glib's properties
|
||||||
@ -78,7 +204,15 @@ typedef struct _VipsObjectClass {
|
|||||||
/* Class description. Used for help messages, so internationalised.
|
/* Class description. Used for help messages, so internationalised.
|
||||||
*/
|
*/
|
||||||
const char *description;
|
const char *description;
|
||||||
} VipsObjectClass;
|
|
||||||
|
/* Table of arguments for this class and any derived classes. Order
|
||||||
|
* is important, so keep a traverse list too. We can't rely on the
|
||||||
|
* ordering given by g_object_class_list_properties() since it comes
|
||||||
|
* from a hash :-(
|
||||||
|
*/
|
||||||
|
VipsArgumentTable *argument_table;
|
||||||
|
GSList *argument_table_traverse;
|
||||||
|
};
|
||||||
|
|
||||||
void *vips_object_changed( VipsObject *object );
|
void *vips_object_changed( VipsObject *object );
|
||||||
void vips_object_print_class( VipsObjectClass *klass );
|
void vips_object_print_class( VipsObjectClass *klass );
|
||||||
@ -86,6 +220,9 @@ void vips_object_print( VipsObject *object );
|
|||||||
|
|
||||||
GType vips_object_get_type( void );
|
GType vips_object_get_type( void );
|
||||||
|
|
||||||
|
void vips_object_class_install_argument( VipsObjectClass *,
|
||||||
|
GParamSpec *pspec, VipsArgumentFlags flags, guint offset );
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif /*__cplusplus*/
|
#endif /*__cplusplus*/
|
||||||
|
@ -937,3 +937,4 @@ im__meta_init_types( void )
|
|||||||
g_value_register_transform_func( IM_TYPE_SAVE_STRING, G_TYPE_DOUBLE,
|
g_value_register_transform_func( IM_TYPE_SAVE_STRING, G_TYPE_DOUBLE,
|
||||||
transform_save_string_double );
|
transform_save_string_double );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,16 +100,247 @@ vips_object_print( VipsObject *object )
|
|||||||
printf( "\n%s (%p)\n", im_buf_all( &buf ), object );
|
printf( "\n%s (%p)\n", im_buf_all( &buf ), object );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Extra stuff we track for properties to do our argument handling.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Free a VipsArgumentInstance ... VipsArgumentClass can just be g_free()d.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
vips_argument_instance_free (VipsArgumentInstance *argument_instance)
|
||||||
|
{
|
||||||
|
if (argument_instance->destroy_id) {
|
||||||
|
g_signal_handler_disconnect (argument_instance->object,
|
||||||
|
argument_instance->destroy_id);
|
||||||
|
argument_instance->destroy_id = 0;
|
||||||
|
}
|
||||||
|
g_free (argument_instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
VipsArgument *
|
||||||
|
vips__argument_table_lookup (VipsArgumentTable *table,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
return (g_hash_table_lookup (table, pspec));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_argument_table_replace (VipsArgumentTable *table, VipsArgument *argument)
|
||||||
|
{
|
||||||
|
g_hash_table_replace (table, argument->pspec, argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_argument_table_destroy (VipsArgumentTable *table)
|
||||||
|
{
|
||||||
|
g_hash_table_destroy (table);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *
|
||||||
|
vips_argument_init_sub (VipsObject *object, GParamSpec *pspec,
|
||||||
|
VipsArgumentClass *argument_class,
|
||||||
|
VipsArgumentInstance *argument_instance)
|
||||||
|
{
|
||||||
|
VipsArgument *argument;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf ("vips_argument_init_sub: adding instance argument for %s\n",
|
||||||
|
pspec->name);
|
||||||
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
|
/* argument_instance should be NULL since we've not set it yet.
|
||||||
|
*/
|
||||||
|
g_assert (argument_instance == NULL);
|
||||||
|
|
||||||
|
argument_instance = g_new (VipsArgumentInstance, 1);
|
||||||
|
argument = (VipsArgument *) argument_instance;
|
||||||
|
|
||||||
|
argument->pspec = ((VipsArgument *) argument_class)->pspec;
|
||||||
|
argument_instance->object = object;
|
||||||
|
argument_instance->assigned = FALSE;
|
||||||
|
argument_instance->destroy_id = 0;
|
||||||
|
|
||||||
|
vips_argument_table_replace (object->argument_table, argument);
|
||||||
|
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a VipsArgumentInstance for each installed argument property. Ideally
|
||||||
|
* we'd do this during _init() but g_object_class_find_property() does not seem
|
||||||
|
* to work then :-( so we have to delay it until first access.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
vips_argument_init (VipsObject *object)
|
||||||
|
{
|
||||||
|
if( !object->argument_table ) {
|
||||||
|
object->argument_table = g_hash_table_new_full (g_direct_hash,
|
||||||
|
g_direct_equal, NULL,
|
||||||
|
(GDestroyNotify) vips_argument_instance_free);
|
||||||
|
|
||||||
|
/* Make a VipsArgumentInstance for each installed argument
|
||||||
|
* property.
|
||||||
|
*/
|
||||||
|
vips__argument_map (object,
|
||||||
|
(VipsArgumentMapFn) vips_argument_init_sub, NULL, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convenience ... given the VipsArgumentClass, get the VipsArgumentInstance.
|
||||||
|
*/
|
||||||
|
VipsArgumentInstance *
|
||||||
|
vips__argument_get_instance (VipsArgumentClass *argument_class,
|
||||||
|
VipsObject *object)
|
||||||
|
{
|
||||||
|
/* Make sure the instance args are built.
|
||||||
|
*/
|
||||||
|
vips_argument_init (object);
|
||||||
|
|
||||||
|
return ((VipsArgumentInstance *)
|
||||||
|
vips__argument_table_lookup (object->argument_table,
|
||||||
|
((VipsArgument *) argument_class)->pspec));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loop over the vips_arguments to an object.
|
||||||
|
*
|
||||||
|
* Note: this code copy-pasted into vips_operation_call_valist(), keep in sync.
|
||||||
|
*/
|
||||||
|
void *
|
||||||
|
vips__argument_map (VipsObject *object, VipsArgumentMapFn fn, void *a, void *b)
|
||||||
|
{
|
||||||
|
VipsObjectClass *object_class = VIPS_OBJECT_GET_CLASS (object);
|
||||||
|
GSList *p;
|
||||||
|
|
||||||
|
for (p = object_class->argument_table_traverse; p; p = p->next) {
|
||||||
|
VipsArgumentClass *argument_class =
|
||||||
|
(VipsArgumentClass *) p->data;
|
||||||
|
VipsArgument *argument =
|
||||||
|
(VipsArgument *) argument_class;
|
||||||
|
GParamSpec *pspec = argument->pspec;
|
||||||
|
VipsArgumentInstance *argument_instance =
|
||||||
|
vips__argument_get_instance (argument_class, object);
|
||||||
|
|
||||||
|
/* We have many props on the arg table ... filter out the ones
|
||||||
|
* for this class.
|
||||||
|
*/
|
||||||
|
if (g_object_class_find_property (G_OBJECT_CLASS (object_class),
|
||||||
|
pspec->name) == pspec) {
|
||||||
|
void *result;
|
||||||
|
|
||||||
|
if ((result = fn (object, pspec,
|
||||||
|
argument_class, argument_instance, a, b)))
|
||||||
|
return (result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_object_clear_object (VipsObject *object, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS (object);
|
||||||
|
VipsArgumentClass *argument_class = (VipsArgumentClass *)
|
||||||
|
vips__argument_table_lookup (class->argument_table, pspec);
|
||||||
|
VipsArgumentInstance *argument_instance =
|
||||||
|
vips__argument_get_instance (argument_class, object);
|
||||||
|
GObject **member = &G_STRUCT_MEMBER (GObject *, object,
|
||||||
|
argument_class->offset);
|
||||||
|
|
||||||
|
if (*member) {
|
||||||
|
if (argument_class->flags & VIPS_ARGUMENT_INPUT) {
|
||||||
|
#ifdef DEBUG_REF
|
||||||
|
printf ("vips_object_clear_object: vips object: ");
|
||||||
|
vips_object_print (object);
|
||||||
|
printf (" no longer refers to gobject %s (%p)\n",
|
||||||
|
G_OBJECT_TYPE_NAME (*member), *member);
|
||||||
|
printf (" count down to %d\n",
|
||||||
|
G_OBJECT (*member)->ref_count - 1);
|
||||||
|
#endif /*DEBUG_REF*/
|
||||||
|
|
||||||
|
/* We reffed the object.
|
||||||
|
*/
|
||||||
|
g_object_unref (*member);
|
||||||
|
}
|
||||||
|
else if (argument_class->flags & VIPS_ARGUMENT_OUTPUT) {
|
||||||
|
#ifdef DEBUG_REF
|
||||||
|
printf ("vips_object_clear_object: gobject %s (%p)\n",
|
||||||
|
G_OBJECT_TYPE_NAME (*member), *member);
|
||||||
|
printf (" no longer refers to vips object: ");
|
||||||
|
vips_object_print (object);
|
||||||
|
printf (" count down to %d\n",
|
||||||
|
G_OBJECT (object)->ref_count - 1);
|
||||||
|
#endif /*DEBUG_REF*/
|
||||||
|
|
||||||
|
/* The object reffed us. Stop listening link to the
|
||||||
|
* object's "destroy" signal. We can come here from
|
||||||
|
* object being destroyed, in which case the handler
|
||||||
|
* will already have been disconnected for us.
|
||||||
|
*/
|
||||||
|
if( g_signal_handler_is_connected (object,
|
||||||
|
argument_instance->destroy_id))
|
||||||
|
g_signal_handler_disconnect (object,
|
||||||
|
argument_instance->destroy_id);
|
||||||
|
argument_instance->destroy_id = 0;
|
||||||
|
*member = NULL;
|
||||||
|
|
||||||
|
g_object_unref (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
*member = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Free any args which are holding resources.
|
||||||
|
*/
|
||||||
|
static void *
|
||||||
|
vips_object_dispose_argument (VipsObject *object, GParamSpec *pspec,
|
||||||
|
VipsArgumentClass *argument_class,
|
||||||
|
VipsArgumentInstance *argument_instance,
|
||||||
|
void *a, void *b)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf ("vips_object_dispose_argument: %s.%s\n",
|
||||||
|
object->name, pspec->name);
|
||||||
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
|
g_assert (((VipsArgument *) argument_class)->pspec == pspec);
|
||||||
|
g_assert (((VipsArgument *) argument_instance)->pspec == pspec);
|
||||||
|
|
||||||
|
if (G_IS_PARAM_SPEC_STRING (pspec)) {
|
||||||
|
char **member = &G_STRUCT_MEMBER (char *, object,
|
||||||
|
argument_class->offset);
|
||||||
|
|
||||||
|
IM_FREE (*member);
|
||||||
|
}
|
||||||
|
else if (G_IS_PARAM_SPEC_OBJECT (pspec))
|
||||||
|
vips_object_clear_object (object, pspec);
|
||||||
|
else if (G_IS_PARAM_SPEC_BOXED (pspec)) {
|
||||||
|
gpointer *member = &G_STRUCT_MEMBER (gpointer, object,
|
||||||
|
argument_class->offset);
|
||||||
|
|
||||||
|
if (*member) {
|
||||||
|
g_boxed_free (G_PARAM_SPEC_VALUE_TYPE (pspec), *member);
|
||||||
|
*member = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vips_object_dispose( GObject *gobject )
|
vips_object_dispose( GObject *gobject )
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
|
||||||
VipsObject *object = VIPS_OBJECT( gobject );
|
VipsObject *object = VIPS_OBJECT( gobject );
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
printf( "vips_object_dispose: " );
|
printf( "vips_object_dispose: " );
|
||||||
vips_object_print( object );
|
vips_object_print( object );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
|
/* Clear all our arguments: they may be holding refs we should drop.
|
||||||
|
*/
|
||||||
|
vips__argument_map (object,
|
||||||
|
vips_object_dispose_argument, NULL, NULL);
|
||||||
|
|
||||||
G_OBJECT_CLASS( vips_object_parent_class )->dispose( gobject );
|
G_OBJECT_CLASS( vips_object_parent_class )->dispose( gobject );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,11 +354,260 @@ vips_object_finalize( GObject *gobject )
|
|||||||
vips_object_print( object );
|
vips_object_print( object );
|
||||||
#endif /*DEBUG*/
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
|
IM_FREEF (vips_argument_table_destroy, object->argument_table);
|
||||||
IM_FREE( object->name );
|
IM_FREE( object->name );
|
||||||
|
|
||||||
G_OBJECT_CLASS( vips_object_parent_class )->finalize( gobject );
|
G_OBJECT_CLASS( vips_object_parent_class )->finalize( gobject );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_object_arg_destroy (GObject *argument,
|
||||||
|
VipsArgumentInstance *argument_instance)
|
||||||
|
{
|
||||||
|
VipsObject *object = argument_instance->object;
|
||||||
|
GParamSpec *pspec = ((VipsArgument *) argument_instance)->pspec;
|
||||||
|
|
||||||
|
/* Argument had reffed us ... now it's being destroyed, so we unref.
|
||||||
|
*/
|
||||||
|
vips_object_clear_object (object, pspec);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_object_set_object (VipsObject *object, GParamSpec *pspec,
|
||||||
|
GObject *argument)
|
||||||
|
{
|
||||||
|
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS (object);
|
||||||
|
VipsArgumentClass *argument_class = (VipsArgumentClass *)
|
||||||
|
vips__argument_table_lookup (class->argument_table, pspec);
|
||||||
|
VipsArgumentInstance *argument_instance =
|
||||||
|
vips__argument_get_instance (argument_class, object);
|
||||||
|
GObject **member = &G_STRUCT_MEMBER (GObject *, object,
|
||||||
|
argument_class->offset);
|
||||||
|
|
||||||
|
g_assert (!*member);
|
||||||
|
|
||||||
|
*member = argument;
|
||||||
|
|
||||||
|
if (*member) {
|
||||||
|
if (argument_class->flags & VIPS_ARGUMENT_INPUT) {
|
||||||
|
#ifdef DEBUG_REF
|
||||||
|
printf ("vips_object_set_object: vips object: ");
|
||||||
|
vips_object_print (object);
|
||||||
|
printf (" refers to gobject %s (%p)\n",
|
||||||
|
G_OBJECT_TYPE_NAME (*member), *member);
|
||||||
|
printf (" count up to %d\n",
|
||||||
|
G_OBJECT (*member)->ref_count);
|
||||||
|
#endif /*DEBUG_REF*/
|
||||||
|
|
||||||
|
/* Ref the argument.
|
||||||
|
*/
|
||||||
|
g_object_ref (*member);
|
||||||
|
}
|
||||||
|
else if (argument_class->flags & VIPS_ARGUMENT_OUTPUT) {
|
||||||
|
#ifdef DEBUG_REF
|
||||||
|
printf ("vips_object_set_object: gobject %s (%p)\n",
|
||||||
|
G_OBJECT_TYPE_NAME (*member), *member);
|
||||||
|
printf (" refers to vips object: ");
|
||||||
|
vips_object_print (object);
|
||||||
|
printf (" count up to %d\n",
|
||||||
|
G_OBJECT (object)->ref_count);
|
||||||
|
#endif /*DEBUG_REF*/
|
||||||
|
|
||||||
|
/* The argument reffs us.
|
||||||
|
*/
|
||||||
|
g_object_ref (object);
|
||||||
|
argument_instance->destroy_id =
|
||||||
|
g_signal_connect (*member, "destroy",
|
||||||
|
G_CALLBACK (vips_object_arg_destroy),
|
||||||
|
argument_instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_object_set_property (GObject *gobject,
|
||||||
|
guint property_id, const GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
VipsObject *object = VIPS_OBJECT (gobject);
|
||||||
|
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS (gobject);
|
||||||
|
VipsArgumentClass *argument_class = (VipsArgumentClass *)
|
||||||
|
vips__argument_table_lookup (class->argument_table, pspec);
|
||||||
|
VipsArgumentInstance *argument_instance =
|
||||||
|
vips__argument_get_instance (argument_class, object);
|
||||||
|
|
||||||
|
if (!argument_class) {
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject,
|
||||||
|
property_id, pspec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
{
|
||||||
|
char *str_value;
|
||||||
|
|
||||||
|
str_value = g_strdup_value_contents (value);
|
||||||
|
printf ("vips_object_set_property: %s.%s = %s\n",
|
||||||
|
object->name, pspec->name, str_value);
|
||||||
|
g_free (str_value);
|
||||||
|
}
|
||||||
|
#endif /*DEBUG*/
|
||||||
|
|
||||||
|
g_assert (((VipsArgument *) argument_class)->pspec == pspec);
|
||||||
|
g_assert (((VipsArgument *) argument_instance)->pspec == pspec);
|
||||||
|
|
||||||
|
/* If this is a construct-only argument, we can only set before we've
|
||||||
|
* built.
|
||||||
|
|
||||||
|
FIXME ... how do we spot end of construct? put this back
|
||||||
|
|
||||||
|
if (argument_class->flags & VIPS_ARGUMENT_CONSTRUCT &&
|
||||||
|
object->done_build) {
|
||||||
|
g_warning ("%s: can't assign '%s' after construct", G_STRLOC,
|
||||||
|
((VipsArgument *)argument_class)->pspec->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* If this is a set-once argument, check we've not set it before.
|
||||||
|
*/
|
||||||
|
if (argument_class->flags & VIPS_ARGUMENT_SET_ONCE &&
|
||||||
|
argument_instance->assigned) {
|
||||||
|
g_warning ("%s: can only assign '%s' once", G_STRLOC,
|
||||||
|
((VipsArgument *)argument_class)->pspec->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G_IS_PARAM_SPEC_STRING (pspec)) {
|
||||||
|
char **member = &G_STRUCT_MEMBER (char *, object,
|
||||||
|
argument_class->offset);
|
||||||
|
|
||||||
|
IM_SETSTR (*member, g_value_get_string (value));
|
||||||
|
}
|
||||||
|
else if (G_IS_PARAM_SPEC_OBJECT (pspec)) {
|
||||||
|
/* Remove any old object.
|
||||||
|
*/
|
||||||
|
vips_object_clear_object (object, pspec);
|
||||||
|
|
||||||
|
/* Install the new object.
|
||||||
|
*/
|
||||||
|
vips_object_set_object (object, pspec,
|
||||||
|
g_value_get_object (value));
|
||||||
|
}
|
||||||
|
else if (G_IS_PARAM_SPEC_INT (pspec)) {
|
||||||
|
int *member = &G_STRUCT_MEMBER (int, object,
|
||||||
|
argument_class->offset);
|
||||||
|
|
||||||
|
*member = g_value_get_int (value);
|
||||||
|
}
|
||||||
|
else if (G_IS_PARAM_SPEC_BOOLEAN (pspec)) {
|
||||||
|
gboolean *member = &G_STRUCT_MEMBER (gboolean, object,
|
||||||
|
argument_class->offset);
|
||||||
|
|
||||||
|
*member = g_value_get_boolean (value);
|
||||||
|
}
|
||||||
|
else if (G_IS_PARAM_SPEC_ENUM (pspec)) {
|
||||||
|
int *member = &G_STRUCT_MEMBER (int, object,
|
||||||
|
argument_class->offset);
|
||||||
|
|
||||||
|
*member = g_value_get_enum (value);
|
||||||
|
}
|
||||||
|
else if (G_IS_PARAM_SPEC_POINTER (pspec)) {
|
||||||
|
gpointer *member = &G_STRUCT_MEMBER (gpointer, object,
|
||||||
|
argument_class->offset);
|
||||||
|
|
||||||
|
*member = g_value_get_pointer (value);
|
||||||
|
}
|
||||||
|
else if (G_IS_PARAM_SPEC_BOXED (pspec)) {
|
||||||
|
gpointer *member = &G_STRUCT_MEMBER (gpointer, object,
|
||||||
|
argument_class->offset);
|
||||||
|
|
||||||
|
if (*member) {
|
||||||
|
g_boxed_free (G_PARAM_SPEC_VALUE_TYPE (pspec), *member);
|
||||||
|
*member = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy the boxed into our pointer (will use eg.
|
||||||
|
* vips__object_vector_dup ()).
|
||||||
|
*/
|
||||||
|
*member = g_value_dup_boxed (value);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
g_warning ("%s: '%s' has unimplemented type", G_STRLOC,
|
||||||
|
((VipsArgument *)argument_class)->pspec->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note that it's now been set.
|
||||||
|
*/
|
||||||
|
argument_instance->assigned = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
vips_object_get_property (GObject *gobject,
|
||||||
|
guint property_id, GValue *value, GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
VipsObject *object = VIPS_OBJECT (gobject);
|
||||||
|
VipsObjectClass *class = VIPS_OBJECT_GET_CLASS (gobject);
|
||||||
|
VipsArgumentClass *argument_class = (VipsArgumentClass *)
|
||||||
|
vips__argument_table_lookup (class->argument_table, pspec);
|
||||||
|
|
||||||
|
if (!argument_class) {
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject,
|
||||||
|
property_id, pspec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_assert (((VipsArgument *) argument_class)->pspec == pspec);
|
||||||
|
|
||||||
|
if (G_IS_PARAM_SPEC_STRING (pspec)) {
|
||||||
|
char *member = G_STRUCT_MEMBER (char *, object,
|
||||||
|
argument_class->offset);
|
||||||
|
|
||||||
|
g_value_set_string (value, member);
|
||||||
|
}
|
||||||
|
else if (G_IS_PARAM_SPEC_OBJECT (pspec)) {
|
||||||
|
GObject **member = &G_STRUCT_MEMBER (GObject *, object,
|
||||||
|
argument_class->offset);
|
||||||
|
|
||||||
|
g_value_set_object (value, *member);
|
||||||
|
}
|
||||||
|
else if (G_IS_PARAM_SPEC_INT (pspec)) {
|
||||||
|
int *member = &G_STRUCT_MEMBER (int, object,
|
||||||
|
argument_class->offset);
|
||||||
|
|
||||||
|
g_value_set_int (value, *member);
|
||||||
|
}
|
||||||
|
else if (G_IS_PARAM_SPEC_BOOLEAN (pspec)) {
|
||||||
|
gboolean *member = &G_STRUCT_MEMBER (gboolean, object,
|
||||||
|
argument_class->offset);
|
||||||
|
|
||||||
|
g_value_set_boolean (value, *member);
|
||||||
|
}
|
||||||
|
else if (G_IS_PARAM_SPEC_ENUM (pspec)) {
|
||||||
|
int *member = &G_STRUCT_MEMBER (int, object,
|
||||||
|
argument_class->offset);
|
||||||
|
|
||||||
|
g_value_set_enum (value, *member);
|
||||||
|
}
|
||||||
|
else if (G_IS_PARAM_SPEC_POINTER (pspec)) {
|
||||||
|
gpointer *member = &G_STRUCT_MEMBER (gpointer, object,
|
||||||
|
argument_class->offset);
|
||||||
|
|
||||||
|
g_value_set_pointer (value, *member);
|
||||||
|
}
|
||||||
|
else if (G_IS_PARAM_SPEC_BOXED (pspec)) {
|
||||||
|
gpointer *member = &G_STRUCT_MEMBER (gpointer, object,
|
||||||
|
argument_class->offset);
|
||||||
|
|
||||||
|
/* Copy the boxed into our pointer (will use eg.
|
||||||
|
* vips__object_vector_dup ()).
|
||||||
|
*/
|
||||||
|
g_value_set_boxed (value, *member);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
g_warning ("%s: unimplemented property type", G_STRLOC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
vips_object_real_changed( VipsObject *object )
|
vips_object_real_changed( VipsObject *object )
|
||||||
{
|
{
|
||||||
@ -163,6 +643,8 @@ vips_object_class_init( VipsObjectClass *class )
|
|||||||
|
|
||||||
gobject_class->dispose = vips_object_dispose;
|
gobject_class->dispose = vips_object_dispose;
|
||||||
gobject_class->finalize = vips_object_finalize;
|
gobject_class->finalize = vips_object_finalize;
|
||||||
|
gobject_class->set_property = vips_object_set_property;
|
||||||
|
gobject_class->get_property = vips_object_get_property;
|
||||||
|
|
||||||
class->changed = vips_object_real_changed;
|
class->changed = vips_object_real_changed;
|
||||||
class->print_class = vips_object_real_print_class;
|
class->print_class = vips_object_real_print_class;
|
||||||
@ -195,3 +677,64 @@ vips_object_set_name( VipsObject *object, const char *name )
|
|||||||
vips_object_changed( object );
|
vips_object_changed( object );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add a vipsargument ... automate some stuff with this.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
vips_object_class_install_argument (VipsObjectClass *object_class,
|
||||||
|
GParamSpec *pspec, VipsArgumentFlags flags, guint offset)
|
||||||
|
{
|
||||||
|
VipsArgumentClass *argument_class = g_new (VipsArgumentClass, 1);
|
||||||
|
|
||||||
|
/* Must be a new one.
|
||||||
|
*/
|
||||||
|
g_assert (!vips__argument_table_lookup (object_class->argument_table,
|
||||||
|
pspec));
|
||||||
|
|
||||||
|
/* Mustn't have INPUT and OUTPUT both set.
|
||||||
|
*/
|
||||||
|
g_assert ((flags & (VIPS_ARGUMENT_INPUT | VIPS_ARGUMENT_OUTPUT)) !=
|
||||||
|
(VIPS_ARGUMENT_INPUT | VIPS_ARGUMENT_OUTPUT));
|
||||||
|
|
||||||
|
((VipsArgument *) argument_class)->pspec = pspec;
|
||||||
|
argument_class->object_class = object_class;
|
||||||
|
argument_class->flags = flags;
|
||||||
|
argument_class->offset = offset;
|
||||||
|
|
||||||
|
vips_argument_table_replace (object_class->argument_table,
|
||||||
|
(VipsArgument *) argument_class);
|
||||||
|
object_class->argument_table_traverse = g_slist_append (
|
||||||
|
object_class->argument_table_traverse, argument_class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Has a property been set?
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
vips_object_argument_assigned (VipsObject *object, const char *property_name)
|
||||||
|
{
|
||||||
|
VipsObjectClass *object_class = VIPS_OBJECT_GET_CLASS (object);
|
||||||
|
GParamSpec *pspec;
|
||||||
|
VipsArgumentClass *argument_class;
|
||||||
|
VipsArgumentInstance *argument_instance;
|
||||||
|
|
||||||
|
if (!(pspec = g_object_class_find_property (
|
||||||
|
G_OBJECT_CLASS (object_class), property_name))) {
|
||||||
|
g_warning ("property %s not found", property_name);
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
if (!(argument_class = (VipsArgumentClass *)
|
||||||
|
vips__argument_table_lookup (object_class->argument_table,
|
||||||
|
pspec))) {
|
||||||
|
g_warning ("vips argument for property %s not found",
|
||||||
|
property_name);
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
if (!(argument_instance = vips__argument_get_instance (
|
||||||
|
argument_class, object))) {
|
||||||
|
g_warning ("properties for vips argument %s not found",
|
||||||
|
property_name);
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (argument_instance->assigned);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -128,6 +128,14 @@
|
|||||||
*/
|
*/
|
||||||
#define SMOOTH_SHARPENING_SCALE (0.453125f)
|
#define SMOOTH_SHARPENING_SCALE (0.453125f)
|
||||||
|
|
||||||
|
/* Properties.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
PROP_SHARPENING = 1,
|
||||||
|
PROP_LAST
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#define VIPS_TYPE_INTERPOLATE_YAFRSMOOTH \
|
#define VIPS_TYPE_INTERPOLATE_YAFRSMOOTH \
|
||||||
(vips_interpolate_yafrsmooth_get_type())
|
(vips_interpolate_yafrsmooth_get_type())
|
||||||
#define VIPS_INTERPOLATE_YAFRSMOOTH( obj ) \
|
#define VIPS_INTERPOLATE_YAFRSMOOTH( obj ) \
|
||||||
@ -740,10 +748,13 @@ vips_interpolate_yafrsmooth_interpolate( VipsInterpolate *interpolate,
|
|||||||
static void
|
static void
|
||||||
vips_interpolate_yafrsmooth_class_init( VipsInterpolateYafrsmoothClass *iclass )
|
vips_interpolate_yafrsmooth_class_init( VipsInterpolateYafrsmoothClass *iclass )
|
||||||
{
|
{
|
||||||
|
GObjectClass *gobject_class = G_OBJECT_CLASS( iclass );
|
||||||
VipsObjectClass *object_class = VIPS_OBJECT_CLASS( iclass );
|
VipsObjectClass *object_class = VIPS_OBJECT_CLASS( iclass );
|
||||||
VipsInterpolateClass *interpolate_class =
|
VipsInterpolateClass *interpolate_class =
|
||||||
VIPS_INTERPOLATE_CLASS( iclass );
|
VIPS_INTERPOLATE_CLASS( iclass );
|
||||||
|
|
||||||
|
GParamSpec *pspec;
|
||||||
|
|
||||||
object_class->nickname = "yafrsmooth";
|
object_class->nickname = "yafrsmooth";
|
||||||
object_class->description = _( "YAFR smooth interpolation" );
|
object_class->description = _( "YAFR smooth interpolation" );
|
||||||
|
|
||||||
@ -762,6 +773,19 @@ vips_interpolate_yafrsmooth_class_init( VipsInterpolateYafrsmoothClass *iclass )
|
|||||||
iclass->matrixi[x][i] =
|
iclass->matrixi[x][i] =
|
||||||
iclass->matrixf[x][i] * VIPS_INTERPOLATE_SCALE;
|
iclass->matrixf[x][i] * VIPS_INTERPOLATE_SCALE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Create properties.
|
||||||
|
*/
|
||||||
|
pspec = g_param_spec_double( "sharpening",
|
||||||
|
_( "Sharpening" ),
|
||||||
|
_( "Degree of extra edge enhancement" ),
|
||||||
|
0, 4, 1,
|
||||||
|
(GParamFlags) G_PARAM_READWRITE );
|
||||||
|
g_object_class_install_property( gobject_class,
|
||||||
|
PROP_SHARPENING, pspec );
|
||||||
|
vips_object_class_install_argument( object_class, pspec,
|
||||||
|
VIPS_ARGUMENT_SET_ONCE,
|
||||||
|
G_STRUCT_OFFSET( VipsInterpolateYafrsmooth, sharpening ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
Reference in New Issue
Block a user