*/
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
#define VIPS_OBJECT_H
extern “C” {
#endif /*__cplusplus*/
*/
#ifdef VIPS_DEBUG
#define VIPS_UNREF( X ) G_STMT_START { \
if( X ) { \
g_assert( G_OBJECT( X )->ref_count > 0 ); \
g_object_unref( X ); \
(X) = 0; \
} \
} G_STMT_END
#else /*!VIPS_DEBUG*/
#define VIPS_UNREF( X ) VIPS_FREEF( g_object_unref, (X) )
#endif /*VIPS_DEBUG*/
typedef struct _VipsObjectClass VipsObjectClass;
*/
VIPS_ARGUMENT_NONE = 0,
VIPS_ARGUMENT_REQUIRED = 1,
VIPS_ARGUMENT_CONSTRUCT = 2,
VIPS_ARGUMENT_SET_ONCE = 4,
VIPS_ARGUMENT_SET_ALWAYS = 8,
VIPS_ARGUMENT_INPUT = 16,
VIPS_ARGUMENT_OUTPUT = 32,
VIPS_ARGUMENT_DEPRECATED = 64,
VIPS_ARGUMENT_MODIFY = 128
} VipsArgumentFlags;
arithmetic operation
(VIPS_ARGUMENT_INPUT | \
VIPS_ARGUMENT_REQUIRED | \
VIPS_ARGUMENT_CONSTRUCT)
(VIPS_ARGUMENT_INPUT | \
VIPS_ARGUMENT_CONSTRUCT)
(VIPS_ARGUMENT_OUTPUT | \
VIPS_ARGUMENT_REQUIRED | \
VIPS_ARGUMENT_CONSTRUCT)
(VIPS_ARGUMENT_OUTPUT | \
VIPS_ARGUMENT_CONSTRUCT)
GParamSpec *pspec; \
\
pspec = g_param_spec_object( (NAME), (LONG), (DESC), \
VIPS_TYPE_IMAGE, \
(GParamFlags) (G_PARAM_READWRITE) ); \
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
}
GParamSpec *pspec; \
\
pspec = g_param_spec_object( (NAME), (LONG), (DESC), \
VIPS_TYPE_INTERPOLATE, \
(GParamFlags) (G_PARAM_READWRITE) ); \
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
}
FLAGS, OFFSET, VALUE ) { \
GParamSpec *pspec; \
\
pspec = g_param_spec_boolean( (NAME), (LONG), (DESC), \
(VALUE), \
(GParamFlags) (G_PARAM_READWRITE) ); \
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
}
FLAGS, OFFSET, MIN, MAX, VALUE ) { \
GParamSpec *pspec; \
\
pspec = g_param_spec_double( (NAME), (LONG), (DESC), \
(MIN), (MAX), (VALUE), \
(GParamFlags) (G_PARAM_READWRITE) );\
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
}
FLAGS, OFFSET, TYPE ) { \
GParamSpec *pspec; \
\
pspec = g_param_spec_boxed( (NAME), (LONG), (DESC), \
(TYPE), \
(GParamFlags) (G_PARAM_READWRITE) );\
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
}
FLAGS, OFFSET, MIN, MAX, VALUE ) { \
GParamSpec *pspec; \
\
pspec = g_param_spec_int( (NAME), (LONG), (DESC), \
(MIN), (MAX), (VALUE), \
(GParamFlags) (G_PARAM_READWRITE) );\
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
}
FLAGS, OFFSET, MIN, MAX, VALUE ) { \
GParamSpec *pspec; \
\
pspec = g_param_spec_uint64( (NAME), (LONG), (DESC), \
(MIN), (MAX), (VALUE), \
(GParamFlags) (G_PARAM_READWRITE) );\
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
}
FLAGS, OFFSET, TYPE, VALUE ) { \
GParamSpec *pspec; \
\
pspec = g_param_spec_enum( (NAME), (LONG), (DESC), \
(TYPE), (VALUE), \
(GParamFlags) (G_PARAM_READWRITE) );\
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
}
FLAGS, OFFSET, TYPE, VALUE ) { \
GParamSpec *pspec; \
\
pspec = g_param_spec_flags( (NAME), (LONG), (DESC), \
(TYPE), (VALUE), \
(GParamFlags) (G_PARAM_READWRITE) );\
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
}
VALUE ) { \
GParamSpec *pspec; \
\
pspec = g_param_spec_string( (NAME), (LONG), (DESC), \
(VALUE), \
(GParamFlags) (G_PARAM_READWRITE) ); \
g_object_class_install_property( G_OBJECT_CLASS( CLASS ), \
_vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
}
GParamSpec *pspec; \
\
pspec = g_param_spec_pointer( (NAME), (LONG), (DESC), \
(GParamFlags) (G_PARAM_READWRITE) ); \
g_object_class_install_property( gobject_class, \
_vips__argument_id++, pspec ); \
vips_object_class_install_argument( VIPS_OBJECT_CLASS( CLASS ), \
pspec, (VipsArgumentFlags) (FLAGS), (PRIORITY), (OFFSET) ); \
}
*/
typedef struct _VipsArgument {
GParamSpec *pspec; /* pspec for this argument */
} VipsArgument;
*/
typedef struct _VipsArgumentClass {
VipsArgument parent;
*/
VipsObjectClass *object_class;
int priority; /* Order args by this */
guint offset; /* G_STRUCT_OFFSET of member in object */
} VipsArgumentClass;
*/
typedef struct _VipsArgumentInstance {
VipsArgument parent;
*/
VipsArgumentClass *argument_class;
*/
VipsObject *object;
*/
gboolean assigned;
* here.
*/
gulong close_id;
* “invalidate” out. If we go, we need to disconnect.
*/
gulong invalidate_id;
} VipsArgumentInstance;
* pointer (ie. we assume pspecs are never shared, is this correct?)
*/
typedef GHashTable VipsArgumentTable;
GObject **member, GObject *argument );
typedef void *(*VipsArgumentMapFn)( VipsObject *object, GParamSpec *pspec,
VipsArgumentClass *argument_class,
VipsArgumentInstance *argument_instance, void *a, void *b );
void *vips_argument_map( VipsObject *object,
VipsArgumentMapFn fn, void *a, void *b );
typedef void *(*VipsArgumentClassMapFn)( VipsObjectClass *object_class,
GParamSpec *pspec,
VipsArgumentClass *argument_class, void *a, void *b );
void *vips_argument_class_map( VipsObjectClass *object_class,
VipsArgumentClassMapFn fn, void *a, void *b );
gboolean vips_argument_class_needsstring( VipsArgumentClass *argument_class );
int vips_object_get_argument( VipsObject *object, const char *name,
GParamSpec **pspec,
VipsArgumentClass **argument_class,
VipsArgumentInstance **argument_instance );
gboolean vips_object_argument_isset( VipsObject *object, const char *name );
VipsArgumentFlags vips_object_get_argument_flags( VipsObject *object,
const char *name );
int vips_object_get_argument_priority( VipsObject *object, const char *name );
* use vips_argument_map(), the preferred looper. Have the loop code as a
* macro as well for these odd cases.
*/
#define VIPS_ARGUMENT_FOR_ALL( OBJECT, PSPEC, ARG_CLASS, ARG_INSTANCE ) { \
VipsObjectClass *object_class = VIPS_OBJECT_GET_CLASS( OBJECT ); \
GSList *p; \
\
for( p = object_class->argument_table_traverse; p; p = p->next ) { \
VipsArgumentClass *ARG_CLASS = \
(VipsArgumentClass *) p->data; \
VipsArgument *argument = (VipsArgument *) argument_class; \
GParamSpec *PSPEC = argument->pspec; \
VipsArgumentInstance *ARG_INSTANCE __attribute__ ((unused)) = \
vips__argument_get_instance( argument_class, \
VIPS_OBJECT( OBJECT ) ); \
*
* Use something like this:
VipsArgumentClass *argument_class;
VipsArgumentInstance *argument_instance;
&pspec, &argument_class, &argument_instance ) )
return( -1 );
something with it
*/
#define VIPS_ARGUMENT_COLLECT_SET( PSPEC, ARG_CLASS, AP ) \
if( (ARG_CLASS->flags & VIPS_ARGUMENT_INPUT) ) { \
GValue value = { 0, }; \
gchar *error = NULL; \
\
/* Input args are given inline, eg. (“factor”, 12.0) \
* and must be collected. \
*/ \
g_value_init( &value, G_PARAM_SPEC_VALUE_TYPE( PSPEC ) ); \
G_VALUE_COLLECT( &value, AP, 0, &error ); \
\
/* Don’t bother with the error message. \
*/ \
if( error ) { \
VIPS_DEBUG_MSG( “VIPS_OBJECT_COLLECT_SET: err\n” ); \
g_free( error ); \
}
g_value_unset( &value ); \
} \
else if( (ARG_CLASS->flags & VIPS_ARGUMENT_OUTPUT) ) { \
void **arg __attribute__ ((unused)); \
\
/* Output args are a pointer to where to send the \
* result. \
*/ \
arg = va_arg( AP, void ** );
}
#define VIPS_OBJECT( obj ) \
(G_TYPE_CHECK_INSTANCE_CAST( (obj), VIPS_TYPE_OBJECT, VipsObject ))
#define VIPS_OBJECT_CLASS( klass ) \
(G_TYPE_CHECK_CLASS_CAST( (klass), VIPS_TYPE_OBJECT, VipsObjectClass))
#define VIPS_IS_OBJECT( obj ) \
(G_TYPE_CHECK_INSTANCE_TYPE( (obj), VIPS_TYPE_OBJECT ))
#define VIPS_IS_OBJECT_CLASS( klass ) \
(G_TYPE_CHECK_CLASS_TYPE( (klass), VIPS_TYPE_OBJECT ))
#define VIPS_OBJECT_GET_CLASS( obj ) \
(G_TYPE_INSTANCE_GET_CLASS( (obj), VIPS_TYPE_OBJECT, VipsObjectClass ))
GObject parent_instance;
* and checked.
*/
gboolean constructed;
* freed. These objects are ommitted from leak reports.
*/
gboolean static_object;
*/
VipsArgumentTable *argument_table;
* get at them easily via the property system.
*/
char *nickname;
char *description;
*/
gboolean preclose;
gboolean close;
gboolean postclose;
* profiling.
*/
size_t local_memory;
GObjectClass parent_class;
* now build the thing.
*/
int (*build)( VipsObject *object );
*/
int (*postbuild)( VipsObject *object );
* Keep to one line.
*/
void (*summary_class)( struct _VipsObjectClass *cls, VipsBuf *buf );
* this output via things like “header fred.tif”, –vips-cache-trace,
* etc.
*/
void (*summary)( VipsObject *object, VipsBuf *buf );
*/
void (*dump)( VipsObject *object, VipsBuf *buf );
* Handy for debugging.
*/
void (*sanity)( VipsObject *object, VipsBuf *buf );
* dispose().
*/
void (*rewind)( VipsObject *object );
*/
void (*preclose)( VipsObject *object );
*/
void (*close)( VipsObject *object );
* Useful for eg. deleting the file associated with a temp image.
*/
void (*postclose)( VipsObject *object );
* for your object.
*/
* object. Just do the g_object_new(), don’t call _build().
*
* Don’t call this directly, see vips_object_new_from_string().
*/
VipsObject *(*new_from_string)( const char *string );
* would have been given to make that object.
*/
void (*to_string)( VipsObject *object, VipsBuf *buf );
* output, for example, needs a filename to write to.
*/
gboolean output_needs_arg;
* error, setting vips_error(). string is NULL if output_needs_arg()
* was FALSE.
*/
int (*output_to_arg)( VipsObject *object, const char *string );
* nickname. Not internationalised.
*/
const char *nickname;
*/
const char *description;
*
* This records the VipsArgumentClass for every pspec used in
* VipsObject and any subclass (ie. everywhere), so it’s huge. Don’t
* loop over this hash! Fine for lookups though.
*/
VipsArgumentTable *argument_table;
* and any superclasses. This is small and specific to this class.
*
* Use the stored GType to work out when to restart the list for a
* subclass.
*/
GSList *argument_table_traverse;
GType argument_table_traverse_gtype;
*
* VipsOperation has a deprecated flag, use that in preference to this
* if you can.
*/
gboolean deprecated;
*/
void (*_vips_reserved1)( void );
void (*_vips_reserved2)( void );
void (*_vips_reserved3)( void );
void (*_vips_reserved4)( void );
};
void vips_object_set_property( GObject *gobject,
guint property_id, const GValue *value, GParamSpec *pspec );
void vips_object_get_property( GObject *gobject,
guint property_id, GValue *value, GParamSpec *pspec );
int vips_object_build( VipsObject *object );
void vips_object_summary( VipsObject *object, VipsBuf *buf );
void vips_object_dump( VipsObject *object, VipsBuf *buf );
void vips_object_print_summary( VipsObject *object );
void vips_object_print_dump( VipsObject *object );
void vips_object_print_name( VipsObject *object );
*/
GType vips_object_get_type(void);
GParamSpec *pspec, VipsArgumentFlags flags,
int priority, guint offset );
int vips_object_set_argument_from_string( VipsObject *object,
const char *name, const char *value );
gboolean vips_object_argument_needsstring( VipsObject *object,
const char *name );
int vips_object_get_argument_to_string( VipsObject *object,
const char *name, const char *arg );
int vips_object_set_required( VipsObject *object, const char *value );
VipsObject *vips_object_new( GType type,
VipsObjectSetArguments set, void *a, void *b );
int vips_object_set( VipsObject *object, … )
__attribute__((sentinel));
int vips_object_set_from_string( VipsObject *object, const char *string );
const char *p );
void vips_object_to_string( VipsObject *object, VipsBuf *buf );
typedef void *(*VipsTypeMap2Fn)( GType type, void *a, void *b );
typedef void *(*VipsClassMapFn)( VipsObjectClass *cls, void *a );
void *vips_type_map( GType base, VipsTypeMap2Fn fn, void *a, void *b );
void *vips_type_map_all( GType base, VipsTypeMapFn fn, void *a );
int vips_type_depth( GType type );
GType vips_type_find( const char *basename, const char *nickname );
const char *vips_nickname_find( GType type );
const VipsObjectClass *vips_class_find( const char *basename,
const char *nickname );
#define vips_object_local( V, G ) \
(g_signal_connect( V, “close”, G_CALLBACK( vips_object_local_cb ), G ))
void vips_object_print_all( void );
void vips_object_sanity_all( void );
}
#endif /*__cplusplus*/