[gnome-color-manager: 3/3] Add a simple tone curve widget that is not used just yet
- From: Richard Hughes <rhughes src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gnome-color-manager: 3/3] Add a simple tone curve widget that is not used just yet
- Date: Wed, 9 Dec 2009 20:04:36 +0000 (UTC)
commit e9cfd20d840c31a3ce753b427c16b5a8f798f138
Author: Richard Hughes <richard hughsie com>
Date: Wed Dec 9 20:03:42 2009 +0000
Add a simple tone curve widget that is not used just yet
data/tests/trc-widget.png | Bin 0 -> 13194 bytes
src/Makefile.am | 2 +
src/gcm-self-test.c | 2 +
src/gcm-trc-widget.c | 463 +++++++++++++++++++++++++++++++++++++++++++++
src/gcm-trc-widget.h | 56 ++++++
5 files changed, 523 insertions(+), 0 deletions(-)
---
diff --git a/data/tests/trc-widget.png b/data/tests/trc-widget.png
new file mode 100644
index 0000000..fe6dbb1
Binary files /dev/null and b/data/tests/trc-widget.png differ
diff --git a/src/Makefile.am b/src/Makefile.am
index d46fa3a..f819361 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -191,6 +191,8 @@ gcm_self_test_SOURCES = \
gcm-dmi.c \
gcm-xyz.c \
gcm-cie-widget.c \
+ gcm-trc-widget.c \
+ gcm-trc-widget.h \
egg-test.h \
egg-test.c \
$(NULL)
diff --git a/src/gcm-self-test.c b/src/gcm-self-test.c
index 1c2f1fc..c3d42a7 100644
--- a/src/gcm-self-test.c
+++ b/src/gcm-self-test.c
@@ -34,6 +34,7 @@ void gcm_clut_test (EggTest *test);
void gcm_dmi_test (EggTest *test);
void gcm_xyz_test (EggTest *test);
void gcm_cie_widget_test (EggTest *test);
+void gcm_trc_widget_test (EggTest *test);
int
main (int argc, char **argv)
@@ -47,6 +48,7 @@ main (int argc, char **argv)
egg_debug_init (&argc, &argv);
/* components */
+ gcm_trc_widget_test (test);
gcm_edid_test (test);
gcm_tables_test (test);
gcm_utils_test (test);
diff --git a/src/gcm-trc-widget.c b/src/gcm-trc-widget.c
new file mode 100644
index 0000000..4bfe05b
--- /dev/null
+++ b/src/gcm-trc-widget.c
@@ -0,0 +1,463 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006-2009 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include <gtk/gtk.h>
+#include <glib/gi18n.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "gcm-clut.h"
+#include "gcm-trc-widget.h"
+
+#include "egg-debug.h"
+
+G_DEFINE_TYPE (GcmTrcWidget, gcm_trc_widget, GTK_TYPE_DRAWING_AREA);
+#define GCM_TRC_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GCM_TYPE_TRC_WIDGET, GcmTrcWidgetPrivate))
+#define GCM_TRC_WIDGET_FONT "Sans 8"
+
+struct GcmTrcWidgetPrivate
+{
+ gboolean use_grid;
+ guint chart_width;
+ guint chart_height;
+ cairo_t *cr;
+ PangoLayout *layout;
+ GPtrArray *clut_data;
+ GcmClutData *data;
+ guint x_offset;
+ guint y_offset;
+};
+
+static gboolean gcm_trc_widget_expose (GtkWidget *trc, GdkEventExpose *event);
+static void gcm_trc_widget_finalize (GObject *object);
+
+enum
+{
+ PROP_0,
+ PROP_USE_GRID,
+ PROP_RED,
+ PROP_GREEN,
+ PROP_BLUE,
+ PROP_WHITE,
+ PROP_LAST
+};
+
+/**
+ * dkp_trc_get_property:
+ **/
+static void
+dkp_trc_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ GcmTrcWidget *trc = GCM_TRC_WIDGET (object);
+ switch (prop_id) {
+ case PROP_USE_GRID:
+ g_value_set_boolean (value, trc->priv->use_grid);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+/**
+ * dkp_trc_set_property:
+ **/
+static void
+dkp_trc_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+ GcmTrcWidget *trc = GCM_TRC_WIDGET (object);
+
+ switch (prop_id) {
+ case PROP_USE_GRID:
+ trc->priv->use_grid = g_value_get_boolean (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+
+ /* refresh widget */
+ gtk_widget_hide (GTK_WIDGET (trc));
+ gtk_widget_show (GTK_WIDGET (trc));
+}
+
+/**
+ * gcm_trc_widget_class_init:
+ **/
+static void
+gcm_trc_widget_class_init (GcmTrcWidgetClass *class)
+{
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ widget_class->expose_event = gcm_trc_widget_expose;
+ object_class->get_property = dkp_trc_get_property;
+ object_class->set_property = dkp_trc_set_property;
+ object_class->finalize = gcm_trc_widget_finalize;
+
+ g_type_class_add_private (class, sizeof (GcmTrcWidgetPrivate));
+
+ /* properties */
+ g_object_class_install_property (object_class,
+ PROP_USE_GRID,
+ g_param_spec_boolean ("use-grid", NULL, NULL,
+ TRUE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_RED,
+ g_param_spec_object ("red", NULL, NULL,
+ G_TYPE_OBJECT,
+ G_PARAM_WRITABLE));
+}
+
+/**
+ * gcm_trc_widget_init:
+ **/
+static void
+gcm_trc_widget_init (GcmTrcWidget *trc)
+{
+ PangoFontMap *fontmap;
+ PangoContext *context;
+ PangoFontDescription *desc;
+
+ trc->priv = GCM_TRC_WIDGET_GET_PRIVATE (trc);
+ trc->priv->use_grid = TRUE;
+ trc->priv->clut_data = g_ptr_array_new_with_free_func (g_free);
+
+ /* do pango stuff */
+ fontmap = pango_cairo_font_map_get_default ();
+ context = pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap));
+ pango_context_set_base_gravity (context, PANGO_GRAVITY_AUTO);
+
+ trc->priv->layout = pango_layout_new (context);
+ desc = pango_font_description_from_string (GCM_TRC_WIDGET_FONT);
+ pango_layout_set_font_description (trc->priv->layout, desc);
+ pango_font_description_free (desc);
+}
+
+/**
+ * gcm_trc_widget_finalize:
+ **/
+static void
+gcm_trc_widget_finalize (GObject *object)
+{
+ PangoContext *context;
+ GcmTrcWidget *trc = (GcmTrcWidget*) object;
+
+ context = pango_layout_get_context (trc->priv->layout);
+ g_object_unref (trc->priv->layout);
+ g_object_unref (context);
+ g_ptr_array_unref (trc->priv->clut_data);
+ G_OBJECT_CLASS (gcm_trc_widget_parent_class)->finalize (object);
+}
+
+/**
+ * gcm_trc_widget_draw_grid:
+ *
+ * Draw the 10x10 dotted grid onto the trc.
+ **/
+static void
+gcm_trc_widget_draw_grid (GcmTrcWidget *trc, cairo_t *cr)
+{
+ guint i;
+ gdouble b;
+ gdouble dotted[] = {1., 2.};
+ gdouble divwidth = (gdouble)trc->priv->chart_width / 10.0f;
+ gdouble divheight = (gdouble)trc->priv->chart_height / 10.0f;
+
+ cairo_save (cr);
+ cairo_set_line_width (cr, 1);
+ cairo_set_dash (cr, dotted, 2, 0.0);
+
+ /* do vertical lines */
+ cairo_set_source_rgb (cr, 0.1, 0.1, 0.1);
+ for (i=1; i<10; i++) {
+ b = ((gdouble) i * divwidth);
+ cairo_move_to (cr, (gint)b + 0.5f, 0);
+ cairo_line_to (cr, (gint)b + 0.5f, trc->priv->chart_height);
+ cairo_stroke (cr);
+ }
+
+ /* do horizontal lines */
+ for (i=1; i<10; i++) {
+ b = ((gdouble) i * divheight);
+ cairo_move_to (cr, 0, (gint)b + 0.5f);
+ cairo_line_to (cr, trc->priv->chart_width, (int)b + 0.5f);
+ cairo_stroke (cr);
+ }
+
+ cairo_restore (cr);
+}
+
+/**
+ * gcm_trc_widget_map_to_display:
+ **/
+static void
+gcm_trc_widget_map_to_display (GcmTrcWidget *trc, gdouble x, gdouble y, gdouble *x_retval, gdouble *y_retval)
+{
+ GcmTrcWidgetPrivate *priv = trc->priv;
+
+ *x_retval = (x * (priv->chart_width - 1)) + priv->x_offset;
+ *y_retval = ((priv->chart_height - 1) - y * (priv->chart_height - 1)) - priv->y_offset;
+}
+
+/**
+ * gcm_trc_widget_map_from_display:
+ **/
+static void
+gcm_trc_widget_map_from_display (GcmTrcWidget *trc, gdouble x, gdouble y, gdouble *x_retval, gdouble *y_retval)
+{
+ GcmTrcWidgetPrivate *priv = trc->priv;
+
+ *x_retval = ((gdouble) x - priv->x_offset) / (priv->chart_width - 1);
+ *y_retval = 1.0 - ((gdouble) y + priv->y_offset) / (priv->chart_height - 1);
+}
+
+/**
+ * gcm_trc_widget_draw_line:
+ **/
+static void
+gcm_trc_widget_draw_line (GcmTrcWidget *trc, cairo_t *cr)
+{
+ gdouble wx, wy;
+ GcmTrcWidgetPrivate *priv = trc->priv;
+ GcmClutData tmp;
+ gfloat i;
+ gfloat value;
+ const gfloat size = 256.0f;
+
+ cairo_save (cr);
+
+
+ /* do red */
+ cairo_set_line_width (cr, 3);
+ cairo_set_source_rgb (cr, 0.5f, 0.0f, 0.0f);
+ for (i=0; i<size; i++) {
+ tmp = priv->data[(guint)i];
+ value = tmp.red/65536.0f;
+ gcm_trc_widget_map_to_display (trc, i/size, value, &wx, &wy);
+ if (i == 0)
+ cairo_move_to (cr, wx, wy);
+ else
+ cairo_line_to (cr, wx, wy);
+ }
+ cairo_stroke_preserve (cr);
+ cairo_set_line_width (cr, 2);
+ cairo_set_source_rgb (cr, 1.0f, 0.0f, 0.0f);
+ cairo_stroke (cr);
+
+ /* do green */
+ cairo_set_line_width (cr, 3);
+ cairo_set_source_rgb (cr, 0.0f, 0.5f, 0.0f);
+ for (i=0; i<size; i++) {
+ tmp = priv->data[(guint)i];
+ value = tmp.green/65536.0f;
+ gcm_trc_widget_map_to_display (trc, i/size, value, &wx, &wy);
+ if (i == 0)
+ cairo_move_to (cr, wx, wy);
+ else
+ cairo_line_to (cr, wx, wy);
+ }
+ cairo_stroke_preserve (cr);
+ cairo_set_line_width (cr, 2);
+ cairo_set_source_rgb (cr, 0.0f, 1.0f, 0.0f);
+ cairo_stroke (cr);
+
+ /* do blue */
+ cairo_set_line_width (cr, 3);
+ cairo_set_source_rgb (cr, 0.0f, 0.0f, 0.5f);
+ for (i=0; i<size; i++) {
+ tmp = priv->data[(guint)i];
+ value = tmp.blue/65536.0f;
+ gcm_trc_widget_map_to_display (trc, i/size, value, &wx, &wy);
+ if (i == 0)
+ cairo_move_to (cr, wx, wy);
+ else
+ cairo_line_to (cr, wx, wy);
+ }
+ cairo_stroke_preserve (cr);
+ cairo_set_line_width (cr, 2);
+ cairo_set_source_rgb (cr, 0.0f, 0.0f, 1.0f);
+ cairo_stroke (cr);
+
+ cairo_restore (cr);
+}
+
+/**
+ * gcm_trc_widget_draw_bounding_box:
+ **/
+static void
+gcm_trc_widget_draw_bounding_box (cairo_t *cr, gint x, gint y, gint width, gint height)
+{
+ /* background */
+ cairo_rectangle (cr, x, y, width, height);
+ cairo_set_source_rgb (cr, 1, 1, 1);
+ cairo_fill (cr);
+
+ /* solid outline box */
+ cairo_rectangle (cr, x + 0.5f, y + 0.5f, width - 1, height - 1);
+ cairo_set_source_rgb (cr, 0.1, 0.1, 0.1);
+ cairo_set_line_width (cr, 1);
+ cairo_stroke (cr);
+}
+
+/**
+ * gcm_trc_widget_draw_trc:
+ *
+ * Draw the complete trc, with the box, the grid, the horseshoe and the shading.
+ **/
+static void
+gcm_trc_widget_draw_trc (GtkWidget *trc_widget, cairo_t *cr)
+{
+ GtkAllocation allocation;
+
+ GcmTrcWidget *trc = (GcmTrcWidget*) trc_widget;
+ g_return_if_fail (trc != NULL);
+ g_return_if_fail (GCM_IS_TRC_WIDGET (trc));
+
+ cairo_save (cr);
+
+ /* make size adjustment */
+ gtk_widget_get_allocation (trc_widget, &allocation);
+ trc->priv->chart_height = allocation.height;
+ trc->priv->chart_width = allocation.width;
+ trc->priv->x_offset = 1;
+ trc->priv->y_offset = 1;
+
+ /* trc background */
+ gcm_trc_widget_draw_bounding_box (cr, 0, 0, trc->priv->chart_width, trc->priv->chart_height);
+ if (trc->priv->use_grid)
+ gcm_trc_widget_draw_grid (trc, cr);
+
+ gcm_trc_widget_draw_line (trc, cr);
+
+ cairo_restore (cr);
+}
+
+/**
+ * gcm_trc_widget_expose:
+ *
+ * Just repaint the entire trc widget on expose.
+ **/
+static gboolean
+gcm_trc_widget_expose (GtkWidget *trc, GdkEventExpose *event)
+{
+ cairo_t *cr;
+
+ /* get a cairo_t */
+ cr = gdk_cairo_create (gtk_widget_get_window (trc));
+ cairo_rectangle (cr,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+ cairo_clip (cr);
+ ((GcmTrcWidget *)trc)->priv->cr = cr;
+
+ gcm_trc_widget_draw_trc (trc, cr);
+
+ cairo_destroy (cr);
+ return FALSE;
+}
+
+/**
+ * gcm_trc_widget_new:
+ * Return value: A new GcmTrcWidget object.
+ **/
+GtkWidget *
+gcm_trc_widget_new (void)
+{
+ return g_object_new (GCM_TYPE_TRC_WIDGET, NULL);
+}
+
+/***************************************************************************
+ *** MAKE CHECK TESTS ***
+ ***************************************************************************/
+#ifdef EGG_TEST
+#include "egg-test.h"
+
+#include "gcm-profile.h"
+#include "gcm-xyz.h"
+
+void
+gcm_trc_widget_test (EggTest *test)
+{
+ GtkWidget *widget;
+ GtkWidget *image;
+ GtkWidget *dialog;
+ GtkWidget *vbox;
+ gboolean ret;
+ GError *error = NULL;
+ GcmProfile *profile;
+ gint response;
+ gchar *filename_profile;
+ gchar *filename_image;
+ GcmClutData *data;
+
+ if (!egg_test_start (test, "GcmTrcWidget"))
+ return;
+
+ /************************************************************/
+ egg_test_title (test, "get a TRC widget object");
+ widget = gcm_trc_widget_new ();
+ egg_test_assert (test, widget != NULL);
+
+ /************************************************************/
+ egg_test_title (test, "get filename of image file");
+ filename_image = egg_test_get_data_file ("trc-widget.png");
+ egg_test_assert (test, (filename_image != NULL));
+
+ /************************************************************/
+ egg_test_title (test, "get filename of data file");
+ filename_profile = egg_test_get_data_file ("AdobeGammaTest.icm");
+ egg_test_assert (test, (filename_profile != NULL));
+
+ profile = gcm_profile_new ();
+ gcm_profile_parse (profile, filename_profile, NULL);
+
+ ((GcmTrcWidget*)widget)->priv->data = gcm_profile_generate (profile, 256);
+
+ /* show in a dialog as an example */
+ dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, "Does TRC widget match\nthe picture below?");
+ image = gtk_image_new_from_file (filename_image);
+ vbox = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
+ gtk_box_pack_end (GTK_BOX(vbox), widget, TRUE, TRUE, 12);
+ gtk_box_pack_end (GTK_BOX(vbox), image, TRUE, TRUE, 12);
+ gtk_widget_set_size_request (widget, 300, 300);
+ gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
+ gtk_widget_show (widget);
+ gtk_widget_show (image);
+
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+ /************************************************************/
+ egg_test_title (test, "plotted as expected?");
+ egg_test_assert (test, (response == GTK_RESPONSE_YES));
+
+ gtk_widget_destroy (dialog);
+
+ g_object_unref (profile);
+ g_free (filename_profile);
+ g_free (filename_image);
+
+ egg_test_end (test);
+}
+#endif
+
diff --git a/src/gcm-trc-widget.h b/src/gcm-trc-widget.h
new file mode 100644
index 0000000..eb6c118
--- /dev/null
+++ b/src/gcm-trc-widget.h
@@ -0,0 +1,56 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006-2009 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GCM_TRC_WIDGET_H__
+#define __GCM_TRC_WIDGET_H__
+
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GCM_TYPE_TRC_WIDGET (gcm_trc_widget_get_type ())
+#define GCM_TRC_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GCM_TYPE_TRC_WIDGET, GcmTrcWidget))
+#define GCM_TRC_WIDGET_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj), GCM_TRC_WIDGET, GcmTrcWidgetClass))
+#define GCM_IS_TRC_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GCM_TYPE_TRC_WIDGET))
+#define GCM_IS_TRC_WIDGET_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj), EFF_TYPE_TRC_WIDGET))
+#define GCM_TRC_WIDGET_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj), GCM_TYPE_TRC_WIDGET, GcmTrcWidgetClass))
+
+typedef struct GcmTrcWidget GcmTrcWidget;
+typedef struct GcmTrcWidgetClass GcmTrcWidgetClass;
+typedef struct GcmTrcWidgetPrivate GcmTrcWidgetPrivate;
+
+struct GcmTrcWidget
+{
+ GtkDrawingArea parent;
+ GcmTrcWidgetPrivate *priv;
+};
+
+struct GcmTrcWidgetClass
+{
+ GtkDrawingAreaClass parent_class;
+};
+
+GType gcm_trc_widget_get_type (void);
+GtkWidget *gcm_trc_widget_new (void);
+
+G_END_DECLS
+
+#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]