[clutter/wip/actor-content: 15/24] Add ClutterRGBA, a color content



commit 883ac6e75d3465c56179f2a1b0685c3052520570
Author: Emmanuele Bassi <ebassi linux intel com>
Date:   Mon Nov 22 12:50:30 2010 +0000

    Add ClutterRGBA, a color content

 clutter/Makefile.am                   |    2 +
 clutter/clutter-rgba.c                |  479 +++++++++++++++++++++++++++++++++
 clutter/clutter-rgba.h                |   55 ++++
 clutter/clutter.h                     |    1 +
 tests/interactive/Makefile.am         |    3 +-
 tests/interactive/test-rgba-content.c |   78 ++++++
 6 files changed, 617 insertions(+), 1 deletions(-)
---
diff --git a/clutter/Makefile.am b/clutter/Makefile.am
index f1d7fdb..6cfafab 100644
--- a/clutter/Makefile.am
+++ b/clutter/Makefile.am
@@ -132,6 +132,7 @@ source_h =					\
 	$(srcdir)/clutter-path-constraint.h	\
 	$(srcdir)/clutter-path.h		\
 	$(srcdir)/clutter-rectangle.h		\
+	$(srcdir)/clutter-rgba.h		\
 	$(srcdir)/clutter-score.h 		\
 	$(srcdir)/clutter-script.h		\
 	$(srcdir)/clutter-scriptable.h		\
@@ -217,6 +218,7 @@ source_c = \
 	$(srcdir)/clutter-path-constraint.c	\
 	$(srcdir)/clutter-path.c		\
 	$(srcdir)/clutter-rectangle.c 		\
+	$(srcdir)/clutter-rgba.c		\
 	$(srcdir)/clutter-score.c 		\
 	$(srcdir)/clutter-script.c		\
 	$(srcdir)/clutter-script-parser.c	\
