From e42129241681dde7adae7d20697e7b421682fbb4 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 18:23:22 +0200 Subject: Adding upstream version 2.10.22. Signed-off-by: Daniel Baumann --- app/tools/gimpcolortool.c | 702 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 702 insertions(+) create mode 100644 app/tools/gimpcolortool.c (limited to 'app/tools/gimpcolortool.c') diff --git a/app/tools/gimpcolortool.c b/app/tools/gimpcolortool.c new file mode 100644 index 0000000..683a713 --- /dev/null +++ b/app/tools/gimpcolortool.c @@ -0,0 +1,702 @@ +/* GIMP - The GNU Image Manipulation Program + * Copyright (C) 1995-2001 Spencer Kimball, Peter Mattis, and others + * + * 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 3 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, see . + */ + +#include "config.h" + +#include +#include + +#include "libgimpcolor/gimpcolor.h" +#include "libgimpwidgets/gimpwidgets.h" + +#include "tools-types.h" + +#include "config/gimpdisplayconfig.h" + +#include "core/gimp.h" +#include "core/gimpdata.h" +#include "core/gimpimage.h" +#include "core/gimpimage-pick-color.h" +#include "core/gimpimage-pick-item.h" +#include "core/gimpimage-sample-points.h" +#include "core/gimpmarshal.h" +#include "core/gimpsamplepoint.h" + +#include "widgets/gimpcolormapeditor.h" +#include "widgets/gimpdialogfactory.h" +#include "widgets/gimpdockable.h" +#include "widgets/gimpdockcontainer.h" +#include "widgets/gimppaletteeditor.h" +#include "widgets/gimpwidgets-utils.h" +#include "widgets/gimpwindowstrategy.h" + +#include "display/gimpcanvasitem.h" +#include "display/gimpdisplay.h" +#include "display/gimpdisplayshell.h" +#include "display/gimpdisplayshell-appearance.h" + +#include "gimpcoloroptions.h" +#include "gimpcolortool.h" +#include "gimpsamplepointtool.h" +#include "gimptoolcontrol.h" + +#include "gimp-intl.h" + + +enum +{ + PICKED, + LAST_SIGNAL +}; + + +/* local function prototypes */ + +static void gimp_color_tool_finalize (GObject *object); + +static void gimp_color_tool_button_press (GimpTool *tool, + const GimpCoords *coords, + guint32 time, + GdkModifierType state, + GimpButtonPressType press_type, + GimpDisplay *display); +static void gimp_color_tool_button_release (GimpTool *tool, + const GimpCoords *coords, + guint32 time, + GdkModifierType state, + GimpButtonReleaseType release_type, + GimpDisplay *display); +static void gimp_color_tool_motion (GimpTool *tool, + const GimpCoords *coords, + guint32 time, + GdkModifierType state, + GimpDisplay *display); +static void gimp_color_tool_oper_update (GimpTool *tool, + const GimpCoords *coords, + GdkModifierType state, + gboolean proximity, + GimpDisplay *display); +static void gimp_color_tool_cursor_update (GimpTool *tool, + const GimpCoords *coords, + GdkModifierType state, + GimpDisplay *display); + +static void gimp_color_tool_draw (GimpDrawTool *draw_tool); + +static gboolean + gimp_color_tool_real_can_pick (GimpColorTool *color_tool, + const GimpCoords *coords, + GimpDisplay *display); +static gboolean gimp_color_tool_real_pick (GimpColorTool *color_tool, + const GimpCoords *coords, + GimpDisplay *display, + const Babl **sample_format, + gpointer pixel, + GimpRGB *color); +static void gimp_color_tool_real_picked (GimpColorTool *color_tool, + const GimpCoords *coords, + GimpDisplay *display, + GimpColorPickState pick_state, + const Babl *sample_format, + gpointer pixel, + const GimpRGB *color); + +static gboolean gimp_color_tool_can_pick (GimpColorTool *tool, + const GimpCoords *coords, + GimpDisplay *display); +static void gimp_color_tool_pick (GimpColorTool *tool, + const GimpCoords *coords, + GimpDisplay *display, + GimpColorPickState pick_state); + + +G_DEFINE_TYPE (GimpColorTool, gimp_color_tool, GIMP_TYPE_DRAW_TOOL) + +#define parent_class gimp_color_tool_parent_class + +static guint gimp_color_tool_signals[LAST_SIGNAL] = { 0 }; + + +static void +gimp_color_tool_class_init (GimpColorToolClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GimpToolClass *tool_class = GIMP_TOOL_CLASS (klass); + GimpDrawToolClass *draw_class = GIMP_DRAW_TOOL_CLASS (klass); + + gimp_color_tool_signals[PICKED] = + g_signal_new ("picked", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GimpColorToolClass, picked), + NULL, NULL, + gimp_marshal_VOID__POINTER_OBJECT_ENUM_POINTER_POINTER_BOXED, + G_TYPE_NONE, 6, + G_TYPE_POINTER, + GIMP_TYPE_DISPLAY, + GIMP_TYPE_COLOR_PICK_STATE, + G_TYPE_POINTER, + G_TYPE_POINTER, + GIMP_TYPE_RGB | G_SIGNAL_TYPE_STATIC_SCOPE); + + object_class->finalize = gimp_color_tool_finalize; + + tool_class->button_press = gimp_color_tool_button_press; + tool_class->button_release = gimp_color_tool_button_release; + tool_class->motion = gimp_color_tool_motion; + tool_class->oper_update = gimp_color_tool_oper_update; + tool_class->cursor_update = gimp_color_tool_cursor_update; + + draw_class->draw = gimp_color_tool_draw; + + klass->can_pick = gimp_color_tool_real_can_pick; + klass->pick = gimp_color_tool_real_pick; + klass->picked = gimp_color_tool_real_picked; +} + +static void +gimp_color_tool_init (GimpColorTool *color_tool) +{ + GimpTool *tool = GIMP_TOOL (color_tool); + + gimp_tool_control_set_action_size (tool->control, + "tools/tools-color-average-radius-set"); +} + +static void +gimp_color_tool_finalize (GObject *object) +{ + GimpColorTool *color_tool = GIMP_COLOR_TOOL (object); + + g_clear_object (&color_tool->options); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gimp_color_tool_button_press (GimpTool *tool, + const GimpCoords *coords, + guint32 time, + GdkModifierType state, + GimpButtonPressType press_type, + GimpDisplay *display) +{ + GimpColorTool *color_tool = GIMP_COLOR_TOOL (tool); + + if (color_tool->enabled) + { + if (color_tool->sample_point) + { + gimp_sample_point_tool_start_edit (tool, display, + color_tool->sample_point); + } + else if (gimp_color_tool_can_pick (color_tool, coords, display)) + { + gimp_color_tool_pick (color_tool, coords, display, + GIMP_COLOR_PICK_STATE_START); + + gimp_tool_control_activate (tool->control); + } + } + else + { + GIMP_TOOL_CLASS (parent_class)->button_press (tool, coords, time, state, + press_type, display); + } +} + +static void +gimp_color_tool_button_release (GimpTool *tool, + const GimpCoords *coords, + guint32 time, + GdkModifierType state, + GimpButtonReleaseType release_type, + GimpDisplay *display) +{ + GimpColorTool *color_tool = GIMP_COLOR_TOOL (tool); + + if (color_tool->enabled) + { + gimp_tool_control_halt (tool->control); + + if (! color_tool->sample_point && + gimp_color_tool_can_pick (color_tool, coords, display)) + { + gimp_color_tool_pick (color_tool, coords, display, + GIMP_COLOR_PICK_STATE_END); + } + } + else + { + GIMP_TOOL_CLASS (parent_class)->button_release (tool, coords, time, state, + release_type, display); + } +} + +static void +gimp_color_tool_motion (GimpTool *tool, + const GimpCoords *coords, + guint32 time, + GdkModifierType state, + GimpDisplay *display) +{ + GimpColorTool *color_tool = GIMP_COLOR_TOOL (tool); + + if (color_tool->enabled) + { + if (! color_tool->sample_point) + { + gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool)); + + color_tool->can_pick = gimp_color_tool_can_pick (color_tool, + coords, display); + color_tool->center_x = coords->x; + color_tool->center_y = coords->y; + + if (color_tool->can_pick) + { + gimp_color_tool_pick (color_tool, coords, display, + GIMP_COLOR_PICK_STATE_UPDATE); + } + + gimp_draw_tool_resume (GIMP_DRAW_TOOL (tool)); + } + } + else + { + GIMP_TOOL_CLASS (parent_class)->motion (tool, coords, time, state, + display); + } +} + +static void +gimp_color_tool_oper_update (GimpTool *tool, + const GimpCoords *coords, + GdkModifierType state, + gboolean proximity, + GimpDisplay *display) +{ + GimpColorTool *color_tool = GIMP_COLOR_TOOL (tool); + + if (color_tool->enabled) + { + GimpDrawTool *draw_tool = GIMP_DRAW_TOOL (tool); + GimpDisplayShell *shell = gimp_display_get_shell (display); + GimpSamplePoint *sample_point = NULL; + + gimp_draw_tool_pause (draw_tool); + + if (! draw_tool->widget && + + gimp_draw_tool_is_active (draw_tool) && + (draw_tool->display != display || + ! proximity)) + { + gimp_draw_tool_stop (draw_tool); + } + + if (gimp_display_shell_get_show_sample_points (shell) && + proximity) + { + GimpImage *image = gimp_display_get_image (display); + gint snap_distance = display->config->snap_distance; + + sample_point = + gimp_image_pick_sample_point (image, + coords->x, coords->y, + FUNSCALEX (shell, snap_distance), + FUNSCALEY (shell, snap_distance)); + } + + color_tool->sample_point = sample_point; + + color_tool->can_pick = gimp_color_tool_can_pick (color_tool, + coords, display); + color_tool->center_x = coords->x; + color_tool->center_y = coords->y; + + if (! draw_tool->widget && + + ! gimp_draw_tool_is_active (draw_tool) && + proximity) + { + gimp_draw_tool_start (draw_tool, display); + } + + gimp_draw_tool_resume (draw_tool); + } + else + { + GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state, + proximity, display); + } +} + +static void +gimp_color_tool_cursor_update (GimpTool *tool, + const GimpCoords *coords, + GdkModifierType state, + GimpDisplay *display) +{ + GimpColorTool *color_tool = GIMP_COLOR_TOOL (tool); + + if (color_tool->enabled) + { + if (color_tool->sample_point) + { + gimp_tool_set_cursor (tool, display, + GIMP_CURSOR_MOUSE, + GIMP_TOOL_CURSOR_COLOR_PICKER, + GIMP_CURSOR_MODIFIER_MOVE); + } + else + { + GimpCursorModifier modifier = GIMP_CURSOR_MODIFIER_BAD; + + if (gimp_color_tool_can_pick (color_tool, coords, display)) + { + switch (color_tool->pick_target) + { + case GIMP_COLOR_PICK_TARGET_NONE: + modifier = GIMP_CURSOR_MODIFIER_NONE; + break; + case GIMP_COLOR_PICK_TARGET_FOREGROUND: + modifier = GIMP_CURSOR_MODIFIER_FOREGROUND; + break; + case GIMP_COLOR_PICK_TARGET_BACKGROUND: + modifier = GIMP_CURSOR_MODIFIER_BACKGROUND; + break; + case GIMP_COLOR_PICK_TARGET_PALETTE: + modifier = GIMP_CURSOR_MODIFIER_PLUS; + break; + } + } + + gimp_tool_set_cursor (tool, display, + GIMP_CURSOR_COLOR_PICKER, + GIMP_TOOL_CURSOR_COLOR_PICKER, + modifier); + } + } + else + { + GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, + display); + } +} + +static void +gimp_color_tool_draw (GimpDrawTool *draw_tool) +{ + GimpColorTool *color_tool = GIMP_COLOR_TOOL (draw_tool); + + GIMP_DRAW_TOOL_CLASS (parent_class)->draw (draw_tool); + + if (color_tool->enabled) + { + if (color_tool->sample_point) + { + GimpImage *image = gimp_display_get_image (draw_tool->display); + GimpCanvasItem *item; + gint index; + gint x; + gint y; + + gimp_sample_point_get_position (color_tool->sample_point, &x, &y); + + index = g_list_index (gimp_image_get_sample_points (image), + color_tool->sample_point) + 1; + + item = gimp_draw_tool_add_sample_point (draw_tool, x, y, index); + gimp_canvas_item_set_highlight (item, TRUE); + } + else if (color_tool->can_pick && color_tool->options->sample_average) + { + gdouble radius = color_tool->options->average_radius; + + gimp_draw_tool_add_rectangle (draw_tool, + FALSE, + color_tool->center_x - radius, + color_tool->center_y - radius, + 2 * radius + 1, + 2 * radius + 1); + } + } +} + +static gboolean +gimp_color_tool_real_can_pick (GimpColorTool *color_tool, + const GimpCoords *coords, + GimpDisplay *display) +{ + GimpDisplayShell *shell = gimp_display_get_shell (display); + GimpImage *image = gimp_display_get_image (display); + + return gimp_image_coords_in_active_pickable (image, coords, + shell->show_all, + color_tool->options->sample_merged, + FALSE); +} + +static gboolean +gimp_color_tool_real_pick (GimpColorTool *color_tool, + const GimpCoords *coords, + GimpDisplay *display, + const Babl **sample_format, + gpointer pixel, + GimpRGB *color) +{ + GimpDisplayShell *shell = gimp_display_get_shell (display); + GimpImage *image = gimp_display_get_image (display); + GimpDrawable *drawable = gimp_image_get_active_drawable (image); + + g_return_val_if_fail (drawable != NULL, FALSE); + + return gimp_image_pick_color (image, drawable, + coords->x, coords->y, + shell->show_all, + color_tool->options->sample_merged, + color_tool->options->sample_average, + color_tool->options->average_radius, + sample_format, + pixel, + color); +} + +static void +gimp_color_tool_real_picked (GimpColorTool *color_tool, + const GimpCoords *coords, + GimpDisplay *display, + GimpColorPickState pick_state, + const Babl *sample_format, + gpointer pixel, + const GimpRGB *color) +{ + GimpTool *tool = GIMP_TOOL (color_tool); + GimpDisplayShell *shell = gimp_display_get_shell (display); + GimpImageWindow *image_window; + GimpDialogFactory *dialog_factory; + GimpContext *context; + + image_window = gimp_display_shell_get_window (shell); + dialog_factory = gimp_dock_container_get_dialog_factory (GIMP_DOCK_CONTAINER (image_window)); + + /* use this tool's own options here (NOT color_tool->options) */ + context = GIMP_CONTEXT (gimp_tool_get_options (tool)); + + if (color_tool->pick_target == GIMP_COLOR_PICK_TARGET_FOREGROUND || + color_tool->pick_target == GIMP_COLOR_PICK_TARGET_BACKGROUND) + { + GtkWidget *widget; + + widget = gimp_dialog_factory_find_widget (dialog_factory, + "gimp-indexed-palette"); + if (widget) + { + GtkWidget *editor = gtk_bin_get_child (GTK_BIN (widget)); + GimpImage *image = gimp_display_get_image (display); + + if (babl_format_is_palette (sample_format)) + { + guchar *index = pixel; + + gimp_colormap_editor_set_index (GIMP_COLORMAP_EDITOR (editor), + *index, NULL); + } + else if (gimp_image_get_base_type (image) == GIMP_INDEXED) + { + /* When Sample merged is set, we don't have the index + * information and it is possible to pick colors out of + * the colormap (with compositing). In such a case, the + * sample format will not be a palette format even though + * the image is indexed. Still search if the color exists + * in the colormap. + * Note that even if it does, we might still pick the + * wrong color, since several indexes may contain the same + * color and we can't know for sure which is the right + * one. + */ + gint index = gimp_colormap_editor_get_index (GIMP_COLORMAP_EDITOR (editor), + color); + if (index > -1) + gimp_colormap_editor_set_index (GIMP_COLORMAP_EDITOR (editor), + index, NULL); + } + } + + widget = gimp_dialog_factory_find_widget (dialog_factory, + "gimp-palette-editor"); + if (widget) + { + GtkWidget *editor = gtk_bin_get_child (GTK_BIN (widget)); + gint index; + + index = gimp_palette_editor_get_index (GIMP_PALETTE_EDITOR (editor), + color); + if (index != -1) + gimp_palette_editor_set_index (GIMP_PALETTE_EDITOR (editor), + index, NULL); + } + } + + switch (color_tool->pick_target) + { + case GIMP_COLOR_PICK_TARGET_NONE: + break; + + case GIMP_COLOR_PICK_TARGET_FOREGROUND: + gimp_context_set_foreground (context, color); + break; + + case GIMP_COLOR_PICK_TARGET_BACKGROUND: + gimp_context_set_background (context, color); + break; + + case GIMP_COLOR_PICK_TARGET_PALETTE: + { + GdkScreen *screen = gtk_widget_get_screen (GTK_WIDGET (shell)); + gint monitor = gimp_widget_get_monitor (GTK_WIDGET (shell)); + GtkWidget *dockable; + + dockable = + gimp_window_strategy_show_dockable_dialog (GIMP_WINDOW_STRATEGY (gimp_get_window_strategy (display->gimp)), + display->gimp, + dialog_factory, + screen, + monitor, + "gimp-palette-editor"); + + if (dockable) + { + GtkWidget *palette_editor; + GimpData *data; + + /* don't blink like mad when updating */ + if (pick_state != GIMP_COLOR_PICK_STATE_START) + gimp_widget_blink_cancel (dockable); + + palette_editor = gtk_bin_get_child (GTK_BIN (dockable)); + + data = gimp_data_editor_get_data (GIMP_DATA_EDITOR (palette_editor)); + + if (! data) + { + data = GIMP_DATA (gimp_context_get_palette (context)); + + gimp_data_editor_set_data (GIMP_DATA_EDITOR (palette_editor), + data); + } + + gimp_palette_editor_pick_color (GIMP_PALETTE_EDITOR (palette_editor), + color, pick_state); + } + } + break; + } +} + +static gboolean +gimp_color_tool_can_pick (GimpColorTool *tool, + const GimpCoords *coords, + GimpDisplay *display) +{ + GimpColorToolClass *klass; + + klass = GIMP_COLOR_TOOL_GET_CLASS (tool); + + return klass->can_pick && klass->can_pick (tool, coords, display); +} + +static void +gimp_color_tool_pick (GimpColorTool *tool, + const GimpCoords *coords, + GimpDisplay *display, + GimpColorPickState pick_state) +{ + GimpColorToolClass *klass; + const Babl *sample_format; + gdouble pixel[4]; + GimpRGB color; + + klass = GIMP_COLOR_TOOL_GET_CLASS (tool); + + if (klass->pick && + klass->pick (tool, coords, display, &sample_format, pixel, &color)) + { + g_signal_emit (tool, gimp_color_tool_signals[PICKED], 0, + coords, display, pick_state, + sample_format, pixel, &color); + } +} + + +/* public functions */ + +void +gimp_color_tool_enable (GimpColorTool *color_tool, + GimpColorOptions *options) +{ + GimpTool *tool; + + g_return_if_fail (GIMP_IS_COLOR_TOOL (color_tool)); + g_return_if_fail (GIMP_IS_COLOR_OPTIONS (options)); + + tool = GIMP_TOOL (color_tool); + + if (gimp_tool_control_is_active (tool->control)) + { + g_warning ("Trying to enable GimpColorTool while it is active."); + return; + } + + g_set_object (&color_tool->options, options); + + /* color picking doesn't snap, see bug #768058 */ + color_tool->saved_snap_to = gimp_tool_control_get_snap_to (tool->control); + gimp_tool_control_set_snap_to (tool->control, FALSE); + + color_tool->enabled = TRUE; +} + +void +gimp_color_tool_disable (GimpColorTool *color_tool) +{ + GimpTool *tool; + + g_return_if_fail (GIMP_IS_COLOR_TOOL (color_tool)); + + tool = GIMP_TOOL (color_tool); + + if (gimp_tool_control_is_active (tool->control)) + { + g_warning ("Trying to disable GimpColorTool while it is active."); + return; + } + + g_clear_object (&color_tool->options); + + gimp_tool_control_set_snap_to (tool->control, color_tool->saved_snap_to); + color_tool->saved_snap_to = FALSE; + + color_tool->enabled = FALSE; +} + +gboolean +gimp_color_tool_is_enabled (GimpColorTool *color_tool) +{ + return color_tool->enabled; +} -- cgit v1.2.3