diff --git a/ChangeLog b/ChangeLog index b786809a0..6040d2663 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2008-04-17 Emmanuele Bassi + + * clutter/clutter-fixed.[ch]: Add a ClutterFixed fundamental + type, and wrappers for storing it into GValues; also add a + GParamSpec subclass for defining parameters holding + ClutterFixed values. This allows creating GObject properties + using fixed point values. + + * doc/reference/clutter-sections.txt: Document the newly + added API. + 2008-04-17 Emmanuele Bassi * clutter/Makefile.am: Add clutter-units.c diff --git a/clutter/clutter-fixed.c b/clutter/clutter-fixed.c index cf0964e9a..b92d4e25e 100644 --- a/clutter/clutter-fixed.c +++ b/clutter/clutter-fixed.c @@ -27,6 +27,9 @@ #include "config.h" #endif +#include +#include + #include "clutter-fixed.h" #include "clutter-private.h" @@ -972,3 +975,229 @@ clutter_powx (guint x, ClutterFixed y) return clutter_pow2x (CFX_MUL (y, clutter_log2x (x))); } +static GTypeInfo _info = { + 0, + NULL, + NULL, + NULL, + NULL, + NULL, + 0, + 0, + NULL, + NULL, +}; + +static GTypeFundamentalInfo _finfo = { 0, }; + +static void +clutter_value_init_fixed (GValue *value) +{ + value->data[0].v_int = 0; +} + +static void +clutter_value_copy_fixed (const GValue *src, + GValue *dest) +{ + dest->data[0].v_int = src->data[0].v_int; +} + +static gchar * +clutter_value_collect_fixed (GValue *value, + guint n_collect_values, + GTypeCValue *collect_values, + guint collect_flags) +{ + value->data[0].v_int = collect_values[0].v_int; + + return NULL; +} + +static gchar * +clutter_value_lcopy_fixed (const GValue *value, + guint n_collect_values, + GTypeCValue *collect_values, + guint collect_flags) +{ + gint32 *fixed_p = collect_values[0].v_pointer; + + if (!fixed_p) + return g_strdup_printf ("value location for `%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); + + *fixed_p = value->data[0].v_int; + + return NULL; +} + +static const GTypeValueTable _clutter_fixed_value_table = { + clutter_value_init_fixed, + NULL, + clutter_value_copy_fixed, + NULL, + "i", + clutter_value_collect_fixed, + "p", + clutter_value_lcopy_fixed +}; + +GType +clutter_fixed_get_type (void) +{ + static GType _clutter_fixed_type = 0; + + if (G_UNLIKELY (_clutter_fixed_type == 0)) + { + _info.value_table = & _clutter_fixed_value_table; + _clutter_fixed_type = + g_type_register_fundamental (g_type_fundamental_next (), + I_("ClutterFixed"), + &_info, &_finfo, 0); + } + + return _clutter_fixed_type; +} + +/** + * clutter_value_set_fixed: + * @value: a #GValue initialized to #CLUTTER_TYPE_FIXED + * @fixed_: the fixed point value to set + * + * Sets @value to @fixed_. + * + * Since: 0.8 + */ +void +clutter_value_set_fixed (GValue *value, + ClutterFixed fixed_) +{ + g_return_if_fail (CLUTTER_VALUE_HOLDS_FIXED (value)); + + value->data[0].v_int = fixed_; +} + +/** + * clutter_value_get_fixed: + * @value: a #GValue initialized to #CLUTTER_TYPE_FIXED + * + * Gets the fixed point value stored inside @value. + * + * Return value: the value inside the passed #GValue + * + * Since: 0.8 + */ +ClutterFixed +cluttter_value_get_fixed (const GValue *value) +{ + g_return_val_if_fail (CLUTTER_VALUE_HOLDS_FIXED (value), 0); + + return value->data[0].v_int; +} + +static void +param_fixed_init (GParamSpec *pspec) +{ + ClutterParamSpecFixed *fspec = CLUTTER_PARAM_SPEC_FIXED (pspec); + + fspec->minimum = -G_MAXINT32; + fspec->maximum = G_MAXINT32; + fspec->default_value = 0; +} + +static void +param_fixed_set_default (GParamSpec *pspec, + GValue *value) +{ + value->data[0].v_int = CLUTTER_PARAM_SPEC_FIXED (pspec)->default_value; +} + +static gboolean +param_fixed_validate (GParamSpec *pspec, + GValue *value) +{ + ClutterParamSpecFixed *fspec = CLUTTER_PARAM_SPEC_FIXED (pspec); + gint oval = value->data[0].v_int; + + value->data[0].v_int = CLAMP (value->data[0].v_int, + fspec->minimum, + fspec->maximum); + + return value->data[0].v_int != oval; +} + +static gint +param_fixed_values_cmp (GParamSpec *pspec, + const GValue *value1, + const GValue *value2) +{ + if (value1->data[0].v_int < value2->data[0].v_int) + return -1; + else + return value1->data[0].v_int > value2->data[0].v_int; +} + +GType +clutter_param_fixed_get_type (void) +{ + static GType pspec_type = 0; + + if (G_UNLIKELY (pspec_type == 0)) + { + const GParamSpecTypeInfo pspec_info = { + sizeof (ClutterParamSpecFixed), + 16, + param_fixed_init, + CLUTTER_TYPE_FIXED, + NULL, + param_fixed_set_default, + param_fixed_validate, + param_fixed_values_cmp, + }; + + pspec_type = g_param_type_register_static (I_("ClutterParamSpecFixed"), + &pspec_info); + } + + return pspec_type; +} + +/** + * clutter_param_spec_fixed: + * @name: name of the property + * @nick: short name + * @blurb: description (can be translatable) + * @minimum: lower boundary + * @maximum: higher boundary + * @default_value: default value + * @flags: flags for the param spec + * + * Creates a #GParamSpec for properties using #ClutterFixed values + * + * Return value: the newly created #GParamSpec + * + * Since: 0.8 + */ +GParamSpec * +clutter_param_spec_fixed (const gchar *name, + const gchar *nick, + const gchar *blurb, + ClutterUnit minimum, + ClutterUnit maximum, + ClutterUnit default_value, + GParamFlags flags) +{ + ClutterParamSpecFixed *fspec; + + g_return_val_if_fail (default_value >= minimum && default_value <= maximum, + NULL); + + fspec = g_param_spec_internal (CLUTTER_TYPE_PARAM_FIXED, + name, nick, blurb, + flags); + fspec->minimum = minimum; + fspec->maximum = maximum; + fspec->default_value = default_value; + + return G_PARAM_SPEC (fspec); +} diff --git a/clutter/clutter-fixed.h b/clutter/clutter-fixed.h index 2e5c14d01..e91d19dcb 100644 --- a/clutter/clutter-fixed.h +++ b/clutter/clutter-fixed.h @@ -27,7 +27,7 @@ #ifndef _HAVE_CLUTTER_FIXED_H #define _HAVE_CLUTTER_FIXED_H -#include +#include G_BEGIN_DECLS @@ -372,6 +372,59 @@ ClutterFixed clutter_log2x (guint x); guint clutter_pow2x (ClutterFixed x); guint clutter_powx (guint x, ClutterFixed y); +#define CLUTTER_TYPE_FIXED (clutter_fixed_get_type ()) +#define CLUTTER_TYPE_PARAM_FIXED (clutter_param_fixed_get_type ()) +#define CLUTTER_PARAM_SPEC_FIXED(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), CLUTTER_TYPE_PARAM_FIXED, ClutterParamSpecFixed)) +#define CLUTTER_IS_PARAM_SPEC_FIXED(pspec) (G_TYPE_CHECK_INSTANCE_TYPE ((pspec), CLUTTER_TYPE_PARAM_FIXED)) + +/** + * CLUTTER_VALUE_HOLDS_FIXED: + * @x: a #GValue + * + * Evaluates to %TRUE if @x holds a #ClutterFixed. + * + * Since: 0.8 + */ +#define CLUTTER_VALUE_HOLDS_FIXED(x) (G_VALUE_HOLDS ((x), CLUTTER_TYPE_FIXED)) + +typedef struct _ClutterParamSpecFixed ClutterParamSpecFixed; + +/** + * ClutterParamSpecFixed + * @minimum: lower boundary + * @maximum: higher boundary + * @default_value: default value + * + * #GParamSpec subclass for fixed point based properties + * + * Since: 0.8 + */ +struct _ClutterParamSpecFixed +{ + /*< private >*/ + GParamSpec parent_instance; + + /*< public >*/ + ClutterFixed minimum; + ClutterFixed maximum; + ClutterFixed default_value; +}; + +GType clutter_fixed_get_type (void) G_GNUC_CONST; +GType clutter_param_fixed_get_type (void) G_GNUC_CONST; + +void clutter_value_set_fixed (GValue *value, + ClutterFixed fixed_); +ClutterFixed clutter_value_get_fixed (const GValue *value); + +GParamSpec * clutter_param_spec_fixed (const gchar *name, + const gchar *nick, + const gchar *blurb, + ClutterFixed minimum, + ClutterFixed maximum, + ClutterFixed default_value, + GParamFlags flags); + /* */ extern ClutterFixed clutter_double_to_fixed (double value); extern gint clutter_double_to_int (double value); diff --git a/doc/reference/clutter-sections.txt b/doc/reference/clutter-sections.txt index d2b2045d4..dabd822d9 100644 --- a/doc/reference/clutter-sections.txt +++ b/doc/reference/clutter-sections.txt @@ -872,12 +872,29 @@ clutter_qmulx clutter_qdivx clutter_tani + +CLUTTER_VALUE_HOLDS_FIXED +clutter_value_set_fixed +clutter_value_get_fixed + + +ClutterParamSpecFixed +clutter_param_spec_fixed + + +CLUTTER_PARAM_SPEC_FIXED +CLUTTER_IS_PARAM_SPEC_FIXED + CFX_DIV CFX_INT CFX_MUL CFX_QMUL CFX_QDIV +CLUTTER_TYPE_FIXED +CLUTTER_TYPE_PARAM_FIXED +clutter_fixed_get_type +clutter_param_fixed_get_type