diff --git a/clutter/clutter-rgba.c b/clutter/clutter-rgba.c
new file mode 100644
index 0000000..d5c79fe
--- /dev/null
+++ b/clutter/clutter-rgba.c
@@ -0,0 +1,479 @@
+/**
+ * SECTION:clutter-rgba
+ * @Title: ClutterRGBA
+ * @Short_Description: A solid color
+ *
+ * #ClutterRGBA is an object implementing the #ClutterContent interface. It
+ * can be used to paint a solid color covering the same area as the allocation
+ * of the #ClutterActor<!-- -->s that use it as their content.
+ *
+ * #ClutterRGBA is available since Clutter 1.6.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "clutter-rgba.h"
+
+#include "clutter-actor.h"
+#include "clutter-color.h"
+#include "clutter-content.h"
+#include "clutter-debug.h"
+#include "clutter-private.h"
+
+typedef struct _ClutterRGBAClass        ClutterRGBAClass;
+
+struct _ClutterRGBA
+{
+  GObject parent_instance;
+
+  gdouble red;
+  gdouble green;
+  gdouble blue;
+  gdouble alpha;
+};
+
+struct _ClutterRGBAClass
+{
+  GObjectClass parent_class;
+};
+
+enum
+{
+  PROP_0,
+
+  PROP_RED,
+  PROP_GREEN,
+  PROP_BLUE,
+  PROP_ALPHA,
+
+  PROP_COLOR,
+
+  PROP_STRING,
+
+  PROP_LAST
+};
+
+static void clutter_content_iface_init (ClutterContentIface *iface);
+
+static GParamSpec *obj_props[PROP_LAST] = { NULL, };
+
+static const ClutterColor default_color = { 0, 0, 0, 0 };
+
+G_DEFINE_TYPE_WITH_CODE (ClutterRGBA, clutter_rgba, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTENT,
+                                                clutter_content_iface_init));
+
+static gboolean
+clutter_rgba_setup_material (ClutterContent *content,
+                             ClutterActor   *actor)
+{
+  ClutterRGBA *self = CLUTTER_RGBA (content);
+  gfloat paint_opacity;
+
+  paint_opacity = ((float) clutter_actor_get_paint_opacity (actor) / 255.0f)
+                * self->alpha;
+
+  cogl_set_source_color4f (self->red,
+                           self->green,
+                           self->blue,
+                           CLAMP (paint_opacity, 0.0, 1.0));
+
+  return TRUE;
+}
+
+static void
+clutter_content_iface_init (ClutterContentIface *iface)
+{
+  iface->setup_material = clutter_rgba_setup_material;
+}
+
+static void
+clutter_rgba_set_property (GObject      *gobject,
+                           guint         prop_id,
+                           const GValue *value,
+                           GParamSpec   *pspec)
+{
+  ClutterRGBA *self = CLUTTER_RGBA (gobject);
+
+  switch (prop_id)
+    {
+    case PROP_RED:
+      clutter_rgba_set_red (self, g_value_get_double (value));
+      break;
+
+    case PROP_GREEN:
+      clutter_rgba_set_green (self, g_value_get_double (value));
+      break;
+
+    case PROP_BLUE:
+      clutter_rgba_set_blue (self, g_value_get_double (value));
+      break;
+
+    case PROP_ALPHA:
+      clutter_rgba_set_alpha (self, g_value_get_double (value));
+      break;
+
+    case PROP_COLOR:
+      clutter_rgba_set_color (self, clutter_value_get_color (value));
+      break;
+
+    case PROP_STRING:
+      clutter_rgba_set_string (self, g_value_get_string (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+    }
+}
+
+static void
+clutter_rgba_get_property (GObject    *gobject,
+                           guint       prop_id,
+                           GValue     *value,
+                           GParamSpec *pspec)
+{
+  ClutterRGBA *self = CLUTTER_RGBA (gobject);
+
+  switch (prop_id)
+    {
+    case PROP_RED:
+      g_value_set_double (value, self->red);
+      break;
+
+    case PROP_GREEN:
+      g_value_set_double (value, self->green);
+      break;
+
+    case PROP_BLUE:
+      g_value_set_double (value, self->blue);
+      break;
+
+    case PROP_ALPHA:
+      g_value_set_double (value, self->alpha);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
+    }
+}
+
+static void
+clutter_rgba_class_init (ClutterRGBAClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  /**
+   * ClutterRGBA:red:
+   *
+   * The value of the red channel.
+   *
+   * Since: 1.6
+   */
+  obj_props[PROP_RED] =
+    g_param_spec_double ("red",
+                         P_("Red"),
+                         P_("The red value"),
+                         0.0, 1.0,
+                         0.0,
+                         CLUTTER_PARAM_READWRITE);
+
+  /**
+   * ClutterRGBA:green:
+   *
+   * The value of the green channel.
+   *
+   * Since: 1.6
+   */
+  obj_props[PROP_GREEN] =
+    g_param_spec_double ("green",
+                         P_("Green"),
+                         P_("The green value"),
+                         0.0, 1.0,
+                         0.0,
+                         CLUTTER_PARAM_READWRITE);
+
+  /**
+   * ClutterRGBA:blue:
+   *
+   * The value of the blue channel.
+   *
+   * Since: 1.6
+   */
+  obj_props[PROP_BLUE] =
+    g_param_spec_double ("blue",
+                         P_("Blue"),
+                         P_("The blue value"),
+                         0.0, 1.0,
+                         0.0,
+                         CLUTTER_PARAM_READWRITE);
+
+  /**
+   * ClutterRGBA:alpha:
+   *
+   * The value of the alpha channel.
+   *
+   * Since: 1.6
+   */
+  obj_props[PROP_ALPHA] =
+    g_param_spec_double ("alpha",
+                         P_("Alpha"),
+                         P_("The alpha value"),
+                         0.0, 1.0,
+                         0.0,
+                         CLUTTER_PARAM_READWRITE);
+
+  /**
+   * ClutterRGBA:color:
+   *
+   * Sets all the channels of a #ClutterRGBA using a #ClutterColor.
+   *
+   * Since: 1.6
+   */
+  obj_props[PROP_COLOR] =
+    clutter_param_spec_color ("color",
+                              P_("Color"),
+                              P_("The full color, as a ClutterColor"),
+                              &default_color,
+                              CLUTTER_PARAM_WRITABLE);
+
+  /**
+   * ClutterRGBA:string:
+   *
+   * Sets all the channels of a #ClutterRGBA using a string that
+   * can be parsed by clutter_color_from_string().
+   *
+   * Since: 1.6
+   */
+  obj_props[PROP_STRING] =
+    g_param_spec_string ("string",
+                         P_("String"),
+                         P_("The full color, as a string"),
+                         NULL,
+                         CLUTTER_PARAM_WRITABLE);
+
+  gobject_class->set_property = clutter_rgba_set_property;
+  gobject_class->get_property = clutter_rgba_get_property;
+  g_object_class_install_properties (gobject_class, PROP_LAST, obj_props);
+}
+
+static void
+clutter_rgba_init (ClutterRGBA *self)
+{
+}
+
+/**
+ * clutter_rgba_new:
+ * @red: the value of the red channel, between 0 and 1
+ * @green: the value of the green channel, between 0 and 1
+ * @blue: the value of the blue channel, between 0 and 1
+ * @alpha: the value of the alpha channel, between 0 and 1
+ *
+ * Creates a new #ClutterRGBA object for the given color. This
+ * object can be used to paint a solid color inside a #ClutterActor,
+ * by calling clutter_actor_set_content().
+ *
+ * Return value: (transfer full): the newly created #ClutterRGBA instance.
+ *
+ * Since: 1.6
+ */
+ClutterContent *
+clutter_rgba_new (gdouble red,
+                  gdouble green,
+                  gdouble blue,
+                  gdouble alpha)
+{
+  return g_object_new (CLUTTER_TYPE_RGBA,
+                       "red", red,
+                       "green", green,
+                       "blue", blue,
+                       "alpha", alpha,
+                       NULL);
+}
+
+/**
+ * clutter_rgba_new_from_color:
+ * @color: a #ClutterColor
+ *
+ * Creates a new #ClutterRGBA instance, using @color as the source
+ * for the color definition.
+ *
+ * Return value: (transfer full): the newly created #ClutterRGBA instance.
+ *
+ * Since: 1.6
+ */
+ClutterContent *
+clutter_rgba_new_from_color (const ClutterColor *color)
+{
+  return g_object_new (CLUTTER_TYPE_RGBA,
+                       "color", color,
+                       NULL);
+}
+
+/**
+ * clutter_rgba_new_from_string:
+ * @string: a color definition, as parseable by clutter_color_from_string()
+ *
+ * Creates a new #ClutterRGBA instance, using the color definition contained
+ * inside the passed @string.
+ *
+ * Return value: (transfer full): the newly created #ClutterRGBA instance
+ *
+ * Since: 1.6
+ */
+ClutterContent *
+clutter_rgba_new_from_string (const gchar *string)
+{
+  return g_object_new (CLUTTER_TYPE_RGBA,
+                       "string", string,
+                       NULL);
+}
+
+void
+clutter_rgba_set_red (ClutterRGBA *self,
+                      gdouble      red)
+{
+  g_return_if_fail (CLUTTER_IS_RGBA (self));
+  g_return_if_fail (red >= 0.0 && red <= 1.0);
+
+  if (self->red == red)
+    return;
+
+  self->red = red;
+
+  clutter_content_invalidate (CLUTTER_CONTENT (self));
+  g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_RED]);
+}
+
+gdouble
+clutter_rgba_get_red (ClutterRGBA *self)
+{
+  g_return_val_if_fail (CLUTTER_IS_RGBA (self), 0.0);
+
+  return self->red;
+}
+
+void
+clutter_rgba_set_green (ClutterRGBA *self,
+                        gdouble      green)
+{
+  g_return_if_fail (CLUTTER_IS_RGBA (self));
+  g_return_if_fail (green >= 0.0 && green <= 1.0);
+
+  if (self->green == green)
+    return;
+
+  self->green = green;
+
+  clutter_content_invalidate (CLUTTER_CONTENT (self));
+  g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_GREEN]);
+}
+
+gdouble
+clutter_rgba_get_green (ClutterRGBA *self)
+{
+  g_return_val_if_fail (CLUTTER_IS_RGBA (self), 0.0);
+
+  return self->green;
+}
+
+void
+clutter_rgba_set_blue (ClutterRGBA *self,
+                       gdouble      blue)
+{
+  g_return_if_fail (CLUTTER_IS_RGBA (self));
+  g_return_if_fail (blue >= 0.0 && blue <= 1.0);
+
+  if (self->blue == blue)
+    return;
+
+  self->blue = blue;
+
+  clutter_content_invalidate (CLUTTER_CONTENT (self));
+  g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_BLUE]);
+}
+
+gdouble
+clutter_rgba_get_blue (ClutterRGBA *self)
+{
+  g_return_val_if_fail (CLUTTER_IS_RGBA (self), 0.0);
+
+  return self->blue;
+}
+
+void
+clutter_rgba_set_alpha (ClutterRGBA *self,
+                        gdouble      alpha)
+{
+  g_return_if_fail (CLUTTER_IS_RGBA (self));
+  g_return_if_fail (alpha >= 0.0 && alpha <= 1.0);
+
+  if (self->alpha == alpha)
+    return;
+
+  self->alpha = alpha;
+
+  clutter_content_invalidate (CLUTTER_CONTENT (self));
+  g_object_notify_by_pspec (G_OBJECT (self), obj_props[PROP_ALPHA]);
+}
+
+gdouble
+clutter_rgba_get_alpha (ClutterRGBA *self)
+{
+  g_return_val_if_fail (CLUTTER_IS_RGBA (self), 0.0);
+
+  return self->alpha;
+}
+
+/**
+ * clutter_rgba_set_color:
+ * @self: a #ClutterRGBA
+ * @color: a #ClutterColor
+ *
+ * Sets the color values of a #ClutterRGBA using a #ClutterColor.
+ *
+ * Since: 1.6
+ */
+void
+clutter_rgba_set_color (ClutterRGBA        *self,
+                        const ClutterColor *color)
+{
+  GObject *obj;
+
+  g_return_if_fail (CLUTTER_IS_RGBA (self));
+
+  self->red   = CLAMP (color->red   / 255.0, 0.0, 1.0);
+  self->green = CLAMP (color->green / 255.0, 0.0, 1.0);
+  self->blue  = CLAMP (color->blue  / 255.0, 0.0, 1.0);
+  self->alpha = CLAMP (color->alpha / 255.0, 0.0, 1.0);
+
+  clutter_content_invalidate (CLUTTER_CONTENT (self));
+
+  obj = G_OBJECT (self);
+  g_object_notify_by_pspec (obj, obj_props[PROP_RED]);
+  g_object_notify_by_pspec (obj, obj_props[PROP_GREEN]);
+  g_object_notify_by_pspec (obj, obj_props[PROP_BLUE]);
+  g_object_notify_by_pspec (obj, obj_props[PROP_ALPHA]);
+}
+
+/**
+ * clutter_rgba_set_string:
+ * @self: a #ClutterRGBA
+ * @string: a color definition, as parseable by clutter_color_from_string()
+ *
+ * Sets the color values of a #ClutterRGBA using a @string definition.
+ *
+ * Since: 1.6
+ */
+void
+clutter_rgba_set_string (ClutterRGBA *self,
+                         const gchar *string)
+{
+  ClutterColor color;
+
+  if (!clutter_color_from_string (&color, string))
+    return;
+
+  clutter_rgba_set_color (self, &color);
+}
diff --git a/clutter/clutter-rgba.h b/clutter/clutter-rgba.h
new file mode 100644
index 0000000..8f78ae8
--- /dev/null
+++ b/clutter/clutter-rgba.h
@@ -0,0 +1,55 @@
+#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
+#error "Only <clutter/clutter.h> can be included directly."
+#endif
+
+#ifndef __CLUTTER_RGBA_H__
+#define __CLUTTER_RGBA_H__
+
+#include <clutter/clutter-types.h>
+
+G_BEGIN_DECLS
+
+#define CLUTTER_TYPE_RGBA               (clutter_rgba_get_type ())
+#define CLUTTER_RGBA(obj)               (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_RGBA, ClutterRGBA))
+#define CLUTTER_IS_RGBA(obj)            (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_RGBA))
+
+/**
+ * ClutterRGBA:
+ *
+ * <structname>ClutterRGBA</structname> is an opaque structure whose
+ * members cannot be directly accessed.
+ *
+ * Since: 1.6
+ */
+typedef struct _ClutterRGBA             ClutterRGBA;
+
+GType clutter_rgba_get_type (void) G_GNUC_CONST;
+
+ClutterContent *clutter_rgba_new                (gdouble             red,
+                                                 gdouble             green,
+                                                 gdouble             blue,
+                                                 gdouble             alpha);
+ClutterContent *clutter_rgba_new_from_color     (const ClutterColor *color);
+ClutterContent *clutter_rgba_new_from_string    (const gchar        *string);
+
+void            clutter_rgba_set_red            (ClutterRGBA        *self,
+                                                 gdouble             red);
+gdouble         clutter_rgba_get_red            (ClutterRGBA        *self);
+void            clutter_rgba_set_green          (ClutterRGBA        *self,
+                                                 gdouble             green);
+gdouble         clutter_rgba_get_green          (ClutterRGBA        *self);
+void            clutter_rgba_set_blue           (ClutterRGBA        *self,
+                                                 gdouble             blue);
+gdouble         clutter_rgba_get_blue           (ClutterRGBA        *self);
+void            clutter_rgba_set_alpha          (ClutterRGBA        *self,
+                                                 gdouble             alpha);
+gdouble         clutter_rgba_get_alpha          (ClutterRGBA        *self);
+
+void            clutter_rgba_set_color          (ClutterRGBA        *self,
+                                                 const ClutterColor *color);
+void            clutter_rgba_set_string         (ClutterRGBA        *self,
+                                                 const gchar        *string);
+
+G_END_DECLS
+
+#endif /* __CLUTTER_RGBA_H__ */
diff --git a/clutter/clutter.h b/clutter/clutter.h
index e5cebc3..a700fae 100644
--- a/clutter/clutter.h
+++ b/clutter/clutter.h
@@ -91,6 +91,7 @@
 #include "clutter-path-constraint.h"
 #include "clutter-path.h"
 #include "clutter-rectangle.h"
