[gnome-color-manager] Add a 3D gamut hull tab to the profile viewer



commit 590cc4af32d3a80f63f89c29ea507cbe8ca06150
Author: Richard Hughes <richard hughsie com>
Date:   Mon Mar 28 10:07:59 2011 +0100

    Add a 3D gamut hull tab to the profile viewer
    
    Note: this requires clutter-gtk and mash, both of which are now *optional* deps.

 configure.ac          |   11 ++-
 data/gcm-viewer.ui    |   65 ++++++++--
 src/Makefile.am       |    8 +
 src/gcm-hull-widget.c |  343 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/gcm-hull-widget.h |   62 +++++++++
 src/gcm-profile.c     |    2 +-
 src/gcm-viewer.c      |   32 +++++-
 7 files changed, 510 insertions(+), 13 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index a8aae82..f24928e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -119,6 +119,14 @@ else
 	PKG_CHECK_MODULES(USB, libusb-1.0 >= 1.0.0)
 fi
 
+PKG_CHECK_MODULES(CLUTTER, clutter-gtk-1.0 mash-0.1, has_clutter=yes, has_clutter=no)
+AM_CONDITIONAL(HAVE_CLUTTER, test x$has_clutter = xyes)
+if test x$has_clutter = xyes; then
+	AC_DEFINE(HAVE_CLUTTER,1,[has clutter support])
+else
+	AC_MSG_WARN([clutter-gtk and mash not found, no 3D support])
+fi
+
 dnl **** Check for VTE ****
 PKG_CHECK_MODULES(VTE, vte-2.90 >= 0.25.1, has_vte=yes, has_vte=no)
 AM_CONDITIONAL(HAVE_VTE, test x$has_vte = xyes)
@@ -161,7 +169,7 @@ if test x$enable_man_pages != xno; then
 	AC_PATH_PROG(XSLTPROC, xsltproc, no)
 	if test x$enable_man_pages = xyes; then
 		if test "$XSLTPROC" = "no" ; then
