1999-05-09 00:34:29 +08:00
|
|
|
/* Watercolor color_select_module, Raph Levien <raph@acm.org>, February 1998
|
|
|
|
*
|
1999-09-05 20:45:17 +08:00
|
|
|
* Ported to loadable color-selector, Sven Neumann <sven@gimp.org>, May 1999
|
1999-05-09 00:34:29 +08:00
|
|
|
*
|
2009-01-18 06:28:01 +08:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
1999-05-09 00:34:29 +08:00
|
|
|
* it under the terms of the GNU General Public License as published by
|
2009-01-18 06:28:01 +08:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
1999-05-09 00:34:29 +08:00
|
|
|
* (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
|
2018-07-12 05:27:07 +08:00
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
1999-05-09 00:34:29 +08:00
|
|
|
*/
|
|
|
|
|
2000-01-15 03:57:42 +08:00
|
|
|
#include "config.h"
|
1999-05-09 00:34:29 +08:00
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2012-05-03 09:36:22 +08:00
|
|
|
#include <gegl.h>
|
1999-05-09 00:34:29 +08:00
|
|
|
#include <gtk/gtk.h>
|
2000-01-26 01:46:56 +08:00
|
|
|
|
2001-01-24 07:56:18 +08:00
|
|
|
#include "libgimpcolor/gimpcolor.h"
|
|
|
|
#include "libgimpmath/gimpmath.h"
|
2002-10-21 22:15:02 +08:00
|
|
|
#include "libgimpmodule/gimpmodule.h"
|
2001-01-25 06:36:18 +08:00
|
|
|
#include "libgimpwidgets/gimpwidgets.h"
|
2001-01-24 07:56:18 +08:00
|
|
|
|
2002-10-30 23:12:30 +08:00
|
|
|
#include "libgimp/libgimp-intl.h"
|
2001-01-16 00:52:22 +08:00
|
|
|
|
|
|
|
|
2008-01-10 06:22:10 +08:00
|
|
|
#define COLORSEL_TYPE_WATER (colorsel_water_get_type ())
|
2002-10-20 18:14:17 +08:00
|
|
|
#define COLORSEL_WATER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), COLORSEL_TYPE_WATER, ColorselWater))
|
|
|
|
#define COLORSEL_WATER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), COLORSEL_TYPE_WATER, ColorselWaterClass))
|
|
|
|
#define COLORSEL_IS_WATER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), COLORSEL_TYPE_WATER))
|
|
|
|
#define COLORSEL_IS_WATER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), COLORSEL_TYPE_WATER))
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct _ColorselWater ColorselWater;
|
|
|
|
typedef struct _ColorselWaterClass ColorselWaterClass;
|
|
|
|
|
|
|
|
struct _ColorselWater
|
2001-01-16 00:52:22 +08:00
|
|
|
{
|
2016-05-28 06:38:57 +08:00
|
|
|
GimpColorSelector parent_instance;
|
2002-10-20 18:14:17 +08:00
|
|
|
|
2016-05-28 06:38:57 +08:00
|
|
|
GtkWidget *area;
|
2023-12-17 22:22:18 +08:00
|
|
|
GtkWidget *label;
|
2002-10-20 18:14:17 +08:00
|
|
|
|
2016-05-28 06:38:57 +08:00
|
|
|
gdouble last_x;
|
|
|
|
gdouble last_y;
|
|
|
|
|
|
|
|
gfloat pressure_adjust;
|
|
|
|
guint32 motion_time;
|
|
|
|
|
|
|
|
GimpColorConfig *config;
|
2023-12-17 11:28:35 +08:00
|
|
|
const Babl *format;
|
2002-10-20 18:14:17 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
struct _ColorselWaterClass
|
1999-05-09 00:34:29 +08:00
|
|
|
{
|
2002-10-20 18:14:17 +08:00
|
|
|
GimpColorSelectorClass parent_class;
|
1999-05-09 00:34:29 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2023-05-22 09:51:36 +08:00
|
|
|
GType colorsel_water_get_type (void);
|
2016-06-02 04:38:58 +08:00
|
|
|
|
|
|
|
static void colorsel_water_dispose (GObject *object);
|
|
|
|
|
2023-12-17 11:28:35 +08:00
|
|
|
static void colorsel_water_set_format (GimpColorSelector *selector,
|
|
|
|
const Babl *format);
|
2016-06-02 04:38:58 +08:00
|
|
|
static void colorsel_water_set_config (GimpColorSelector *selector,
|
|
|
|
GimpColorConfig *config);
|
|
|
|
|
2010-10-21 18:49:13 +08:00
|
|
|
static gboolean select_area_draw (GtkWidget *widget,
|
|
|
|
cairo_t *cr,
|
2016-06-02 04:38:58 +08:00
|
|
|
ColorselWater *water);
|
|
|
|
static gboolean button_press_event (GtkWidget *widget,
|
|
|
|
GdkEventButton *event,
|
|
|
|
ColorselWater *water);
|
|
|
|
static gboolean motion_notify_event (GtkWidget *widget,
|
|
|
|
GdkEventMotion *event,
|
|
|
|
ColorselWater *water);
|
|
|
|
static gboolean proximity_out_event (GtkWidget *widget,
|
|
|
|
GdkEventProximity *event,
|
|
|
|
ColorselWater *water);
|
|
|
|
static void pressure_adjust_update (GtkAdjustment *adj,
|
|
|
|
ColorselWater *water);
|
2002-10-20 18:14:17 +08:00
|
|
|
|
|
|
|
|
2002-10-20 20:40:30 +08:00
|
|
|
static const GimpModuleInfo colorsel_water_info =
|
2001-01-08 05:07:14 +08:00
|
|
|
{
|
2003-01-03 01:44:28 +08:00
|
|
|
GIMP_MODULE_ABI_VERSION,
|
2002-10-23 22:55:07 +08:00
|
|
|
N_("Watercolor style color selector"),
|
2001-01-08 05:07:14 +08:00
|
|
|
"Raph Levien <raph@acm.org>, Sven Neumann <sven@gimp.org>",
|
2006-03-10 21:12:15 +08:00
|
|
|
"v0.4",
|
|
|
|
"released under the GPL",
|
|
|
|
"1998-2006"
|
1999-05-09 00:34:29 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2008-01-10 06:22:10 +08:00
|
|
|
G_DEFINE_DYNAMIC_TYPE (ColorselWater, colorsel_water,
|
|
|
|
GIMP_TYPE_COLOR_SELECTOR)
|
2002-10-20 18:14:17 +08:00
|
|
|
|
|
|
|
|
2002-10-20 20:40:30 +08:00
|
|
|
G_MODULE_EXPORT const GimpModuleInfo *
|
|
|
|
gimp_module_query (GTypeModule *module)
|
|
|
|
{
|
|
|
|
return &colorsel_water_info;
|
|
|
|
}
|
|
|
|
|
2002-10-20 18:14:17 +08:00
|
|
|
G_MODULE_EXPORT gboolean
|
2002-10-20 20:40:30 +08:00
|
|
|
gimp_module_register (GTypeModule *module)
|
1999-05-09 00:34:29 +08:00
|
|
|
{
|
2008-01-10 06:22:10 +08:00
|
|
|
colorsel_water_register_type (module);
|
2001-01-08 05:07:14 +08:00
|
|
|
|
2002-10-20 18:14:17 +08:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
colorsel_water_class_init (ColorselWaterClass *klass)
|
|
|
|
{
|
2016-05-28 06:38:57 +08:00
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
2004-08-16 02:01:11 +08:00
|
|
|
GimpColorSelectorClass *selector_class = GIMP_COLOR_SELECTOR_CLASS (klass);
|
2002-10-20 18:14:17 +08:00
|
|
|
|
2016-05-28 06:38:57 +08:00
|
|
|
object_class->dispose = colorsel_water_dispose;
|
|
|
|
|
|
|
|
selector_class->name = _("Watercolor");
|
|
|
|
selector_class->help_id = "gimp-colorselector-watercolor";
|
2017-03-05 23:01:59 +08:00
|
|
|
selector_class->icon_name = GIMP_ICON_COLOR_SELECTOR_WATER;
|
2023-12-17 11:28:35 +08:00
|
|
|
selector_class->set_format = colorsel_water_set_format;
|
2016-05-28 06:38:57 +08:00
|
|
|
selector_class->set_config = colorsel_water_set_config;
|
2018-06-24 21:36:00 +08:00
|
|
|
|
|
|
|
gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (klass), "ColorselWater");
|
2008-01-10 06:22:10 +08:00
|
|
|
}
|
2002-10-20 18:14:17 +08:00
|
|
|
|
2008-01-10 06:22:10 +08:00
|
|
|
static void
|
|
|
|
colorsel_water_class_finalize (ColorselWaterClass *klass)
|
|
|
|
{
|
2002-10-20 18:14:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
colorsel_water_init (ColorselWater *water)
|
1999-05-09 00:34:29 +08:00
|
|
|
{
|
2011-10-02 20:09:45 +08:00
|
|
|
GtkWidget *hbox;
|
|
|
|
GtkWidget *frame;
|
|
|
|
GtkAdjustment *adj;
|
|
|
|
GtkWidget *scale;
|
2002-10-20 18:14:17 +08:00
|
|
|
|
|
|
|
water->pressure_adjust = 1.0;
|
|
|
|
|
2011-09-30 16:59:40 +08:00
|
|
|
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2);
|
2004-08-17 23:07:27 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (water), hbox, TRUE, TRUE, 0);
|
2002-10-20 18:14:17 +08:00
|
|
|
|
|
|
|
frame = gtk_frame_new (NULL);
|
|
|
|
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
|
2004-08-17 23:07:27 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), frame, TRUE, TRUE, 0);
|
2002-10-20 18:14:17 +08:00
|
|
|
|
2016-05-28 06:38:57 +08:00
|
|
|
water->area = gtk_drawing_area_new ();
|
|
|
|
gtk_container_add (GTK_CONTAINER (frame), water->area);
|
2010-10-21 18:49:13 +08:00
|
|
|
g_signal_connect (water->area, "draw",
|
|
|
|
G_CALLBACK (select_area_draw),
|
2016-05-28 06:38:57 +08:00
|
|
|
water);
|
2002-10-20 18:14:17 +08:00
|
|
|
|
|
|
|
/* Event signals */
|
2016-05-28 06:38:57 +08:00
|
|
|
g_signal_connect (water->area, "motion-notify-event",
|
2002-10-20 18:14:17 +08:00
|
|
|
G_CALLBACK (motion_notify_event),
|
|
|
|
water);
|
2016-05-28 06:38:57 +08:00
|
|
|
g_signal_connect (water->area, "button-press-event",
|
2002-10-20 18:14:17 +08:00
|
|
|
G_CALLBACK (button_press_event),
|
|
|
|
water);
|
2016-05-28 06:38:57 +08:00
|
|
|
g_signal_connect (water->area, "proximity-out-event",
|
2002-10-20 18:14:17 +08:00
|
|
|
G_CALLBACK (proximity_out_event),
|
|
|
|
water);
|
|
|
|
|
2016-05-28 06:38:57 +08:00
|
|
|
gtk_widget_add_events (water->area,
|
2004-08-15 23:31:20 +08:00
|
|
|
GDK_LEAVE_NOTIFY_MASK |
|
|
|
|
GDK_BUTTON_PRESS_MASK |
|
|
|
|
GDK_KEY_PRESS_MASK |
|
|
|
|
GDK_POINTER_MOTION_MASK |
|
|
|
|
GDK_POINTER_MOTION_HINT_MASK |
|
|
|
|
GDK_PROXIMITY_OUT_MASK);
|
2002-10-20 18:14:17 +08:00
|
|
|
|
2016-05-28 06:38:57 +08:00
|
|
|
gtk_widget_grab_focus (water->area);
|
2002-10-20 18:14:17 +08:00
|
|
|
|
2010-10-20 18:17:06 +08:00
|
|
|
adj = gtk_adjustment_new (200.0 - water->pressure_adjust * 100.0,
|
|
|
|
0.0, 200.0, 1.0, 1.0, 0.0);
|
2005-05-28 00:51:39 +08:00
|
|
|
g_signal_connect (adj, "value-changed",
|
2002-10-20 18:14:17 +08:00
|
|
|
G_CALLBACK (pressure_adjust_update),
|
|
|
|
water);
|
2004-08-17 23:07:27 +08:00
|
|
|
|
2011-10-02 20:09:45 +08:00
|
|
|
scale = gtk_scale_new (GTK_ORIENTATION_VERTICAL, adj);
|
2002-10-20 18:14:17 +08:00
|
|
|
gtk_scale_set_digits (GTK_SCALE (scale), 0);
|
|
|
|
gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE);
|
|
|
|
gimp_help_set_help_data (scale, _("Pressure"), NULL);
|
2004-08-17 23:07:27 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), scale, FALSE, FALSE, 0);
|
2002-10-20 18:14:17 +08:00
|
|
|
|
|
|
|
gtk_widget_show_all (hbox);
|
2023-12-17 22:22:18 +08:00
|
|
|
|
|
|
|
water->label = gtk_label_new (NULL);
|
|
|
|
gtk_widget_set_halign (water->label, GTK_ALIGN_START);
|
|
|
|
gtk_widget_set_vexpand (water->label, FALSE);
|
|
|
|
gtk_label_set_justify (GTK_LABEL (water->label), GTK_JUSTIFY_LEFT);
|
|
|
|
gtk_label_set_text (GTK_LABEL (water->label), _("Profile: sRGB"));
|
|
|
|
gtk_box_pack_start (GTK_BOX (water), water->label, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (water->label);
|
1999-05-09 00:34:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static gdouble
|
2001-01-08 05:07:14 +08:00
|
|
|
calc (gdouble x,
|
|
|
|
gdouble y,
|
|
|
|
gdouble angle)
|
1999-05-09 00:34:29 +08:00
|
|
|
{
|
2004-08-17 23:07:27 +08:00
|
|
|
gdouble s = 2.0 * sin (angle * G_PI / 180.0) * 256.0;
|
|
|
|
gdouble c = 2.0 * cos (angle * G_PI / 180.0) * 256.0;
|
2001-01-08 05:07:14 +08:00
|
|
|
|
2004-08-17 23:07:27 +08:00
|
|
|
return 128 + (x - 0.5) * c - (y - 0.5) * s;
|
1999-05-09 00:34:29 +08:00
|
|
|
}
|
|
|
|
|
2016-05-28 06:38:57 +08:00
|
|
|
static void
|
|
|
|
colorsel_water_dispose (GObject *object)
|
|
|
|
{
|
|
|
|
colorsel_water_set_config (GIMP_COLOR_SELECTOR (object), NULL);
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (colorsel_water_parent_class)->dispose (object);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2023-12-17 11:28:35 +08:00
|
|
|
colorsel_water_set_format (GimpColorSelector *selector,
|
|
|
|
const Babl *format)
|
2016-05-28 06:38:57 +08:00
|
|
|
{
|
|
|
|
ColorselWater *water = COLORSEL_WATER (selector);
|
|
|
|
|
2023-12-17 11:28:35 +08:00
|
|
|
if (water->format != format)
|
2016-05-28 06:38:57 +08:00
|
|
|
{
|
2023-12-17 11:28:35 +08:00
|
|
|
water->format = format;
|
2023-12-17 22:22:18 +08:00
|
|
|
|
|
|
|
if (format == NULL || babl_format_get_space (format) == babl_space ("sRGB"))
|
|
|
|
{
|
|
|
|
gtk_label_set_text (GTK_LABEL (water->label), _("Profile: sRGB"));
|
|
|
|
gimp_help_set_help_data (water->label, NULL, NULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GimpColorProfile *profile = NULL;
|
|
|
|
const gchar *icc;
|
|
|
|
gint icc_len;
|
|
|
|
|
|
|
|
icc = babl_space_get_icc (babl_format_get_space (format), &icc_len);
|
|
|
|
profile = gimp_color_profile_new_from_icc_profile ((const guint8 *) icc, icc_len, NULL);
|
|
|
|
|
|
|
|
if (profile != NULL)
|
|
|
|
{
|
|
|
|
gchar *text;
|
|
|
|
|
|
|
|
text = g_strdup_printf (_("Profile: %s"), gimp_color_profile_get_label (profile));
|
|
|
|
gtk_label_set_text (GTK_LABEL (water->label), text);
|
|
|
|
gimp_help_set_help_data (water->label,
|
|
|
|
gimp_color_profile_get_summary (profile),
|
|
|
|
NULL);
|
|
|
|
g_free (text);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gtk_label_set_markup (GTK_LABEL (water->label), _("Profile: <i>unknown</i>"));
|
|
|
|
gimp_help_set_help_data (water->label, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_clear_object (&profile);
|
|
|
|
}
|
2023-12-17 11:28:35 +08:00
|
|
|
gtk_widget_queue_draw (GTK_WIDGET (water));
|
2016-05-28 06:38:57 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-02 04:38:58 +08:00
|
|
|
static void
|
2023-12-17 11:28:35 +08:00
|
|
|
colorsel_water_set_config (GimpColorSelector *selector,
|
|
|
|
GimpColorConfig *config)
|
2016-06-02 04:38:58 +08:00
|
|
|
{
|
2023-12-17 11:28:35 +08:00
|
|
|
ColorselWater *water = COLORSEL_WATER (selector);
|
2016-06-02 04:38:58 +08:00
|
|
|
|
2023-12-17 11:28:35 +08:00
|
|
|
if (config != water->config)
|
|
|
|
g_set_object (&water->config, config);
|
2016-06-02 04:38:58 +08:00
|
|
|
}
|
|
|
|
|
2010-08-09 06:14:35 +08:00
|
|
|
static gboolean
|
2010-10-21 18:49:13 +08:00
|
|
|
select_area_draw (GtkWidget *widget,
|
|
|
|
cairo_t *cr,
|
|
|
|
ColorselWater *water)
|
1999-05-09 00:34:29 +08:00
|
|
|
{
|
2023-12-17 11:28:35 +08:00
|
|
|
const Babl *render_space;
|
|
|
|
const Babl *render_fish;
|
2010-10-21 18:49:13 +08:00
|
|
|
GdkRectangle area;
|
2010-08-09 06:14:35 +08:00
|
|
|
GtkAllocation allocation;
|
2010-10-21 18:49:13 +08:00
|
|
|
gdouble x1, y1, x2, y2;
|
2010-08-09 06:14:35 +08:00
|
|
|
gdouble dx;
|
|
|
|
gdouble dy;
|
|
|
|
cairo_surface_t *surface;
|
|
|
|
guchar *dest;
|
|
|
|
gdouble y;
|
|
|
|
gint j;
|
|
|
|
|
2010-10-21 18:49:13 +08:00
|
|
|
cairo_clip_extents (cr, &x1, &y1, &x2, &y2);
|
2010-08-09 06:14:35 +08:00
|
|
|
|
2010-10-21 18:49:13 +08:00
|
|
|
area.x = floor (x1);
|
|
|
|
area.y = floor (y1);
|
|
|
|
area.width = ceil (x2) - area.x;
|
|
|
|
area.height = ceil (y2) - area.y;
|
2009-10-18 00:58:28 +08:00
|
|
|
|
|
|
|
gtk_widget_get_allocation (widget, &allocation);
|
|
|
|
|
|
|
|
dx = 1.0 / allocation.width;
|
|
|
|
dy = 1.0 / allocation.height;
|
|
|
|
|
2023-12-17 11:28:35 +08:00
|
|
|
render_space = gimp_widget_get_render_space (widget, water->config);
|
|
|
|
render_fish = babl_fish (babl_format_with_space ("cairo-RGB24", water->format),
|
|
|
|
babl_format_with_space ("cairo-RGB24", render_space)),
|
|
|
|
|
2010-08-09 06:14:35 +08:00
|
|
|
surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
|
2010-10-21 18:49:13 +08:00
|
|
|
area.width,
|
|
|
|
area.height);
|
2010-08-09 06:14:35 +08:00
|
|
|
|
|
|
|
dest = cairo_image_surface_get_data (surface);
|
|
|
|
|
2010-10-21 18:49:13 +08:00
|
|
|
for (j = 0, y = area.y / allocation.height;
|
|
|
|
j < area.height;
|
2009-10-18 00:58:28 +08:00
|
|
|
j++, y += dy)
|
1999-05-09 00:34:29 +08:00
|
|
|
{
|
2004-08-17 23:07:27 +08:00
|
|
|
guchar *d = dest;
|
2004-08-16 02:01:11 +08:00
|
|
|
|
2004-08-17 23:07:27 +08:00
|
|
|
gdouble r = calc (0, y, 0);
|
|
|
|
gdouble g = calc (0, y, 120);
|
|
|
|
gdouble b = calc (0, y, 240);
|
1999-05-09 00:34:29 +08:00
|
|
|
|
2004-08-17 23:07:27 +08:00
|
|
|
gdouble dr = calc (dx, y, 0) - r;
|
|
|
|
gdouble dg = calc (dx, y, 120) - g;
|
|
|
|
gdouble db = calc (dx, y, 240) - b;
|
1999-05-09 00:34:29 +08:00
|
|
|
|
2010-08-09 06:14:35 +08:00
|
|
|
gint i;
|
|
|
|
|
2010-10-21 18:49:13 +08:00
|
|
|
r += area.x * dr;
|
|
|
|
g += area.x * dg;
|
|
|
|
b += area.x * db;
|
2004-08-16 02:01:11 +08:00
|
|
|
|
2010-10-21 18:49:13 +08:00
|
|
|
for (i = 0; i < area.width; i++)
|
2004-08-15 23:31:20 +08:00
|
|
|
{
|
2010-08-09 06:14:35 +08:00
|
|
|
GIMP_CAIRO_RGB24_SET_PIXEL (d,
|
|
|
|
CLAMP ((gint) r, 0, 255),
|
|
|
|
CLAMP ((gint) g, 0, 255),
|
|
|
|
CLAMP ((gint) b, 0, 255));
|
2004-08-16 02:01:11 +08:00
|
|
|
|
2004-08-15 23:31:20 +08:00
|
|
|
r += dr;
|
|
|
|
g += dg;
|
|
|
|
b += db;
|
2004-08-17 23:07:27 +08:00
|
|
|
|
2010-08-09 06:14:35 +08:00
|
|
|
d += 4;
|
2004-08-15 23:31:20 +08:00
|
|
|
}
|
2004-08-16 02:01:11 +08:00
|
|
|
|
2023-12-17 11:28:35 +08:00
|
|
|
babl_process (render_fish, dest, dest, area.width);
|
2010-08-09 06:14:35 +08:00
|
|
|
dest += cairo_image_surface_get_stride (surface);
|
2004-08-17 23:07:27 +08:00
|
|
|
}
|
2004-08-16 02:01:11 +08:00
|
|
|
|
2010-08-09 06:14:35 +08:00
|
|
|
cairo_surface_mark_dirty (surface);
|
2010-10-21 18:49:13 +08:00
|
|
|
cairo_set_source_surface (cr, surface, area.x, area.y);
|
2010-08-09 06:14:35 +08:00
|
|
|
cairo_surface_destroy (surface);
|
|
|
|
|
|
|
|
cairo_paint (cr);
|
|
|
|
|
|
|
|
return FALSE;
|
1999-05-09 00:34:29 +08:00
|
|
|
}
|
|
|
|
|
2001-01-15 20:20:38 +08:00
|
|
|
static void
|
2002-10-29 04:13:17 +08:00
|
|
|
add_pigment (ColorselWater *water,
|
2004-08-15 23:31:20 +08:00
|
|
|
gboolean erase,
|
|
|
|
gdouble x,
|
|
|
|
gdouble y,
|
|
|
|
gdouble much)
|
1999-05-09 00:34:29 +08:00
|
|
|
{
|
2004-08-16 02:01:11 +08:00
|
|
|
GimpColorSelector *selector = GIMP_COLOR_SELECTOR (water);
|
app, libgimpwidgets, modules: color selectors are now partly space-invaded.
What this commit does is keep the same code logic while moving to
GeglColor. Yet it's not **really** space-invaded yet. What we need to do
now:
1. Take into account the image space, and this is what we must navigate
through, in particular for various representations of RGB or HSV.
I.e. that if the active image is in anyRGB, the RGB values shown must
be within anyRGB. Right now, everything is still shown/used as sRGB
(even though it's properly retrieved and transformed to the target
space thanks to GeglColor).
2. Show space info to make things clear and explicit, by adding some
label somewhere.
3. Allow to switch between image and softproof spaces, regarding
out-of-gamut display. I.e. that while RGB/HSV must be shown within
the image space (assuming it's anyRGB), we may want to show
out-of-gamut area (pink areas) within the softproof space. This may
mean adding a checkbox. Or maybe simply taking into account whether
we are in softproof mode or not?
4. We can likely move off gimp_widget_get_color_transform() into using
gimp_widget_get_render_space() for display drawing. We don't need any
soft-proofing or black point compensation for any of these widgets so
pure babl is fine. Indeed we want to show any in-gamut color
correctly (and not transformed according to specific intents or
through soft-proofing). We will take care of the proofing case with
out-of-gamut area showing only.
5. In the various drawing functions, we should move to
CAIRO_FORMAT_RGBA128F. The color selection area might be wide enough
that it makes sense to be more accurate, especially as we are
essentially showing color gradients in 1 or 2 directions in these
various widgets.
2023-12-12 16:01:17 +08:00
|
|
|
GeglColor *color = gimp_color_selector_get_color (selector);
|
|
|
|
gdouble rgb[3];
|
2002-10-29 04:13:17 +08:00
|
|
|
|
2004-08-16 02:01:11 +08:00
|
|
|
much *= (gdouble) water->pressure_adjust;
|
1999-05-10 05:50:33 +08:00
|
|
|
|
app, libgimpwidgets, modules: color selectors are now partly space-invaded.
What this commit does is keep the same code logic while moving to
GeglColor. Yet it's not **really** space-invaded yet. What we need to do
now:
1. Take into account the image space, and this is what we must navigate
through, in particular for various representations of RGB or HSV.
I.e. that if the active image is in anyRGB, the RGB values shown must
be within anyRGB. Right now, everything is still shown/used as sRGB
(even though it's properly retrieved and transformed to the target
space thanks to GeglColor).
2. Show space info to make things clear and explicit, by adding some
label somewhere.
3. Allow to switch between image and softproof spaces, regarding
out-of-gamut display. I.e. that while RGB/HSV must be shown within
the image space (assuming it's anyRGB), we may want to show
out-of-gamut area (pink areas) within the softproof space. This may
mean adding a checkbox. Or maybe simply taking into account whether
we are in softproof mode or not?
4. We can likely move off gimp_widget_get_color_transform() into using
gimp_widget_get_render_space() for display drawing. We don't need any
soft-proofing or black point compensation for any of these widgets so
pure babl is fine. Indeed we want to show any in-gamut color
correctly (and not transformed according to specific intents or
through soft-proofing). We will take care of the proofing case with
out-of-gamut area showing only.
5. In the various drawing functions, we should move to
CAIRO_FORMAT_RGBA128F. The color selection area might be wide enough
that it makes sense to be more accurate, especially as we are
essentially showing color gradients in 1 or 2 directions in these
various widgets.
2023-12-12 16:01:17 +08:00
|
|
|
/* TODO: both render (draw() function) and selecting colors should navigate
|
|
|
|
* the target color space, not sRGB.
|
|
|
|
*/
|
|
|
|
gegl_color_get_pixel (color, babl_format ("R'G'B' double"), rgb);
|
2002-10-23 22:55:07 +08:00
|
|
|
if (erase)
|
1999-05-09 00:34:29 +08:00
|
|
|
{
|
app, libgimpwidgets, modules: color selectors are now partly space-invaded.
What this commit does is keep the same code logic while moving to
GeglColor. Yet it's not **really** space-invaded yet. What we need to do
now:
1. Take into account the image space, and this is what we must navigate
through, in particular for various representations of RGB or HSV.
I.e. that if the active image is in anyRGB, the RGB values shown must
be within anyRGB. Right now, everything is still shown/used as sRGB
(even though it's properly retrieved and transformed to the target
space thanks to GeglColor).
2. Show space info to make things clear and explicit, by adding some
label somewhere.
3. Allow to switch between image and softproof spaces, regarding
out-of-gamut display. I.e. that while RGB/HSV must be shown within
the image space (assuming it's anyRGB), we may want to show
out-of-gamut area (pink areas) within the softproof space. This may
mean adding a checkbox. Or maybe simply taking into account whether
we are in softproof mode or not?
4. We can likely move off gimp_widget_get_color_transform() into using
gimp_widget_get_render_space() for display drawing. We don't need any
soft-proofing or black point compensation for any of these widgets so
pure babl is fine. Indeed we want to show any in-gamut color
correctly (and not transformed according to specific intents or
through soft-proofing). We will take care of the proofing case with
out-of-gamut area showing only.
5. In the various drawing functions, we should move to
CAIRO_FORMAT_RGBA128F. The color selection area might be wide enough
that it makes sense to be more accurate, especially as we are
essentially showing color gradients in 1 or 2 directions in these
various widgets.
2023-12-12 16:01:17 +08:00
|
|
|
rgb[0] = 1.0 - (1.0 - rgb[0]) * (1.0 - much);
|
|
|
|
rgb[1] = 1.0 - (1.0 - rgb[1]) * (1.0 - much);
|
|
|
|
rgb[2] = 1.0 - (1.0 - rgb[2]) * (1.0 - much);
|
1999-05-09 00:34:29 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-08-17 23:07:27 +08:00
|
|
|
gdouble r = calc (x, y, 0) / 256.0;
|
|
|
|
gdouble g = calc (x, y, 120) / 256.0;
|
|
|
|
gdouble b = calc (x, y, 240) / 256.0;
|
1999-05-09 00:34:29 +08:00
|
|
|
|
app, libgimpwidgets, modules: color selectors are now partly space-invaded.
What this commit does is keep the same code logic while moving to
GeglColor. Yet it's not **really** space-invaded yet. What we need to do
now:
1. Take into account the image space, and this is what we must navigate
through, in particular for various representations of RGB or HSV.
I.e. that if the active image is in anyRGB, the RGB values shown must
be within anyRGB. Right now, everything is still shown/used as sRGB
(even though it's properly retrieved and transformed to the target
space thanks to GeglColor).
2. Show space info to make things clear and explicit, by adding some
label somewhere.
3. Allow to switch between image and softproof spaces, regarding
out-of-gamut display. I.e. that while RGB/HSV must be shown within
the image space (assuming it's anyRGB), we may want to show
out-of-gamut area (pink areas) within the softproof space. This may
mean adding a checkbox. Or maybe simply taking into account whether
we are in softproof mode or not?
4. We can likely move off gimp_widget_get_color_transform() into using
gimp_widget_get_render_space() for display drawing. We don't need any
soft-proofing or black point compensation for any of these widgets so
pure babl is fine. Indeed we want to show any in-gamut color
correctly (and not transformed according to specific intents or
through soft-proofing). We will take care of the proofing case with
out-of-gamut area showing only.
5. In the various drawing functions, we should move to
CAIRO_FORMAT_RGBA128F. The color selection area might be wide enough
that it makes sense to be more accurate, especially as we are
essentially showing color gradients in 1 or 2 directions in these
various widgets.
2023-12-12 16:01:17 +08:00
|
|
|
rgb[0] *= (1.0 - (1.0 - r) * much);
|
|
|
|
rgb[1] *= (1.0 - (1.0 - g) * much);
|
|
|
|
rgb[2] *= (1.0 - (1.0 - b) * much);
|
1999-05-09 00:34:29 +08:00
|
|
|
}
|
|
|
|
|
app, libgimpwidgets, modules: color selectors are now partly space-invaded.
What this commit does is keep the same code logic while moving to
GeglColor. Yet it's not **really** space-invaded yet. What we need to do
now:
1. Take into account the image space, and this is what we must navigate
through, in particular for various representations of RGB or HSV.
I.e. that if the active image is in anyRGB, the RGB values shown must
be within anyRGB. Right now, everything is still shown/used as sRGB
(even though it's properly retrieved and transformed to the target
space thanks to GeglColor).
2. Show space info to make things clear and explicit, by adding some
label somewhere.
3. Allow to switch between image and softproof spaces, regarding
out-of-gamut display. I.e. that while RGB/HSV must be shown within
the image space (assuming it's anyRGB), we may want to show
out-of-gamut area (pink areas) within the softproof space. This may
mean adding a checkbox. Or maybe simply taking into account whether
we are in softproof mode or not?
4. We can likely move off gimp_widget_get_color_transform() into using
gimp_widget_get_render_space() for display drawing. We don't need any
soft-proofing or black point compensation for any of these widgets so
pure babl is fine. Indeed we want to show any in-gamut color
correctly (and not transformed according to specific intents or
through soft-proofing). We will take care of the proofing case with
out-of-gamut area showing only.
5. In the various drawing functions, we should move to
CAIRO_FORMAT_RGBA128F. The color selection area might be wide enough
that it makes sense to be more accurate, especially as we are
essentially showing color gradients in 1 or 2 directions in these
various widgets.
2023-12-12 16:01:17 +08:00
|
|
|
rgb[0] = CLAMP (rgb[0], 0.0, 1.0);
|
|
|
|
rgb[1] = CLAMP (rgb[1], 0.0, 1.0);
|
|
|
|
rgb[2] = CLAMP (rgb[2], 0.0, 1.0);
|
|
|
|
gegl_color_set_pixel (color, babl_format ("R'G'B' double"), rgb);
|
2004-08-17 23:07:27 +08:00
|
|
|
|
app, libgimpwidgets, modules: color selectors are now partly space-invaded.
What this commit does is keep the same code logic while moving to
GeglColor. Yet it's not **really** space-invaded yet. What we need to do
now:
1. Take into account the image space, and this is what we must navigate
through, in particular for various representations of RGB or HSV.
I.e. that if the active image is in anyRGB, the RGB values shown must
be within anyRGB. Right now, everything is still shown/used as sRGB
(even though it's properly retrieved and transformed to the target
space thanks to GeglColor).
2. Show space info to make things clear and explicit, by adding some
label somewhere.
3. Allow to switch between image and softproof spaces, regarding
out-of-gamut display. I.e. that while RGB/HSV must be shown within
the image space (assuming it's anyRGB), we may want to show
out-of-gamut area (pink areas) within the softproof space. This may
mean adding a checkbox. Or maybe simply taking into account whether
we are in softproof mode or not?
4. We can likely move off gimp_widget_get_color_transform() into using
gimp_widget_get_render_space() for display drawing. We don't need any
soft-proofing or black point compensation for any of these widgets so
pure babl is fine. Indeed we want to show any in-gamut color
correctly (and not transformed according to specific intents or
through soft-proofing). We will take care of the proofing case with
out-of-gamut area showing only.
5. In the various drawing functions, we should move to
CAIRO_FORMAT_RGBA128F. The color selection area might be wide enough
that it makes sense to be more accurate, especially as we are
essentially showing color gradients in 1 or 2 directions in these
various widgets.
2023-12-12 16:01:17 +08:00
|
|
|
gimp_color_selector_set_color (selector, color);
|
2002-10-29 04:13:17 +08:00
|
|
|
|
app, libgimpwidgets, modules: color selectors are now partly space-invaded.
What this commit does is keep the same code logic while moving to
GeglColor. Yet it's not **really** space-invaded yet. What we need to do
now:
1. Take into account the image space, and this is what we must navigate
through, in particular for various representations of RGB or HSV.
I.e. that if the active image is in anyRGB, the RGB values shown must
be within anyRGB. Right now, everything is still shown/used as sRGB
(even though it's properly retrieved and transformed to the target
space thanks to GeglColor).
2. Show space info to make things clear and explicit, by adding some
label somewhere.
3. Allow to switch between image and softproof spaces, regarding
out-of-gamut display. I.e. that while RGB/HSV must be shown within
the image space (assuming it's anyRGB), we may want to show
out-of-gamut area (pink areas) within the softproof space. This may
mean adding a checkbox. Or maybe simply taking into account whether
we are in softproof mode or not?
4. We can likely move off gimp_widget_get_color_transform() into using
gimp_widget_get_render_space() for display drawing. We don't need any
soft-proofing or black point compensation for any of these widgets so
pure babl is fine. Indeed we want to show any in-gamut color
correctly (and not transformed according to specific intents or
through soft-proofing). We will take care of the proofing case with
out-of-gamut area showing only.
5. In the various drawing functions, we should move to
CAIRO_FORMAT_RGBA128F. The color selection area might be wide enough
that it makes sense to be more accurate, especially as we are
essentially showing color gradients in 1 or 2 directions in these
various widgets.
2023-12-12 16:01:17 +08:00
|
|
|
g_object_unref (color);
|
1999-05-09 00:34:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2002-10-29 04:13:17 +08:00
|
|
|
draw_brush (ColorselWater *water,
|
2004-08-15 23:31:20 +08:00
|
|
|
GtkWidget *widget,
|
|
|
|
gboolean erase,
|
|
|
|
gdouble x,
|
|
|
|
gdouble y,
|
|
|
|
gdouble pressure)
|
1999-05-09 00:34:29 +08:00
|
|
|
{
|
2004-08-17 23:07:27 +08:00
|
|
|
gdouble much = sqrt (SQR (x - water->last_x) + SQR (y - water->last_y));
|
1999-05-09 00:34:29 +08:00
|
|
|
|
2004-08-17 23:07:27 +08:00
|
|
|
add_pigment (water, erase, x, y, much * pressure);
|
1999-05-09 00:34:29 +08:00
|
|
|
|
2004-08-17 23:07:27 +08:00
|
|
|
water->last_x = x;
|
|
|
|
water->last_y = y;
|
1999-05-09 00:34:29 +08:00
|
|
|
}
|
|
|
|
|
2002-10-20 18:14:17 +08:00
|
|
|
static gboolean
|
2001-01-08 05:07:14 +08:00
|
|
|
button_press_event (GtkWidget *widget,
|
2004-08-15 23:31:20 +08:00
|
|
|
GdkEventButton *event,
|
|
|
|
ColorselWater *water)
|
1999-05-09 00:34:29 +08:00
|
|
|
{
|
2009-10-18 00:58:28 +08:00
|
|
|
GtkAllocation allocation;
|
|
|
|
gboolean erase;
|
2001-01-16 00:52:22 +08:00
|
|
|
|
2009-10-18 00:58:28 +08:00
|
|
|
gtk_widget_get_allocation (widget, &allocation);
|
|
|
|
|
|
|
|
water->last_x = event->x / allocation.width;
|
|
|
|
water->last_y = event->y / allocation.height;
|
1999-05-09 00:34:29 +08:00
|
|
|
|
2004-08-17 23:07:27 +08:00
|
|
|
erase = (event->button != 1);
|
2002-10-20 18:14:17 +08:00
|
|
|
/* FIXME: (event->source == GDK_SOURCE_ERASER) */
|
1999-05-09 00:34:29 +08:00
|
|
|
|
2006-03-10 21:12:15 +08:00
|
|
|
if (event->state & GDK_SHIFT_MASK)
|
|
|
|
erase = !erase;
|
|
|
|
|
2004-08-17 23:07:27 +08:00
|
|
|
add_pigment (water, erase, water->last_x, water->last_y, 0.05);
|
|
|
|
|
2002-10-20 18:14:17 +08:00
|
|
|
water->motion_time = event->time;
|
1999-05-09 00:34:29 +08:00
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2002-10-20 18:14:17 +08:00
|
|
|
static gboolean
|
2001-01-08 05:07:14 +08:00
|
|
|
motion_notify_event (GtkWidget *widget,
|
2004-08-15 23:31:20 +08:00
|
|
|
GdkEventMotion *event,
|
|
|
|
ColorselWater *water)
|
1999-05-09 00:34:29 +08:00
|
|
|
{
|
2009-10-18 00:58:28 +08:00
|
|
|
GtkAllocation allocation;
|
2002-10-20 18:14:17 +08:00
|
|
|
GdkTimeCoord **coords;
|
2001-01-16 00:52:22 +08:00
|
|
|
gint nevents;
|
|
|
|
gint i;
|
|
|
|
gboolean erase;
|
|
|
|
|
2009-10-18 00:58:28 +08:00
|
|
|
gtk_widget_get_allocation (widget, &allocation);
|
|
|
|
|
2001-01-08 05:07:14 +08:00
|
|
|
if (event->state & (GDK_BUTTON1_MASK |
|
2004-08-15 23:31:20 +08:00
|
|
|
GDK_BUTTON2_MASK |
|
|
|
|
GDK_BUTTON3_MASK |
|
|
|
|
GDK_BUTTON4_MASK))
|
1999-05-09 00:34:29 +08:00
|
|
|
{
|
2006-03-10 21:12:15 +08:00
|
|
|
guint32 last_motion_time = event->time;
|
2002-10-20 18:14:17 +08:00
|
|
|
|
|
|
|
erase = ((event->state &
|
|
|
|
(GDK_BUTTON2_MASK | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK)) ||
|
|
|
|
FALSE);
|
|
|
|
/* FIXME: (event->source == GDK_SOURCE_ERASER) */
|
|
|
|
|
2006-03-10 21:12:15 +08:00
|
|
|
if (event->state & GDK_SHIFT_MASK)
|
|
|
|
erase = !erase;
|
|
|
|
|
2002-10-20 18:14:17 +08:00
|
|
|
water->motion_time = event->time;
|
|
|
|
|
|
|
|
if (gdk_device_get_history (event->device,
|
|
|
|
event->window,
|
|
|
|
last_motion_time,
|
|
|
|
event->time,
|
|
|
|
&coords,
|
|
|
|
&nevents))
|
2004-08-15 23:31:20 +08:00
|
|
|
{
|
|
|
|
for (i = 0; i < nevents; i++)
|
2002-10-20 18:14:17 +08:00
|
|
|
{
|
|
|
|
gdouble x = 0.0;
|
|
|
|
gdouble y = 0.0;
|
|
|
|
gdouble pressure = 0.5;
|
|
|
|
|
|
|
|
gdk_device_get_axis (event->device, coords[i]->axes,
|
|
|
|
GDK_AXIS_X, &x);
|
|
|
|
gdk_device_get_axis (event->device, coords[i]->axes,
|
|
|
|
GDK_AXIS_Y, &y);
|
|
|
|
gdk_device_get_axis (event->device, coords[i]->axes,
|
|
|
|
GDK_AXIS_PRESSURE, &pressure);
|
|
|
|
|
2004-08-17 23:07:27 +08:00
|
|
|
draw_brush (water, widget, erase,
|
2009-10-18 00:58:28 +08:00
|
|
|
x / allocation.width,
|
|
|
|
y / allocation.height, pressure);
|
2002-10-20 18:14:17 +08:00
|
|
|
}
|
2001-01-16 00:52:22 +08:00
|
|
|
|
2018-06-24 01:54:19 +08:00
|
|
|
gdk_device_free_history (coords, nevents);
|
2004-08-15 23:31:20 +08:00
|
|
|
}
|
1999-05-09 00:34:29 +08:00
|
|
|
else
|
2004-08-15 23:31:20 +08:00
|
|
|
{
|
2002-10-20 18:14:17 +08:00
|
|
|
gdouble pressure = 0.5;
|
|
|
|
|
|
|
|
gdk_event_get_axis ((GdkEvent *) event, GDK_AXIS_PRESSURE, &pressure);
|
|
|
|
|
2004-08-17 23:07:27 +08:00
|
|
|
draw_brush (water, widget, erase,
|
2009-10-18 00:58:28 +08:00
|
|
|
event->x / allocation.width,
|
|
|
|
event->y / allocation.height, pressure);
|
2004-08-15 23:31:20 +08:00
|
|
|
}
|
1999-05-09 00:34:29 +08:00
|
|
|
}
|
2002-10-20 18:14:17 +08:00
|
|
|
|
2008-09-04 03:24:51 +08:00
|
|
|
/* Ask for more motion events in case the event was a hint */
|
|
|
|
gdk_event_request_motions (event);
|
1999-05-09 00:34:29 +08:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2002-10-20 18:14:17 +08:00
|
|
|
static gboolean
|
2001-01-08 05:07:14 +08:00
|
|
|
proximity_out_event (GtkWidget *widget,
|
2001-01-16 00:52:22 +08:00
|
|
|
GdkEventProximity *event,
|
2004-08-15 23:31:20 +08:00
|
|
|
ColorselWater *water)
|
1999-05-09 00:34:29 +08:00
|
|
|
{
|
2001-01-16 00:52:22 +08:00
|
|
|
return TRUE;
|
1999-05-09 00:34:29 +08:00
|
|
|
}
|
|
|
|
|
1999-05-10 05:50:33 +08:00
|
|
|
static void
|
2001-01-08 05:07:14 +08:00
|
|
|
pressure_adjust_update (GtkAdjustment *adj,
|
2004-08-15 23:31:20 +08:00
|
|
|
ColorselWater *water)
|
1999-05-10 05:50:33 +08:00
|
|
|
{
|
2009-10-09 17:57:17 +08:00
|
|
|
water->pressure_adjust = (gtk_adjustment_get_upper (adj) -
|
|
|
|
gtk_adjustment_get_value (adj)) / 100.0;
|
1999-09-05 20:45:17 +08:00
|
|
|
}
|