/* gegl-chant contains incantations to that produce the boilerplate
* needed to write GEGL operation plug-ins. It abstracts away inheritance
* by giving a limited amount of base classes, and reduced creation of
* a properties struct and registration of properties for that structure to
* a minimum amount of code through use of the C preprocessor. You should
* look at the operations implemented using chanting (they #include this file)
* to see how it is used in practice.
*
* GEGL is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* GEGL is distributed in the hope that it will be useful,
* 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with GEGL; if not, see .
*
* 2006-2008 © Øyvind Kolås.
*/
#ifdef GEGL_OP_C_SOURCE
#define __GEGL_HEADER(x) #x
#define _GEGL_HEADER(x) __GEGL_HEADER(x)
#define GEGL_HEADER(x) _GEGL_HEADER(x)
#define GEGL_OP_C_FILE GEGL_HEADER(GEGL_OP_C_SOURCE)
#endif
#ifndef GEGL_OP_NAME
#define GEGL_OP_NAME op
#error "define GEGL_OP_NAME"
#endif
#ifndef GEGL_OP_C_FILE
#ifdef GEGL_CHANT_C_FILE
#error GEGL_OP_C_FILE not defined, %s/GEGL_CHANT_C_FILE/GEGL_OP_C_FILE/
#endif
#error "GEGL_OP_C_FILE not defined"
#endif
/* XXX: */
#ifdef GEGL_CHANT_TYPE_POINT_RENDER
#error "GEGL_CHANT_TYPE_POINT_RENDER should be replaced with GEGL_OP_POINT_RENDER"
#endif
#ifdef GEGL_CHANT_PROPERTIES
#error "GEGL_CHANT_PROPERTIES should be replaced with GEGL_PROPERTIES"
#endif
#include
G_BEGIN_DECLS
typedef struct _GeglProperties GeglProperties;
typedef struct _GeglOp GeglOp;
static void gegl_op_init_properties (GeglOp *self);
static void gegl_op_class_intern_init (gpointer klass);
static gpointer gegl_op_parent_class = NULL;
#define define_register_type_(a) \
void gegl_op_##a##_register_type (GTypeModule *module);\
GType gegl_op_##a##_get_type (void);
#define define_register_type(a) define_register_type_(a)
define_register_type(GEGL_OP_NAME)
#undef define_register_type
#undef define_register_type_
#define GEGL_DEFINE_DYNAMIC_OPERATION_EXTENDED(C_FILE, TypeName, type_name, TYPE_PARENT, flags, CODE) \
static void type_name##_init (TypeName *self); \
static void gegl_op_class_init (TypeName##Class *klass); \
static void type_name##_class_finalize (TypeName##Class *klass); \
static GType type_name##_type_id = 0; \
static void type_name##_class_chant_intern_init (gpointer klass) \
{ \
gegl_op_parent_class = g_type_class_peek_parent (klass); \
gegl_op_class_intern_init (klass); \
gegl_op_class_init ((TypeName##Class*) klass); \
} \
GType \
type_name##_get_type (void) \
{ \
return type_name##_type_id; \
} \
void \
type_name##_register_type (GTypeModule *type_module) \
{ \
gchar tempname[256]; \
gchar *p; \
const GTypeInfo g_define_type_info = \
{ \
sizeof (TypeName##Class), \
(GBaseInitFunc) NULL, \
(GBaseFinalizeFunc) NULL, \
(GClassInitFunc) type_name##_class_chant_intern_init, \
(GClassFinalizeFunc) type_name##_class_finalize, \
NULL, /* class_data */ \
sizeof (TypeName), \
0, /* n_preallocs */ \
(GInstanceInitFunc) type_name##_init, \
NULL /* value_table */ \
}; \
g_snprintf (tempname, sizeof (tempname), \
"%s", #TypeName C_FILE); \
for (p = tempname; *p; p++) \
if (*p=='.') *p='_'; \
\
type_name##_type_id = g_type_module_register_type (type_module, \
TYPE_PARENT, \
tempname, \
&g_define_type_info, \
(GTypeFlags) flags); \
{ CODE ; } \
}
#define GEGL_DEFINE_DYNAMIC_OPERATION_(T_P, C_FILE, opname) GEGL_DEFINE_DYNAMIC_OPERATION_EXTENDED(C_FILE, GeglOp, gegl_op_##opname, T_P, 0, {})
#define GEGL_DEFINE_DYNAMIC_OPERATION__(a,b,c) GEGL_DEFINE_DYNAMIC_OPERATION_(a,b,c)
#define GEGL_DEFINE_DYNAMIC_OPERATION(T_P) GEGL_DEFINE_DYNAMIC_OPERATION__(T_P, GEGL_OP_C_FILE, GEGL_OP_NAME)
#define GEGL_PROPERTIES(op) ((GeglProperties *) (((GeglOp*)(op))->properties))
#define MKCLASS(a) MKCLASS2(a)
#define MKCLASS2(a) a##Class
#ifdef GEGL_OP_BASE
#define GEGL_OP_Parent GeglOperation
#define GEGL_OP_PARENT GEGL_TYPE_OPERATION
#endif
#ifdef GEGL_OP_POINT_FILTER
#define GEGL_OP_Parent GeglOperationPointFilter
#define GEGL_OP_PARENT GEGL_TYPE_OPERATION_POINT_FILTER
#endif
#ifdef GEGL_OP_POINT_COMPOSER
#define GEGL_OP_Parent GeglOperationPointComposer
#define GEGL_OP_PARENT GEGL_TYPE_OPERATION_POINT_COMPOSER
#endif
#ifdef GEGL_OP_POINT_COMPOSER3
#define GEGL_OP_Parent GeglOperationPointComposer3
#define GEGL_OP_PARENT GEGL_TYPE_OPERATION_POINT_COMPOSER3
#endif
#ifdef GEGL_OP_POINT_RENDER
#define GEGL_OP_Parent GeglOperationPointRender
#define GEGL_OP_PARENT GEGL_TYPE_OPERATION_POINT_RENDER
#endif
#ifdef GEGL_OP_AREA_FILTER
#define GEGL_OP_Parent GeglOperationAreaFilter
#define GEGL_OP_PARENT GEGL_TYPE_OPERATION_AREA_FILTER
#endif
#ifdef GEGL_OP_FILTER
#define GEGL_OP_Parent GeglOperationFilter
#define GEGL_OP_PARENT GEGL_TYPE_OPERATION_FILTER
#endif
#ifdef GEGL_OP_TEMPORAL
#define GEGL_OP_Parent GeglOperationTemporal
#define GEGL_OP_PARENT GEGL_TYPE_OPERATION_TEMPORAL
#endif
#ifdef GEGL_OP_SOURCE
#define GEGL_OP_Parent GeglOperationSource
#define GEGL_OP_PARENT GEGL_TYPE_OPERATION_SOURCE
#endif
#ifdef GEGL_OP_SINK
#define GEGL_OP_Parent GeglOperationSink
#define GEGL_OP_PARENT GEGL_TYPE_OPERATION_SINK
#endif
#ifdef GEGL_OP_COMPOSER
#define GEGL_OP_Parent GeglOperationComposer
#define GEGL_OP_PARENT GEGL_TYPE_OPERATION_COMPOSER
#endif
#ifdef GEGL_OP_COMPOSER3
#define GEGL_OP_Parent GeglOperationComposer3
#define GEGL_OP_PARENT GEGL_TYPE_OPERATION_COMPOSER3
#endif
#ifdef GEGL_OP_META
#include
#define GEGL_OP_Parent GeglOperationMeta
#define GEGL_OP_PARENT GEGL_TYPE_OPERATION_META
#endif
#ifdef GEGL_OP_Parent
struct _GeglOp
{
GEGL_OP_Parent parent_instance;
gpointer properties;
};
typedef struct
{
MKCLASS(GEGL_OP_Parent) parent_class;
} GeglOpClass;
GEGL_DEFINE_DYNAMIC_OPERATION(GEGL_OP_PARENT)
#else
//#error "no parent class specified"
#endif
#define GEGL_OP(obj) ((GeglOp*)(obj))
/* if GEGL_OP_CUSTOM is defined you have to provide the following
* code or your own implementation of it
*/
#ifndef GEGL_OP_CUSTOM
#define define_init_(a) \
static void gegl_op_##a##_init (GeglOp *self) { gegl_op_init_properties (self); }\
static void gegl_op_##a##_class_finalize (GeglOpClass *self) { }
#define define_init(a) define_init_(a)
define_init(GEGL_OP_NAME)
#undef define_init
#undef define_init_
static const GeglModuleInfo modinfo =
{
GEGL_MODULE_ABI_VERSION
};
/* prototypes added to silence warnings from gcc for -Wmissing-prototypes*/
gboolean gegl_module_register (GTypeModule *module);
const GeglModuleInfo * gegl_module_query (GTypeModule *module);
#ifndef GEGL_OP_BUNDLE
G_MODULE_EXPORT const GeglModuleInfo *
gegl_module_query (GTypeModule *module)
{
return &modinfo;
}
G_MODULE_EXPORT gboolean
gegl_module_register (GTypeModule *module)
{
#define do_reg_(a) gegl_op_##a##_register_type (module)
#define do_reg(b) do_reg_(b)
do_reg(GEGL_OP_NAME);
#undef do_reg
return TRUE;
}
#endif
#endif
#define description(blurb)
#define value_range(min,max)
#define ui_range(min,max)
#define ui_gamma(gamma)
#define ui_steps(small_increment, big_increment)
#define ui_meta(key,val)
#define ui_digits(digits)
#define ITEM(name,label,def_val, type)
#define ITEM2(name,label,def_val,type) ITEM(name,label,def_val,type)
/* enum registration */
#define property_double(name, label, def_val) ITEM(name,label,def_val,double)
#define property_int(name, label, def_val) ITEM(name,label,def_val,int)
#define property_string(name, label, def_val) ITEM(name,label,def_val,string)
#define property_file_path(name, label, def_val) ITEM(name,label,def_val,string)
#define property_uri(name, label, def_val) ITEM(name,label,def_val,string)
#define property_boolean(name, label, def_val) ITEM(name,label,def_val,boolean)
#define property_pointer(name, label, def_val) ITEM(name,label,def_val,pointer)
#define property_object(name, label, def_val) ITEM2(name,label,def_val,object)
#define property_enum(name, label, enm, enum_name, def_val) ITEM(name,label,def_val,pointer)
#define property_seed(name, label, rand_name) ITEM(name,label,def_val,uint)
#define property_format(name, label, def_val) ITEM(name,label,def_val,pointer)
#define property_curve(name, label, def_val) ITEM2(name,label,def_val,object)
#define property_path(name, label, def_val) ITEM2(name,label,def_val,object)
#define property_color(name, label, def_val) ITEM2(name,label,def_val,object)
#define property_audio_fragment(name, label, def_val) ITEM2(name,label,NULL,object)
#define enum_start(enum_name) typedef enum {
#define enum_value(value, nick, name) value ,
#define enum_value_skip(value) value ,
#define enum_end(enum) } enum ;
#include GEGL_OP_C_FILE
#undef enum_start
#undef enum_value
#undef enum_value_skip
#undef enum_end
#ifdef GETTEXT_PACKAGE
static const gchar *gegl_op_gettext_package G_GNUC_UNUSED = GETTEXT_PACKAGE;
#else
static const gchar *gegl_op_gettext_package G_GNUC_UNUSED = NULL;
#endif
#define enum_start(enum_name) \
static GType enum_name ## _get_type (void) G_GNUC_CONST; \
static GType enum_name ## _get_type (void) \
{ \
static GType etype = 0; \
if (etype == 0) { \
static GEnumValue values[] = {
#define enum_value(value, nick, name) \
{ value, name, nick },
#define enum_value_skip(value)
#define enum_end(enum) \
{ 0, NULL, NULL } \
}; \
if (gegl_op_gettext_package) \
{ \
guint i; \
for (i = 0; i < G_N_ELEMENTS (values); i++) \
if (values[i].value_name) \
values[i].value_name = \
dgettext (GETTEXT_PACKAGE, values[i].value_name); \
} \
etype = g_enum_register_static (#enum, values); \
} \
return etype; \
}
#include GEGL_OP_C_FILE
#undef property_double
#undef property_int
#undef property_string
#undef property_boolean
#undef property_file_path
#undef property_uri
#undef property_object
#undef property_pointer
#undef property_format
#undef property_enum
#undef property_seed
#undef property_curve
#undef property_color
#undef property_audio_fragment
#undef property_path
#undef enum_start
#undef enum_value
#undef enum_value_skip
#undef enum_end
#define enum_start(enum_name)
#define enum_value(value, nick, name)
#define enum_value_skip(value)
#define enum_end(enum)
/* Properties */
struct _GeglProperties
{
gpointer user_data; /* for use by the op implementation */
#define property_double(name, label, def_val) gdouble name;
#define property_int(name, label, def_val) gint name;
#define property_string(name, label, def_val) gchar *name;
#define property_boolean(name, label, def_val) gboolean name;
#define property_file_path(name, label, def_val) gchar *name;
#define property_uri(name, label, def_val) gchar *name;
#define property_object(name, label, def_val) GObject *name;
#define property_curve(name, label, def_val) GeglCurve *name;
#define property_color(name, label, def_val) GeglColor *name;
#define property_audio_fragment(name, label, def_val) GeglAudioFragment *name;
#define property_path(name, label, def_val) GeglPath *name; gulong path_changed_handler;
#define property_pointer(name, label, def_val) gpointer name;
#define property_format(name, label, def_val) gpointer name;
#define property_enum(name, label, enum, enum_name, def_val) enum name;
#define property_seed(name, label, rand_name) guint name;\
GeglRandom *rand_name;
#include GEGL_OP_C_FILE
#undef property_double
#undef property_int
#undef property_string
#undef property_boolean
#undef property_file_path
#undef property_uri
#undef property_object
#undef property_pointer
#undef property_format
#undef property_enum
#undef property_seed
#undef property_curve
#undef property_color
#undef property_audio_fragment
#undef property_path
};
#define GEGL_OP_OPERATION(obj) ((Operation*)(obj))
enum
{
PROP_0,
#undef ITEM
#define ITEM(name,label,def_val, type) PROP_##name,
#define ITEM2(name,label,def_val, type) ITEM(name,label,def_val,type)
#define property_double(name, label, def_val) ITEM(name,label,def_val,double)
#define property_int(name, label, def_val) ITEM(name,label,def_val,int)
#define property_string(name, label, def_val) ITEM(name,label,def_val,string)
#define property_file_path(name, label, def_val) ITEM(name,label,def_val,string)
#define property_uri(name, label, def_val) ITEM(name,label,def_val,string)
#define property_boolean(name, label, def_val) ITEM(name,label,def_val,boolean)
#define property_object(name, label, def_val) ITEM2(name,label,def_val,object)
#define property_curve(name, label, def_val) ITEM2(name,label,def_val,object)
#define property_color(name, label, def_val) ITEM2(name,label,def_val,object)
#define property_audio_fragment(name, label, def_val) ITEM2(name,label,def_val,object)
#define property_path(name, label, def_val) ITEM2(name,label,def_val,object)
#define property_pointer(name, label, def_val) ITEM(name,label,def_val,pointer)
#define property_format(name, label, def_val) ITEM(name,label,def_val,pointer)
#define property_enum(name, label, enm, enum_name, def_val) ITEM(name,label,def_val,enum)
#define property_seed(name, label, rand_name) ITEM(name,label,def_val,uint)
#include GEGL_OP_C_FILE
#undef ITEM
#define ITEM(name,label,def_val, type) \
case PROP_##name: \
g_value_set_##type (value, properties->name); \
break;
#define ITEM2(name,label,def_val, type) ITEM(name,label,def_val,type)
PROP_LAST
};
static void
get_property (GObject *gobject,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GeglProperties *properties;
properties = GEGL_PROPERTIES(gobject);
switch (property_id)
{
#include GEGL_OP_C_FILE
#undef property_double
#undef property_int
#undef property_string
#undef property_boolean
#undef property_file_path
#undef property_uri
#undef property_object
#undef property_pointer
#undef property_format
#undef property_enum
#undef property_seed
#undef property_curve
#undef property_color
#undef property_audio_fragment
#undef property_path
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
break;
}
if (properties) {}; /* silence gcc */
}
static void
set_property (GObject *gobject,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GeglProperties *properties;
properties = GEGL_PROPERTIES(gobject);
switch (property_id)
{
#define property_double(name, label, def_val) \
case PROP_##name: \
properties->name = g_value_get_double (value); \
break;
#define property_int(name, label, def_val) \
case PROP_##name: \
properties->name = g_value_get_int (value); \
break;
#define property_string(name, label, def_val) \
case PROP_##name: \
g_free (properties->name); \
properties->name = g_value_dup_string (value); \
break;
#define property_boolean(name, label, def_val) \
case PROP_##name: \
properties->name = g_value_get_boolean (value); \
break;
#define property_file_path(name, label, def_val) \
case PROP_##name: \
g_free (properties->name); \
properties->name = g_value_dup_string (value); \
break;
#define property_uri(name, label, def_val) \
case PROP_##name: \
g_free (properties->name); \
properties->name = g_value_dup_string (value); \
break;
#define property_object(name, label, def_val) \
case PROP_##name: \
g_clear_object (&properties->name); \
properties->name = G_OBJECT (g_value_dup_object (value)); \
break;
#define property_curve(name, label, def_val) \
case PROP_##name: \
g_clear_object (&properties->name); \
properties->name = GEGL_CURVE (g_value_dup_object (value)); \
break;
#define property_color(name, label, def_val) \
case PROP_##name: \
g_clear_object (&properties->name); \
properties->name = GEGL_COLOR (g_value_dup_object (value)); \
break;
#define property_audio_fragment(name, label, def_val) \
case PROP_##name: \
g_clear_object (&properties->name); \
properties->name = \
GEGL_AUDIO_FRAGMENT (g_value_dup_object (value)); \
break;
#define property_path(name, label, def_val) \
case PROP_##name: \
if (properties->name != NULL) \
{ \
if (properties->path_changed_handler) \
g_signal_handler_disconnect (G_OBJECT (properties->name), \
properties->path_changed_handler); \
properties->path_changed_handler = 0; \
g_object_unref (properties->name); \
} \
properties->name = GEGL_PATH (g_value_dup_object (value)); \
if (properties->name != NULL) \
{ \
properties->path_changed_handler = \
g_signal_connect (G_OBJECT (properties->name), "changed", \
G_CALLBACK(path_changed), gobject); \
} \
break;
#define property_pointer(name, label, def_val) \
case PROP_##name: \
properties->name = g_value_get_pointer (value); \
break;
#define property_format(name, label, def_val) \
case PROP_##name: \
properties->name = g_value_get_pointer (value); \
break;
#define property_enum(name, label, enum, enum_name, def_val) \
case PROP_##name: \
properties->name = (enum) g_value_get_enum (value); \
break;
#define property_seed(name, label, rand_name) \
case PROP_##name: \
properties->name = g_value_get_uint (value); \
if (!properties->rand_name) \
properties->rand_name = gegl_random_new_with_seed (properties->name);\
else \
gegl_random_set_seed (properties->rand_name, properties->name);\
break;
#include GEGL_OP_C_FILE
#undef property_double
#undef property_int
#undef property_string
#undef property_boolean
#undef property_file_path
#undef property_uri
#undef property_object
#undef property_pointer
#undef property_curve
#undef property_color
#undef property_audio_fragment
#undef property_path
#undef property_format
#undef property_enum
#undef property_seed
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, property_id, pspec);
break;
}
if (properties) {}; /* silence gcc */
}
static void gegl_op_destroy_notify (gpointer data)
{
GeglProperties *properties = GEGL_PROPERTIES (data);
#define property_double(name, label, def_val)
#define property_int(name, label, def_val)
#define property_string(name, label, ...) \
g_clear_pointer (&properties->name, g_free);
#define property_boolean(name, label, def_val)
#define property_file_path(name, label, def_val) \
g_clear_pointer (&properties->name, g_free);
#define property_uri(name, label, def_val) \
g_clear_pointer (&properties->name, g_free);
#define property_object(name, label, def_val) \
g_clear_object (&properties->name);
#define property_curve(name, label, def_val) \
g_clear_object (&properties->name);
#define property_color(name, label, def_val) \
g_clear_object (&properties->name);
#define property_audio_fragment(name, label, def_val) \
g_clear_object (&properties->name);
#define property_path(name, label, def_val) \
g_clear_object (&properties->name);
#define property_pointer(name, label, ...)
#define property_format(name, label, ...)
#define property_enum(name, label, ...)
#define property_seed(name, label, ...)
#include GEGL_OP_C_FILE
#undef property_double
#undef property_int
#undef property_string
#undef property_boolean
#undef property_file_path
#undef property_uri
#undef property_object
#undef property_pointer
#undef property_format
#undef property_enum
#undef property_seed
#undef property_curve
#undef property_color
#undef property_audio_fragment
#undef property_path
g_slice_free (GeglProperties, properties);
}
static GObject *
gegl_op_constructor (GType type,
guint n_construct_properties,
GObjectConstructParam *construct_properties)
{
GObject *obj;
GeglProperties *properties;
obj = G_OBJECT_CLASS (gegl_op_parent_class)->constructor (
type, n_construct_properties, construct_properties);
/* create dummy colors and vectors */
properties = GEGL_PROPERTIES (obj);
#define property_double(name, label, def_val)
#define property_int(name, label, def_val)
#define property_string(name, label, def_val)
#define property_boolean(name, label, def_val)
#define property_file_path(name, label, def_val)
#define property_uri(name, label, def_val)
#define property_object(name, label, def_val)
#define property_pointer(name, label, def_val)
#define property_format(name, label, def_val)
#define property_curve(name, label, def_val)
#define property_audio_fragment(name, label, def_val)\
if (properties->name == NULL) \
{properties->name = gegl_audio_fragment_new(48000, 2, 0, 8192);}
#define property_color(name, label, def_val)\
if (properties->name == NULL) \
{properties->name = gegl_color_new(def_val?def_val:"black");}
#define property_path(name, label, def_val)
#define property_enum(name, ...)
#define property_seed(name, label, rand_name) \
if (properties->rand_name == NULL) \
{properties->rand_name = gegl_random_new_with_seed (0);}
#include GEGL_OP_C_FILE
#undef property_double
#undef property_int
#undef property_string
#undef property_boolean
#undef property_file_path
#undef property_uri
#undef property_object
#undef property_pointer
#undef property_format
#undef property_enum
#undef property_seed
#undef property_curve
#undef property_color
#undef property_audio_fragment
#undef property_path
g_object_set_data_full (obj, "chant-data", obj, gegl_op_destroy_notify);
properties ++; /* evil hack to silence gcc */
return obj;
}
static gboolean has_key (GParamSpec *pspec,
const gchar *key,
const gchar *value)
{
const char *set_value = gegl_param_spec_get_property_key (pspec, key);
if (set_value && g_str_equal (value, set_value))
return TRUE;
return FALSE;
}
static void
param_spec_update_ui (GParamSpec *pspec,
gboolean ui_range_set,
gboolean ui_steps_set,
gboolean ui_digits_set)
{
if (GEGL_IS_PARAM_SPEC_DOUBLE (pspec))
{
GeglParamSpecDouble *upspec = GEGL_PARAM_SPEC_DOUBLE (pspec);
GParamSpecDouble *vpspec = G_PARAM_SPEC_DOUBLE (pspec);
if (!ui_steps_set)
{
if (!ui_range_set)
{
upspec->ui_maximum = vpspec->maximum;
upspec->ui_minimum = vpspec->minimum;
}
if (has_key (pspec, "unit", "degree"))
{
upspec->ui_step_small = 1.0;
upspec->ui_step_big = 15.0;
}
else if (upspec->ui_maximum <= 5.0)
{
upspec->ui_step_small = 0.001;
upspec->ui_step_big = 0.100;
}
else if (upspec->ui_maximum <= 50)
{
upspec->ui_step_small = 0.01;
upspec->ui_step_big = 1.00;
}
else if (upspec->ui_maximum <= 500)
{
upspec->ui_step_small = 1.0;
upspec->ui_step_big = 10.0;
}
else if (upspec->ui_maximum <= 5000)
{
upspec->ui_step_small = 1.0;
upspec->ui_step_big = 100.0;
}
}
if (!ui_digits_set)
{
if (has_key (pspec, "unit", "degrees"))
{
upspec->ui_digits = 2;
}
else if (upspec->ui_maximum <= 5.0)
{
upspec->ui_digits = 4;
}
if (upspec->ui_maximum <= 50.0)
{
upspec->ui_digits = 3;
}
else if (upspec->ui_maximum <= 500)
{
upspec->ui_digits = 2;
}
else
{
upspec->ui_digits = 1;
}
}
}
else if (GEGL_IS_PARAM_SPEC_INT (pspec))
{
GeglParamSpecInt *upspec = GEGL_PARAM_SPEC_INT (pspec);
GParamSpecInt *vpspec = G_PARAM_SPEC_INT (pspec);
if (!ui_steps_set)
{
if (!ui_range_set)
{
upspec->ui_maximum = vpspec->maximum;
upspec->ui_minimum = vpspec->minimum;
}
if (upspec->ui_maximum <= 5)
{
upspec->ui_step_small = 1;
upspec->ui_step_big = 2;
}
else if (upspec->ui_maximum <= 50)
{
upspec->ui_step_small = 1;
upspec->ui_step_big = 5;
}
else if (upspec->ui_maximum <= 500)
{
upspec->ui_step_small = 1;
upspec->ui_step_big = 10;
}
else if (upspec->ui_maximum <= 5000)
{
upspec->ui_step_small = 1;
upspec->ui_step_big = 100;
}
}
}
}
static void
gegl_op_class_intern_init (gpointer klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
int current_prop = -1;
gboolean G_GNUC_UNUSED ui_range_set = FALSE;
gboolean G_GNUC_UNUSED ui_steps_set = FALSE;
gboolean G_GNUC_UNUSED ui_digits_set = FALSE;
GParamFlags flags G_GNUC_UNUSED = (GParamFlags)(G_PARAM_READWRITE | G_PARAM_CONSTRUCT | GEGL_PARAM_PAD_INPUT);
object_class->set_property = set_property;
object_class->get_property = get_property;
object_class->constructor = gegl_op_constructor;
{
GParamSpec *pspec = NULL;
#undef description
#undef value_range
#undef ui_range
#undef ui_steps
#undef ui_gamma
#undef ui_meta
#undef ui_digits
#define REGISTER_IF_ANY \
if (pspec && current_prop >=0) {\
param_spec_update_ui (pspec, ui_range_set, ui_steps_set, ui_digits_set);\
g_object_class_install_property (object_class, current_prop, pspec);\
pspec = NULL; current_prop = -1;\
ui_range_set = ui_steps_set = ui_digits_set = FALSE;\
}
#define description(blurb) \
pspec->_blurb = g_strdup (blurb);
#define value_range(min,max) \
vpspec->minimum = min; vpspec->maximum = max; \
upspec->ui_minimum = min; upspec->ui_maximum = max;
#define ui_range(min,max) \
upspec->ui_minimum = min; upspec->ui_maximum = max;\
ui_range_set = TRUE;
#define ui_steps(step_small,step_big) \
upspec->ui_step_small = step_small; upspec->ui_step_big = step_big; \
ui_steps_set = TRUE;
#define ui_gamma(gamma) \
upspec->ui_gamma = gamma;
#define ui_meta(key,val) \
gegl_param_spec_set_property_key(pspec, key, val);
#define ui_digits(digits) \
upspec->ui_digits = digits; \
ui_digits_set = TRUE;
#define property_double(name, label, def_val) \
REGISTER_IF_ANY \
}{ GParamSpec *pspec = \
gegl_param_spec_double (#name, label, NULL,-G_MAXDOUBLE,G_MAXDOUBLE,def_val,-100,100,1.0,flags);\
GeglParamSpecDouble *upspec G_GNUC_UNUSED = GEGL_PARAM_SPEC_DOUBLE (pspec);\
GParamSpecDouble *vpspec G_GNUC_UNUSED = G_PARAM_SPEC_DOUBLE (pspec);\
current_prop = PROP_##name ;
#define property_int(name, label, def_val) \
REGISTER_IF_ANY \
}{ GParamSpec *pspec = \
gegl_param_spec_int (#name, label, NULL,G_MININT,G_MAXINT,def_val,-100,100,1.0,flags);\
GeglParamSpecInt *upspec G_GNUC_UNUSED = GEGL_PARAM_SPEC_INT (pspec);\
GParamSpecInt *vpspec G_GNUC_UNUSED = G_PARAM_SPEC_INT (pspec);\
current_prop = PROP_##name ;
#define property_string(name, label, def_val) \
REGISTER_IF_ANY \
}{ GParamSpec *pspec = \
g_param_spec_string (#name, label, NULL, def_val, flags);\
current_prop = PROP_##name ;
#define property_boolean(name, label, def_val) \
REGISTER_IF_ANY \
}{ GParamSpec *pspec = \
g_param_spec_boolean (#name, label, NULL, def_val, flags);\
current_prop = PROP_##name ;
#define property_file_path(name, label, def_val) \
REGISTER_IF_ANY \
}{ GParamSpec *pspec = \
gegl_param_spec_file_path (#name, label, NULL, FALSE, FALSE, def_val, flags);\
current_prop = PROP_##name ;
#define property_uri(name, label, def_val) \
REGISTER_IF_ANY \
}{ GParamSpec *pspec = \
gegl_param_spec_uri (#name, label, NULL, FALSE, FALSE, def_val, flags);\
current_prop = PROP_##name ;
#define property_object(name, label, type) \
REGISTER_IF_ANY \
}{ GParamSpec *pspec = \
g_param_spec_object (#name, label, NULL, type, flags);\
current_prop = PROP_##name ;
#define property_curve(name, label, def_val) \
REGISTER_IF_ANY \
}{ GeglCurve *_gegl_op_default_curve = gegl_curve_new_default (); \
GParamSpec *pspec = \
gegl_param_spec_curve (#name, label, NULL, _gegl_op_default_curve, flags);\
current_prop = PROP_##name ;\
g_object_unref (_gegl_op_default_curve);\
#define property_color(name, label, def_val) \
REGISTER_IF_ANY \
}{ GParamSpec *pspec = \
gegl_param_spec_color_from_string (#name, label, NULL, def_val, flags);\
current_prop = PROP_##name ;
#define property_audio_fragment(name, label, def_val) \
REGISTER_IF_ANY \
}{ GParamSpec *pspec = \
gegl_param_spec_audio_fragment (#name, label, NULL, flags);\
current_prop = PROP_##name ;
#define property_path(name, label, def_val) \
REGISTER_IF_ANY \
}{ GParamSpec *pspec = \
gegl_param_spec_path (#name, label, NULL, def_val, flags);\
current_prop = PROP_##name ;
#define property_pointer(name, label, def_val) \
REGISTER_IF_ANY \
}{ GParamSpec *pspec = \
g_param_spec_pointer (#name, label, NULL, flags);\
current_prop = PROP_##name ;
#define property_format(name, label, def_val) \
REGISTER_IF_ANY \
}{ GParamSpec *pspec = \
gegl_param_spec_format (#name, label, NULL, flags);\
current_prop = PROP_##name ;
#define property_enum(name, label, enum, enum_name, def_val) \
REGISTER_IF_ANY \
}{ GParamSpec *pspec = gegl_param_spec_enum (#name, label, NULL, enum_name ##_get_type(), def_val, flags); \
current_prop = PROP_##name ;
#define property_seed(name, label, rand_name) \
REGISTER_IF_ANY \
}{ GParamSpec *pspec = gegl_param_spec_seed (#name, label, NULL, flags); \
current_prop = PROP_##name ;
#include GEGL_OP_C_FILE
REGISTER_IF_ANY
}
#undef REGISTER_IF_ANY
#undef description
#undef value_range
#undef ui_range
#undef ui_steps
#undef ui_gamma
#undef ui_meta
#undef property_double
#undef property_int
#undef property_string
#undef property_enum
#undef property_seed
#undef property_pointer
#undef property_path
#undef property_curve
#undef property_color
#undef property_audio_fragment
#undef property_object
#undef property_format
}
static void
gegl_op_init_properties (GeglOp *self)
{
self->properties = g_slice_new0 (GeglProperties);
}
G_END_DECLS