[gimp] app: add new GimpToolTransformGrid subclass GimpToolHandleGrid
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: add new GimpToolTransformGrid subclass GimpToolHandleGrid
- Date: Sun, 18 Jun 2017 23:54:54 +0000 (UTC)
commit 6bd316e07086b09af4b43807602a5696e354b6f1
Author: Michael Natterer <mitch gimp org>
Date: Mon Jun 19 01:21:06 2017 +0200
app: add new GimpToolTransformGrid subclass GimpToolHandleGrid
which implents the handle transform tool's interaction.
app/display/Makefile.am | 2 +
app/display/display-enums.c | 31 ++
app/display/display-enums.h | 12 +
app/display/gimptoolhandlegrid.c | 1070 ++++++++++++++++++++++++++++++++++++++
app/display/gimptoolhandlegrid.h | 62 +++
app/tools/tools-enums.c | 31 --
app/tools/tools-enums.h | 12 -
7 files changed, 1177 insertions(+), 43 deletions(-)
---
diff --git a/app/display/Makefile.am b/app/display/Makefile.am
index ccde805..f7c1f41 100644
--- a/app/display/Makefile.am
+++ b/app/display/Makefile.am
@@ -166,6 +166,8 @@ libappdisplay_a_sources = \
gimptoolgui.h \
gimptoolcompass.c \
gimptoolcompass.h \
+ gimptoolhandlegrid.c \
+ gimptoolhandlegrid.h \
gimptoolline.c \
gimptoolline.h \
gimptoolrotategrid.c \
diff --git a/app/display/display-enums.c b/app/display/display-enums.c
index e80a7ad..b3fcae7 100644
--- a/app/display/display-enums.c
+++ b/app/display/display-enums.c
@@ -295,6 +295,37 @@ gimp_transform_function_get_type (void)
}
GType
+gimp_transform_handle_mode_get_type (void)
+{
+ static const GEnumValue values[] =
+ {
+ { GIMP_HANDLE_MODE_ADD_TRANSFORM, "GIMP_HANDLE_MODE_ADD_TRANSFORM", "add-transform" },
+ { GIMP_HANDLE_MODE_MOVE, "GIMP_HANDLE_MODE_MOVE", "move" },
+ { GIMP_HANDLE_MODE_REMOVE, "GIMP_HANDLE_MODE_REMOVE", "remove" },
+ { 0, NULL, NULL }
+ };
+
+ static const GimpEnumDesc descs[] =
+ {
+ { GIMP_HANDLE_MODE_ADD_TRANSFORM, NC_("transform-handle-mode", "Add / Transform"), NULL },
+ { GIMP_HANDLE_MODE_MOVE, NC_("transform-handle-mode", "Move"), NULL },
+ { GIMP_HANDLE_MODE_REMOVE, NC_("transform-handle-mode", "Remove"), NULL },
+ { 0, NULL, NULL }
+ };
+
+ static GType type = 0;
+
+ if (G_UNLIKELY (! type))
+ {
+ type = g_enum_register_static ("GimpTransformHandleMode", values);
+ gimp_type_set_translation_context (type, "transform-handle-mode");
+ gimp_enum_set_value_descriptions (type, descs);
+ }
+
+ return type;
+}
+
+GType
gimp_zoom_focus_get_type (void)
{
static const GEnumValue values[] =
diff --git a/app/display/display-enums.h b/app/display/display-enums.h
index 704856e..3e1d497 100644
--- a/app/display/display-enums.h
+++ b/app/display/display-enums.h
@@ -134,6 +134,18 @@ typedef enum
} GimpTransformFunction;
+#define GIMP_TYPE_TRANSFORM_HANDLE_MODE (gimp_transform_handle_mode_get_type ())
+
+GType gimp_transform_handle_mode_get_type (void) G_GNUC_CONST;
+
+typedef enum
+{
+ GIMP_HANDLE_MODE_ADD_TRANSFORM, /*< desc="Add / Transform" >*/
+ GIMP_HANDLE_MODE_MOVE, /*< desc="Move" >*/
+ GIMP_HANDLE_MODE_REMOVE /*< desc="Remove" >*/
+} GimpTransformHandleMode;
+
+
#define GIMP_TYPE_ZOOM_FOCUS (gimp_zoom_focus_get_type ())
GType gimp_zoom_focus_get_type (void) G_GNUC_CONST;
diff --git a/app/display/gimptoolhandlegrid.c b/app/display/gimptoolhandlegrid.c
new file mode 100644
index 0000000..ad02946
--- /dev/null
+++ b/app/display/gimptoolhandlegrid.c
@@ -0,0 +1,1070 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimptoolhandlegrid.c
+ * Copyright (C) 2017 Michael Natterer <mitch gimp org>
+ *
+ * Based on GimpHandleTransformTool
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+
+#include "libgimpbase/gimpbase.h"
+#include "libgimpmath/gimpmath.h"
+
+#include "display-types.h"
+
+#include "core/gimp-transform-utils.h"
+#include "core/gimp-utils.h"
+
+#include "gimpcanvashandle.h"
+#include "gimpdisplayshell.h"
+#include "gimptoolhandlegrid.h"
+
+#include "gimp-intl.h"
+
+
+#define GIMP_TOOL_HANDLE_SIZE_CIRCLE 13
+
+
+enum
+{
+ PROP_0,
+ PROP_HANDLE_MODE,
+ PROP_N_HANDLES,
+ PROP_ORIG_X1,
+ PROP_ORIG_Y1,
+ PROP_ORIG_X2,
+ PROP_ORIG_Y2,
+ PROP_ORIG_X3,
+ PROP_ORIG_Y3,
+ PROP_ORIG_X4,
+ PROP_ORIG_Y4,
+ PROP_TRANS_X1,
+ PROP_TRANS_Y1,
+ PROP_TRANS_X2,
+ PROP_TRANS_Y2,
+ PROP_TRANS_X3,
+ PROP_TRANS_Y3,
+ PROP_TRANS_X4,
+ PROP_TRANS_Y4
+};
+
+
+struct _GimpToolHandleGridPrivate
+{
+ GimpTransformHandleMode handle_mode; /* enum to be renamed */
+
+ gint n_handles;
+ gdouble orig_x[4];
+ gdouble orig_y[4];
+ gdouble trans_x[4];
+ gdouble trans_y[4];
+
+ gint handle;
+ gdouble last_x;
+ gdouble last_y;
+
+ GimpCanvasItem *handles[5];
+};
+
+
+/* local function prototypes */
+
+static void gimp_tool_handle_grid_constructed (GObject *object);
+static void gimp_tool_handle_grid_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void gimp_tool_handle_grid_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+static void gimp_tool_handle_grid_changed (GimpToolWidget *widget);
+static gint gimp_tool_handle_grid_button_press (GimpToolWidget *widget,
+ const GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state,
+ GimpButtonPressType press_type);
+static void gimp_tool_handle_grid_button_release (GimpToolWidget *widget,
+ const GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state,
+ GimpButtonReleaseType release_type);
+static void gimp_tool_handle_grid_motion (GimpToolWidget *widget,
+ const GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state);
+static void gimp_tool_handle_grid_hover (GimpToolWidget *widget,
+ const GimpCoords *coords,
+ GdkModifierType state,
+ gboolean proximity);
+static gboolean gimp_tool_handle_grid_get_cursor (GimpToolWidget *widget,
+ const GimpCoords *coords,
+ GdkModifierType state,
+ GimpCursorType *cursor,
+ GimpToolCursorType *tool_cursor,
+ GimpCursorModifier *cursor_modifier);
+
+static void gimp_tool_handle_grid_update_hilight (GimpToolHandleGrid *grid);
+static void gimp_tool_handle_grid_update_matrix (GimpToolHandleGrid *grid);
+
+static gboolean is_handle_position_valid (GimpToolHandleGrid *grid,
+ gint handle);
+static void handle_micro_move (GimpToolHandleGrid *grid,
+ gint handle);
+
+static inline gdouble calc_angle (gdouble ax,
+ gdouble ay,
+ gdouble bx,
+ gdouble by);
+static inline gdouble calc_len (gdouble a,
+ gdouble b);
+static inline gdouble calc_lineintersect_ratio (gdouble p1x,
+ gdouble p1y,
+ gdouble p2x,
+ gdouble p2y,
+ gdouble q1x,
+ gdouble q1y,
+ gdouble q2x,
+ gdouble q2y);
+
+
+G_DEFINE_TYPE (GimpToolHandleGrid, gimp_tool_handle_grid,
+ GIMP_TYPE_TOOL_TRANSFORM_GRID)
+
+#define parent_class gimp_tool_handle_grid_parent_class
+
+
+static void
+gimp_tool_handle_grid_class_init (GimpToolHandleGridClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GimpToolWidgetClass *widget_class = GIMP_TOOL_WIDGET_CLASS (klass);
+
+ object_class->constructed = gimp_tool_handle_grid_constructed;
+ object_class->set_property = gimp_tool_handle_grid_set_property;
+ object_class->get_property = gimp_tool_handle_grid_get_property;
+
+ widget_class->changed = gimp_tool_handle_grid_changed;
+ widget_class->button_press = gimp_tool_handle_grid_button_press;
+ widget_class->button_release = gimp_tool_handle_grid_button_release;
+ widget_class->motion = gimp_tool_handle_grid_motion;
+ widget_class->hover = gimp_tool_handle_grid_hover;
+ widget_class->get_cursor = gimp_tool_handle_grid_get_cursor;
+
+ g_object_class_install_property (object_class, PROP_HANDLE_MODE,
+ g_param_spec_enum ("handle-mode",
+ NULL, NULL,
+ GIMP_TYPE_TRANSFORM_HANDLE_MODE,
+ GIMP_HANDLE_MODE_ADD_TRANSFORM,
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class, PROP_N_HANDLES,
+ g_param_spec_int ("n-handles",
+ NULL, NULL,
+ 0, 4, 0,
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class, PROP_ORIG_X1,
+ g_param_spec_double ("orig-x1",
+ NULL, NULL,
+ -GIMP_MAX_IMAGE_SIZE,
+ GIMP_MAX_IMAGE_SIZE,
+ 0.0,
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class, PROP_ORIG_Y1,
+ g_param_spec_double ("orig-y1",
+ NULL, NULL,
+ -GIMP_MAX_IMAGE_SIZE,
+ GIMP_MAX_IMAGE_SIZE,
+ 0.0,
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class, PROP_ORIG_X2,
+ g_param_spec_double ("orig-x2",
+ NULL, NULL,
+ -GIMP_MAX_IMAGE_SIZE,
+ GIMP_MAX_IMAGE_SIZE,
+ 0.0,
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class, PROP_ORIG_Y2,
+ g_param_spec_double ("orig-y2",
+ NULL, NULL,
+ -GIMP_MAX_IMAGE_SIZE,
+ GIMP_MAX_IMAGE_SIZE,
+ 0.0,
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class, PROP_ORIG_X3,
+ g_param_spec_double ("orig-x3",
+ NULL, NULL,
+ -GIMP_MAX_IMAGE_SIZE,
+ GIMP_MAX_IMAGE_SIZE,
+ 0.0,
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class, PROP_ORIG_Y3,
+ g_param_spec_double ("orig-y3",
+ NULL, NULL,
+ -GIMP_MAX_IMAGE_SIZE,
+ GIMP_MAX_IMAGE_SIZE,
+ 0.0,
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class, PROP_ORIG_X4,
+ g_param_spec_double ("orig-x4",
+ NULL, NULL,
+ -GIMP_MAX_IMAGE_SIZE,
+ GIMP_MAX_IMAGE_SIZE,
+ 0.0,
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class, PROP_ORIG_Y4,
+ g_param_spec_double ("orig-y4",
+ NULL, NULL,
+ -GIMP_MAX_IMAGE_SIZE,
+ GIMP_MAX_IMAGE_SIZE,
+ 0.0,
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class, PROP_TRANS_X1,
+ g_param_spec_double ("trans-x1",
+ NULL, NULL,
+ -GIMP_MAX_IMAGE_SIZE,
+ GIMP_MAX_IMAGE_SIZE,
+ 0.0,
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class, PROP_TRANS_Y1,
+ g_param_spec_double ("trans-y1",
+ NULL, NULL,
+ -GIMP_MAX_IMAGE_SIZE,
+ GIMP_MAX_IMAGE_SIZE,
+ 0.0,
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class, PROP_TRANS_X2,
+ g_param_spec_double ("trans-x2",
+ NULL, NULL,
+ -GIMP_MAX_IMAGE_SIZE,
+ GIMP_MAX_IMAGE_SIZE,
+ 0.0,
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class, PROP_TRANS_Y2,
+ g_param_spec_double ("trans-y2",
+ NULL, NULL,
+ -GIMP_MAX_IMAGE_SIZE,
+ GIMP_MAX_IMAGE_SIZE,
+ 0.0,
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class, PROP_TRANS_X3,
+ g_param_spec_double ("trans-x3",
+ NULL, NULL,
+ -GIMP_MAX_IMAGE_SIZE,
+ GIMP_MAX_IMAGE_SIZE,
+ 0.0,
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class, PROP_TRANS_Y3,
+ g_param_spec_double ("trans-y3",
+ NULL, NULL,
+ -GIMP_MAX_IMAGE_SIZE,
+ GIMP_MAX_IMAGE_SIZE,
+ 0.0,
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class, PROP_TRANS_X4,
+ g_param_spec_double ("trans-x4",
+ NULL, NULL,
+ -GIMP_MAX_IMAGE_SIZE,
+ GIMP_MAX_IMAGE_SIZE,
+ 0.0,
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class, PROP_TRANS_Y4,
+ g_param_spec_double ("trans-y4",
+ NULL, NULL,
+ -GIMP_MAX_IMAGE_SIZE,
+ GIMP_MAX_IMAGE_SIZE,
+ 0.0,
+ GIMP_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_type_class_add_private (klass, sizeof (GimpToolHandleGridPrivate));
+}
+
+static void
+gimp_tool_handle_grid_init (GimpToolHandleGrid *grid)
+{
+ grid->private = G_TYPE_INSTANCE_GET_PRIVATE (grid,
+ GIMP_TYPE_TOOL_HANDLE_GRID,
+ GimpToolHandleGridPrivate);
+}
+
+static void
+gimp_tool_handle_grid_constructed (GObject *object)
+{
+ GimpToolHandleGrid *grid = GIMP_TOOL_HANDLE_GRID (object);
+ GimpToolWidget *widget = GIMP_TOOL_WIDGET (object);
+ GimpToolHandleGridPrivate *private = grid->private;
+ gint i;
+
+ G_OBJECT_CLASS (parent_class)->constructed (object);
+
+ for (i = 0; i < 4; i++)
+ {
+ private->handles[i + 1] =
+ gimp_tool_widget_add_handle (widget,
+ GIMP_HANDLE_CIRCLE,
+ 0, 0,
+ GIMP_TOOL_HANDLE_SIZE_CIRCLE,
+ GIMP_TOOL_HANDLE_SIZE_CIRCLE,
+ GIMP_HANDLE_ANCHOR_CENTER);
+ }
+
+ gimp_tool_handle_grid_changed (widget);
+}
+
+static void
+gimp_tool_handle_grid_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ GimpToolHandleGrid *grid = GIMP_TOOL_HANDLE_GRID (object);
+ GimpToolHandleGridPrivate *private = grid->private;
+
+ switch (property_id)
+ {
+ case PROP_HANDLE_MODE:
+ private->handle_mode = g_value_get_enum (value);
+ break;
+
+ case PROP_N_HANDLES:
+ private->n_handles = g_value_get_int (value);
+ break;
+
+ case PROP_ORIG_X1:
+ private->orig_x[0] = g_value_get_double (value);
+ break;
+ case PROP_ORIG_Y1:
+ private->orig_y[0] = g_value_get_double (value);
+ break;
+ case PROP_ORIG_X2:
+ private->orig_x[1] = g_value_get_double (value);
+ break;
+ case PROP_ORIG_Y2:
+ private->orig_y[1] = g_value_get_double (value);
+ break;
+ case PROP_ORIG_X3:
+ private->orig_x[2] = g_value_get_double (value);
+ break;
+ case PROP_ORIG_Y3:
+ private->orig_y[2] = g_value_get_double (value);
+ break;
+ case PROP_ORIG_X4:
+ private->orig_x[3] = g_value_get_double (value);
+ break;
+ case PROP_ORIG_Y4:
+ private->orig_y[3] = g_value_get_double (value);
+ break;
+
+ case PROP_TRANS_X1:
+ private->trans_x[0] = g_value_get_double (value);
+ break;
+ case PROP_TRANS_Y1:
+ private->trans_y[0] = g_value_get_double (value);
+ break;
+ case PROP_TRANS_X2:
+ private->trans_x[1] = g_value_get_double (value);
+ break;
+ case PROP_TRANS_Y2:
+ private->trans_y[1] = g_value_get_double (value);
+ break;
+ case PROP_TRANS_X3:
+ private->trans_x[2] = g_value_get_double (value);
+ break;
+ case PROP_TRANS_Y3:
+ private->trans_y[2] = g_value_get_double (value);
+ break;
+ case PROP_TRANS_X4:
+ private->trans_x[3] = g_value_get_double (value);
+ break;
+ case PROP_TRANS_Y4:
+ private->trans_y[3] = g_value_get_double (value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gimp_tool_handle_grid_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ GimpToolHandleGrid *grid = GIMP_TOOL_HANDLE_GRID (object);
+ GimpToolHandleGridPrivate *private = grid->private;
+
+ switch (property_id)
+ {
+ case PROP_N_HANDLES:
+ g_value_set_int (value, private->n_handles);
+ break;
+
+ case PROP_HANDLE_MODE:
+ g_value_set_enum (value, private->handle_mode);
+ break;
+
+ case PROP_ORIG_X1:
+ g_value_set_double (value, private->orig_x[0]);
+ break;
+ case PROP_ORIG_Y1:
+ g_value_set_double (value, private->orig_y[0]);
+ break;
+ case PROP_ORIG_X2:
+ g_value_set_double (value, private->orig_x[1]);
+ break;
+ case PROP_ORIG_Y2:
+ g_value_set_double (value, private->orig_y[1]);
+ break;
+ case PROP_ORIG_X3:
+ g_value_set_double (value, private->orig_x[2]);
+ break;
+ case PROP_ORIG_Y3:
+ g_value_set_double (value, private->orig_y[2]);
+ break;
+ case PROP_ORIG_X4:
+ g_value_set_double (value, private->orig_x[3]);
+ break;
+ case PROP_ORIG_Y4:
+ g_value_set_double (value, private->orig_y[3]);
+ break;
+
+ case PROP_TRANS_X1:
+ g_value_set_double (value, private->trans_x[0]);
+ break;
+ case PROP_TRANS_Y1:
+ g_value_set_double (value, private->trans_y[0]);
+ break;
+ case PROP_TRANS_X2:
+ g_value_set_double (value, private->trans_x[1]);
+ break;
+ case PROP_TRANS_Y2:
+ g_value_set_double (value, private->trans_y[1]);
+ break;
+ case PROP_TRANS_X3:
+ g_value_set_double (value, private->trans_x[2]);
+ break;
+ case PROP_TRANS_Y3:
+ g_value_set_double (value, private->trans_y[2]);
+ break;
+ case PROP_TRANS_X4:
+ g_value_set_double (value, private->trans_x[3]);
+ break;
+ case PROP_TRANS_Y4:
+ g_value_set_double (value, private->trans_y[3]);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+gimp_tool_handle_grid_changed (GimpToolWidget *widget)
+{
+ GimpToolHandleGrid *grid = GIMP_TOOL_HANDLE_GRID (widget);
+ GimpToolHandleGridPrivate *private = grid->private;
+ gint i;
+
+ GIMP_TOOL_WIDGET_CLASS (parent_class)->changed (widget);
+
+ for (i = 0; i < 4; i++)
+ {
+ gimp_canvas_handle_set_position (private->handles[i + 1],
+ private->trans_x[i],
+ private->trans_y[i]);
+ gimp_canvas_item_set_visible (private->handles[i + 1],
+ i < private->n_handles);
+ }
+
+ gimp_tool_handle_grid_update_hilight (grid);
+}
+
+static gint
+gimp_tool_handle_grid_button_press (GimpToolWidget *widget,
+ const GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state,
+ GimpButtonPressType press_type)
+{
+ GimpToolHandleGrid *grid = GIMP_TOOL_HANDLE_GRID (widget);
+ GimpToolHandleGridPrivate *private = grid->private;
+ gint n_handles = private->n_handles;
+ gint active_handle = private->handle - 1;
+
+ switch (private->handle_mode)
+ {
+ case GIMP_HANDLE_MODE_ADD_TRANSFORM:
+ if (n_handles < 4 && active_handle == -1)
+ {
+ /* add handle */
+
+ GimpMatrix3 *matrix;
+
+ active_handle = n_handles;
+
+ private->trans_x[active_handle] = coords->x;
+ private->trans_y[active_handle] = coords->y;
+ private->n_handles++;
+
+ if (! is_handle_position_valid (grid, active_handle))
+ {
+ handle_micro_move (grid, active_handle);
+ }
+
+ /* handle was added, calculate new original position */
+ g_object_get (grid,
+ "transform", &matrix,
+ NULL);
+
+ gimp_matrix3_invert (matrix);
+ gimp_matrix3_transform_point (matrix,
+ private->trans_x[active_handle],
+ private->trans_y[active_handle],
+ &private->orig_x[active_handle],
+ &private->orig_y[active_handle]);
+
+ g_free (matrix);
+
+ private->handle = active_handle + 1;
+
+ g_object_notify (G_OBJECT (grid), "n-handles");
+ }
+ break;
+
+ case GIMP_HANDLE_MODE_MOVE:
+ /* check for valid position and calculating of OX0...OY3 is
+ * done on button release
+ */
+ break;
+
+ case GIMP_HANDLE_MODE_REMOVE:
+ if (n_handles > 0 &&
+ active_handle >= 0 &&
+ active_handle < 4)
+ {
+ /* remove handle */
+
+ gdouble tempx = private->trans_x[active_handle];
+ gdouble tempy = private->trans_y[active_handle];
+ gdouble tempox = private->orig_x[active_handle];
+ gdouble tempoy = private->orig_y[active_handle];
+ gint i;
+
+ n_handles--;
+ private->n_handles--;
+
+ for (i = active_handle; i < n_handles; i++)
+ {
+ private->trans_x[i] = private->trans_x[i + 1];
+ private->trans_y[i] = private->trans_y[i + 1];
+ private->orig_x[i] = private->orig_x[i + 1];
+ private->orig_y[i] = private->orig_y[i + 1];
+ }
+
+ private->trans_x[n_handles] = tempx;
+ private->trans_y[n_handles] = tempy;
+ private->orig_x[n_handles] = tempox;
+ private->orig_y[n_handles] = tempoy;
+
+ g_object_notify (G_OBJECT (grid), "n-handles");
+ }
+ break;
+ }
+
+ private->last_x = coords->x;
+ private->last_y = coords->y;
+
+ return private->handle;
+}
+
+static void
+gimp_tool_handle_grid_button_release (GimpToolWidget *widget,
+ const GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state,
+ GimpButtonReleaseType release_type)
+{
+ GimpToolHandleGrid *grid = GIMP_TOOL_HANDLE_GRID (widget);
+ GimpToolHandleGridPrivate *private = grid->private;
+ gint active_handle = private->handle - 1;
+
+ if (private->handle_mode == GIMP_HANDLE_MODE_MOVE &&
+ active_handle >= 0 &&
+ active_handle < 4)
+ {
+ GimpMatrix3 *matrix;
+
+ if (! is_handle_position_valid (grid, active_handle))
+ {
+ handle_micro_move (grid, active_handle);
+ }
+
+ /* handle was moved, calculate new original position */
+ g_object_get (grid,
+ "transform", &matrix,
+ NULL);
+
+ gimp_matrix3_invert (matrix);
+ gimp_matrix3_transform_point (matrix,
+ private->trans_x[active_handle],
+ private->trans_y[active_handle],
+ &private->orig_x[active_handle],
+ &private->orig_y[active_handle]);
+
+ g_free (matrix);
+
+ gimp_tool_handle_grid_update_matrix (grid);
+ }
+}
+
+void
+gimp_tool_handle_grid_motion (GimpToolWidget *widget,
+ const GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state)
+{
+ GimpToolHandleGrid *grid = GIMP_TOOL_HANDLE_GRID (widget);
+ GimpToolHandleGridPrivate *private = grid->private;
+ gint n_handles = private->n_handles;
+ gint active_handle = private->handle - 1;
+ gdouble diff_x = coords->x - private->last_x;
+ gdouble diff_y = coords->y - private->last_y;
+
+ if (active_handle >= 0 && active_handle < 4)
+ {
+ if (private->handle_mode == GIMP_HANDLE_MODE_MOVE)
+ {
+ private->trans_x[active_handle] += diff_x;
+ private->trans_y[active_handle] += diff_y;
+
+ /* check for valid position and calculating of OX0...OY3 is
+ * done on button release hopefully this makes the code run
+ * faster Moving could be even faster if there was caching
+ * for the image preview
+ */
+ gimp_canvas_handle_set_position (private->handles[active_handle + 1],
+ private->trans_x[active_handle],
+ private->trans_y[active_handle]);
+ }
+ else if (private->handle_mode == GIMP_HANDLE_MODE_ADD_TRANSFORM)
+ {
+ gdouble angle, angle_sin, angle_cos, scale;
+ gdouble fixed_handles_x[3];
+ gdouble fixed_handles_y[3];
+ gdouble oldpos_x[4], oldpos_y[4];
+ gdouble newpos_x[4], newpos_y[4];
+ gint i, j;
+
+ for (i = 0, j = 0; i < 4; i++)
+ {
+ /* Find all visible handles that are not being moved */
+ if (i < n_handles && i != active_handle)
+ {
+ fixed_handles_x[j] = private->trans_x[i];
+ fixed_handles_y[j] = private->trans_y[i];
+ j++;
+ }
+
+ newpos_x[i] = oldpos_x[i] = private->trans_x[i];
+ newpos_y[i] = oldpos_y[i] = private->trans_y[i];
+ }
+
+ newpos_x[active_handle] = oldpos_x[active_handle] + diff_x;
+ newpos_y[active_handle] = oldpos_y[active_handle] + diff_y;
+
+ switch (n_handles)
+ {
+ case 1:
+ /* move */
+ for (i = 1; i < 4; i++)
+ {
+ newpos_x[i] = oldpos_x[i] + diff_y;
+ newpos_y[i] = oldpos_y[i] + diff_y;
+ }
+ break;
+
+ case 2:
+ /* rotate and keep-aspect-scale */
+ scale =
+ calc_len (newpos_x[active_handle] - fixed_handles_x[0],
+ newpos_y[active_handle] - fixed_handles_y[0]) /
+ calc_len (oldpos_x[active_handle] - fixed_handles_x[0],
+ oldpos_y[active_handle] - fixed_handles_y[0]);
+
+ angle = calc_angle (oldpos_x[active_handle] - fixed_handles_x[0],
+ oldpos_y[active_handle] - fixed_handles_y[0],
+ newpos_x[active_handle] - fixed_handles_x[0],
+ newpos_y[active_handle] - fixed_handles_y[0]);
+
+ angle_sin = sin (angle);
+ angle_cos = cos (angle);
+
+ for (i = 2; i < 4; i++)
+ {
+ newpos_x[i] =
+ fixed_handles_x[0] +
+ scale * (angle_cos * (oldpos_x[i] - fixed_handles_x[0]) +
+ angle_sin * (oldpos_y[i] - fixed_handles_y[0]));
+
+ newpos_y[i] =
+ fixed_handles_y[0] +
+ scale * (-angle_sin * (oldpos_x[i] - fixed_handles_x[0]) +
+ angle_cos * (oldpos_y[i] - fixed_handles_y[0]));
+ }
+ break;
+
+ case 3:
+ /* shear and non-aspect-scale */
+ scale = calc_lineintersect_ratio (oldpos_x[3],
+ oldpos_y[3],
+ oldpos_x[active_handle],
+ oldpos_y[active_handle],
+ fixed_handles_x[0],
+ fixed_handles_y[0],
+ fixed_handles_x[1],
+ fixed_handles_y[1]);
+
+ newpos_x[3] = oldpos_x[3] + scale * diff_x;
+ newpos_y[3] = oldpos_y[3] + scale * diff_y;
+ break;
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ private->trans_x[i] = newpos_x[i];
+ private->trans_y[i] = newpos_y[i];
+ }
+
+ gimp_tool_handle_grid_update_matrix (grid);
+ }
+ }
+
+ private->last_x = coords->x;
+ private->last_y = coords->y;
+}
+
+static void
+gimp_tool_handle_grid_hover (GimpToolWidget *widget,
+ const GimpCoords *coords,
+ GdkModifierType state,
+ gboolean proximity)
+{
+ GimpToolHandleGrid *grid = GIMP_TOOL_HANDLE_GRID (widget);
+ GimpToolHandleGridPrivate *private = grid->private;
+ gint i;
+
+ private->handle = 0;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (private->handles[i + 1] &&
+ gimp_canvas_item_hit (private->handles[i + 1],
+ coords->x, coords->y))
+ {
+ private->handle = i + 1;
+ break;
+ }
+ }
+
+ gimp_tool_handle_grid_update_hilight (grid);
+}
+
+static gboolean
+gimp_tool_handle_grid_get_cursor (GimpToolWidget *widget,
+ const GimpCoords *coords,
+ GdkModifierType state,
+ GimpCursorType *cursor,
+ GimpToolCursorType *tool_cursor,
+ GimpCursorModifier *cursor_modifier)
+{
+ GimpToolHandleGrid *grid = GIMP_TOOL_HANDLE_GRID (widget);
+ GimpToolHandleGridPrivate *private = grid->private;
+
+ *cursor = GIMP_CURSOR_CROSSHAIR_SMALL;
+ *tool_cursor = GIMP_TOOL_CURSOR_NONE;
+ *cursor_modifier = GIMP_CURSOR_MODIFIER_NONE;
+
+ switch (private->handle_mode)
+ {
+ case GIMP_HANDLE_MODE_ADD_TRANSFORM:
+ if (private->handle > 0)
+ {
+ switch (private->n_handles)
+ {
+ case 1:
+ *tool_cursor = GIMP_TOOL_CURSOR_MOVE;
+ break;
+ case 2:
+ *tool_cursor = GIMP_TOOL_CURSOR_ROTATE;
+ break;
+ case 3:
+ *tool_cursor = GIMP_TOOL_CURSOR_SHEAR;
+ break;
+ case 4:
+ *tool_cursor = GIMP_TOOL_CURSOR_PERSPECTIVE;
+ break;
+ }
+ }
+ else
+ {
+ if (private->n_handles < 4)
+ *cursor_modifier = GIMP_CURSOR_MODIFIER_PLUS;
+ else
+ *cursor_modifier = GIMP_CURSOR_MODIFIER_BAD;
+ }
+ break;
+
+ case GIMP_HANDLE_MODE_MOVE:
+ if (private->handle > 0)
+ *cursor_modifier = GIMP_CURSOR_MODIFIER_MOVE;
+ else
+ *cursor_modifier = GIMP_CURSOR_MODIFIER_BAD;
+ break;
+
+ case GIMP_HANDLE_MODE_REMOVE:
+ if (private->handle > 0)
+ *cursor_modifier = GIMP_CURSOR_MODIFIER_MINUS;
+ else
+ *cursor_modifier = GIMP_CURSOR_MODIFIER_BAD;
+ break;
+ }
+
+ return TRUE;
+}
+
+static void
+gimp_tool_handle_grid_update_hilight (GimpToolHandleGrid *grid)
+{
+ GimpToolHandleGridPrivate *private = grid->private;
+ gint i;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (private->handles[i + 1])
+ {
+ gimp_canvas_item_set_highlight (private->handles[i + 1],
+ (i + 1) == private->handle);
+ }
+ }
+}
+
+static void
+gimp_tool_handle_grid_update_matrix (GimpToolHandleGrid *grid)
+{
+ GimpToolHandleGridPrivate *private = grid->private;
+ GimpMatrix3 transform;
+
+ gimp_matrix3_identity (&transform);
+ gimp_transform_matrix_handles (&transform,
+ private->orig_x[0],
+ private->orig_y[0],
+ private->orig_x[1],
+ private->orig_y[1],
+ private->orig_x[2],
+ private->orig_y[2],
+ private->orig_x[3],
+ private->orig_y[3],
+ private->trans_x[0],
+ private->trans_y[0],
+ private->trans_x[1],
+ private->trans_y[1],
+ private->trans_x[2],
+ private->trans_y[2],
+ private->trans_x[3],
+ private->trans_y[3]);
+
+ g_object_set (grid,
+ "transform", &transform,
+ NULL);
+}
+
+/* check if a handle is not on the connection line of two other handles */
+static gboolean
+is_handle_position_valid (GimpToolHandleGrid *grid,
+ gint handle)
+{
+ GimpToolHandleGridPrivate *private = grid->private;
+ gint i, j, k;
+
+ for (i = 0; i < 2; i++)
+ {
+ for (j = i + 1; j < 3; j++)
+ {
+ for (k = j + 1; i < 4; i++)
+ {
+ if (handle == i ||
+ handle == j ||
+ handle == k)
+ {
+ if ((private->trans_x[i] -
+ private->trans_x[j]) *
+ (private->trans_y[j] -
+ private->trans_y[k]) ==
+
+ (private->trans_x[j] -
+ private->trans_x[k]) *
+ (private->trans_y[i] -
+ private->trans_y[j]))
+ {
+ return FALSE;
+ }
+ }
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+/* three handles on a line causes problems.
+ * Let's move the new handle around a bit to find a better position */
+static void
+handle_micro_move (GimpToolHandleGrid *grid,
+ gint handle)
+{
+ GimpToolHandleGridPrivate *private = grid->private;
+ gdouble posx = private->trans_x[handle];
+ gdouble posy = private->trans_y[handle];
+ gdouble dx, dy;
+
+ for (dx = -0.1; dx < 0.11; dx += 0.1)
+ {
+ private->trans_x[handle] = posx + dx;
+
+ for (dy = -0.1; dy < 0.11; dy += 0.1)
+ {
+ private->trans_y[handle] = posy + dy;
+
+ if (is_handle_position_valid (grid, handle))
+ {
+ return;
+ }
+ }
+ }
+}
+
+/* finds the clockwise angle between the vectors given, 0-2π */
+static inline gdouble
+calc_angle (gdouble ax,
+ gdouble ay,
+ gdouble bx,
+ gdouble by)
+{
+ gdouble angle;
+ gdouble direction;
+ gdouble length = sqrt ((ax * ax + ay * ay) * (bx * bx + by * by));
+
+ angle = acos ((ax * bx + ay * by) / length);
+ direction = ax * by - ay * bx;
+
+ return ((direction < 0) ? angle : 2 * G_PI - angle);
+}
+
+static inline gdouble
+calc_len (gdouble a,
+ gdouble b)
+{
+ return sqrt (a * a + b * b);
+}
+
+/* imagine two lines, one through the points p1 and p2, the other one
+ * through the points q1 and q2. Find the intersection point r.
+ * Calculate (distance p1 to r)/(distance p2 to r)
+ */
+static inline gdouble
+calc_lineintersect_ratio (gdouble p1x, gdouble p1y,
+ gdouble p2x, gdouble p2y,
+ gdouble q1x, gdouble q1y,
+ gdouble q2x, gdouble q2y)
+{
+ gdouble denom, u;
+
+ denom = (q2y - q1y) * (p2x - p1x) - (q2x - q1x) * (p2y - p1y);
+ if (denom == 0.0)
+ {
+ /* u is infinite, so u/(u-1) is 1 */
+ return 1.0;
+ }
+
+ u = (q2y - q1y) * (q1x - p1x) - (q1y - p1y) * (q2x - q1x);
+ u /= denom;
+
+ return u / (u - 1);
+}
+
+
+/* public functions */
+
+GimpToolWidget *
+gimp_tool_handle_grid_new (GimpDisplayShell *shell,
+ gdouble x1,
+ gdouble y1,
+ gdouble x2,
+ gdouble y2)
+{
+ g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), NULL);
+
+ return g_object_new (GIMP_TYPE_TOOL_HANDLE_GRID,
+ "shell", shell,
+ "x1", x1,
+ "y1", y1,
+ "x2", x2,
+ "y2", y2,
+ NULL);
+}
diff --git a/app/display/gimptoolhandlegrid.h b/app/display/gimptoolhandlegrid.h
new file mode 100644
index 0000000..5a979c0
--- /dev/null
+++ b/app/display/gimptoolhandlegrid.h
@@ -0,0 +1,62 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimptoolhandlegrid.h
+ * Copyright (C) 2017 Michael Natterer <mitch gimp org>
+ *
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_TOOL_HANDLE_GRID_H__
+#define __GIMP_TOOL_HANDLE_GRID_H__
+
+
+#include "gimptooltransformgrid.h"
+
+
+#define GIMP_TYPE_TOOL_HANDLE_GRID (gimp_tool_handle_grid_get_type ())
+#define GIMP_TOOL_HANDLE_GRID(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),
GIMP_TYPE_TOOL_HANDLE_GRID, GimpToolHandleGrid))
+#define GIMP_TOOL_HANDLE_GRID_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_TOOL_HANDLE_GRID,
GimpToolHandleGridClass))
+#define GIMP_IS_TOOL_HANDLE_GRID(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),
GIMP_TYPE_TOOL_HANDLE_GRID))
+#define GIMP_IS_TOOL_HANDLE_GRID_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_TOOL_HANDLE_GRID))
+#define GIMP_TOOL_HANDLE_GRID_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_TOOL_HANDLE_GRID,
GimpToolHandleGridClass))
+
+
+typedef struct _GimpToolHandleGrid GimpToolHandleGrid;
+typedef struct _GimpToolHandleGridPrivate GimpToolHandleGridPrivate;
+typedef struct _GimpToolHandleGridClass GimpToolHandleGridClass;
+
+struct _GimpToolHandleGrid
+{
+ GimpToolTransformGrid parent_instance;
+
+ GimpToolHandleGridPrivate *private;
+};
+
+struct _GimpToolHandleGridClass
+{
+ GimpToolTransformGridClass parent_class;
+};
+
+
+GType gimp_tool_handle_grid_get_type (void) G_GNUC_CONST;
+
+GimpToolWidget * gimp_tool_handle_grid_new (GimpDisplayShell *shell,
+ gdouble x1,
+ gdouble y1,
+ gdouble x2,
+ gdouble y2);
+
+
+#endif /* __GIMP_TOOL_HANDLE_GRID_H__ */
diff --git a/app/tools/tools-enums.c b/app/tools/tools-enums.c
index 972532f..261d78a 100644
--- a/app/tools/tools-enums.c
+++ b/app/tools/tools-enums.c
@@ -10,37 +10,6 @@
/* enumerations from "tools-enums.h" */
GType
-gimp_transform_handle_mode_get_type (void)
-{
- static const GEnumValue values[] =
- {
- { GIMP_HANDLE_MODE_ADD_TRANSFORM, "GIMP_HANDLE_MODE_ADD_TRANSFORM", "add-transform" },
- { GIMP_HANDLE_MODE_MOVE, "GIMP_HANDLE_MODE_MOVE", "move" },
- { GIMP_HANDLE_MODE_REMOVE, "GIMP_HANDLE_MODE_REMOVE", "remove" },
- { 0, NULL, NULL }
- };
-
- static const GimpEnumDesc descs[] =
- {
- { GIMP_HANDLE_MODE_ADD_TRANSFORM, NC_("transform-handle-mode", "Add / Transform"), NULL },
- { GIMP_HANDLE_MODE_MOVE, NC_("transform-handle-mode", "Move"), NULL },
- { GIMP_HANDLE_MODE_REMOVE, NC_("transform-handle-mode", "Remove"), NULL },
- { 0, NULL, NULL }
- };
-
- static GType type = 0;
-
- if (G_UNLIKELY (! type))
- {
- type = g_enum_register_static ("GimpTransformHandleMode", values);
- gimp_type_set_translation_context (type, "transform-handle-mode");
- gimp_enum_set_value_descriptions (type, descs);
- }
-
- return type;
-}
-
-GType
gimp_rectangle_constraint_get_type (void)
{
static const GEnumValue values[] =
diff --git a/app/tools/tools-enums.h b/app/tools/tools-enums.h
index 25a0527..43d3882 100644
--- a/app/tools/tools-enums.h
+++ b/app/tools/tools-enums.h
@@ -23,18 +23,6 @@
* these enums are registered with the type system
*/
-#define GIMP_TYPE_TRANSFORM_HANDLE_MODE (gimp_transform_handle_mode_get_type ())
-
-GType gimp_transform_handle_mode_get_type (void) G_GNUC_CONST;
-
-typedef enum
-{
- GIMP_HANDLE_MODE_ADD_TRANSFORM, /*< desc="Add / Transform" >*/
- GIMP_HANDLE_MODE_MOVE, /*< desc="Move" >*/
- GIMP_HANDLE_MODE_REMOVE /*< desc="Remove" >*/
-} GimpTransformHandleMode;
-
-
#define GIMP_TYPE_RECTANGLE_CONSTRAINT (gimp_rectangle_constraint_get_type ())
GType gimp_rectangle_constraint_get_type (void) G_GNUC_CONST;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]