don't ser im_error() on a failed callback

This commit is contained in:
John Cupitt 2008-11-26 20:56:13 +00:00
parent f1a5be924c
commit c5de67a542
9 changed files with 158 additions and 9 deletions

View File

@ -13,6 +13,7 @@
- yafr-smooth reworked along the lines of bicubic
- cleanups after yafr hacking
- added affinei_all
- don't set im_error() on failed callback
11/9/08 started 7.16.3
- oop typo in manpage for im_project()

42
TODO
View File

@ -1,5 +1,6 @@
- make a new package for "resample"? im_shrink & friends could go in there too
- started adding
#define IM_TYPE_GOBJECT "gobject" /* A GObject of a specified class */
or maybe "transform"? flip/rot90/embed etc. as well?
- make a "deprecated" package too
@ -9,11 +10,41 @@
- try walking the class hierarchy below VipsInterpolate and see if we can see
all the interpolators
classes need some extra fields
want bicubic args to be
nickname, eg. "bicubic"
caption, eg. "catmull-rom bicubic interpolation"
IM_GOBJECT( "VipsInterpolate", "interpolate" );
ie. pass a gobject which is a sub-type of VipsInterpolate in an arg called
"interpolate"
then we need to create an object of that class, get the param list, set from
any args, call object_init, and pass
on return, unref the object
so
im_affinei_all in.v out.v "yafrsmooth(2.4)" 0.9 0 0 0.9 0 0
creates a yafrsmooth, sets the param,
in nip2,
inter = g_object_new "VipsInterpolateBicubic" [$sharpness => 2.4];
also need something to return a list of GTypes below a name etc., find class
description:w
need k
- make a new package for "resample"? im_shrink & friends could go in there too
- how to expose things like yafrsmooth's "sharpening" parameter to
nip2/C++/Python?
can we write a find-by-nickname function? eg.
GType vips_get_type (const char *base, const char *nickname)
@ -54,9 +85,6 @@
- im_render should use a hash for tile lookup ... or+shift x/y together
- eval callbacks shouldn't set an errormsg? or maybe it should for debugging
and stuff
- bilinear should be a true subclass of interpolate ... and put the tables
into the base class

View File

@ -55,6 +55,7 @@ extern "C" {
#define IM_TYPE_IMAGE "image" /* IMAGE descriptor */
#define IM_TYPE_DISPLAY "display" /* Display descriptor */
#define IM_TYPE_GVALUE "gvalue" /* GValue wrapper */
#define IM_TYPE_GOBJECT "gobject" /* A GObject of a specified class */
typedef char *im_arg_type; /* Type of argument id */
/* Internal representation of an argument to an image processing function.

View File

@ -65,6 +65,15 @@ typedef struct _VipsObjectClass {
/* Try to print something about the object, handy for debugging.
*/
void (*print)( VipsObject *, im_buf_t * );
/* Class nickname, eg. "VipsInterpolateBicubic" has "bicubic" as a
* nickname. Not internationalised.
*/
const char *nickname;
/* Class description. Used for help messages, so internationalised.
*/
const char *description;
} VipsObjectClass;
void *vips_object_changed( VipsObject *vips_object );

View File

@ -300,6 +300,12 @@ void *im_map_equal( void *a, void *b );
void *im_hash_table_map( GHashTable *hash, VSListMap2Fn fn, void *a, void *b );
typedef void *(*VTypeMapFn)( GType, void * );
typedef void *(*VTypeMap2Fn)( GType, void *, void * );
void *im_type_map( GType base, VTypeMap2Fn fn, void *a, void *b );
void *im_type_map_concrete_all( GType base, VTypeMapFn fn, void *a );
GType im_type_find( const char *basename, const char *nickname );
char *im_strncpy( char *dest, const char *src, int n );
char *im_strrstr( const char *haystack, const char *needle );
char *im_strdup( IMAGE *im, const char *str );

View File