-			AC_MSG_ERROR([xsltproc not found, it's needod to build man pages])
+			AC_MSG_ERROR([xsltproc not found])
 		fi
 	fi
 else
@@ -259,6 +267,7 @@ echo "
         RAW support:               ${enable_exiv}
         VTE support:               ${has_vte}
         New LIBUSB:                ${has_new_libusb}
+        3D support:                ${has_clutter}
         building unit tests:       ${enable_tests}
 "
 
diff --git a/data/gcm-viewer.ui b/data/gcm-viewer.ui
index a4df722..1116cfd 100644
--- a/data/gcm-viewer.ui
+++ b/data/gcm-viewer.ui
@@ -879,6 +879,51 @@
                   </packing>
                 </child>
                 <child>
+                  <object class="GtkVBox" id="vbox_3d">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="border_width">9</property>
+                    <property name="spacing">6</property>
+                    <child>
+                      <object class="GtkImage" id="image8">
+                        <property name="can_focus">False</property>
+                        <property name="stock">gtk-underline</property>
+                      </object>
+                      <packing>
+                        <property name="expand">True</property>
+                        <property name="fill">True</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="label20">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="label" translatable="yes">This 3D hull is what the profile looks like in Lab space</property>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">False</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+                <child type="tab">
+                  <object class="GtkLabel" id="label130">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes">3D Gamut</property>
+                  </object>
+                  <packing>
+                    <property name="position">2</property>
+                    <property name="tab_fill">False</property>
+                  </packing>
+                </child>
+                <child>
                   <object class="GtkVBox" id="vbox_trc">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
@@ -958,17 +1003,17 @@
                     </child>
                   </object>
                   <packing>
-                    <property name="position">2</property>
+                    <property name="position">3</property>
                   </packing>
                 </child>
                 <child type="tab">
-                  <object class="GtkLabel" id="label10">
+                  <object class="GtkLabel" id="label11">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <property name="label" translatable="yes">TRC</property>
                   </object>
                   <packing>
-                    <property name="position">2</property>
+                    <property name="position">3</property>
                     <property name="tab_fill">False</property>
                   </packing>
                 </child>
@@ -1052,17 +1097,17 @@
                     </child>
                   </object>
                   <packing>
-                    <property name="position">3</property>
+                    <property name="position">4</property>
                   </packing>
                 </child>
                 <child type="tab">
-                  <object class="GtkLabel" id="label11">
+                  <object class="GtkLabel" id="label12">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <property name="label" translatable="yes">VCGT</property>
                   </object>
                   <packing>
-                    <property name="position">3</property>
+                    <property name="position">1</property>
                     <property name="tab_fill">False</property>
                   </packing>
                 </child>
@@ -1162,17 +1207,17 @@
                     </child>
                   </object>
                   <packing>
-                    <property name="position">4</property>
+                    <property name="position">5</property>
                   </packing>
                 </child>
                 <child type="tab">
-                  <object class="GtkLabel" id="label12">
+                  <object class="GtkLabel" id="label10">
                     <property name="visible">True</property>
                     <property name="can_focus">False</property>
                     <property name="label" translatable="yes">From sRGB</property>
                   </object>
                   <packing>
-                    <property name="position">1</property>
+                    <property name="position">2</property>
                     <property name="tab_fill">False</property>
                   </packing>
                 </child>
@@ -1272,7 +1317,7 @@
                     </child>
                   </object>
                   <packing>
-                    <property name="position">5</property>
+                    <property name="position">6</property>
                   </packing>
                 </child>
                 <child type="tab">
diff --git a/src/Makefile.am b/src/Makefile.am
index 92f35ac..3a781b1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -10,6 +10,7 @@ INCLUDES =						\
 	$(COLORD_CFLAGS)				\
 	$(NOTIFY_CFLAGS)				\
 	$(CANBERRA_CFLAGS)				\
+	$(CLUTTER_CFLAGS)				\
 	$(SETTINGS_DAEMON_CFLAGS)			\
 	-DG_UDEV_API_IS_SUBJECT_TO_CHANGE		\
 	$(GUDEV_CFLAGS)					\
@@ -101,6 +102,12 @@ libgcmshared_a_SOURCES =				\
 	gcm-x11-screen.c				\
 	gcm-x11-screen.h
 
+if HAVE_CLUTTER
+libgcmshared_a_SOURCES +=				\
+	gcm-hull-widget.c				\
+	gcm-hull-widget.h
+endif
+
 libgcmshared_a_CFLAGS =					\
 	$(WARNINGFLAGS_C)
 
@@ -198,6 +205,7 @@ gcm_viewer_LDADD =					\
 	$(LCMS_LIBS)					\
 	$(EXIF_LIBS)					\
 	$(COLORD_LIBS)					\
+	$(CLUTTER_LIBS)					\
 	-lm
 
 gcm_viewer_CFLAGS =					\
diff --git a/src/gcm-hull-widget.c b/src/gcm-hull-widget.c
new file mode 100644
index 0000000..ad317cf
--- /dev/null
+++ b/src/gcm-hull-widget.c
@@ -0,0 +1,343 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2011 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "config.h"
+#include <gtk/gtk.h>
+
+#ifdef HAVE_CLUTTER
+ #include <mash/mash.h>
+#endif
+
+#include "gcm-hull.h"
+#include "gcm-hull-widget.h"
+
+G_DEFINE_TYPE (GcmHullWidget, gcm_hull_widget, GTK_CLUTTER_TYPE_EMBED);
+#define GCM_HULL_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GCM_TYPE_HULL_WIDGET, GcmHullWidgetPrivate))
+
+struct GcmHullWidgetPrivate
+{
+	ClutterActor		*stage;
+	gboolean		 stage_color;
+	gdouble			 existing_rotation;
+	gdouble			 old_x;
+	gdouble			 old_y;
+	GPtrArray		*models;
+	guint			 button;
+};
+
+static void	gcm_hull_widget_finalize (GObject *object);
+
+enum
+{
+	PROP_0,
+	PROP_STAGE_COLOR,
+	PROP_LAST
+};
+
+/**
+ * gcm_hull_widget_clear:
+ **/
+void
+gcm_hull_widget_clear (GcmHullWidget *hull_widget)
+{
+	ClutterActor *model;
+	guint i;
+
+	for (i=0; i<hull_widget->priv->models->len; i++) {
+		model = g_ptr_array_index (hull_widget->priv->models, i);
+		clutter_container_remove_actor (CLUTTER_CONTAINER (hull_widget->priv->stage),
+						model);
+	}
+	g_ptr_array_set_size (hull_widget->priv->models, 0);
+}
+
+/**
+ * gcm_hull_widget_add:
+ **/
+gboolean
+gcm_hull_widget_add (GcmHullWidget *hull_widget,
+		     GcmProfile *profile)
+{
+	ClutterActor *model = NULL;
+	gboolean ret = FALSE;
+	gchar *ply_data = NULL;
+	GcmHull *hull = NULL;
+	GError *error = NULL;
+
+	/* generate hull */
+	hull = gcm_profile_generate_gamut_hull (profile, 12);
+	if (hull == NULL)
+		goto out;
+
+	/* save as PLY file */
+	ply_data = gcm_hull_export_to_ply (hull);
+	ret = g_file_set_contents ("/tmp/gamut.ply", ply_data, -1, &error);
+	if (!ret) {
+		g_warning ("%s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* load model: TODO: use mash_model_new_from_data() */
+	model = mash_model_new_from_file (MASH_DATA_NONE, "/tmp/gamut.ply",
+					  &error);
+	if (model == NULL) {
+		g_warning ("%s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	/* set some good defaults */
+	clutter_actor_set_size (model,
+				clutter_actor_get_width (hull_widget->priv->stage) * 0.7f,
+				clutter_actor_get_height (hull_widget->priv->stage) * 0.7f);
+	clutter_actor_set_position (model,
+				    clutter_actor_get_width (hull_widget->priv->stage) * 0.15f,
+				    clutter_actor_get_height (hull_widget->priv->stage) * 0.15f);
+
+	/* add the actor to the stage */
+	clutter_container_add_actor (CLUTTER_CONTAINER (hull_widget->priv->stage),
+				     model);
+	g_ptr_array_add (hull_widget->priv->models,
+			 g_object_ref (model));
+
+	/* enable depth testing */
+	g_signal_connect_swapped (model, "paint",
+				  G_CALLBACK (cogl_set_depth_test_enabled),
+				  GINT_TO_POINTER (TRUE));
+	g_signal_connect_data (model, "paint",
+			       G_CALLBACK (cogl_set_depth_test_enabled),
+			       GINT_TO_POINTER (FALSE), NULL,
+			       G_CONNECT_AFTER | G_CONNECT_SWAPPED);
+
+	/* set the old rotation */
+	clutter_actor_set_rotation (model,
+				    CLUTTER_Y_AXIS,
+				    hull_widget->priv->existing_rotation,
+				    clutter_actor_get_width (hull_widget->priv->stage) * 0.35f,
+				    0.0, 0.0);
+
+	/* success */
+	clutter_actor_set_opacity (model, 240);
+	clutter_actor_show (model);
+	ret = TRUE;
+out:
+	g_free (ply_data);
+	if (hull != NULL)
+		g_object_unref (hull);
+	return ret;
+}
+
+/**
+ * gcm_hull_widget_button_press_cb:
+ **/
+static gboolean
+gcm_hull_widget_button_press_cb (GtkWidget *widget,
+				 GdkEvent *event,
+				 GcmHullWidget *hull_widget)
+{
+	GdkEventButton *button = (GdkEventButton *) event;
+	hull_widget->priv->button = button->button;
+	hull_widget->priv->old_x = 0;
+	hull_widget->priv->old_y = 0;
+	return TRUE;
+}
+
+/**
+ * gcm_hull_widget_button_release_cb:
+ **/
+static gboolean
+gcm_hull_widget_button_release_cb (GtkWidget *widget,
+				   GdkEvent  *event,
+				   GcmHullWidget *hull_widget)
+{
+	hull_widget->priv->button = 0;
+	return TRUE;
+}
+
+/**
+ * gcm_hull_widget_motion_notify_cb:
+ **/
+static gboolean
+gcm_hull_widget_motion_notify_cb (GtkWidget *widget,
+				  GdkEvent  *event,
+				  GcmHullWidget *hull_widget)
+{
+	ClutterActor *model;
+	GdkEventMotion *motion = (GdkEventMotion *) event;
+	gdouble angle_x;
+	guint i;
+
+	if (hull_widget->priv->button == 0)
+		goto out;
+	if (hull_widget->priv->old_x < 0.001 ||
+	    hull_widget->priv->old_y < 0.001) {
+		goto out;
+	}
+
+	if (hull_widget->priv->models->len == 0)
+		return FALSE;
+
+	/* work out the offset */
+	angle_x = motion->x - hull_widget->priv->old_x;
+
+	/* get old rotation of primary model */
+	model = g_ptr_array_index (hull_widget->priv->models, 0);
+	hull_widget->priv->existing_rotation =
+		clutter_actor_get_rotation (model,
+					    CLUTTER_Y_AXIS,
+					    NULL, NULL, NULL);
+
+	/* rotate all the models on the stage */
+	for (i=0; i<hull_widget->priv->models->len; i++) {
+		model = g_ptr_array_index (hull_widget->priv->models, i);
+		clutter_actor_set_rotation (model,
+					    CLUTTER_Y_AXIS,
+					    hull_widget->priv->existing_rotation + angle_x,
+					    clutter_actor_get_width (hull_widget->priv->stage) * 0.35f,
+					    0.0, 0.0);
+	}
+out:
+	hull_widget->priv->old_x = motion->x;
+	hull_widget->priv->old_y = motion->y;
+	return TRUE;
+}
+
+/**
+ * gcm_hull_widget_get_property:
+ **/
+static void
+gcm_hull_widget_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+	GcmHullWidget *hull_widget = GCM_HULL_WIDGET (object);
+	switch (prop_id) {
+	case PROP_STAGE_COLOR:
+		g_value_set_double (value, hull_widget->priv->stage_color);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+/**
+ * gcm_hull_widget_set_property:
+ **/
+static void
+gcm_hull_widget_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+	GcmHullWidget *hull_widget = GCM_HULL_WIDGET (object);
+
+	switch (prop_id) {
+	case PROP_STAGE_COLOR:
+		hull_widget->priv->stage_color = g_value_get_double (value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+
+	/* refresh widget */
+	gtk_widget_hide (GTK_WIDGET (hull_widget));
+	gtk_widget_show (GTK_WIDGET (hull_widget));
+}
+
+/**
+ * gcm_hull_widget_class_init:
+ **/
+static void
+gcm_hull_widget_class_init (GcmHullWidgetClass *class)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+	object_class->get_property = gcm_hull_widget_get_property;
+	object_class->set_property = gcm_hull_widget_set_property;
+	object_class->finalize = gcm_hull_widget_finalize;
+
+	g_type_class_add_private (class, sizeof (GcmHullWidgetPrivate));
+
+	/* properties */
+	g_object_class_install_property (object_class,
+					 PROP_STAGE_COLOR,
+					 g_param_spec_double ("stage-color", NULL, NULL,
+							      0.0, 1.0, 0.8,
+							      G_PARAM_READWRITE));
+}
+
+/**
+ * gcm_hull_widget_init:
+ **/
+static void
+gcm_hull_widget_init (GcmHullWidget *hull_widget)
+{
+	ClutterColor color;
+
+	hull_widget->priv = GCM_HULL_WIDGET_GET_PRIVATE (hull_widget);
+	hull_widget->priv->stage = gtk_clutter_embed_get_stage (GTK_CLUTTER_EMBED (hull_widget));
+
+	/* list of models */
+	hull_widget->priv->models = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
+
+	/* grey stage background */
+	color.red = 120;
+	color.green = 120;
+	color.blue = 120;
+	color.alpha = 0;
+	clutter_stage_set_color (CLUTTER_STAGE (hull_widget->priv->stage), &color);
+
+	/* allow user to rotate */
+	gtk_widget_add_events (GTK_WIDGET (hull_widget),
+			       GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK |
+			       GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+			       GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK);
+	g_signal_connect (hull_widget, "button-press-event",
+			  G_CALLBACK (gcm_hull_widget_button_press_cb),
+			  hull_widget);
+	g_signal_connect (hull_widget, "button-release-event",
+			  G_CALLBACK (gcm_hull_widget_button_release_cb),
+			  hull_widget);
+	g_signal_connect (hull_widget, "motion-notify-event",
+			  G_CALLBACK (gcm_hull_widget_motion_notify_cb),
+			  hull_widget);
+
+}
+
+/**
+ * gcm_hull_widget_finalize:
+ **/
+static void
+gcm_hull_widget_finalize (GObject *object)
+{
+	GcmHullWidget *hull_widget = (GcmHullWidget*) object;
+	g_ptr_array_unref (hull_widget->priv->models);
+	G_OBJECT_CLASS (gcm_hull_widget_parent_class)->finalize (object);
+}
+
+/**
+ * gcm_hull_widget_new:
+ * Return value: A new GcmHullWidget object.
+ **/
+GtkWidget *
+gcm_hull_widget_new (void)
+{
+	return g_object_new (GCM_TYPE_HULL_WIDGET, NULL);
+}
+
diff --git a/src/gcm-hull-widget.h b/src/gcm-hull-widget.h
new file mode 100644
index 0000000..d169547
--- /dev/null
+++ b/src/gcm-hull-widget.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2011 Richard Hughes <richard hughsie com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __GCM_HULL_WIDGET_H__
+#define __GCM_HULL_WIDGET_H__
+
+#include <gtk/gtk.h>
+#include <clutter-gtk/clutter-gtk.h>
+
+#include "gcm-profile.h"
+
+G_BEGIN_DECLS
+
+#define GCM_TYPE_HULL_WIDGET		(gcm_hull_widget_get_type ())
+#define GCM_HULL_WIDGET(obj)		(G_TYPE_CHECK_INSTANCE_CAST ((obj), GCM_TYPE_HULL_WIDGET, GcmHullWidget))
+#define GCM_HULL_WIDGET_CLASS(obj)	(G_TYPE_CHECK_CLASS_CAST ((obj), GCM_HULL_WIDGET, GcmHullWidgetClass))
+#define GCM_IS_HULL_WIDGET(obj)		(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCM_TYPE_HULL_WIDGET))
+#define GCM_IS_HULL_WIDGET_CLASS(obj)	(G_TYPE_CHECK_CLASS_TYPE ((obj), EFF_TYPE_HULL_WIDGET))
+#define GCM_HULL_WIDGET_GET_CLASS	(G_TYPE_INSTANCE_GET_CLASS ((obj), GCM_TYPE_HULL_WIDGET, GcmHullWidgetClass))
+
+typedef struct GcmHullWidget		GcmHullWidget;
+typedef struct GcmHullWidgetClass	GcmHullWidgetClass;
+typedef struct GcmHullWidgetPrivate	GcmHullWidgetPrivate;
+
+struct GcmHullWidget
+{
+	GtkClutterEmbed		 parent;
+	GcmHullWidgetPrivate	*priv;
+};
+
+struct GcmHullWidgetClass
+{
+	GtkClutterEmbedClass	 parent_class;
+};
+
+GType		 gcm_hull_widget_get_type	(void);
+GtkWidget	*gcm_hull_widget_new		(void);
+void		 gcm_hull_widget_clear		(GcmHullWidget	*hull_widget);
+gboolean	 gcm_hull_widget_add		(GcmHullWidget	*hull_widget,
+						 GcmProfile	*profile);
+
+G_END_DECLS
+
+#endif
diff --git a/src/gcm-profile.c b/src/gcm-profile.c
index 6bfd8dc..e3813af 100644
--- a/src/gcm-profile.c
+++ b/src/gcm-profile.c
@@ -1876,7 +1876,7 @@ gcm_profile_generate_gamut_hull (GcmProfile *profile, guint res)
 	srgb_profile = cmsCreate_sRGBProfile ();
 	srgb_transform = cmsCreateTransform (lab_profile, TYPE_Lab_DBL,
 					     srgb_profile, TYPE_RGB_DBL,
-					     INTENT_PERCEPTUAL, 0);
+					     INTENT_ABSOLUTE_COLORIMETRIC, 0);
 	if (srgb_transform == NULL) {
 		g_warning ("failed to create sRGB transform");
 		goto out;
diff --git a/src/gcm-viewer.c b/src/gcm-viewer.c
index 4498818..7756422 100644
--- a/src/gcm-viewer.c
+++ b/src/gcm-viewer.c
@@ -29,6 +29,10 @@
 #include <canberra-gtk.h>
 #include <colord.h>
 
+#ifdef HAVE_CLUTTER
+ #include <clutter-gtk/clutter-gtk.h>
+#endif
+
 #include "gcm-cell-renderer-profile-text.h"
 #include "gcm-cie-widget.h"
 #include "gcm-image.h"
@@ -38,6 +42,10 @@
 #include "gcm-color.h"
 #include "gcm-debug.h"
 
+#ifdef HAVE_CLUTTER
+ #include "gcm-hull-widget.h"
+#endif
+
 static guint xid = 0;
 
 typedef struct {
@@ -46,6 +54,7 @@ typedef struct {
 	GtkListStore	*list_store_profiles;
 	CdClient	*client;
 	GtkWidget	*cie_widget;
+	GtkWidget	*hull_widget;
 	GtkWidget	*trc_widget;
 	GtkWidget	*vcgt_widget;
 	GtkWidget	*preview_widget_input;
@@ -707,6 +716,15 @@ gcm_viewer_profiles_treeview_clicked_cb (GtkTreeSelection *selection, GcmViewerP
 		gtk_widget_hide (widget);
 	}
 
+#ifdef HAVE_CLUTTER
+	/* show 3d gamut hull */
+	gtk_widget_show (viewer->hull_widget);
+	gcm_hull_widget_clear (GCM_HULL_WIDGET (viewer->hull_widget));
+	ret = gcm_hull_widget_add (GCM_HULL_WIDGET (viewer->hull_widget), gcm_profile);
+	widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "vbox_3d"));
+	gtk_widget_set_visible (widget, ret);
+#endif
+
 	/* get vcgt data */
 	clut_vcgt = gcm_profile_generate_vcgt (gcm_profile, 256);
 
@@ -724,7 +742,6 @@ gcm_viewer_profiles_treeview_clicked_cb (GtkTreeSelection *selection, GcmViewerP
 		gtk_widget_hide (widget);
 	}
 
-
 	/* set kind */
 	widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "hbox_type"));
 	profile_kind = cd_profile_get_kind (profile);
@@ -1049,6 +1066,16 @@ gcm_viewer_startup_cb (GApplication *application, GcmViewerPrivate *viewer)
 	gtk_box_pack_start (GTK_BOX(widget), viewer->cie_widget, TRUE, TRUE, 0);
 	gtk_box_reorder_child (GTK_BOX(widget), viewer->cie_widget, 0);
 
+	/* use clutter widget */
+	widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "vbox_3d"));
+#ifdef HAVE_CLUTTER
+	viewer->hull_widget = gcm_hull_widget_new ();
+	gtk_box_pack_start (GTK_BOX(widget), viewer->hull_widget, TRUE, TRUE, 0);
+	gtk_box_reorder_child (GTK_BOX(widget), viewer->hull_widget, 0);
+#else
+	gtk_widget_hide (widget);
+#endif
+
 	/* use trc widget */
 	viewer->trc_widget = gcm_trc_widget_new ();
 	widget = GTK_WIDGET (gtk_builder_get_object (viewer->builder, "vbox_trc_widget"));
@@ -1114,6 +1141,9 @@ main (int argc, char **argv)
 	textdomain (GETTEXT_PACKAGE);
 
 	gtk_init (&argc, &argv);
+#ifdef HAVE_CLUTTER
+	gtk_clutter_init (&argc, &argv);
+#endif
 
 	context = g_option_context_new ("gnome-color-manager profile viewer");
 	g_option_context_add_main_entries (context, options, NULL);



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