[clutter/wip/apocalypses/apocalypse-6: 1/17] interval: Add variadic arguments for initial/final setters
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [clutter/wip/apocalypses/apocalypse-6: 1/17] interval: Add variadic arguments for initial/final setters
- Date: Thu, 15 Mar 2012 17:02:11 +0000 (UTC)
commit beb91d76763b3b3aede1be1da8bc3c1f8184ed8a
Author: Emmanuele Bassi <ebassi linux intel com>
Date: Thu Mar 15 11:02:30 2012 +0000
interval: Add variadic arguments for initial/final setters
As a convenience for the C API.
Language bindings should already be using the GValue variants.
This commit also moves the custom progress functions out of the
clutter-interval.c, as they are meant to be generic interpolation
functions and not ClutterInterval-specific.
clutter/clutter-interval.c | 277 +++++++++++++++++++++-----------------------
clutter/clutter-interval.h | 33 +-----
clutter/clutter-private.h | 7 +
clutter/clutter-types.h | 28 +++++
clutter/clutter-util.c | 148 +++++++++++++++++++++++
5 files changed, 322 insertions(+), 171 deletions(-)
---
diff --git a/clutter/clutter-interval.c b/clutter/clutter-interval.c
index c151231..d0ccec0 100644
--- a/clutter/clutter-interval.c
+++ b/clutter/clutter-interval.c
@@ -63,14 +63,6 @@
#include "clutter-private.h"
#include "clutter-units.h"
-typedef struct
-{
- GType value_type;
- ClutterProgressFunc func;
-} ProgressData;
-
-static GHashTable *progress_funcs = NULL;
-
enum
{
PROP_0,
@@ -195,23 +187,15 @@ clutter_interval_real_compute_value (ClutterInterval *interval,
value_type = clutter_interval_get_value_type (interval);
- if (G_UNLIKELY (progress_funcs != NULL))
+ if (_clutter_has_progress_function (value_type))
{
- ProgressData *p_data;
-
- p_data =
- g_hash_table_lookup (progress_funcs, GUINT_TO_POINTER (value_type));
-
- /* if we have a progress function, and that function was
- * successful in computing the progress, then we bail out
- * as fast as we can
- */
- if (p_data != NULL)
- {
- retval = p_data->func (initial, final, factor, value);
- if (retval)
- return retval;
- }
+ retval = _clutter_run_progress_function (value_type,
+ initial,
+ final,
+ factor,
+ value);
+ if (retval)
+ return TRUE;
}
switch (G_TYPE_FUNDAMENTAL (value_type))
@@ -413,16 +397,44 @@ clutter_interval_init (ClutterInterval *self)
priv->values = g_malloc0 (sizeof (GValue) * N_VALUES);
}
-static void
-clutter_interval_set_interval_valist (ClutterInterval *interval,
- va_list var_args)
+static inline void
+clutter_interval_set_value_internal (ClutterInterval *interval,
+ gint index_,
+ const GValue *value)
+{
+ ClutterIntervalPrivate *priv = interval->priv;
+
+ g_assert (index_ >= INITIAL && index_ <= RESULT);
+
+ if (G_IS_VALUE (&priv->values[index_]))
+ g_value_unset (&priv->values[index_]);
+
+ g_value_init (&priv->values[index_], priv->value_type);
+ g_value_copy (value, &priv->values[index_]);
+}
+
+static inline void
+clutter_interval_get_value_internal (ClutterInterval *interval,
+ gint index_,
+ GValue *value)
+{
+ ClutterIntervalPrivate *priv = interval->priv;
+
+ g_assert (index_ >= INITIAL && index_ <= RESULT);
+
+ g_value_copy (&priv->values[index_], value);
+}
+
+static gboolean
+clutter_interval_set_initial_internal (ClutterInterval *interval,
+ va_list *args)
{
GType gtype = interval->priv->value_type;
GValue value = { 0, };
gchar *error;
/* initial value */
- G_VALUE_COLLECT_INIT (&value, gtype, var_args, 0, &error);
+ G_VALUE_COLLECT_INIT (&value, gtype, *args, 0, &error);
if (error)
{
@@ -433,26 +445,42 @@ clutter_interval_set_interval_valist (ClutterInterval *interval,
* undefined behaviour
*/
g_free (error);
- return;
+ return FALSE;
}
- clutter_interval_set_initial_value (interval, &value);
+ clutter_interval_set_value_internal (interval, INITIAL, &value);
g_value_unset (&value);
- /* final value */
- G_VALUE_COLLECT_INIT (&value, gtype, var_args, 0, &error);
+ return TRUE;
+}
+
+static gboolean
+clutter_interval_set_final_internal (ClutterInterval *interval,
+ va_list *args)
+{
+ GType gtype = interval->priv->value_type;
+ GValue value = { 0, };
+ gchar *error;
+
+ /* initial value */
+ G_VALUE_COLLECT_INIT (&value, gtype, *args, 0, &error);
if (error)
{
g_warning ("%s: %s", G_STRLOC, error);
- /* see above */
+ /* we leak the value here as it might not be in a valid state
+ * given the error and calling g_value_unset() might lead to
+ * undefined behaviour
+ */
g_free (error);
- return;
+ return FALSE;
}
- clutter_interval_set_final_value (interval, &value);
+ clutter_interval_set_value_internal (interval, FINAL, &value);
g_value_unset (&value);
+
+ return TRUE;
}
static void
@@ -524,7 +552,13 @@ clutter_interval_new (GType gtype,
retval = g_object_new (CLUTTER_TYPE_INTERVAL, "value-type", gtype, NULL);
va_start (args, gtype);
- clutter_interval_set_interval_valist (retval, args);
+
+ if (!clutter_interval_set_initial_internal (retval, &args))
+ goto out;
+
+ clutter_interval_set_final_internal (retval, &args);
+
+out:
va_end (args);
return retval;
@@ -616,34 +650,6 @@ clutter_interval_get_value_type (ClutterInterval *interval)
return interval->priv->value_type;
}
-static inline void
-clutter_interval_set_value_internal (ClutterInterval *interval,
- gint index_,
- const GValue *value)
-{
- ClutterIntervalPrivate *priv = interval->priv;
-
- g_assert (index_ >= INITIAL && index_ <= RESULT);
-
- if (G_IS_VALUE (&priv->values[index_]))
- g_value_unset (&priv->values[index_]);
-
- g_value_init (&priv->values[index_], priv->value_type);
- g_value_copy (value, &priv->values[index_]);
-}
-
-static inline void
-clutter_interval_get_value_internal (ClutterInterval *interval,
- gint index_,
- GValue *value)
-{
- ClutterIntervalPrivate *priv = interval->priv;
-
- g_assert (index_ >= INITIAL && index_ <= RESULT);
-
- g_value_copy (&priv->values[index_], value);
-}
-
/**
* clutter_interval_set_initial_value:
* @interval: a #ClutterInterval
@@ -652,6 +658,8 @@ clutter_interval_get_value_internal (ClutterInterval *interval,
* Sets the initial value of @interval to @value. The value is copied
* inside the #ClutterInterval.
*
+ * Rename to: clutter_interval_set_initial
+ *
* Since: 1.0
*/
void
@@ -671,6 +679,33 @@ clutter_interval_set_initial_value (ClutterInterval *interval,
}
/**
+ * clutter_interval_set_initial: (skip)
+ * @interval: a #ClutterInterval
+ * @...: the initial value of the interval.
+ *
+ * Variadic arguments version of clutter_interval_set_initial_value().
+ *
+ * This function is meant as a convenience for the C API.
+ *
+ * Language bindings should use clutter_interval_set_initial_value()
+ * instead.
+ *
+ * Since: 1.10
+ */
+void
+clutter_interval_set_initial (ClutterInterval *interval,
+ ...)
+{
+ va_list args;
+
+ g_return_if_fail (CLUTTER_IS_INTERVAL (interval));
+
+ va_start (args, interval);
+ clutter_interval_set_initial_internal (interval, &args);
+ va_end (args);
+}
+
+/**
* clutter_interval_get_initial_value:
* @interval: a #ClutterInterval
* @value: (out caller-allocates): a #GValue
@@ -721,6 +756,8 @@ clutter_interval_peek_initial_value (ClutterInterval *interval)
* Sets the final value of @interval to @value. The value is
* copied inside the #ClutterInterval.
*
+ * Rename to: clutter_interval_set_final
+ *
* Since: 1.0
*/
void
@@ -763,6 +800,32 @@ clutter_interval_get_final_value (ClutterInterval *interval,
}
/**
+ * clutter_interval_set_final: (skip)
+ * @interval: a #ClutterInterval
+ * @...: the final value of the interval
+ *
+ * Variadic arguments version of clutter_interval_set_final_value().
+ *
+ * This function is meant as a convenience for the C API.
+ *
+ * Language bindings should use clutter_interval_set_final_value() instead.
+ *
+ * Since: 1.10
+ */
+void
+clutter_interval_set_final (ClutterInterval *interval,
+ ...)
+{
+ va_list args;
+
+ g_return_if_fail (CLUTTER_IS_INTERVAL (interval));
+
+ va_start (args, interval);
+ clutter_interval_set_final_internal (interval, &args);
+ va_end (args);
+}
+
+/**
* clutter_interval_peek_final_value:
* @interval: a #ClutterInterval
*
@@ -812,7 +875,13 @@ clutter_interval_set_interval (ClutterInterval *interval,
g_return_if_fail (interval->priv->value_type != G_TYPE_INVALID);
va_start (args, interval);
- clutter_interval_set_interval_valist (interval, args);
+
+ if (!clutter_interval_set_initial_internal (interval, &args))
+ goto out;
+
+ clutter_interval_set_final_internal (interval, &args);
+
+out:
va_end (args);
}
@@ -941,81 +1010,3 @@ clutter_interval_compute (ClutterInterval *interval,
return NULL;
}
-
-/**
- * clutter_interval_register_progress_func: (skip)
- * @value_type: a #GType
- * @func: a #ClutterProgressFunc, or %NULL to unset a previously
- * set progress function
- *
- * Sets the progress function for a given @value_type, like:
- *
- * |[
- * clutter_interval_register_progress_func (MY_TYPE_FOO,
- * my_foo_progress);
- * ]|
- *
- * Whenever a #ClutterInterval instance using the default
- * #ClutterInterval::compute_value implementation is set as an
- * interval between two #GValue of type @value_type, it will call
- * @func to establish the value depending on the given progress,
- * for instance:
- *
- * |[
- * static gboolean
- * my_int_progress (const GValue *a,
- * const GValue *b,
- * gdouble progress,
- * GValue *retval)
- * {
- * gint ia = g_value_get_int (a);
- * gint ib = g_value_get_int (b);
- * gint res = factor * (ib - ia) + ia;
- *
- * g_value_set_int (retval, res);
- *
- * return TRUE;
- * }
- *
- * clutter_interval_register_progress_func (G_TYPE_INT, my_int_progress);
- * ]|
- *
- * To unset a previously set progress function of a #GType, pass %NULL
- * for @func.
- *
- * Since: 1.0
- */
-void
-clutter_interval_register_progress_func (GType value_type,
- ClutterProgressFunc func)
-{
- ProgressData *progress_func;
-
- g_return_if_fail (value_type != G_TYPE_INVALID);
-
- if (G_UNLIKELY (progress_funcs == NULL))
- progress_funcs = g_hash_table_new (NULL, NULL);
-
- progress_func =
- g_hash_table_lookup (progress_funcs, GUINT_TO_POINTER (value_type));
- if (G_UNLIKELY (progress_func))
- {
- if (func == NULL)
- {
- g_hash_table_remove (progress_funcs, GUINT_TO_POINTER (value_type));
- g_slice_free (ProgressData, progress_func);
- }
- else
- progress_func->func = func;
- }
- else
- {
- progress_func = g_slice_new (ProgressData);
- progress_func->value_type = value_type;
- progress_func->func = func;
-
- g_hash_table_replace (progress_funcs,
- GUINT_TO_POINTER (value_type),
- progress_func);
- }
-}
diff --git a/clutter/clutter-interval.h b/clutter/clutter-interval.h
index 44174f3..f845de9 100644
--- a/clutter/clutter-interval.h
+++ b/clutter/clutter-interval.h
@@ -44,34 +44,6 @@ typedef struct _ClutterIntervalPrivate ClutterIntervalPrivate;
typedef struct _ClutterIntervalClass ClutterIntervalClass;
/**
- * ClutterProgressFunc:
- * @a: the initial value of an interval
- * @b: the final value of an interval
- * @progress: the progress factor, between 0 and 1
- * @retval: the value used to store the progress
- *
- * Prototype of the progress function used to compute the value
- * between the two ends @a and @b of an interval depending on
- * the value of @progress.
- *
- * The #GValue in @retval is already initialized with the same
- * type as @a and @b.
- *
- * This function will be called by #ClutterInterval if the
- * type of the values of the interval was registered using
- * clutter_interval_register_progress_func().
- *
- * Return value: %TRUE if the function successfully computed
- * the value and stored it inside @retval
- *
- * Since: 1.0
- */
-typedef gboolean (* ClutterProgressFunc) (const GValue *a,
- const GValue *b,
- gdouble progress,
- GValue *retval);
-
-/**
* ClutterInterval:
*
* The #ClutterInterval structure contains only private data and should
@@ -131,11 +103,16 @@ ClutterInterval *clutter_interval_new_with_values (GType gtype,
ClutterInterval *clutter_interval_clone (ClutterInterval *interval);
GType clutter_interval_get_value_type (ClutterInterval *interval);
+
+void clutter_interval_set_initial (ClutterInterval *interval,
+ ...);
void clutter_interval_set_initial_value (ClutterInterval *interval,
const GValue *value);
void clutter_interval_get_initial_value (ClutterInterval *interval,
GValue *value);
GValue * clutter_interval_peek_initial_value (ClutterInterval *interval);
+void clutter_interval_set_final (ClutterInterval *interval,
+ ...);
void clutter_interval_set_final_value (ClutterInterval *interval,
const GValue *value);
void clutter_interval_get_final_value (ClutterInterval *interval,
diff --git a/clutter/clutter-private.h b/clutter/clutter-private.h
index 916ee73..bd099e9 100644
--- a/clutter/clutter-private.h
+++ b/clutter/clutter-private.h
@@ -265,6 +265,13 @@ typedef enum _ClutterCullResult
CLUTTER_CULL_RESULT_PARTIAL
} ClutterCullResult;
+gboolean _clutter_has_progress_function (GType gtype);
+gboolean _clutter_run_progress_function (GType gtype,
+ const GValue *initial,
+ const GValue *final,
+ gdouble progress,
+ GValue *retval);
+
G_END_DECLS
#endif /* __CLUTTER_PRIVATE_H__ */
diff --git a/clutter/clutter-types.h b/clutter/clutter-types.h
index d2b5fe2..fdc81fa 100644
--- a/clutter/clutter-types.h
+++ b/clutter/clutter-types.h
@@ -287,6 +287,34 @@ ClutterMargin * clutter_margin_new (void) G_GNUC_MALLOC;
ClutterMargin * clutter_margin_copy (const ClutterMargin *margin_);
void clutter_margin_free (ClutterMargin *margin_);
+/**
+ * ClutterProgressFunc:
+ * @a: the initial value of an interval
+ * @b: the final value of an interval
+ * @progress: the progress factor, between 0 and 1
+ * @retval: the value used to store the progress
+ *
+ * Prototype of the progress function used to compute the value
+ * between the two ends @a and @b of an interval depending on
+ * the value of @progress.
+ *
+ * The #GValue in @retval is already initialized with the same
+ * type as @a and @b.
+ *
+ * This function will be called by #ClutterInterval if the
+ * type of the values of the interval was registered using
+ * clutter_interval_register_progress_func().
+ *
+ * Return value: %TRUE if the function successfully computed
+ * the value and stored it inside @retval
+ *
+ * Since: 1.0
+ */
+typedef gboolean (* ClutterProgressFunc) (const GValue *a,
+ const GValue *b,
+ gdouble progress,
+ GValue *retval);
+
G_END_DECLS
#endif /* __CLUTTER_TYPES_H__ */
diff --git a/clutter/clutter-util.c b/clutter/clutter-util.c
index eeecb63..b95629c 100644
--- a/clutter/clutter-util.c
+++ b/clutter/clutter-util.c
@@ -37,6 +37,7 @@
#include <glib/gi18n-lib.h>
#include "clutter-main.h"
+#include "clutter-interval.h"
#include "clutter-private.h"
#include "deprecated/clutter-util.h"
@@ -180,3 +181,150 @@ _clutter_util_rectangle_union (const cairo_rectangle_int_t *src1,
dest->x = dest_x;
dest->y = dest_y;
}
+
+typedef struct
+{
+ GType value_type;
+ ClutterProgressFunc func;
+} ProgressData;
+
+G_LOCK_DEFINE_STATIC (progress_funcs);
+static GHashTable *progress_funcs = NULL;
+
+gboolean
+_clutter_has_progress_function (GType gtype)
+{
+ const char *type_name = g_type_name (gtype);
+
+ if (progress_funcs == NULL)
+ return FALSE;
+
+ return g_hash_table_lookup (progress_funcs, type_name) != NULL;
+}
+
+gboolean
+_clutter_run_progress_function (GType gtype,
+ const GValue *initial,
+ const GValue *final,
+ gdouble progress,
+ GValue *retval)
+{
+ ProgressData *pdata;
+ gboolean res;
+
+ G_LOCK (progress_funcs);
+
+ if (G_UNLIKELY (progress_funcs == NULL))
+ {
+ res = FALSE;
+ goto out;
+ }
+
+ pdata = g_hash_table_lookup (progress_funcs, g_type_name (gtype));
+ if (G_UNLIKELY (pdata == NULL))
+ {
+ res = FALSE;
+ goto out;
+ }
+
+ res = pdata->func (initial, final, progress, retval);
+
+out:
+ G_UNLOCK (progress_funcs);
+
+ return res;
+}
+
+static void
+progress_data_destroy (gpointer data_)
+{
+ g_slice_free (ProgressData, data_);
+}
+
+/**
+ * clutter_interval_register_progress_func: (skip)
+ * @value_type: a #GType
+ * @func: a #ClutterProgressFunc, or %NULL to unset a previously
+ * set progress function
+ *
+ * Sets the progress function for a given @value_type, like:
+ *
+ * |[
+ * clutter_interval_register_progress_func (MY_TYPE_FOO,
+ * my_foo_progress);
+ * ]|
+ *
+ * Whenever a #ClutterInterval instance using the default
+ * #ClutterInterval::compute_value implementation is set as an
+ * interval between two #GValue of type @value_type, it will call
+ * @func to establish the value depending on the given progress,
+ * for instance:
+ *
+ * |[
+ * static gboolean
+ * my_int_progress (const GValue *a,
+ * const GValue *b,
+ * gdouble progress,
+ * GValue *retval)
+ * {
+ * gint ia = g_value_get_int (a);
+ * gint ib = g_value_get_int (b);
+ * gint res = factor * (ib - ia) + ia;
+ *
+ * g_value_set_int (retval, res);
+ *
+ * return TRUE;
+ * }
+ *
+ * clutter_interval_register_progress_func (G_TYPE_INT, my_int_progress);
+ * ]|
+ *
+ * To unset a previously set progress function of a #GType, pass %NULL
+ * for @func.
+ *
+ * Since: 1.0
+ */
+void
+clutter_interval_register_progress_func (GType value_type,
+ ClutterProgressFunc func)
+{
+ ProgressData *progress_func;
+ const char *type_name;
+
+ g_return_if_fail (value_type != G_TYPE_INVALID);
+
+ type_name = g_type_name (value_type);
+
+ G_LOCK (progress_funcs);
+
+ if (G_UNLIKELY (progress_funcs == NULL))
+ progress_funcs = g_hash_table_new_full (NULL, NULL,
+ NULL,
+ progress_data_destroy);
+
+ progress_func =
+ g_hash_table_lookup (progress_funcs, type_name);
+
+ if (G_UNLIKELY (progress_func))
+ {
+ if (func == NULL)
+ {
+ g_hash_table_remove (progress_funcs, type_name);
+ g_slice_free (ProgressData, progress_func);
+ }
+ else
+ progress_func->func = func;
+ }
+ else
+ {
+ progress_func = g_slice_new (ProgressData);
+ progress_func->value_type = value_type;
+ progress_func->func = func;
+
+ g_hash_table_replace (progress_funcs,
+ (gpointer) type_name,
+ progress_func);
+ }
+
+ G_UNLOCK (progress_funcs);
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]