@ -9,6 +9,8 @@
* - now always calls all callbacks, even if some fail
* 2/7/08
* - added invalidate callbacks
* 26/11/08
* - don't set im_error() on callback failed, that's the user's job
*/
/*
@ -135,8 +137,9 @@ call_callback( VCallback *cbs, int *result )
int res;
if( (res = cbs->fn( cbs->a, cbs->b )) ) {
im_error( "im__trigger_callbacks", _( "user callback "
"failed for %s" ), cbs->im->filename );
/* We don't set im_error() here, that's the callback's
* responsibility.
*/
*result = res;
#ifdef DEBUG_IO

View File

@ -148,6 +148,8 @@ vips_object_class_init( VipsObjectClass *class )
class->changed = vips_object_real_changed;
class->print = vips_object_real_print;
class->nickname = "object";
class->description = _( "VIPS base class" );
vips_object_signals[SIG_CHANGED] = g_signal_new( "changed",
G_OBJECT_CLASS_TYPE( gobject_class ),

View File

@ -242,6 +242,101 @@ im_hash_table_map( GHashTable *hash, VSListMap2Fn fn, void *a, void *b )
return( pair.result );
}
/* Map over all a type's children.
*/
void *
im_type_map( GType base, VTypeMap2Fn fn, void *a, void *b )
{
GType *child;
guint n_children;
int i;
void *result;
child = g_type_children( base, &n_children );
result = NULL;
for( i = 0; i < n_children && !result; i++ )
result = fn( child[i], a, b );
g_free( child );
return( result );
}
/* Loop over all the concrete subtypes of a base type.
*/
void *
im_type_map_concrete_all( GType base, VTypeMapFn fn, void *a )
{
void *result;
result = NULL;
if( !G_TYPE_IS_ABSTRACT( base ) )
result = fn( base, a );
if( !result )
result = im_type_map( base,
(VTypeMap2Fn) im_type_map_concrete_all, fn, a );
return( result );
}
static GType
test_name( GType type, const char *nickname )
{
GTypeClass *class;
VipsObjectClass *vips_class;
/* Does this class exist? Try to create if not.
*/
if( !(class = g_type_class_peek( type )) )
/* We don't unref, so the class is never finalized. This will
* make the peek work next time around and save us from
* constantly building and destroying classes.
*/
if( !(class = g_type_class_ref( type )) )
return( 0 );
if( !VIPS_IS_OBJECT_CLASS( class ) )
return( 0 );
vips_class = VIPS_OBJECT_CLASS( class );
if( strcasecmp( vips_class->nickname, nickname ) != 0 )
return( 0 );
return( type );
}
/* Find a GType ... search below base, return the first match on a nickname or
* a name.
*/
GType
im_type_find( const char *basename, const char *nickname )
{
GType base;
GType type;
if( !(base = g_type_from_name( basename )) ) {
im_error( "im_type_find",
_( "base type \"%s\" not found" ), basename );
return( 0 );
}
/* Users can pass the real name instead of a nickname, provided the
* real name names a subclass of base.
*/
if( (type = g_type_from_name( nickname )) )
if( g_type_is_a( type, base ) )
return( type );
/* Nope, need to search.
*/
if( (type = (GType) im_type_map_concrete_all( base,
(VTypeMapFn) test_name, (void *) nickname )) )
return( type );
im_error( "im_type_find",
_( "type \"%s\" not found" ), nickname );
return( 0 );
}
/* Like strncpy(), but always NULL-terminate, and don't pad with NULLs.
*/
char *

View File

@ -380,12 +380,16 @@ vips_interpolate_bicubic_interpolate( VipsInterpolate *interpolate,
static void
vips_interpolate_bicubic_class_init( VipsInterpolateBicubicClass *iclass )
{
VipsObjectClass *object_class = VIPS_OBJECT_CLASS( iclass );
VipsInterpolateClass *interpolate_class =
VIPS_INTERPOLATE_CLASS( iclass );
vips_interpolate_bicubic_parent_class =
VIPS_INTERPOLATE_CLASS( g_type_class_peek_parent( iclass ) );
object_class->nickname = "bicubic";
object_class->description = _( "Bicubic interpolation (Catmull-Rom)" );
interpolate_class->interpolate = vips_interpolate_bicubic_interpolate;
interpolate_class->window_size = 4;