+#include "clutter-rgba.h"
 #include "clutter-score.h"
 #include "clutter-scriptable.h"
 #include "clutter-script.h"
diff --git a/tests/interactive/Makefile.am b/tests/interactive/Makefile.am
index 5c04bf6..b03ff78 100644
--- a/tests/interactive/Makefile.am
+++ b/tests/interactive/Makefile.am
@@ -55,7 +55,8 @@ UNIT_TESTS = \
 	test-cogl-point-sprites.c \
 	test-table-layout.c \
 	test-path-constraint.c \
-	test-snap-constraint.c
+	test-snap-constraint.c \
+	test-rgba-content.c
 
 if X11_TESTS
 UNIT_TESTS += test-pixmap.c test-devices.c
diff --git a/tests/interactive/test-rgba-content.c b/tests/interactive/test-rgba-content.c
new file mode 100644
index 0000000..dbb3713
--- /dev/null
+++ b/tests/interactive/test-rgba-content.c
@@ -0,0 +1,78 @@
+#include <stdlib.h>
+#include <gmodule.h>
+#include <clutter/clutter.h>
+
+#define STAGE_WIDTH     400
+#define STAGE_HEIGHT    400
+#define PADDING         10
+#define SPACING         2
+#define RECT_SIZE       64
+
+G_MODULE_EXPORT int
+test_rgba_content_main (int   argc,
+                        char *argv[])
+{
+  ClutterActor *stage, *group;
+  ClutterContent *content;
+  int i, j, n_cols, n_rows;
+  float last_x, last_y;
+
+  if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
+    return EXIT_FAILURE;
+
+  stage = clutter_stage_new ();
+  clutter_stage_set_title (CLUTTER_STAGE (stage), "RGBA Content");
+  clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
+  clutter_actor_set_size (stage, 400, 400);
+  clutter_actor_show (stage);
+
+  g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
+
+  content = clutter_rgba_new (g_random_double_range (0.0, 1.0),
+                              g_random_double_range (0.0, 1.0),
+                              g_random_double_range (0.0, 1.0),
+                              1.0);
+
+  group = clutter_group_new ();
+  clutter_container_add_actor (CLUTTER_CONTAINER (stage), group);
+  clutter_actor_add_constraint (group, clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.5));
+  clutter_actor_add_constraint (group, clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.5));
+  clutter_actor_set_content (group, content);
+  g_object_unref (content);
+
+  content = clutter_rgba_new (g_random_double_range (0.0, 1.0),
+                              g_random_double_range (0.0, 1.0),
+                              g_random_double_range (0.0, 1.0),
+                              1.0);
+
+  n_cols = (STAGE_WIDTH  - (2 * PADDING)) / (RECT_SIZE + (2 * SPACING));
+  n_rows = (STAGE_HEIGHT - (2 * PADDING)) / (RECT_SIZE + (2 * SPACING));
+
+  last_y = PADDING + SPACING;
+  for (i = 0; i < n_rows; i++)
+    {
+      last_x = PADDING + SPACING;
+      for (j = 0; j < n_cols; j++)
+        {
+          ClutterActor *rect = g_object_new (CLUTTER_TYPE_ACTOR, NULL);
+
+          clutter_actor_set_position (rect, last_x, last_y);
+          clutter_actor_set_size (rect, RECT_SIZE, RECT_SIZE);
+          clutter_actor_set_content (rect, content);
+
+          clutter_container_add_actor (CLUTTER_CONTAINER (group), rect);
+
+          last_x += RECT_SIZE + SPACING;
+        }
+
+      last_y += RECT_SIZE + SPACING;
+    }
+
+  clutter_actor_set_size (group, last_x + PADDING, last_y + PADDING);
+
+  g_object_unref (content);
+
+  clutter_main ();
+
+  return EXIT_SUCCESS;
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]