2018-06-10 04:25:03 +08:00
|
|
|
/* 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
|
2018-07-12 05:27:07 +08:00
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
2018-06-10 04:25:03 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <gegl.h>
|
|
|
|
#include <gtk/gtk.h>
|
|
|
|
#include <gdk/gdkkeysyms.h>
|
|
|
|
|
|
|
|
#include "libgimpmath/gimpmath.h"
|
|
|
|
#include "libgimpwidgets/gimpwidgets.h"
|
|
|
|
|
|
|
|
#include "tools-types.h"
|
|
|
|
|
2020-01-16 06:17:56 +08:00
|
|
|
#include "gegl/gimpapplicator.h"
|
|
|
|
#include "gegl/gimp-gegl-nodes.h"
|
|
|
|
#include "gegl/gimp-gegl-utils.h"
|
|
|
|
|
2018-06-10 04:25:03 +08:00
|
|
|
#include "core/gimp.h"
|
2020-01-16 06:17:56 +08:00
|
|
|
#include "core/gimp-transform-resize.h"
|
|
|
|
#include "core/gimp-transform-utils.h"
|
2018-06-10 04:25:03 +08:00
|
|
|
#include "core/gimpboundary.h"
|
2020-01-16 06:17:56 +08:00
|
|
|
#include "core/gimpcontainer.h"
|
|
|
|
#include "core/gimpdrawablefilter.h"
|
2018-06-10 04:25:03 +08:00
|
|
|
#include "core/gimperror.h"
|
2020-01-16 06:17:56 +08:00
|
|
|
#include "core/gimpfilter.h"
|
|
|
|
#include "core/gimpgrouplayer.h"
|
2018-06-10 04:25:03 +08:00
|
|
|
#include "core/gimpimage.h"
|
2020-01-18 21:11:51 +08:00
|
|
|
#include "core/gimpimage-item-list.h"
|
2018-06-10 04:25:03 +08:00
|
|
|
#include "core/gimpimage-undo.h"
|
|
|
|
#include "core/gimpimage-undo-push.h"
|
|
|
|
#include "core/gimplayer.h"
|
|
|
|
#include "core/gimplayermask.h"
|
2019-08-10 23:46:14 +08:00
|
|
|
#include "core/gimppickable.h"
|
2018-06-10 04:25:03 +08:00
|
|
|
#include "core/gimpprojection.h"
|
|
|
|
#include "core/gimptoolinfo.h"
|
2020-01-16 06:14:15 +08:00
|
|
|
#include "core/gimpviewable.h"
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
#include "vectors/gimpvectors.h"
|
|
|
|
#include "vectors/gimpstroke.h"
|
|
|
|
|
|
|
|
#include "widgets/gimpwidgets-utils.h"
|
|
|
|
|
|
|
|
#include "display/gimpcanvasitem.h"
|
|
|
|
#include "display/gimpdisplay.h"
|
2019-08-11 03:57:55 +08:00
|
|
|
#include "display/gimpdisplayshell.h"
|
2018-06-10 04:25:03 +08:00
|
|
|
#include "display/gimptoolgui.h"
|
|
|
|
#include "display/gimptoolwidget.h"
|
|
|
|
|
|
|
|
#include "gimptoolcontrol.h"
|
|
|
|
#include "gimptransformgridoptions.h"
|
|
|
|
#include "gimptransformgridtool.h"
|
|
|
|
#include "gimptransformgridtoolundo.h"
|
|
|
|
#include "gimptransformoptions.h"
|
|
|
|
|
|
|
|
#include "gimp-intl.h"
|
|
|
|
|
|
|
|
|
2019-03-13 17:20:51 +08:00
|
|
|
#define EPSILON 1e-6
|
|
|
|
|
|
|
|
|
2020-01-06 18:00:27 +08:00
|
|
|
#define RESPONSE_RESET 1
|
|
|
|
#define RESPONSE_READJUST 2
|
|
|
|
|
|
|
|
#define UNDO_COMPRESS_TIME (0.5 * G_TIME_SPAN_SECOND)
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
|
2020-01-16 06:17:56 +08:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
GimpTransformGridTool *tg_tool;
|
|
|
|
|
|
|
|
GimpDrawable *drawable;
|
|
|
|
GimpDrawableFilter *filter;
|
|
|
|
|
2020-01-18 21:11:51 +08:00
|
|
|
GimpDrawable *root_drawable;
|
2020-01-16 06:17:56 +08:00
|
|
|
|
|
|
|
GeglNode *transform_node;
|
|
|
|
GeglNode *crop_node;
|
|
|
|
|
|
|
|
GimpMatrix3 transform;
|
|
|
|
GeglRectangle bounds;
|
|
|
|
} Filter;
|
|
|
|
|
2020-01-18 21:11:51 +08:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
GimpTransformGridTool *tg_tool;
|
|
|
|
GimpDrawable *root_drawable;
|
|
|
|
} AddFilterData;
|
|
|
|
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
typedef struct
|
|
|
|
{
|
2020-01-06 18:00:27 +08:00
|
|
|
gint64 time;
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
GimpTransformDirection direction;
|
|
|
|
TransInfo trans_infos[2];
|
|
|
|
} UndoInfo;
|
|
|
|
|
|
|
|
|
2018-06-10 04:25:03 +08:00
|
|
|
static void gimp_transform_grid_tool_finalize (GObject *object);
|
|
|
|
|
|
|
|
static gboolean gimp_transform_grid_tool_initialize (GimpTool *tool,
|
|
|
|
GimpDisplay *display,
|
|
|
|
GError **error);
|
|
|
|
static void gimp_transform_grid_tool_control (GimpTool *tool,
|
|
|
|
GimpToolAction action,
|
|
|
|
GimpDisplay *display);
|
|
|
|
static void gimp_transform_grid_tool_button_press (GimpTool *tool,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
guint32 time,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpButtonPressType press_type,
|
|
|
|
GimpDisplay *display);
|
|
|
|
static void gimp_transform_grid_tool_button_release (GimpTool *tool,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
guint32 time,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpButtonReleaseType release_type,
|
|
|
|
GimpDisplay *display);
|
|
|
|
static void gimp_transform_grid_tool_motion (GimpTool *tool,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
guint32 time,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpDisplay *display);
|
|
|
|
static void gimp_transform_grid_tool_modifier_key (GimpTool *tool,
|
|
|
|
GdkModifierType key,
|
|
|
|
gboolean press,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpDisplay *display);
|
|
|
|
static void gimp_transform_grid_tool_cursor_update (GimpTool *tool,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpDisplay *display);
|
|
|
|
static const gchar * gimp_transform_grid_tool_can_undo (GimpTool *tool,
|
|
|
|
GimpDisplay *display);
|
|
|
|
static const gchar * gimp_transform_grid_tool_can_redo (GimpTool *tool,
|
|
|
|
GimpDisplay *display);
|
|
|
|
static gboolean gimp_transform_grid_tool_undo (GimpTool *tool,
|
|
|
|
GimpDisplay *display);
|
|
|
|
static gboolean gimp_transform_grid_tool_redo (GimpTool *tool,
|
|
|
|
GimpDisplay *display);
|
|
|
|
static void gimp_transform_grid_tool_options_notify (GimpTool *tool,
|
|
|
|
GimpToolOptions *options,
|
|
|
|
const GParamSpec *pspec);
|
|
|
|
|
|
|
|
static void gimp_transform_grid_tool_draw (GimpDrawTool *draw_tool);
|
|
|
|
|
2018-06-16 03:42:19 +08:00
|
|
|
static void gimp_transform_grid_tool_recalc_matrix (GimpTransformTool *tr_tool);
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
static gchar * gimp_transform_grid_tool_get_undo_desc (GimpTransformTool *tr_tool);
|
|
|
|
static GimpTransformDirection gimp_transform_grid_tool_get_direction
|
|
|
|
(GimpTransformTool *tr_tool);
|
2018-06-10 04:25:03 +08:00
|
|
|
static GeglBuffer * gimp_transform_grid_tool_transform (GimpTransformTool *tr_tool,
|
2020-05-26 22:15:15 +08:00
|
|
|
GList *objects,
|
2018-06-10 04:25:03 +08:00
|
|
|
GeglBuffer *orig_buffer,
|
|
|
|
gint orig_offset_x,
|
|
|
|
gint orig_offset_y,
|
|
|
|
GimpColorProfile **buffer_profile,
|
|
|
|
gint *new_offset_x,
|
|
|
|
gint *new_offset_y);
|
|
|
|
|
2020-04-27 21:44:40 +08:00
|
|
|
static void gimp_transform_grid_tool_real_apply_info (GimpTransformGridTool *tg_tool,
|
|
|
|
const TransInfo info);
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
static gchar * gimp_transform_grid_tool_real_get_undo_desc (GimpTransformGridTool *tg_tool);
|
|
|
|
static void gimp_transform_grid_tool_real_update_widget (GimpTransformGridTool *tg_tool);
|
2018-06-16 03:42:19 +08:00
|
|
|
static void gimp_transform_grid_tool_real_widget_changed (GimpTransformGridTool *tg_tool);
|
2018-06-10 04:25:03 +08:00
|
|
|
static GeglBuffer * gimp_transform_grid_tool_real_transform (GimpTransformGridTool *tg_tool,
|
2020-05-26 22:15:15 +08:00
|
|
|
GList *objects,
|
2018-06-10 04:25:03 +08:00
|
|
|
GeglBuffer *orig_buffer,
|
|
|
|
gint orig_offset_x,
|
|
|
|
gint orig_offset_y,
|
|
|
|
GimpColorProfile **buffer_profile,
|
|
|
|
gint *new_offset_x,
|
|
|
|
gint *new_offset_y);
|
|
|
|
|
|
|
|
static void gimp_transform_grid_tool_widget_changed (GimpToolWidget *widget,
|
|
|
|
GimpTransformGridTool *tg_tool);
|
|
|
|
static void gimp_transform_grid_tool_widget_response (GimpToolWidget *widget,
|
|
|
|
gint response_id,
|
|
|
|
GimpTransformGridTool *tg_tool);
|
|
|
|
|
2020-01-16 06:17:56 +08:00
|
|
|
static void gimp_transform_grid_tool_filter_flush (GimpDrawableFilter *filter,
|
|
|
|
GimpTransformGridTool *tg_tool);
|
|
|
|
|
2018-06-10 04:25:03 +08:00
|
|
|
static void gimp_transform_grid_tool_halt (GimpTransformGridTool *tg_tool);
|
|
|
|
static void gimp_transform_grid_tool_commit (GimpTransformGridTool *tg_tool);
|
|
|
|
|
|
|
|
static void gimp_transform_grid_tool_dialog (GimpTransformGridTool *tg_tool);
|
|
|
|
static void gimp_transform_grid_tool_dialog_update (GimpTransformGridTool *tg_tool);
|
|
|
|
static void gimp_transform_grid_tool_prepare (GimpTransformGridTool *tg_tool,
|
|
|
|
GimpDisplay *display);
|
|
|
|
static GimpToolWidget * gimp_transform_grid_tool_get_widget (GimpTransformGridTool *tg_tool);
|
2018-06-16 03:42:19 +08:00
|
|
|
static void gimp_transform_grid_tool_update_widget (GimpTransformGridTool *tg_tool);
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
static void gimp_transform_grid_tool_response (GimpToolGui *gui,
|
|
|
|
gint response_id,
|
|
|
|
GimpTransformGridTool *tg_tool);
|
|
|
|
|
2020-01-16 06:17:56 +08:00
|
|
|
static gboolean gimp_transform_grid_tool_composited_preview (GimpTransformGridTool *tg_tool);
|
2018-06-10 04:25:03 +08:00
|
|
|
static void gimp_transform_grid_tool_update_sensitivity (GimpTransformGridTool *tg_tool);
|
2018-06-16 03:42:19 +08:00
|
|
|
static void gimp_transform_grid_tool_update_preview (GimpTransformGridTool *tg_tool);
|
2020-01-18 21:11:51 +08:00
|
|
|
static void gimp_transform_grid_tool_update_filters (GimpTransformGridTool *tg_tool);
|
2020-05-26 22:15:15 +08:00
|
|
|
static void gimp_transform_grid_tool_hide_selected_objects (GimpTransformGridTool *tg_tool,
|
|
|
|
GList *objects);
|
|
|
|
static void gimp_transform_grid_tool_show_selected_objects (GimpTransformGridTool *tg_tool);
|
2018-06-10 04:25:03 +08:00
|
|
|
|
2020-01-16 06:17:56 +08:00
|
|
|
static void gimp_transform_grid_tool_add_filter (GimpDrawable *drawable,
|
2020-01-18 21:11:51 +08:00
|
|
|
AddFilterData *data);
|
2020-01-16 06:17:56 +08:00
|
|
|
static void gimp_transform_grid_tool_remove_filter (GimpDrawable *drawable,
|
|
|
|
GimpTransformGridTool *tg_tool);
|
|
|
|
|
|
|
|
static void gimp_transform_grid_tool_effective_mode_changed
|
|
|
|
(GimpLayer *layer,
|
|
|
|
GimpTransformGridTool *tg_tool);
|
|
|
|
|
|
|
|
static Filter * filter_new (GimpTransformGridTool *tg_tool,
|
|
|
|
GimpDrawable *drawable,
|
2020-01-18 21:11:51 +08:00
|
|
|
GimpDrawable *root_drawable,
|
2020-01-16 06:17:56 +08:00
|
|
|
gboolean add_filter);
|
|
|
|
static void filter_free (Filter *filter);
|
|
|
|
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
static UndoInfo * undo_info_new (void);
|
|
|
|
static void undo_info_free (UndoInfo *info);
|
2018-06-10 04:25:03 +08:00
|
|
|
|
2019-03-13 17:20:51 +08:00
|
|
|
static gboolean trans_info_equal (const TransInfo trans_info1,
|
|
|
|
const TransInfo trans_info2);
|
|
|
|
static gboolean trans_infos_equal (const TransInfo *trans_infos1,
|
|
|
|
const TransInfo *trans_infos2);
|
|
|
|
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
G_DEFINE_TYPE (GimpTransformGridTool, gimp_transform_grid_tool, GIMP_TYPE_TRANSFORM_TOOL)
|
|
|
|
|
|
|
|
#define parent_class gimp_transform_grid_tool_parent_class
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_class_init (GimpTransformGridToolClass *klass)
|
|
|
|
{
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
GimpToolClass *tool_class = GIMP_TOOL_CLASS (klass);
|
|
|
|
GimpDrawToolClass *draw_class = GIMP_DRAW_TOOL_CLASS (klass);
|
|
|
|
GimpTransformToolClass *tr_class = GIMP_TRANSFORM_TOOL_CLASS (klass);
|
|
|
|
|
|
|
|
object_class->finalize = gimp_transform_grid_tool_finalize;
|
|
|
|
|
|
|
|
tool_class->initialize = gimp_transform_grid_tool_initialize;
|
|
|
|
tool_class->control = gimp_transform_grid_tool_control;
|
|
|
|
tool_class->button_press = gimp_transform_grid_tool_button_press;
|
|
|
|
tool_class->button_release = gimp_transform_grid_tool_button_release;
|
|
|
|
tool_class->motion = gimp_transform_grid_tool_motion;
|
|
|
|
tool_class->modifier_key = gimp_transform_grid_tool_modifier_key;
|
|
|
|
tool_class->cursor_update = gimp_transform_grid_tool_cursor_update;
|
|
|
|
tool_class->can_undo = gimp_transform_grid_tool_can_undo;
|
|
|
|
tool_class->can_redo = gimp_transform_grid_tool_can_redo;
|
|
|
|
tool_class->undo = gimp_transform_grid_tool_undo;
|
|
|
|
tool_class->redo = gimp_transform_grid_tool_redo;
|
|
|
|
tool_class->options_notify = gimp_transform_grid_tool_options_notify;
|
|
|
|
|
|
|
|
draw_class->draw = gimp_transform_grid_tool_draw;
|
|
|
|
|
2018-06-16 03:42:19 +08:00
|
|
|
tr_class->recalc_matrix = gimp_transform_grid_tool_recalc_matrix;
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
tr_class->get_undo_desc = gimp_transform_grid_tool_get_undo_desc;
|
|
|
|
tr_class->get_direction = gimp_transform_grid_tool_get_direction;
|
2018-06-10 04:25:03 +08:00
|
|
|
tr_class->transform = gimp_transform_grid_tool_transform;
|
|
|
|
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
klass->info_to_matrix = NULL;
|
app: in GimpTransformGridTool, allow linking forward/backward transforms
Add a GimpTransformGridTool::matrix_to_info() virtual function,
which should extract the tool-specific transformation parameters
given a transformation matrix, and the old parameter set (which is
needed in some tools, to derive the parameters that aren't encoded
in the matrix, such as the pivot point). The transformation matrix
can be any combination of matrices calculated by the tool, and
their inverses. Subclasses should only implement this function if
every such matrix can be mapped back to transformation parameters.
This is currently the case for all the transform-grid tools, except
for the shear tool (since it only supports shearing along one of
the horizontal or the vertical directions, however, the combined
matrix may require shearing in both directions).
When a transform-grid tool implements this function, show a chain-
button between the two transform-direction radio-buttons in the
tool options. When the chain-button is linked, whenever the
transform corresponding to the active direction is modified, adjust
the transform corresponding to the non-active direction such that
the overall transform remains the same.
One notable workflow that this enables is transforming a layer
while adjusting a different area than its boundary, by first
defining the area while the transform-directions are linked, and
then transforming the area while the transform-directions are
unlinked.
2019-02-05 04:33:44 +08:00
|
|
|
klass->matrix_to_info = NULL;
|
2020-04-27 21:44:40 +08:00
|
|
|
klass->apply_info = gimp_transform_grid_tool_real_apply_info;
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
klass->get_undo_desc = gimp_transform_grid_tool_real_get_undo_desc;
|
2018-06-10 04:25:03 +08:00
|
|
|
klass->dialog = NULL;
|
|
|
|
klass->dialog_update = NULL;
|
|
|
|
klass->prepare = NULL;
|
2019-03-08 05:05:18 +08:00
|
|
|
klass->readjust = NULL;
|
2018-06-16 03:42:19 +08:00
|
|
|
klass->get_widget = NULL;
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
klass->update_widget = gimp_transform_grid_tool_real_update_widget;
|
2018-06-16 03:42:19 +08:00
|
|
|
klass->widget_changed = gimp_transform_grid_tool_real_widget_changed;
|
2018-06-10 04:25:03 +08:00
|
|
|
klass->transform = gimp_transform_grid_tool_real_transform;
|
|
|
|
|
|
|
|
klass->ok_button_label = _("_Transform");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_init (GimpTransformGridTool *tg_tool)
|
|
|
|
{
|
|
|
|
GimpTool *tool = GIMP_TOOL (tg_tool);
|
|
|
|
|
|
|
|
gimp_tool_control_set_scroll_lock (tool->control, TRUE);
|
|
|
|
gimp_tool_control_set_preserve (tool->control, FALSE);
|
|
|
|
gimp_tool_control_set_dirty_mask (tool->control,
|
2020-01-16 06:17:56 +08:00
|
|
|
GIMP_DIRTY_IMAGE_SIZE |
|
|
|
|
GIMP_DIRTY_IMAGE_STRUCTURE |
|
|
|
|
GIMP_DIRTY_DRAWABLE |
|
|
|
|
GIMP_DIRTY_SELECTION |
|
2018-06-10 04:25:03 +08:00
|
|
|
GIMP_DIRTY_ACTIVE_DRAWABLE);
|
|
|
|
gimp_tool_control_set_active_modifiers (tool->control,
|
|
|
|
GIMP_TOOL_ACTIVE_MODIFIERS_SAME);
|
|
|
|
gimp_tool_control_set_precision (tool->control,
|
|
|
|
GIMP_CURSOR_PRECISION_SUBPIXEL);
|
|
|
|
gimp_tool_control_set_cursor (tool->control,
|
|
|
|
GIMP_CURSOR_CROSSHAIR_SMALL);
|
|
|
|
gimp_tool_control_set_action_opacity (tool->control,
|
2023-02-27 02:53:24 +08:00
|
|
|
"tools-transform-preview-opacity-set");
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
tg_tool->strokes = g_ptr_array_new ();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_finalize (GObject *object)
|
|
|
|
{
|
|
|
|
GimpTransformGridTool *tg_tool = GIMP_TRANSFORM_GRID_TOOL (object);
|
|
|
|
|
|
|
|
g_clear_object (&tg_tool->gui);
|
|
|
|
g_clear_pointer (&tg_tool->strokes, g_ptr_array_unref);
|
|
|
|
|
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gimp_transform_grid_tool_initialize (GimpTool *tool,
|
|
|
|
GimpDisplay *display,
|
|
|
|
GError **error)
|
|
|
|
{
|
2020-04-27 21:41:43 +08:00
|
|
|
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tool);
|
|
|
|
GimpTransformGridTool *tg_tool = GIMP_TRANSFORM_GRID_TOOL (tool);
|
|
|
|
GimpTransformGridOptions *tg_options = GIMP_TRANSFORM_GRID_TOOL_GET_OPTIONS (tool);
|
|
|
|
GimpImage *image = gimp_display_get_image (display);
|
2020-05-25 17:30:31 +08:00
|
|
|
GList *drawables;
|
2020-05-26 22:15:15 +08:00
|
|
|
GList *objects;
|
|
|
|
GList *iter;
|
2020-04-27 21:41:43 +08:00
|
|
|
UndoInfo *undo_info;
|
2018-06-10 04:25:03 +08:00
|
|
|
|
2020-05-26 22:15:15 +08:00
|
|
|
objects = gimp_transform_tool_check_selected_objects (tr_tool, display, error);
|
2018-06-10 04:25:03 +08:00
|
|
|
|
2020-05-26 22:15:15 +08:00
|
|
|
if (! objects)
|
2018-06-10 04:25:03 +08:00
|
|
|
return FALSE;
|
|
|
|
|
2020-05-25 17:30:31 +08:00
|
|
|
drawables = gimp_image_get_selected_drawables (image);
|
2020-05-26 22:15:15 +08:00
|
|
|
if (g_list_length (drawables) < 1)
|
2020-05-25 17:30:31 +08:00
|
|
|
{
|
2020-05-26 22:15:15 +08:00
|
|
|
gimp_tool_message_literal (tool, display, _("No selected drawables."));
|
2020-05-25 17:30:31 +08:00
|
|
|
g_list_free (drawables);
|
2020-05-26 22:15:15 +08:00
|
|
|
g_list_free (objects);
|
2020-05-25 17:30:31 +08:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2020-05-26 22:15:15 +08:00
|
|
|
tool->display = display;
|
|
|
|
tool->drawables = drawables;
|
2018-06-10 19:22:52 +08:00
|
|
|
|
2020-05-26 22:15:15 +08:00
|
|
|
tr_tool->objects = objects;
|
2018-06-10 04:25:03 +08:00
|
|
|
|
2020-05-26 22:15:15 +08:00
|
|
|
for (iter = objects; iter; iter = iter->next)
|
|
|
|
if (GIMP_IS_DRAWABLE (iter->data))
|
|
|
|
gimp_viewable_preview_freeze (iter->data);
|
2020-01-16 06:14:15 +08:00
|
|
|
|
2018-06-10 04:25:03 +08:00
|
|
|
/* Initialize the transform_grid tool dialog */
|
|
|
|
if (! tg_tool->gui)
|
|
|
|
gimp_transform_grid_tool_dialog (tg_tool);
|
|
|
|
|
|
|
|
/* Find the transform bounds for some tools (like scale,
|
|
|
|
* perspective) that actually need the bounds for initializing
|
|
|
|
*/
|
|
|
|
gimp_transform_tool_bounds (tr_tool, display);
|
|
|
|
|
|
|
|
/* Initialize the tool-specific trans_info, and adjust the tool dialog */
|
|
|
|
gimp_transform_grid_tool_prepare (tg_tool, display);
|
|
|
|
|
2018-06-16 03:42:19 +08:00
|
|
|
/* Recalculate the tool's transformation matrix */
|
|
|
|
gimp_transform_tool_recalc_matrix (tr_tool, display);
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
/* Get the on-canvas gui */
|
|
|
|
tg_tool->widget = gimp_transform_grid_tool_get_widget (tg_tool);
|
|
|
|
|
2020-05-26 22:15:15 +08:00
|
|
|
gimp_transform_grid_tool_hide_selected_objects (tg_tool, objects);
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
/* start drawing the bounding box and handles... */
|
|
|
|
gimp_draw_tool_start (GIMP_DRAW_TOOL (tool), display);
|
|
|
|
|
|
|
|
/* Initialize undo and redo lists */
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
undo_info = undo_info_new ();
|
|
|
|
tg_tool->undo_list = g_list_prepend (NULL, undo_info);
|
2018-06-10 04:25:03 +08:00
|
|
|
tg_tool->redo_list = NULL;
|
|
|
|
|
|
|
|
/* Save the current transformation info */
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
memcpy (undo_info->trans_infos, tg_tool->trans_infos,
|
|
|
|
sizeof (tg_tool->trans_infos));
|
2018-06-10 04:25:03 +08:00
|
|
|
|
2020-04-27 21:41:43 +08:00
|
|
|
if (tg_options->direction_chain_button)
|
|
|
|
gtk_widget_set_sensitive (tg_options->direction_chain_button, TRUE);
|
|
|
|
|
2018-06-10 04:25:03 +08:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_control (GimpTool *tool,
|
|
|
|
GimpToolAction action,
|
|
|
|
GimpDisplay *display)
|
|
|
|
{
|
|
|
|
GimpTransformGridTool *tg_tool = GIMP_TRANSFORM_GRID_TOOL (tool);
|
|
|
|
|
|
|
|
switch (action)
|
|
|
|
{
|
|
|
|
case GIMP_TOOL_ACTION_PAUSE:
|
|
|
|
case GIMP_TOOL_ACTION_RESUME:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_TOOL_ACTION_HALT:
|
|
|
|
gimp_transform_grid_tool_halt (tg_tool);
|
2019-08-11 05:07:20 +08:00
|
|
|
break;
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
case GIMP_TOOL_ACTION_COMMIT:
|
|
|
|
if (tool->display)
|
|
|
|
gimp_transform_grid_tool_commit (tg_tool);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
GIMP_TOOL_CLASS (parent_class)->control (tool, action, display);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_button_press (GimpTool *tool,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
guint32 time,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpButtonPressType press_type,
|
|
|
|
GimpDisplay *display)
|
|
|
|
{
|
|
|
|
GimpTransformGridTool *tg_tool = GIMP_TRANSFORM_GRID_TOOL (tool);
|
|
|
|
|
|
|
|
if (tg_tool->widget)
|
|
|
|
{
|
|
|
|
gimp_tool_widget_hover (tg_tool->widget, coords, state, TRUE);
|
|
|
|
|
|
|
|
if (gimp_tool_widget_button_press (tg_tool->widget, coords, time, state,
|
|
|
|
press_type))
|
|
|
|
{
|
|
|
|
tg_tool->grab_widget = tg_tool->widget;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_tool_control_activate (tool->control);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_button_release (GimpTool *tool,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
guint32 time,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpButtonReleaseType release_type,
|
|
|
|
GimpDisplay *display)
|
|
|
|
{
|
2018-06-16 03:42:19 +08:00
|
|
|
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tool);
|
2018-06-10 04:25:03 +08:00
|
|
|
GimpTransformGridTool *tg_tool = GIMP_TRANSFORM_GRID_TOOL (tool);
|
|
|
|
|
|
|
|
gimp_tool_control_halt (tool->control);
|
|
|
|
|
|
|
|
if (tg_tool->grab_widget)
|
|
|
|
{
|
|
|
|
gimp_tool_widget_button_release (tg_tool->grab_widget,
|
|
|
|
coords, time, state, release_type);
|
|
|
|
tg_tool->grab_widget = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (release_type != GIMP_BUTTON_RELEASE_CANCEL)
|
|
|
|
{
|
|
|
|
/* We're done with an interaction, save it on the undo list */
|
2020-01-06 18:00:27 +08:00
|
|
|
gimp_transform_grid_tool_push_internal_undo (tg_tool, FALSE);
|
2018-06-10 04:25:03 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
UndoInfo *undo_info = tg_tool->undo_list->data;
|
|
|
|
|
2018-06-10 04:25:03 +08:00
|
|
|
/* Restore the last saved state */
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
memcpy (tg_tool->trans_infos, undo_info->trans_infos,
|
|
|
|
sizeof (tg_tool->trans_infos));
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
/* recalculate the tool's transformation matrix */
|
2018-06-16 03:42:19 +08:00
|
|
|
gimp_transform_tool_recalc_matrix (tr_tool, display);
|
2018-06-10 04:25:03 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_motion (GimpTool *tool,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
guint32 time,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpDisplay *display)
|
|
|
|
{
|
|
|
|
GimpTransformGridTool *tg_tool = GIMP_TRANSFORM_GRID_TOOL (tool);
|
|
|
|
|
|
|
|
if (tg_tool->grab_widget)
|
|
|
|
{
|
|
|
|
gimp_tool_widget_motion (tg_tool->grab_widget, coords, time, state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_modifier_key (GimpTool *tool,
|
|
|
|
GdkModifierType key,
|
|
|
|
gboolean press,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpDisplay *display)
|
|
|
|
{
|
|
|
|
GimpTransformGridTool *tg_tool = GIMP_TRANSFORM_GRID_TOOL (tool);
|
|
|
|
|
|
|
|
if (tg_tool->widget)
|
|
|
|
{
|
|
|
|
GIMP_TOOL_CLASS (parent_class)->modifier_key (tool, key, press,
|
|
|
|
state, display);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GimpTransformGridOptions *options = GIMP_TRANSFORM_GRID_TOOL_GET_OPTIONS (tool);
|
|
|
|
|
|
|
|
if (key == gimp_get_constrain_behavior_mask ())
|
|
|
|
{
|
|
|
|
g_object_set (options,
|
|
|
|
"frompivot-scale", ! options->frompivot_scale,
|
|
|
|
"frompivot-shear", ! options->frompivot_shear,
|
|
|
|
"frompivot-perspective", ! options->frompivot_perspective,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
else if (key == gimp_get_extend_selection_mask ())
|
|
|
|
{
|
|
|
|
g_object_set (options,
|
|
|
|
"cornersnap", ! options->cornersnap,
|
|
|
|
"constrain-move", ! options->constrain_move,
|
|
|
|
"constrain-scale", ! options->constrain_scale,
|
|
|
|
"constrain-rotate", ! options->constrain_rotate,
|
|
|
|
"constrain-shear", ! options->constrain_shear,
|
|
|
|
"constrain-perspective", ! options->constrain_perspective,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_cursor_update (GimpTool *tool,
|
|
|
|
const GimpCoords *coords,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpDisplay *display)
|
|
|
|
{
|
|
|
|
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tool);
|
2020-05-26 22:15:15 +08:00
|
|
|
GList *objects;
|
2018-06-10 04:25:03 +08:00
|
|
|
|
2020-05-26 22:15:15 +08:00
|
|
|
objects = gimp_transform_tool_check_selected_objects (tr_tool, display, NULL);
|
|
|
|
|
|
|
|
if (display != tool->display && ! objects)
|
2018-06-10 04:25:03 +08:00
|
|
|
{
|
|
|
|
gimp_tool_set_cursor (tool, display,
|
|
|
|
gimp_tool_control_get_cursor (tool->control),
|
|
|
|
gimp_tool_control_get_tool_cursor (tool->control),
|
|
|
|
GIMP_CURSOR_MODIFIER_BAD);
|
|
|
|
return;
|
|
|
|
}
|
2020-05-26 22:15:15 +08:00
|
|
|
g_list_free (objects);
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
|
|
|
|
}
|
|
|
|
|
|
|
|
static const gchar *
|
|
|
|
gimp_transform_grid_tool_can_undo (GimpTool *tool,
|
|
|
|
GimpDisplay *display)
|
|
|
|
{
|
|
|
|
GimpTransformGridTool *tg_tool = GIMP_TRANSFORM_GRID_TOOL (tool);
|
|
|
|
|
|
|
|
if (! tg_tool->undo_list || ! tg_tool->undo_list->next)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return _("Transform Step");
|
|
|
|
}
|
|
|
|
|
|
|
|
static const gchar *
|
|
|
|
gimp_transform_grid_tool_can_redo (GimpTool *tool,
|
|
|
|
GimpDisplay *display)
|
|
|
|
{
|
|
|
|
GimpTransformGridTool *tg_tool = GIMP_TRANSFORM_GRID_TOOL (tool);
|
|
|
|
|
|
|
|
if (! tg_tool->redo_list)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return _("Transform Step");
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gimp_transform_grid_tool_undo (GimpTool *tool,
|
|
|
|
GimpDisplay *display)
|
|
|
|
{
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tool);
|
|
|
|
GimpTransformGridTool *tg_tool = GIMP_TRANSFORM_GRID_TOOL (tool);
|
|
|
|
GimpTransformOptions *tr_options = GIMP_TRANSFORM_TOOL_GET_OPTIONS (tool);
|
|
|
|
UndoInfo *undo_info;
|
|
|
|
GimpTransformDirection direction;
|
2018-06-10 04:25:03 +08:00
|
|
|
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
undo_info = tg_tool->undo_list->data;
|
|
|
|
direction = undo_info->direction;
|
2018-06-10 04:25:03 +08:00
|
|
|
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
/* Move undo_info from undo_list to redo_list */
|
|
|
|
tg_tool->redo_list = g_list_prepend (tg_tool->redo_list, undo_info);
|
|
|
|
tg_tool->undo_list = g_list_remove (tg_tool->undo_list, undo_info);
|
2018-06-10 04:25:03 +08:00
|
|
|
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
undo_info = tg_tool->undo_list->data;
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
/* Restore the previous transformation info */
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
memcpy (tg_tool->trans_infos, undo_info->trans_infos,
|
|
|
|
sizeof (tg_tool->trans_infos));
|
|
|
|
|
|
|
|
/* Restore the previous transformation direction */
|
|
|
|
if (direction != tr_options->direction)
|
|
|
|
{
|
|
|
|
g_object_set (tr_options,
|
|
|
|
"direction", direction,
|
|
|
|
NULL);
|
|
|
|
}
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
/* recalculate the tool's transformation matrix */
|
2018-06-16 03:42:19 +08:00
|
|
|
gimp_transform_tool_recalc_matrix (tr_tool, display);
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gimp_transform_grid_tool_redo (GimpTool *tool,
|
|
|
|
GimpDisplay *display)
|
|
|
|
{
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tool);
|
|
|
|
GimpTransformGridTool *tg_tool = GIMP_TRANSFORM_GRID_TOOL (tool);
|
|
|
|
GimpTransformOptions *tr_options = GIMP_TRANSFORM_TOOL_GET_OPTIONS (tool);
|
|
|
|
UndoInfo *undo_info;
|
|
|
|
GimpTransformDirection direction;
|
2018-06-10 04:25:03 +08:00
|
|
|
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
undo_info = tg_tool->redo_list->data;
|
|
|
|
direction = undo_info->direction;
|
2018-06-10 04:25:03 +08:00
|
|
|
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
/* Move undo_info from redo_list to undo_list */
|
|
|
|
tg_tool->undo_list = g_list_prepend (tg_tool->undo_list, undo_info);
|
|
|
|
tg_tool->redo_list = g_list_remove (tg_tool->redo_list, undo_info);
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
/* Restore the previous transformation info */
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
memcpy (tg_tool->trans_infos, undo_info->trans_infos,
|
|
|
|
sizeof (tg_tool->trans_infos));
|
|
|
|
|
|
|
|
/* Restore the previous transformation direction */
|
|
|
|
if (direction != tr_options->direction)
|
|
|
|
{
|
|
|
|
g_object_set (tr_options,
|
|
|
|
"direction", direction,
|
|
|
|
NULL);
|
|
|
|
}
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
/* recalculate the tool's transformation matrix */
|
2018-06-16 03:42:19 +08:00
|
|
|
gimp_transform_tool_recalc_matrix (tr_tool, display);
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_options_notify (GimpTool *tool,
|
|
|
|
GimpToolOptions *options,
|
|
|
|
const GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tool);
|
|
|
|
GimpTransformGridTool *tg_tool = GIMP_TRANSFORM_GRID_TOOL (tool);
|
|
|
|
GimpTransformGridOptions *tg_options = GIMP_TRANSFORM_GRID_OPTIONS (options);
|
|
|
|
|
|
|
|
GIMP_TOOL_CLASS (parent_class)->options_notify (tool, options, pspec);
|
|
|
|
|
|
|
|
if (! strcmp (pspec->name, "type"))
|
|
|
|
{
|
|
|
|
gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, tool->display);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! tg_tool->widget)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (! strcmp (pspec->name, "direction"))
|
|
|
|
{
|
|
|
|
/* recalculate the tool's transformation matrix */
|
2018-06-16 03:42:19 +08:00
|
|
|
gimp_transform_tool_recalc_matrix (tr_tool, tool->display);
|
2018-06-10 04:25:03 +08:00
|
|
|
}
|
2020-01-16 06:17:56 +08:00
|
|
|
else if (! strcmp (pspec->name, "show-preview") ||
|
|
|
|
! strcmp (pspec->name, "composited-preview"))
|
2018-06-10 04:25:03 +08:00
|
|
|
{
|
2022-10-12 23:46:24 +08:00
|
|
|
if (tg_tool->previews)
|
2018-06-10 04:25:03 +08:00
|
|
|
{
|
|
|
|
GimpDisplay *display;
|
2020-05-26 22:15:15 +08:00
|
|
|
GList *objects;
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
display = tool->display;
|
2020-05-26 22:15:15 +08:00
|
|
|
objects = gimp_transform_tool_get_selected_objects (tr_tool, display);
|
2019-08-11 03:57:55 +08:00
|
|
|
|
2020-05-26 22:15:15 +08:00
|
|
|
if (objects)
|
2018-06-10 04:25:03 +08:00
|
|
|
{
|
2020-01-16 06:17:56 +08:00
|
|
|
if (tg_options->show_preview &&
|
|
|
|
! gimp_transform_grid_tool_composited_preview (tg_tool))
|
|
|
|
{
|
2020-05-26 22:15:15 +08:00
|
|
|
gimp_transform_grid_tool_hide_selected_objects (tg_tool, objects);
|
2020-01-16 06:17:56 +08:00
|
|
|
}
|
2018-06-10 04:25:03 +08:00
|
|
|
else
|
2020-01-16 06:17:56 +08:00
|
|
|
{
|
2020-05-26 22:15:15 +08:00
|
|
|
gimp_transform_grid_tool_show_selected_objects (tg_tool);
|
2020-01-16 06:17:56 +08:00
|
|
|
}
|
2021-08-22 16:56:13 +08:00
|
|
|
|
|
|
|
g_list_free (objects);
|
2018-06-10 04:25:03 +08:00
|
|
|
}
|
2020-01-16 06:17:56 +08:00
|
|
|
|
|
|
|
gimp_transform_grid_tool_update_preview (tg_tool);
|
2018-06-10 04:25:03 +08:00
|
|
|
}
|
|
|
|
}
|
2020-01-16 06:17:56 +08:00
|
|
|
else if (! strcmp (pspec->name, "interpolation") ||
|
|
|
|
! strcmp (pspec->name, "clip") ||
|
2020-01-11 23:10:25 +08:00
|
|
|
! strcmp (pspec->name, "preview-opacity"))
|
|
|
|
{
|
|
|
|
gimp_transform_grid_tool_update_preview (tg_tool);
|
|
|
|
}
|
2018-06-10 04:25:03 +08:00
|
|
|
else if (g_str_has_prefix (pspec->name, "constrain-") ||
|
|
|
|
g_str_has_prefix (pspec->name, "frompivot-") ||
|
|
|
|
! strcmp (pspec->name, "fixedpivot") ||
|
|
|
|
! strcmp (pspec->name, "cornersnap"))
|
|
|
|
{
|
|
|
|
gimp_transform_grid_tool_dialog_update (tg_tool);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_draw (GimpDrawTool *draw_tool)
|
|
|
|
{
|
|
|
|
GimpTool *tool = GIMP_TOOL (draw_tool);
|
|
|
|
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (draw_tool);
|
|
|
|
GimpTransformGridTool *tg_tool = GIMP_TRANSFORM_GRID_TOOL (draw_tool);
|
|
|
|
GimpTransformGridOptions *options = GIMP_TRANSFORM_GRID_TOOL_GET_OPTIONS (tool);
|
|
|
|
GimpTransformOptions *tr_options = GIMP_TRANSFORM_OPTIONS (options);
|
2019-09-04 23:33:47 +08:00
|
|
|
GimpDisplayShell *shell = gimp_display_get_shell (tool->display);
|
2018-06-10 04:25:03 +08:00
|
|
|
GimpImage *image = gimp_display_get_image (tool->display);
|
|
|
|
GimpMatrix3 matrix = tr_tool->transform;
|
|
|
|
GimpCanvasItem *item;
|
|
|
|
|
|
|
|
if (tr_options->direction == GIMP_TRANSFORM_BACKWARD)
|
|
|
|
gimp_matrix3_invert (&matrix);
|
|
|
|
|
2020-01-16 06:17:56 +08:00
|
|
|
if (tr_options->type == GIMP_TRANSFORM_TYPE_LAYER ||
|
|
|
|
tr_options->type == GIMP_TRANSFORM_TYPE_IMAGE)
|
2018-06-10 04:25:03 +08:00
|
|
|
{
|
2022-10-12 23:46:24 +08:00
|
|
|
GList *pickables = NULL;
|
|
|
|
GList *iter;
|
2019-08-11 03:57:55 +08:00
|
|
|
|
|
|
|
if (tr_options->type == GIMP_TRANSFORM_TYPE_IMAGE)
|
2019-09-04 23:33:47 +08:00
|
|
|
{
|
|
|
|
if (! shell->show_all)
|
2022-10-12 23:46:24 +08:00
|
|
|
pickables = g_list_prepend (pickables, image);
|
2019-09-04 23:33:47 +08:00
|
|
|
else
|
2022-10-12 23:46:24 +08:00
|
|
|
pickables = g_list_prepend (pickables, gimp_image_get_projection (image));
|
2019-09-04 23:33:47 +08:00
|
|
|
}
|
2019-08-11 03:57:55 +08:00
|
|
|
else
|
2019-09-04 23:33:47 +08:00
|
|
|
{
|
2022-10-12 23:46:24 +08:00
|
|
|
for (iter = tool->drawables; iter; iter = iter->next)
|
|
|
|
pickables = g_list_prepend (pickables, iter->data);
|
2019-09-04 23:33:47 +08:00
|
|
|
}
|
2019-08-11 03:57:55 +08:00
|
|
|
|
2022-10-12 23:46:24 +08:00
|
|
|
for (iter = pickables; iter; iter = iter->next)
|
|
|
|
{
|
|
|
|
GimpCanvasItem *preview;
|
|
|
|
|
|
|
|
preview = gimp_draw_tool_add_transform_preview (draw_tool,
|
|
|
|
GIMP_PICKABLE (iter->data),
|
|
|
|
&matrix,
|
|
|
|
tr_tool->x1,
|
|
|
|
tr_tool->y1,
|
|
|
|
tr_tool->x2,
|
|
|
|
tr_tool->y2);
|
|
|
|
tg_tool->previews = g_list_prepend (tg_tool->previews, preview);
|
2023-05-23 00:13:44 +08:00
|
|
|
|
|
|
|
/* NOT g_set_weak_pointr() because the pointer is already set */
|
2022-10-12 23:46:24 +08:00
|
|
|
g_object_add_weak_pointer (G_OBJECT (tg_tool->previews->data),
|
|
|
|
(gpointer) &tg_tool->previews->data);
|
|
|
|
}
|
|
|
|
g_list_free (pickables);
|
2018-06-10 04:25:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (tr_options->type == GIMP_TRANSFORM_TYPE_SELECTION)
|
|
|
|
{
|
|
|
|
const GimpBoundSeg *segs_in;
|
|
|
|
const GimpBoundSeg *segs_out;
|
|
|
|
gint n_segs_in;
|
|
|
|
gint n_segs_out;
|
|
|
|
|
|
|
|
gimp_channel_boundary (gimp_image_get_mask (image),
|
|
|
|
&segs_in, &segs_out,
|
|
|
|
&n_segs_in, &n_segs_out,
|
|
|
|
0, 0, 0, 0);
|
|
|
|
|
|
|
|
if (segs_in)
|
|
|
|
{
|
2023-05-23 00:13:44 +08:00
|
|
|
g_set_weak_pointer
|
|
|
|
(&tg_tool->boundary_in,
|
|
|
|
gimp_draw_tool_add_boundary (draw_tool,
|
|
|
|
segs_in, n_segs_in,
|
|
|
|
&matrix,
|
|
|
|
0, 0));
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
gimp_canvas_item_set_visible (tg_tool->boundary_in,
|
|
|
|
tr_tool->transform_valid);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (segs_out)
|
|
|
|
{
|
2023-05-23 00:13:44 +08:00
|
|
|
g_set_weak_pointer
|
|
|
|
(&tg_tool->boundary_out,
|
|
|
|
gimp_draw_tool_add_boundary (draw_tool,
|
|
|
|
segs_out, n_segs_out,
|
|
|
|
&matrix,
|
|
|
|
0, 0));
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
gimp_canvas_item_set_visible (tg_tool->boundary_out,
|
|
|
|
tr_tool->transform_valid);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (tr_options->type == GIMP_TRANSFORM_TYPE_PATH)
|
|
|
|
{
|
2022-10-12 23:16:48 +08:00
|
|
|
GList *iter;
|
2018-06-10 04:25:03 +08:00
|
|
|
|
2022-10-12 23:16:48 +08:00
|
|
|
for (iter = gimp_image_get_selected_vectors (image); iter; iter = iter->next)
|
2018-06-10 04:25:03 +08:00
|
|
|
{
|
2022-10-12 23:16:48 +08:00
|
|
|
GimpVectors *vectors = iter->data;
|
|
|
|
GimpStroke *stroke = NULL;
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
while ((stroke = gimp_vectors_stroke_get_next (vectors, stroke)))
|
|
|
|
{
|
|
|
|
GArray *coords;
|
|
|
|
gboolean closed;
|
|
|
|
|
|
|
|
coords = gimp_stroke_interpolate (stroke, 1.0, &closed);
|
|
|
|
|
|
|
|
if (coords && coords->len)
|
|
|
|
{
|
|
|
|
item =
|
|
|
|
gimp_draw_tool_add_strokes (draw_tool,
|
|
|
|
&g_array_index (coords,
|
|
|
|
GimpCoords, 0),
|
|
|
|
coords->len, &matrix, FALSE);
|
|
|
|
|
|
|
|
g_ptr_array_add (tg_tool->strokes, item);
|
|
|
|
g_object_weak_ref (G_OBJECT (item),
|
|
|
|
(GWeakNotify) g_ptr_array_remove,
|
|
|
|
tg_tool->strokes);
|
|
|
|
|
|
|
|
gimp_canvas_item_set_visible (item, tr_tool->transform_valid);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (coords)
|
|
|
|
g_array_free (coords, TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-01-11 23:10:25 +08:00
|
|
|
|
2020-01-16 06:17:56 +08:00
|
|
|
GIMP_DRAW_TOOL_CLASS (parent_class)->draw (draw_tool);
|
|
|
|
|
2020-01-11 23:10:25 +08:00
|
|
|
gimp_transform_grid_tool_update_preview (tg_tool);
|
2018-06-10 04:25:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2018-06-16 03:42:19 +08:00
|
|
|
gimp_transform_grid_tool_recalc_matrix (GimpTransformTool *tr_tool)
|
2018-06-10 04:25:03 +08:00
|
|
|
{
|
app: in GimpTransformGridTool, allow linking forward/backward transforms
Add a GimpTransformGridTool::matrix_to_info() virtual function,
which should extract the tool-specific transformation parameters
given a transformation matrix, and the old parameter set (which is
needed in some tools, to derive the parameters that aren't encoded
in the matrix, such as the pivot point). The transformation matrix
can be any combination of matrices calculated by the tool, and
their inverses. Subclasses should only implement this function if
every such matrix can be mapped back to transformation parameters.
This is currently the case for all the transform-grid tools, except
for the shear tool (since it only supports shearing along one of
the horizontal or the vertical directions, however, the combined
matrix may require shearing in both directions).
When a transform-grid tool implements this function, show a chain-
button between the two transform-direction radio-buttons in the
tool options. When the chain-button is linked, whenever the
transform corresponding to the active direction is modified, adjust
the transform corresponding to the non-active direction such that
the overall transform remains the same.
One notable workflow that this enables is transforming a layer
while adjusting a different area than its boundary, by first
defining the area while the transform-directions are linked, and
then transforming the area while the transform-directions are
unlinked.
2019-02-05 04:33:44 +08:00
|
|
|
GimpTransformGridTool *tg_tool = GIMP_TRANSFORM_GRID_TOOL (tr_tool);
|
|
|
|
GimpTransformOptions *tr_options = GIMP_TRANSFORM_TOOL_GET_OPTIONS (tr_tool);
|
|
|
|
GimpTransformGridOptions *tg_options = GIMP_TRANSFORM_GRID_TOOL_GET_OPTIONS (tr_tool);
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
|
|
|
|
if (GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->info_to_matrix)
|
|
|
|
{
|
|
|
|
GimpMatrix3 forward_transform;
|
|
|
|
GimpMatrix3 backward_transform;
|
app: in GimpTransformGridTool, allow linking forward/backward transforms
Add a GimpTransformGridTool::matrix_to_info() virtual function,
which should extract the tool-specific transformation parameters
given a transformation matrix, and the old parameter set (which is
needed in some tools, to derive the parameters that aren't encoded
in the matrix, such as the pivot point). The transformation matrix
can be any combination of matrices calculated by the tool, and
their inverses. Subclasses should only implement this function if
every such matrix can be mapped back to transformation parameters.
This is currently the case for all the transform-grid tools, except
for the shear tool (since it only supports shearing along one of
the horizontal or the vertical directions, however, the combined
matrix may require shearing in both directions).
When a transform-grid tool implements this function, show a chain-
button between the two transform-direction radio-buttons in the
tool options. When the chain-button is linked, whenever the
transform corresponding to the active direction is modified, adjust
the transform corresponding to the non-active direction such that
the overall transform remains the same.
One notable workflow that this enables is transforming a layer
while adjusting a different area than its boundary, by first
defining the area while the transform-directions are linked, and
then transforming the area while the transform-directions are
unlinked.
2019-02-05 04:33:44 +08:00
|
|
|
gboolean forward_transform_valid;
|
|
|
|
gboolean backward_transform_valid;
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
|
|
|
|
tg_tool->trans_info = tg_tool->trans_infos[GIMP_TRANSFORM_FORWARD];
|
app: in GimpTransformGridTool, allow linking forward/backward transforms
Add a GimpTransformGridTool::matrix_to_info() virtual function,
which should extract the tool-specific transformation parameters
given a transformation matrix, and the old parameter set (which is
needed in some tools, to derive the parameters that aren't encoded
in the matrix, such as the pivot point). The transformation matrix
can be any combination of matrices calculated by the tool, and
their inverses. Subclasses should only implement this function if
every such matrix can be mapped back to transformation parameters.
This is currently the case for all the transform-grid tools, except
for the shear tool (since it only supports shearing along one of
the horizontal or the vertical directions, however, the combined
matrix may require shearing in both directions).
When a transform-grid tool implements this function, show a chain-
button between the two transform-direction radio-buttons in the
tool options. When the chain-button is linked, whenever the
transform corresponding to the active direction is modified, adjust
the transform corresponding to the non-active direction such that
the overall transform remains the same.
One notable workflow that this enables is transforming a layer
while adjusting a different area than its boundary, by first
defining the area while the transform-directions are linked, and
then transforming the area while the transform-directions are
unlinked.
2019-02-05 04:33:44 +08:00
|
|
|
forward_transform_valid = gimp_transform_grid_tool_info_to_matrix (
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
tg_tool, &forward_transform);
|
|
|
|
|
|
|
|
tg_tool->trans_info = tg_tool->trans_infos[GIMP_TRANSFORM_BACKWARD];
|
app: in GimpTransformGridTool, allow linking forward/backward transforms
Add a GimpTransformGridTool::matrix_to_info() virtual function,
which should extract the tool-specific transformation parameters
given a transformation matrix, and the old parameter set (which is
needed in some tools, to derive the parameters that aren't encoded
in the matrix, such as the pivot point). The transformation matrix
can be any combination of matrices calculated by the tool, and
their inverses. Subclasses should only implement this function if
every such matrix can be mapped back to transformation parameters.
This is currently the case for all the transform-grid tools, except
for the shear tool (since it only supports shearing along one of
the horizontal or the vertical directions, however, the combined
matrix may require shearing in both directions).
When a transform-grid tool implements this function, show a chain-
button between the two transform-direction radio-buttons in the
tool options. When the chain-button is linked, whenever the
transform corresponding to the active direction is modified, adjust
the transform corresponding to the non-active direction such that
the overall transform remains the same.
One notable workflow that this enables is transforming a layer
while adjusting a different area than its boundary, by first
defining the area while the transform-directions are linked, and
then transforming the area while the transform-directions are
unlinked.
2019-02-05 04:33:44 +08:00
|
|
|
backward_transform_valid = gimp_transform_grid_tool_info_to_matrix (
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
tg_tool, &backward_transform);
|
|
|
|
|
app: in GimpTransformGridTool, allow linking forward/backward transforms
Add a GimpTransformGridTool::matrix_to_info() virtual function,
which should extract the tool-specific transformation parameters
given a transformation matrix, and the old parameter set (which is
needed in some tools, to derive the parameters that aren't encoded
in the matrix, such as the pivot point). The transformation matrix
can be any combination of matrices calculated by the tool, and
their inverses. Subclasses should only implement this function if
every such matrix can be mapped back to transformation parameters.
This is currently the case for all the transform-grid tools, except
for the shear tool (since it only supports shearing along one of
the horizontal or the vertical directions, however, the combined
matrix may require shearing in both directions).
When a transform-grid tool implements this function, show a chain-
button between the two transform-direction radio-buttons in the
tool options. When the chain-button is linked, whenever the
transform corresponding to the active direction is modified, adjust
the transform corresponding to the non-active direction such that
the overall transform remains the same.
One notable workflow that this enables is transforming a layer
while adjusting a different area than its boundary, by first
defining the area while the transform-directions are linked, and
then transforming the area while the transform-directions are
unlinked.
2019-02-05 04:33:44 +08:00
|
|
|
if (GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->matrix_to_info &&
|
|
|
|
tg_options->direction_linked)
|
|
|
|
{
|
|
|
|
GimpMatrix3 transform = tr_tool->transform;
|
|
|
|
|
|
|
|
switch (tr_options->direction)
|
|
|
|
{
|
|
|
|
case GIMP_TRANSFORM_FORWARD:
|
|
|
|
if (forward_transform_valid)
|
|
|
|
{
|
|
|
|
gimp_matrix3_invert (&transform);
|
|
|
|
|
|
|
|
backward_transform = forward_transform;
|
|
|
|
gimp_matrix3_mult (&transform, &backward_transform);
|
|
|
|
|
|
|
|
tg_tool->trans_info =
|
|
|
|
tg_tool->trans_infos[GIMP_TRANSFORM_BACKWARD];
|
|
|
|
gimp_transform_grid_tool_matrix_to_info (tg_tool,
|
|
|
|
&backward_transform);
|
|
|
|
backward_transform_valid =
|
|
|
|
gimp_transform_grid_tool_info_to_matrix (
|
|
|
|
tg_tool, &backward_transform);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_TRANSFORM_BACKWARD:
|
|
|
|
if (backward_transform_valid)
|
|
|
|
{
|
|
|
|
forward_transform = backward_transform;
|
|
|
|
gimp_matrix3_mult (&transform, &forward_transform);
|
|
|
|
|
|
|
|
tg_tool->trans_info =
|
|
|
|
tg_tool->trans_infos[GIMP_TRANSFORM_FORWARD];
|
|
|
|
gimp_transform_grid_tool_matrix_to_info (tg_tool,
|
|
|
|
&forward_transform);
|
|
|
|
forward_transform_valid =
|
|
|
|
gimp_transform_grid_tool_info_to_matrix (
|
|
|
|
tg_tool, &forward_transform);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (forward_transform_valid && backward_transform_valid)
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
{
|
|
|
|
tr_tool->transform = backward_transform;
|
|
|
|
gimp_matrix3_invert (&tr_tool->transform);
|
|
|
|
gimp_matrix3_mult (&forward_transform, &tr_tool->transform);
|
|
|
|
}
|
app: in GimpTransformGridTool, allow linking forward/backward transforms
Add a GimpTransformGridTool::matrix_to_info() virtual function,
which should extract the tool-specific transformation parameters
given a transformation matrix, and the old parameter set (which is
needed in some tools, to derive the parameters that aren't encoded
in the matrix, such as the pivot point). The transformation matrix
can be any combination of matrices calculated by the tool, and
their inverses. Subclasses should only implement this function if
every such matrix can be mapped back to transformation parameters.
This is currently the case for all the transform-grid tools, except
for the shear tool (since it only supports shearing along one of
the horizontal or the vertical directions, however, the combined
matrix may require shearing in both directions).
When a transform-grid tool implements this function, show a chain-
button between the two transform-direction radio-buttons in the
tool options. When the chain-button is linked, whenever the
transform corresponding to the active direction is modified, adjust
the transform corresponding to the non-active direction such that
the overall transform remains the same.
One notable workflow that this enables is transforming a layer
while adjusting a different area than its boundary, by first
defining the area while the transform-directions are linked, and
then transforming the area while the transform-directions are
unlinked.
2019-02-05 04:33:44 +08:00
|
|
|
|
|
|
|
tr_tool->transform_valid = forward_transform_valid &&
|
|
|
|
backward_transform_valid;
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
tg_tool->trans_info = tg_tool->trans_infos[tr_options->direction];
|
2018-06-10 04:25:03 +08:00
|
|
|
|
2018-06-16 03:42:19 +08:00
|
|
|
gimp_transform_grid_tool_dialog_update (tg_tool);
|
|
|
|
gimp_transform_grid_tool_update_sensitivity (tg_tool);
|
|
|
|
gimp_transform_grid_tool_update_widget (tg_tool);
|
|
|
|
gimp_transform_grid_tool_update_preview (tg_tool);
|
|
|
|
|
|
|
|
if (tg_tool->gui)
|
|
|
|
gimp_tool_gui_show (tg_tool->gui);
|
2018-06-10 04:25:03 +08:00
|
|
|
}
|
|
|
|
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
static gchar *
|
|
|
|
gimp_transform_grid_tool_get_undo_desc (GimpTransformTool *tr_tool)
|
|
|
|
{
|
|
|
|
GimpTransformGridTool *tg_tool = GIMP_TRANSFORM_GRID_TOOL (tr_tool);
|
|
|
|
GimpTransformOptions *tr_options = GIMP_TRANSFORM_TOOL_GET_OPTIONS (tr_tool);
|
|
|
|
gchar *result;
|
|
|
|
|
app: in GimpTransformGridTool, allow linking forward/backward transforms
Add a GimpTransformGridTool::matrix_to_info() virtual function,
which should extract the tool-specific transformation parameters
given a transformation matrix, and the old parameter set (which is
needed in some tools, to derive the parameters that aren't encoded
in the matrix, such as the pivot point). The transformation matrix
can be any combination of matrices calculated by the tool, and
their inverses. Subclasses should only implement this function if
every such matrix can be mapped back to transformation parameters.
This is currently the case for all the transform-grid tools, except
for the shear tool (since it only supports shearing along one of
the horizontal or the vertical directions, however, the combined
matrix may require shearing in both directions).
When a transform-grid tool implements this function, show a chain-
button between the two transform-direction radio-buttons in the
tool options. When the chain-button is linked, whenever the
transform corresponding to the active direction is modified, adjust
the transform corresponding to the non-active direction such that
the overall transform remains the same.
One notable workflow that this enables is transforming a layer
while adjusting a different area than its boundary, by first
defining the area while the transform-directions are linked, and
then transforming the area while the transform-directions are
unlinked.
2019-02-05 04:33:44 +08:00
|
|
|
if (GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->matrix_to_info)
|
|
|
|
{
|
|
|
|
TransInfo trans_info;
|
|
|
|
|
|
|
|
memcpy (&trans_info, &tg_tool->init_trans_info, sizeof (TransInfo));
|
|
|
|
|
|
|
|
tg_tool->trans_info = trans_info;
|
|
|
|
gimp_transform_grid_tool_matrix_to_info (tg_tool, &tr_tool->transform);
|
|
|
|
result = GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->get_undo_desc (
|
|
|
|
tg_tool);
|
|
|
|
}
|
2019-03-13 17:20:51 +08:00
|
|
|
else if (trans_info_equal (tg_tool->trans_infos[GIMP_TRANSFORM_BACKWARD],
|
|
|
|
tg_tool->init_trans_info))
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
{
|
|
|
|
tg_tool->trans_info = tg_tool->trans_infos[GIMP_TRANSFORM_FORWARD];
|
|
|
|
result = GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->get_undo_desc (
|
|
|
|
tg_tool);
|
|
|
|
}
|
2019-03-13 17:20:51 +08:00
|
|
|
else if (trans_info_equal (tg_tool->trans_infos[GIMP_TRANSFORM_FORWARD],
|
|
|
|
tg_tool->init_trans_info))
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
{
|
|
|
|
gchar *desc;
|
|
|
|
|
|
|
|
tg_tool->trans_info = tg_tool->trans_infos[GIMP_TRANSFORM_BACKWARD];
|
|
|
|
desc = GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->get_undo_desc (
|
|
|
|
tg_tool);
|
|
|
|
|
|
|
|
result = g_strdup_printf (_("%s (Corrective)"), desc);
|
|
|
|
|
|
|
|
g_free (desc);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result = GIMP_TRANSFORM_TOOL_CLASS (parent_class)->get_undo_desc (
|
|
|
|
tr_tool);
|
|
|
|
}
|
|
|
|
|
|
|
|
tg_tool->trans_info = tg_tool->trans_infos[tr_options->direction];
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GimpTransformDirection
|
|
|
|
gimp_transform_grid_tool_get_direction (GimpTransformTool *tr_tool)
|
|
|
|
{
|
|
|
|
return GIMP_TRANSFORM_FORWARD;
|
|
|
|
}
|
|
|
|
|
2018-06-10 04:25:03 +08:00
|
|
|
static GeglBuffer *
|
|
|
|
gimp_transform_grid_tool_transform (GimpTransformTool *tr_tool,
|
2020-05-26 22:15:15 +08:00
|
|
|
GList *objects,
|
2018-06-10 04:25:03 +08:00
|
|
|
GeglBuffer *orig_buffer,
|
|
|
|
gint orig_offset_x,
|
|
|
|
gint orig_offset_y,
|
|
|
|
GimpColorProfile **buffer_profile,
|
|
|
|
gint *new_offset_x,
|
|
|
|
gint *new_offset_y)
|
|
|
|
{
|
|
|
|
GimpTool *tool = GIMP_TOOL (tr_tool);
|
|
|
|
GimpTransformGridTool *tg_tool = GIMP_TRANSFORM_GRID_TOOL (tr_tool);
|
|
|
|
GimpDisplay *display = tool->display;
|
|
|
|
GimpImage *image = gimp_display_get_image (display);
|
|
|
|
GeglBuffer *new_buffer;
|
|
|
|
|
|
|
|
/* Send the request for the transformation to the tool...
|
|
|
|
*/
|
|
|
|
new_buffer =
|
|
|
|
GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->transform (tg_tool,
|
2020-05-26 22:15:15 +08:00
|
|
|
objects,
|
2018-06-10 04:25:03 +08:00
|
|
|
orig_buffer,
|
|
|
|
orig_offset_x,
|
|
|
|
orig_offset_y,
|
|
|
|
buffer_profile,
|
|
|
|
new_offset_x,
|
|
|
|
new_offset_y);
|
|
|
|
|
|
|
|
gimp_image_undo_push (image, GIMP_TYPE_TRANSFORM_GRID_TOOL_UNDO,
|
|
|
|
GIMP_UNDO_TRANSFORM_GRID, NULL,
|
|
|
|
0,
|
|
|
|
"transform-tool", tg_tool,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
return new_buffer;
|
|
|
|
}
|
|
|
|
|
2020-04-27 21:44:40 +08:00
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_real_apply_info (GimpTransformGridTool *tg_tool,
|
|
|
|
const TransInfo info)
|
|
|
|
{
|
|
|
|
memcpy (tg_tool->trans_info, info, sizeof (TransInfo));
|
|
|
|
}
|
|
|
|
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
static gchar *
|
|
|
|
gimp_transform_grid_tool_real_get_undo_desc (GimpTransformGridTool *tg_tool)
|
|
|
|
{
|
|
|
|
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tg_tool);
|
|
|
|
|
|
|
|
return GIMP_TRANSFORM_TOOL_CLASS (parent_class)->get_undo_desc (tr_tool);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_real_update_widget (GimpTransformGridTool *tg_tool)
|
|
|
|
{
|
|
|
|
if (GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->info_to_matrix)
|
|
|
|
{
|
|
|
|
GimpMatrix3 transform;
|
|
|
|
|
|
|
|
gimp_transform_grid_tool_info_to_matrix (tg_tool, &transform);
|
|
|
|
|
|
|
|
g_object_set (tg_tool->widget,
|
|
|
|
"transform", &transform,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-16 03:42:19 +08:00
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_real_widget_changed (GimpTransformGridTool *tg_tool)
|
|
|
|
{
|
|
|
|
GimpTool *tool = GIMP_TOOL (tg_tool);
|
|
|
|
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tg_tool);
|
|
|
|
GimpToolWidget *widget = tg_tool->widget;
|
|
|
|
|
2018-07-14 19:15:26 +08:00
|
|
|
/* suppress the call to GimpTransformGridTool::update_widget() when
|
2018-06-16 03:42:19 +08:00
|
|
|
* recalculating the matrix
|
|
|
|
*/
|
|
|
|
tg_tool->widget = NULL;
|
|
|
|
|
|
|
|
gimp_transform_tool_recalc_matrix (tr_tool, tool->display);
|
|
|
|
|
|
|
|
tg_tool->widget = widget;
|
|
|
|
}
|
|
|
|
|
2018-06-10 04:25:03 +08:00
|
|
|
static GeglBuffer *
|
|
|
|
gimp_transform_grid_tool_real_transform (GimpTransformGridTool *tg_tool,
|
2020-05-26 22:15:15 +08:00
|
|
|
GList *objects,
|
2018-06-10 04:25:03 +08:00
|
|
|
GeglBuffer *orig_buffer,
|
|
|
|
gint orig_offset_x,
|
|
|
|
gint orig_offset_y,
|
|
|
|
GimpColorProfile **buffer_profile,
|
|
|
|
gint *new_offset_x,
|
|
|
|
gint *new_offset_y)
|
|
|
|
{
|
|
|
|
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tg_tool);
|
|
|
|
|
|
|
|
return GIMP_TRANSFORM_TOOL_CLASS (parent_class)->transform (tr_tool,
|
2020-05-26 22:15:15 +08:00
|
|
|
objects,
|
2018-06-10 04:25:03 +08:00
|
|
|
orig_buffer,
|
|
|
|
orig_offset_x,
|
|
|
|
orig_offset_y,
|
|
|
|
buffer_profile,
|
|
|
|
new_offset_x,
|
|
|
|
new_offset_y);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_widget_changed (GimpToolWidget *widget,
|
|
|
|
GimpTransformGridTool *tg_tool)
|
|
|
|
{
|
2018-06-16 03:42:19 +08:00
|
|
|
if (GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->widget_changed)
|
|
|
|
GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->widget_changed (tg_tool);
|
2018-06-10 04:25:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_widget_response (GimpToolWidget *widget,
|
|
|
|
gint response_id,
|
|
|
|
GimpTransformGridTool *tg_tool)
|
|
|
|
{
|
|
|
|
switch (response_id)
|
|
|
|
{
|
|
|
|
case GIMP_TOOL_WIDGET_RESPONSE_CONFIRM:
|
|
|
|
gimp_transform_grid_tool_response (NULL, GTK_RESPONSE_OK, tg_tool);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_TOOL_WIDGET_RESPONSE_CANCEL:
|
|
|
|
gimp_transform_grid_tool_response (NULL, GTK_RESPONSE_CANCEL, tg_tool);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GIMP_TOOL_WIDGET_RESPONSE_RESET:
|
|
|
|
gimp_transform_grid_tool_response (NULL, RESPONSE_RESET, tg_tool);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-16 06:17:56 +08:00
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_filter_flush (GimpDrawableFilter *filter,
|
|
|
|
GimpTransformGridTool *tg_tool)
|
|
|
|
{
|
|
|
|
GimpTool *tool = GIMP_TOOL (tg_tool);
|
|
|
|
GimpImage *image = gimp_display_get_image (tool->display);
|
|
|
|
|
|
|
|
gimp_projection_flush (gimp_image_get_projection (image));
|
|
|
|
}
|
|
|
|
|
2018-06-10 04:25:03 +08:00
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_halt (GimpTransformGridTool *tg_tool)
|
|
|
|
{
|
2020-04-27 21:41:43 +08:00
|
|
|
GimpTool *tool = GIMP_TOOL (tg_tool);
|
|
|
|
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tg_tool);
|
|
|
|
GimpTransformGridOptions *tg_options = GIMP_TRANSFORM_GRID_TOOL_GET_OPTIONS (tg_tool);
|
2022-10-12 23:46:24 +08:00
|
|
|
GList *iter;
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
if (gimp_draw_tool_is_active (GIMP_DRAW_TOOL (tg_tool)))
|
|
|
|
gimp_draw_tool_stop (GIMP_DRAW_TOOL (tg_tool));
|
|
|
|
|
|
|
|
gimp_draw_tool_set_widget (GIMP_DRAW_TOOL (tg_tool), NULL);
|
|
|
|
g_clear_object (&tg_tool->widget);
|
|
|
|
|
2020-01-16 06:17:56 +08:00
|
|
|
g_clear_pointer (&tg_tool->filters, g_hash_table_unref);
|
2020-01-18 21:11:51 +08:00
|
|
|
g_clear_pointer (&tg_tool->preview_drawables, g_list_free);
|
2020-01-16 06:17:56 +08:00
|
|
|
|
2022-10-12 23:46:24 +08:00
|
|
|
for (iter = tg_tool->previews; iter; iter = iter->next)
|
|
|
|
{
|
|
|
|
if (iter->data)
|
|
|
|
g_object_unref (iter->data);
|
|
|
|
}
|
|
|
|
g_clear_pointer (&tg_tool->previews, g_list_free);
|
|
|
|
|
2018-06-10 04:25:03 +08:00
|
|
|
if (tg_tool->gui)
|
|
|
|
gimp_tool_gui_hide (tg_tool->gui);
|
|
|
|
|
|
|
|
if (tg_tool->redo_list)
|
|
|
|
{
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
g_list_free_full (tg_tool->redo_list, (GDestroyNotify) undo_info_free);
|
2018-06-10 04:25:03 +08:00
|
|
|
tg_tool->redo_list = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tg_tool->undo_list)
|
|
|
|
{
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
g_list_free_full (tg_tool->undo_list, (GDestroyNotify) undo_info_free);
|
2018-06-10 04:25:03 +08:00
|
|
|
tg_tool->undo_list = NULL;
|
|
|
|
}
|
|
|
|
|
2020-05-26 22:15:15 +08:00
|
|
|
gimp_transform_grid_tool_show_selected_objects (tg_tool);
|
2018-06-10 04:25:03 +08:00
|
|
|
|
2020-04-27 21:41:43 +08:00
|
|
|
if (tg_options->direction_chain_button)
|
|
|
|
{
|
|
|
|
g_object_set (tg_options,
|
|
|
|
"direction-linked", FALSE,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
gtk_widget_set_sensitive (tg_options->direction_chain_button, FALSE);
|
|
|
|
}
|
|
|
|
|
2019-08-11 03:57:55 +08:00
|
|
|
tool->display = NULL;
|
2020-05-25 17:30:31 +08:00
|
|
|
g_list_free (tool->drawables);
|
|
|
|
tool->drawables = NULL;
|
2018-06-10 19:22:52 +08:00
|
|
|
|
2020-05-26 22:15:15 +08:00
|
|
|
if (tr_tool->objects)
|
2020-01-16 06:14:15 +08:00
|
|
|
{
|
2020-05-26 22:15:15 +08:00
|
|
|
GList *iter;
|
|
|
|
|
|
|
|
for (iter = tr_tool->objects; iter; iter = iter->next)
|
|
|
|
if (GIMP_IS_DRAWABLE (iter->data))
|
|
|
|
gimp_viewable_preview_thaw (iter->data);
|
2020-01-16 06:14:15 +08:00
|
|
|
|
2020-05-26 22:15:15 +08:00
|
|
|
g_list_free (tr_tool->objects);
|
|
|
|
tr_tool->objects = NULL;
|
2020-01-16 06:14:15 +08:00
|
|
|
}
|
2018-06-10 04:25:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_commit (GimpTransformGridTool *tg_tool)
|
|
|
|
{
|
|
|
|
GimpTool *tool = GIMP_TOOL (tg_tool);
|
|
|
|
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tg_tool);
|
|
|
|
GimpDisplay *display = tool->display;
|
|
|
|
|
|
|
|
/* undraw the tool before we muck around with the transform matrix */
|
|
|
|
gimp_draw_tool_stop (GIMP_DRAW_TOOL (tg_tool));
|
|
|
|
|
|
|
|
gimp_transform_tool_transform (tr_tool, display);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_dialog (GimpTransformGridTool *tg_tool)
|
|
|
|
{
|
|
|
|
GimpTool *tool = GIMP_TOOL (tg_tool);
|
|
|
|
GimpToolInfo *tool_info = tool->tool_info;
|
|
|
|
GimpDisplayShell *shell;
|
|
|
|
const gchar *ok_button_label;
|
|
|
|
|
|
|
|
if (! GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->dialog)
|
|
|
|
return;
|
|
|
|
|
|
|
|
g_return_if_fail (tool->display != NULL);
|
|
|
|
|
|
|
|
shell = gimp_display_get_shell (tool->display);
|
|
|
|
|
|
|
|
ok_button_label = GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->ok_button_label;
|
|
|
|
|
|
|
|
tg_tool->gui = gimp_tool_gui_new (tool_info,
|
|
|
|
NULL, NULL, NULL, NULL,
|
|
|
|
gimp_widget_get_monitor (GTK_WIDGET (shell)),
|
|
|
|
TRUE,
|
|
|
|
NULL);
|
|
|
|
|
2019-03-08 05:05:18 +08:00
|
|
|
gimp_tool_gui_add_button (tg_tool->gui, _("_Reset"), RESPONSE_RESET);
|
|
|
|
if (GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->readjust)
|
2019-03-08 16:44:26 +08:00
|
|
|
gimp_tool_gui_add_button (tg_tool->gui, _("Re_adjust"), RESPONSE_READJUST);
|
2019-03-08 05:05:18 +08:00
|
|
|
gimp_tool_gui_add_button (tg_tool->gui, _("_Cancel"), GTK_RESPONSE_CANCEL);
|
|
|
|
gimp_tool_gui_add_button (tg_tool->gui, ok_button_label, GTK_RESPONSE_OK);
|
|
|
|
|
2018-06-10 04:25:03 +08:00
|
|
|
gimp_tool_gui_set_auto_overlay (tg_tool->gui, TRUE);
|
|
|
|
gimp_tool_gui_set_default_response (tg_tool->gui, GTK_RESPONSE_OK);
|
|
|
|
|
|
|
|
gimp_tool_gui_set_alternative_button_order (tg_tool->gui,
|
|
|
|
RESPONSE_RESET,
|
2019-03-08 05:05:18 +08:00
|
|
|
RESPONSE_READJUST,
|
2018-06-10 04:25:03 +08:00
|
|
|
GTK_RESPONSE_OK,
|
|
|
|
GTK_RESPONSE_CANCEL,
|
|
|
|
-1);
|
|
|
|
|
|
|
|
g_signal_connect (tg_tool->gui, "response",
|
|
|
|
G_CALLBACK (gimp_transform_grid_tool_response),
|
|
|
|
tg_tool);
|
|
|
|
|
|
|
|
GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->dialog (tg_tool);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_dialog_update (GimpTransformGridTool *tg_tool)
|
|
|
|
{
|
|
|
|
if (tg_tool->gui &&
|
|
|
|
GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->dialog_update)
|
|
|
|
{
|
|
|
|
GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->dialog_update (tg_tool);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_prepare (GimpTransformGridTool *tg_tool,
|
|
|
|
GimpDisplay *display)
|
|
|
|
{
|
|
|
|
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tg_tool);
|
|
|
|
|
|
|
|
if (tg_tool->gui)
|
|
|
|
{
|
2020-05-26 22:15:15 +08:00
|
|
|
GList *objects = gimp_transform_tool_get_selected_objects (tr_tool, display);
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
gimp_tool_gui_set_shell (tg_tool->gui, gimp_display_get_shell (display));
|
2020-05-26 22:15:15 +08:00
|
|
|
gimp_tool_gui_set_viewables (tg_tool->gui, objects);
|
|
|
|
g_list_free (objects);
|
2018-06-10 04:25:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->prepare)
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
{
|
|
|
|
tg_tool->trans_info = tg_tool->init_trans_info;
|
|
|
|
GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->prepare (tg_tool);
|
|
|
|
|
|
|
|
memcpy (tg_tool->trans_infos[GIMP_TRANSFORM_FORWARD],
|
|
|
|
tg_tool->init_trans_info, sizeof (TransInfo));
|
|
|
|
memcpy (tg_tool->trans_infos[GIMP_TRANSFORM_BACKWARD],
|
|
|
|
tg_tool->init_trans_info, sizeof (TransInfo));
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_matrix3_identity (&tr_tool->transform);
|
|
|
|
tr_tool->transform_valid = TRUE;
|
2018-06-10 04:25:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static GimpToolWidget *
|
|
|
|
gimp_transform_grid_tool_get_widget (GimpTransformGridTool *tg_tool)
|
|
|
|
{
|
|
|
|
static const gchar *properties[] =
|
|
|
|
{
|
|
|
|
"constrain-move",
|
|
|
|
"constrain-scale",
|
|
|
|
"constrain-rotate",
|
|
|
|
"constrain-shear",
|
|
|
|
"constrain-perspective",
|
|
|
|
"frompivot-scale",
|
|
|
|
"frompivot-shear",
|
|
|
|
"frompivot-perspective",
|
|
|
|
"cornersnap",
|
|
|
|
"fixedpivot"
|
|
|
|
};
|
|
|
|
|
|
|
|
GimpToolWidget *widget = NULL;
|
|
|
|
|
|
|
|
if (GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->get_widget)
|
|
|
|
{
|
|
|
|
GimpTransformGridOptions *options = GIMP_TRANSFORM_GRID_TOOL_GET_OPTIONS (tg_tool);
|
|
|
|
gint i;
|
|
|
|
|
|
|
|
widget = GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->get_widget (tg_tool);
|
|
|
|
|
|
|
|
gimp_draw_tool_set_widget (GIMP_DRAW_TOOL (tg_tool), widget);
|
|
|
|
|
|
|
|
g_object_bind_property (G_OBJECT (options), "grid-type",
|
|
|
|
G_OBJECT (widget), "guide-type",
|
|
|
|
G_BINDING_SYNC_CREATE |
|
|
|
|
G_BINDING_BIDIRECTIONAL);
|
|
|
|
g_object_bind_property (G_OBJECT (options), "grid-size",
|
|
|
|
G_OBJECT (widget), "n-guides",
|
|
|
|
G_BINDING_SYNC_CREATE |
|
|
|
|
G_BINDING_BIDIRECTIONAL);
|
|
|
|
|
|
|
|
for (i = 0; i < G_N_ELEMENTS (properties); i++)
|
|
|
|
g_object_bind_property (G_OBJECT (options), properties[i],
|
|
|
|
G_OBJECT (widget), properties[i],
|
|
|
|
G_BINDING_SYNC_CREATE |
|
|
|
|
G_BINDING_BIDIRECTIONAL);
|
|
|
|
|
|
|
|
g_signal_connect (widget, "changed",
|
|
|
|
G_CALLBACK (gimp_transform_grid_tool_widget_changed),
|
|
|
|
tg_tool);
|
|
|
|
g_signal_connect (widget, "response",
|
|
|
|
G_CALLBACK (gimp_transform_grid_tool_widget_response),
|
|
|
|
tg_tool);
|
|
|
|
}
|
|
|
|
|
|
|
|
return widget;
|
|
|
|
}
|
|
|
|
|
2018-06-16 03:42:19 +08:00
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_update_widget (GimpTransformGridTool *tg_tool)
|
|
|
|
{
|
|
|
|
if (tg_tool->widget &&
|
|
|
|
GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->update_widget)
|
|
|
|
{
|
|
|
|
g_signal_handlers_block_by_func (
|
|
|
|
tg_tool->widget,
|
|
|
|
G_CALLBACK (gimp_transform_grid_tool_widget_changed),
|
|
|
|
tg_tool);
|
|
|
|
|
|
|
|
GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->update_widget (tg_tool);
|
|
|
|
|
|
|
|
g_signal_handlers_unblock_by_func (
|
|
|
|
tg_tool->widget,
|
|
|
|
G_CALLBACK (gimp_transform_grid_tool_widget_changed),
|
|
|
|
tg_tool);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-10 04:25:03 +08:00
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_response (GimpToolGui *gui,
|
|
|
|
gint response_id,
|
|
|
|
GimpTransformGridTool *tg_tool)
|
|
|
|
{
|
2019-03-08 05:05:18 +08:00
|
|
|
GimpTool *tool = GIMP_TOOL (tg_tool);
|
|
|
|
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tg_tool);
|
2019-03-13 17:20:51 +08:00
|
|
|
GimpTransformOptions *tr_options = GIMP_TRANSFORM_TOOL_GET_OPTIONS (tg_tool);
|
2019-03-08 05:05:18 +08:00
|
|
|
GimpTransformGridOptions *tg_options = GIMP_TRANSFORM_GRID_TOOL_GET_OPTIONS (tg_tool);
|
|
|
|
GimpDisplay *display = tool->display;
|
2018-06-10 04:25:03 +08:00
|
|
|
|
2020-03-06 00:56:08 +08:00
|
|
|
/* we can get here while already committing a transformation. just return in
|
|
|
|
* this case. see issue #4734.
|
|
|
|
*/
|
|
|
|
if (! gimp_draw_tool_is_active (GIMP_DRAW_TOOL (tg_tool)))
|
|
|
|
return;
|
|
|
|
|
2018-06-10 04:25:03 +08:00
|
|
|
switch (response_id)
|
|
|
|
{
|
|
|
|
case RESPONSE_RESET:
|
2019-03-08 06:42:52 +08:00
|
|
|
{
|
|
|
|
gboolean direction_linked;
|
2018-06-10 04:25:03 +08:00
|
|
|
|
2019-03-08 06:42:52 +08:00
|
|
|
/* restore the initial transformation info */
|
|
|
|
memcpy (tg_tool->trans_infos[GIMP_TRANSFORM_FORWARD],
|
|
|
|
tg_tool->init_trans_info,
|
|
|
|
sizeof (TransInfo));
|
|
|
|
memcpy (tg_tool->trans_infos[GIMP_TRANSFORM_BACKWARD],
|
|
|
|
tg_tool->init_trans_info,
|
|
|
|
sizeof (TransInfo));
|
2018-06-10 04:25:03 +08:00
|
|
|
|
2019-03-08 06:42:52 +08:00
|
|
|
/* recalculate the tool's transformation matrix */
|
|
|
|
direction_linked = tg_options->direction_linked;
|
|
|
|
tg_options->direction_linked = FALSE;
|
|
|
|
gimp_transform_tool_recalc_matrix (tr_tool, display);
|
|
|
|
tg_options->direction_linked = direction_linked;
|
|
|
|
|
|
|
|
/* push the restored info to the undo stack */
|
2020-01-06 18:00:27 +08:00
|
|
|
gimp_transform_grid_tool_push_internal_undo (tg_tool, FALSE);
|
2019-03-08 06:42:52 +08:00
|
|
|
}
|
2018-06-10 04:25:03 +08:00
|
|
|
break;
|
|
|
|
|
2019-03-08 05:05:18 +08:00
|
|
|
case RESPONSE_READJUST:
|
2019-03-13 17:20:51 +08:00
|
|
|
if (GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->readjust &&
|
|
|
|
GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->matrix_to_info &&
|
|
|
|
tr_tool->transform_valid)
|
2019-03-08 16:44:26 +08:00
|
|
|
{
|
2019-03-13 17:20:51 +08:00
|
|
|
TransInfo old_trans_infos[2];
|
|
|
|
gboolean direction_linked;
|
|
|
|
gboolean transform_valid;
|
|
|
|
|
|
|
|
/* save the current transformation info */
|
|
|
|
memcpy (old_trans_infos, tg_tool->trans_infos,
|
|
|
|
sizeof (old_trans_infos));
|
2019-03-08 05:05:18 +08:00
|
|
|
|
2019-03-13 17:20:51 +08:00
|
|
|
/* readjust the transformation info to view */
|
2019-03-08 16:44:26 +08:00
|
|
|
GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->readjust (tg_tool);
|
2019-03-08 05:05:18 +08:00
|
|
|
|
2019-03-08 16:44:26 +08:00
|
|
|
/* recalculate the tool's transformation matrix, preserving the
|
|
|
|
* overall transformation
|
|
|
|
*/
|
|
|
|
direction_linked = tg_options->direction_linked;
|
|
|
|
tg_options->direction_linked = TRUE;
|
|
|
|
gimp_transform_tool_recalc_matrix (tr_tool, display);
|
|
|
|
tg_options->direction_linked = direction_linked;
|
2019-03-08 05:05:18 +08:00
|
|
|
|
2019-03-13 17:20:51 +08:00
|
|
|
transform_valid = tr_tool->transform_valid;
|
|
|
|
|
|
|
|
/* if the resulting transformation is invalid, or if the
|
|
|
|
* transformation info is already adjusted to view ...
|
|
|
|
*/
|
|
|
|
if (! transform_valid ||
|
|
|
|
trans_infos_equal (old_trans_infos, tg_tool->trans_infos))
|
|
|
|
{
|
|
|
|
/* ... readjust the transformation info to the item bounds */
|
|
|
|
GimpMatrix3 transform = tr_tool->transform;
|
|
|
|
|
|
|
|
if (tr_options->direction == GIMP_TRANSFORM_BACKWARD)
|
|
|
|
gimp_matrix3_invert (&transform);
|
|
|
|
|
2020-04-27 21:44:40 +08:00
|
|
|
GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->apply_info (
|
|
|
|
tg_tool, tg_tool->init_trans_info);
|
2019-03-13 17:20:51 +08:00
|
|
|
GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->matrix_to_info (
|
|
|
|
tg_tool, &transform);
|
|
|
|
|
2019-03-13 22:09:49 +08:00
|
|
|
/* recalculate the tool's transformation matrix, preserving the
|
|
|
|
* overall transformation
|
|
|
|
*/
|
2019-03-13 17:20:51 +08:00
|
|
|
direction_linked = tg_options->direction_linked;
|
2019-03-13 22:09:49 +08:00
|
|
|
tg_options->direction_linked = TRUE;
|
2019-03-13 17:20:51 +08:00
|
|
|
gimp_transform_tool_recalc_matrix (tr_tool, display);
|
|
|
|
tg_options->direction_linked = direction_linked;
|
|
|
|
|
|
|
|
if (! tr_tool->transform_valid ||
|
|
|
|
! trans_infos_equal (old_trans_infos, tg_tool->trans_infos))
|
|
|
|
{
|
|
|
|
transform_valid = tr_tool->transform_valid;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (transform_valid)
|
|
|
|
{
|
|
|
|
/* push the new info to the undo stack */
|
2020-01-06 18:00:27 +08:00
|
|
|
gimp_transform_grid_tool_push_internal_undo (tg_tool, FALSE);
|
2019-03-13 17:20:51 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* restore the old transformation info */
|
|
|
|
memcpy (tg_tool->trans_infos, old_trans_infos,
|
|
|
|
sizeof (old_trans_infos));
|
|
|
|
|
|
|
|
/* recalculate the tool's transformation matrix */
|
|
|
|
direction_linked = tg_options->direction_linked;
|
|
|
|
tg_options->direction_linked = FALSE;
|
|
|
|
gimp_transform_tool_recalc_matrix (tr_tool, display);
|
|
|
|
tg_options->direction_linked = direction_linked;
|
|
|
|
|
|
|
|
gimp_tool_message_literal (tool, tool->display,
|
|
|
|
_("Cannot readjust the transformation"));
|
|
|
|
}
|
2019-03-08 16:44:26 +08:00
|
|
|
}
|
2019-03-08 05:05:18 +08:00
|
|
|
break;
|
|
|
|
|
2018-06-10 04:25:03 +08:00
|
|
|
case GTK_RESPONSE_OK:
|
|
|
|
g_return_if_fail (display != NULL);
|
|
|
|
gimp_tool_control (tool, GIMP_TOOL_ACTION_COMMIT, display);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display);
|
|
|
|
|
|
|
|
/* update the undo actions / menu items */
|
|
|
|
if (display)
|
|
|
|
gimp_image_flush (gimp_display_get_image (display));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-16 06:17:56 +08:00
|
|
|
static gboolean
|
|
|
|
gimp_transform_grid_tool_composited_preview (GimpTransformGridTool *tg_tool)
|
|
|
|
{
|
|
|
|
GimpTool *tool = GIMP_TOOL (tg_tool);
|
|
|
|
GimpTransformOptions *tr_options = GIMP_TRANSFORM_TOOL_GET_OPTIONS (tg_tool);
|
|
|
|
GimpTransformGridOptions *tg_options = GIMP_TRANSFORM_GRID_TOOL_GET_OPTIONS (tg_tool);
|
|
|
|
GimpImage *image = gimp_display_get_image (tool->display);
|
|
|
|
|
|
|
|
return tg_options->composited_preview &&
|
|
|
|
tr_options->type == GIMP_TRANSFORM_TYPE_LAYER &&
|
|
|
|
gimp_channel_is_empty (gimp_image_get_mask (image));
|
|
|
|
}
|
|
|
|
|
2018-06-10 04:25:03 +08:00
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_update_sensitivity (GimpTransformGridTool *tg_tool)
|
|
|
|
{
|
|
|
|
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tg_tool);
|
|
|
|
|
|
|
|
if (! tg_tool->gui)
|
|
|
|
return;
|
|
|
|
|
2019-03-08 06:42:52 +08:00
|
|
|
gimp_tool_gui_set_response_sensitive (
|
|
|
|
tg_tool->gui, GTK_RESPONSE_OK,
|
|
|
|
tr_tool->transform_valid);
|
|
|
|
|
|
|
|
gimp_tool_gui_set_response_sensitive (
|
|
|
|
tg_tool->gui, RESPONSE_RESET,
|
2019-03-13 17:20:51 +08:00
|
|
|
! (trans_info_equal (tg_tool->trans_infos[GIMP_TRANSFORM_FORWARD],
|
|
|
|
tg_tool->init_trans_info) &&
|
|
|
|
trans_info_equal (tg_tool->trans_infos[GIMP_TRANSFORM_BACKWARD],
|
|
|
|
tg_tool->init_trans_info)));
|
|
|
|
|
|
|
|
gimp_tool_gui_set_response_sensitive (
|
|
|
|
tg_tool->gui, RESPONSE_READJUST,
|
|
|
|
tr_tool->transform_valid);
|
2018-06-10 04:25:03 +08:00
|
|
|
}
|
|
|
|
|
2018-06-16 03:42:19 +08:00
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_update_preview (GimpTransformGridTool *tg_tool)
|
|
|
|
{
|
2020-01-16 06:17:56 +08:00
|
|
|
GimpTool *tool = GIMP_TOOL (tg_tool);
|
2020-01-11 23:10:25 +08:00
|
|
|
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tg_tool);
|
|
|
|
GimpTransformOptions *tr_options = GIMP_TRANSFORM_TOOL_GET_OPTIONS (tg_tool);
|
|
|
|
GimpTransformGridOptions *tg_options = GIMP_TRANSFORM_GRID_TOOL_GET_OPTIONS (tg_tool);
|
2022-10-12 23:46:24 +08:00
|
|
|
GList *iter;
|
2018-06-16 03:42:19 +08:00
|
|
|
gint i;
|
|
|
|
|
2020-01-18 21:11:51 +08:00
|
|
|
if (! tool->display)
|
|
|
|
return;
|
|
|
|
|
2020-01-16 06:17:56 +08:00
|
|
|
if (tg_options->show_preview &&
|
|
|
|
gimp_transform_grid_tool_composited_preview (tg_tool) &&
|
|
|
|
tr_tool->transform_valid)
|
2018-06-16 03:42:19 +08:00
|
|
|
{
|
2020-01-16 06:17:56 +08:00
|
|
|
GHashTableIter iter;
|
|
|
|
GimpDrawable *drawable;
|
|
|
|
Filter *filter;
|
2020-01-16 17:34:17 +08:00
|
|
|
gboolean flush = FALSE;
|
2020-01-11 23:10:25 +08:00
|
|
|
|
2020-01-16 06:17:56 +08:00
|
|
|
if (! tg_tool->filters)
|
|
|
|
{
|
|
|
|
tg_tool->filters = g_hash_table_new_full (
|
|
|
|
g_direct_hash, g_direct_equal,
|
|
|
|
NULL, (GDestroyNotify) filter_free);
|
2018-06-16 03:42:19 +08:00
|
|
|
|
2020-01-18 21:11:51 +08:00
|
|
|
gimp_transform_grid_tool_update_filters (tg_tool);
|
2020-01-16 06:17:56 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
g_hash_table_iter_init (&iter, tg_tool->filters);
|
|
|
|
|
|
|
|
while (g_hash_table_iter_next (&iter,
|
|
|
|
(gpointer *) &drawable,
|
|
|
|
(gpointer *) &filter))
|
|
|
|
{
|
|
|
|
GimpMatrix3 transform;
|
|
|
|
GeglRectangle bounds;
|
|
|
|
gint offset_x;
|
|
|
|
gint offset_y;
|
2020-01-18 21:11:51 +08:00
|
|
|
gint width;
|
|
|
|
gint height;
|
2020-01-16 06:17:56 +08:00
|
|
|
gint x1, y1;
|
|
|
|
gint x2, y2;
|
|
|
|
gboolean update = FALSE;
|
|
|
|
|
|
|
|
if (! filter->filter)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
gimp_item_get_offset (GIMP_ITEM (drawable), &offset_x, &offset_y);
|
|
|
|
|
2020-01-18 21:11:51 +08:00
|
|
|
width = gimp_item_get_width (GIMP_ITEM (drawable));
|
|
|
|
height = gimp_item_get_height (GIMP_ITEM (drawable));
|
|
|
|
|
2020-01-16 06:17:56 +08:00
|
|
|
gimp_matrix3_identity (&transform);
|
|
|
|
gimp_matrix3_translate (&transform, +offset_x, +offset_y);
|
|
|
|
gimp_matrix3_mult (&tr_tool->transform, &transform);
|
|
|
|
gimp_matrix3_translate (&transform, -offset_x, -offset_y);
|
|
|
|
|
|
|
|
gimp_transform_resize_boundary (&tr_tool->transform,
|
|
|
|
gimp_item_get_clip (
|
2020-01-18 21:11:51 +08:00
|
|
|
GIMP_ITEM (filter->root_drawable),
|
2020-01-16 06:17:56 +08:00
|
|
|
tr_options->clip),
|
2020-01-18 21:11:51 +08:00
|
|
|
offset_x, offset_y,
|
|
|
|
offset_x + width, offset_y + height,
|
|
|
|
&x1, &y1,
|
|
|
|
&x2, &y2);
|
2020-01-16 06:17:56 +08:00
|
|
|
|
|
|
|
bounds.x = x1 - offset_x;
|
|
|
|
bounds.y = y1 - offset_y;
|
|
|
|
bounds.width = x2 - x1;
|
|
|
|
bounds.height = y2 - y1;
|
|
|
|
|
|
|
|
if (! gimp_matrix3_equal (&transform, &filter->transform))
|
|
|
|
{
|
|
|
|
filter->transform = transform;
|
|
|
|
|
|
|
|
gimp_gegl_node_set_matrix (filter->transform_node, &transform);
|
|
|
|
|
|
|
|
update = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! gegl_rectangle_equal (&bounds, &filter->bounds))
|
|
|
|
{
|
|
|
|
filter->bounds = bounds;
|
|
|
|
|
|
|
|
gegl_node_set (filter->crop_node,
|
|
|
|
"x", (gdouble) bounds.x,
|
|
|
|
"y", (gdouble) bounds.y,
|
|
|
|
"width", (gdouble) bounds.width,
|
|
|
|
"height", (gdouble) bounds.height,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
update = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GIMP_IS_LAYER (drawable))
|
|
|
|
{
|
|
|
|
gimp_drawable_filter_set_add_alpha (
|
|
|
|
filter->filter,
|
|
|
|
tr_options->interpolation != GIMP_INTERPOLATION_NONE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (update)
|
2020-01-16 17:34:17 +08:00
|
|
|
{
|
|
|
|
if (tg_options->synchronous_preview)
|
|
|
|
{
|
|
|
|
g_signal_handlers_block_by_func (
|
|
|
|
filter->filter,
|
|
|
|
G_CALLBACK (gimp_transform_grid_tool_filter_flush),
|
|
|
|
tg_tool);
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_drawable_filter_apply (filter->filter, NULL);
|
|
|
|
|
|
|
|
if (tg_options->synchronous_preview)
|
|
|
|
{
|
|
|
|
g_signal_handlers_unblock_by_func (
|
|
|
|
filter->filter,
|
|
|
|
G_CALLBACK (gimp_transform_grid_tool_filter_flush),
|
|
|
|
tg_tool);
|
|
|
|
|
|
|
|
flush = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (flush)
|
|
|
|
{
|
|
|
|
GimpImage *image = gimp_display_get_image (tool->display);
|
|
|
|
|
|
|
|
gimp_projection_flush_now (gimp_image_get_projection (image), TRUE);
|
|
|
|
gimp_display_flush_now (tool->display);
|
2020-01-16 06:17:56 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_clear_pointer (&tg_tool->filters, g_hash_table_unref);
|
2020-01-18 21:11:51 +08:00
|
|
|
g_clear_pointer (&tg_tool->preview_drawables, g_list_free);
|
2020-01-16 06:17:56 +08:00
|
|
|
}
|
|
|
|
|
2022-10-12 23:46:24 +08:00
|
|
|
for (iter = tg_tool->previews; iter; iter = iter->next)
|
2020-01-16 06:17:56 +08:00
|
|
|
{
|
2022-10-12 23:46:24 +08:00
|
|
|
GimpCanvasItem *preview = iter->data;
|
|
|
|
|
|
|
|
if (preview == NULL)
|
|
|
|
continue;
|
|
|
|
|
2020-01-16 06:17:56 +08:00
|
|
|
if (tg_options->show_preview &&
|
|
|
|
! gimp_transform_grid_tool_composited_preview (tg_tool) &&
|
|
|
|
tr_tool->transform_valid)
|
|
|
|
{
|
2022-10-12 23:46:24 +08:00
|
|
|
gimp_canvas_item_begin_change (preview);
|
|
|
|
gimp_canvas_item_set_visible (preview, TRUE);
|
2020-01-16 06:17:56 +08:00
|
|
|
g_object_set (
|
2022-10-12 23:46:24 +08:00
|
|
|
preview,
|
2020-01-16 06:17:56 +08:00
|
|
|
"transform", &tr_tool->transform,
|
2020-05-25 17:30:31 +08:00
|
|
|
"clip", gimp_item_get_clip (GIMP_ITEM (tool->drawables->data),
|
2020-01-16 06:17:56 +08:00
|
|
|
tr_options->clip),
|
|
|
|
"opacity", tg_options->preview_opacity,
|
|
|
|
NULL);
|
2022-10-12 23:46:24 +08:00
|
|
|
gimp_canvas_item_end_change (preview);
|
2020-01-16 06:17:56 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2022-10-12 23:46:24 +08:00
|
|
|
gimp_canvas_item_set_visible (preview, FALSE);
|
2020-01-16 06:17:56 +08:00
|
|
|
}
|
2018-06-16 03:42:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (tg_tool->boundary_in)
|
|
|
|
{
|
|
|
|
gimp_canvas_item_begin_change (tg_tool->boundary_in);
|
|
|
|
gimp_canvas_item_set_visible (tg_tool->boundary_in,
|
|
|
|
tr_tool->transform_valid);
|
|
|
|
g_object_set (tg_tool->boundary_in,
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
"transform", &tr_tool->transform,
|
2018-06-16 03:42:19 +08:00
|
|
|
NULL);
|
|
|
|
gimp_canvas_item_end_change (tg_tool->boundary_in);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tg_tool->boundary_out)
|
|
|
|
{
|
|
|
|
gimp_canvas_item_begin_change (tg_tool->boundary_out);
|
|
|
|
gimp_canvas_item_set_visible (tg_tool->boundary_out,
|
|
|
|
tr_tool->transform_valid);
|
|
|
|
g_object_set (tg_tool->boundary_out,
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
"transform", &tr_tool->transform,
|
2018-06-16 03:42:19 +08:00
|
|
|
NULL);
|
|
|
|
gimp_canvas_item_end_change (tg_tool->boundary_out);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < tg_tool->strokes->len; i++)
|
|
|
|
{
|
|
|
|
GimpCanvasItem *item = g_ptr_array_index (tg_tool->strokes, i);
|
|
|
|
|
|
|
|
gimp_canvas_item_begin_change (item);
|
|
|
|
gimp_canvas_item_set_visible (item, tr_tool->transform_valid);
|
|
|
|
g_object_set (item,
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
"transform", &tr_tool->transform,
|
2018-06-16 03:42:19 +08:00
|
|
|
NULL);
|
|
|
|
gimp_canvas_item_end_change (item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-18 21:11:51 +08:00
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_update_filters (GimpTransformGridTool *tg_tool)
|
|
|
|
{
|
2022-10-12 23:53:04 +08:00
|
|
|
GimpTool *tool = GIMP_TOOL (tg_tool);
|
2020-01-18 21:11:51 +08:00
|
|
|
GHashTable *new_drawables;
|
|
|
|
GList *drawables;
|
|
|
|
GList *iter;
|
|
|
|
GimpDrawable *drawable;
|
|
|
|
GHashTableIter hash_iter;
|
|
|
|
|
|
|
|
if (! tg_tool->filters)
|
|
|
|
return;
|
|
|
|
|
2021-12-16 07:08:15 +08:00
|
|
|
drawables = gimp_image_item_list_filter (g_list_copy (tool->drawables));
|
2020-01-18 21:11:51 +08:00
|
|
|
|
|
|
|
new_drawables = g_hash_table_new (g_direct_hash, g_direct_equal);
|
|
|
|
|
|
|
|
for (iter = drawables; iter; iter = g_list_next (iter))
|
|
|
|
g_hash_table_add (new_drawables, iter->data);
|
|
|
|
|
|
|
|
for (iter = tg_tool->preview_drawables; iter; iter = g_list_next (iter))
|
|
|
|
{
|
|
|
|
drawable = iter->data;
|
|
|
|
|
|
|
|
if (! g_hash_table_remove (new_drawables, drawable))
|
|
|
|
gimp_transform_grid_tool_remove_filter (drawable, tg_tool);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_hash_table_iter_init (&hash_iter, new_drawables);
|
|
|
|
|
|
|
|
while (g_hash_table_iter_next (&hash_iter, (gpointer *) &drawable, NULL))
|
|
|
|
{
|
|
|
|
AddFilterData data;
|
|
|
|
|
|
|
|
data.tg_tool = tg_tool;
|
|
|
|
data.root_drawable = drawable;
|
|
|
|
|
|
|
|
gimp_transform_grid_tool_add_filter (drawable, &data);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_hash_table_unref (new_drawables);
|
|
|
|
|
|
|
|
g_list_free (tg_tool->preview_drawables);
|
|
|
|
tg_tool->preview_drawables = drawables;
|
|
|
|
}
|
|
|
|
|
2018-06-10 04:25:03 +08:00
|
|
|
static void
|
2020-05-26 22:15:15 +08:00
|
|
|
gimp_transform_grid_tool_hide_selected_objects (GimpTransformGridTool *tg_tool,
|
|
|
|
GList *objects)
|
2018-06-10 04:25:03 +08:00
|
|
|
{
|
|
|
|
GimpTransformGridOptions *options = GIMP_TRANSFORM_GRID_TOOL_GET_OPTIONS (tg_tool);
|
|
|
|
GimpTransformOptions *tr_options = GIMP_TRANSFORM_OPTIONS (options);
|
|
|
|
GimpDisplay *display = GIMP_TOOL (tg_tool)->display;
|
|
|
|
GimpImage *image = gimp_display_get_image (display);
|
|
|
|
|
2020-05-26 22:15:15 +08:00
|
|
|
g_return_if_fail (tr_options->type != GIMP_TRANSFORM_TYPE_IMAGE ||
|
|
|
|
(g_list_length (objects) == 1 && GIMP_IS_IMAGE (objects->data)));
|
|
|
|
|
|
|
|
g_list_free (tg_tool->hidden_objects);
|
|
|
|
tg_tool->hidden_objects = NULL;
|
|
|
|
|
2019-08-11 03:57:55 +08:00
|
|
|
if (options->show_preview)
|
2018-06-10 04:25:03 +08:00
|
|
|
{
|
2020-05-26 22:15:15 +08:00
|
|
|
if (tr_options->type == GIMP_TRANSFORM_TYPE_IMAGE)
|
2019-08-11 03:57:55 +08:00
|
|
|
{
|
2020-05-26 22:15:15 +08:00
|
|
|
tg_tool->hidden_objects = g_list_copy (objects);
|
|
|
|
gimp_display_shell_set_show_image (gimp_display_get_shell (display),
|
|
|
|
FALSE);
|
2019-08-11 03:57:55 +08:00
|
|
|
}
|
2020-05-26 22:15:15 +08:00
|
|
|
else
|
2019-08-11 03:57:55 +08:00
|
|
|
{
|
2020-05-26 22:15:15 +08:00
|
|
|
/* hide only complete layers and channels, not layer masks */
|
|
|
|
GList *iter;
|
2019-08-11 03:57:55 +08:00
|
|
|
|
2020-05-26 22:15:15 +08:00
|
|
|
for (iter = objects; iter; iter = iter->next)
|
|
|
|
{
|
|
|
|
if (tr_options->type == GIMP_TRANSFORM_TYPE_LAYER &&
|
|
|
|
! options->composited_preview &&
|
|
|
|
GIMP_IS_DRAWABLE (iter->data) &&
|
|
|
|
! GIMP_IS_LAYER_MASK (iter->data) &&
|
|
|
|
gimp_item_get_visible (iter->data) &&
|
|
|
|
gimp_channel_is_empty (gimp_image_get_mask (image)))
|
|
|
|
{
|
|
|
|
tg_tool->hidden_objects = g_list_prepend (tg_tool->hidden_objects, iter->data);
|
|
|
|
|
|
|
|
gimp_item_set_visible (iter->data, FALSE, FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_projection_flush (gimp_image_get_projection (image));
|
2019-08-11 03:57:55 +08:00
|
|
|
}
|
2018-06-10 04:25:03 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-05-26 22:15:15 +08:00
|
|
|
gimp_transform_grid_tool_show_selected_objects (GimpTransformGridTool *tg_tool)
|
2018-06-10 04:25:03 +08:00
|
|
|
{
|
2020-05-26 22:15:15 +08:00
|
|
|
if (tg_tool->hidden_objects)
|
2018-06-10 04:25:03 +08:00
|
|
|
{
|
|
|
|
GimpDisplay *display = GIMP_TOOL (tg_tool)->display;
|
|
|
|
GimpImage *image = gimp_display_get_image (display);
|
2020-05-26 22:15:15 +08:00
|
|
|
GList *iter;
|
2018-06-10 04:25:03 +08:00
|
|
|
|
2020-05-26 22:15:15 +08:00
|
|
|
for (iter = tg_tool->hidden_objects; iter; iter = iter->next)
|
2019-08-11 03:57:55 +08:00
|
|
|
{
|
2020-05-26 22:15:15 +08:00
|
|
|
if (GIMP_IS_ITEM (iter->data))
|
|
|
|
{
|
|
|
|
gimp_item_set_visible (GIMP_ITEM (iter->data), TRUE,
|
|
|
|
FALSE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_IMAGE (iter->data));
|
2019-08-11 03:57:55 +08:00
|
|
|
|
2020-05-26 22:15:15 +08:00
|
|
|
gimp_display_shell_set_show_image (gimp_display_get_shell (display),
|
|
|
|
TRUE);
|
|
|
|
}
|
2019-08-11 03:57:55 +08:00
|
|
|
}
|
|
|
|
|
2020-05-26 22:15:15 +08:00
|
|
|
g_list_free (tg_tool->hidden_objects);
|
|
|
|
tg_tool->hidden_objects = NULL;
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
gimp_image_flush (image);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-16 06:17:56 +08:00
|
|
|
static void
|
2020-01-18 21:11:51 +08:00
|
|
|
gimp_transform_grid_tool_add_filter (GimpDrawable *drawable,
|
|
|
|
AddFilterData *data)
|
2020-01-16 06:17:56 +08:00
|
|
|
{
|
|
|
|
Filter *filter;
|
|
|
|
GimpLayerMode mode = GIMP_LAYER_MODE_NORMAL;
|
|
|
|
|
|
|
|
if (GIMP_IS_LAYER (drawable))
|
|
|
|
{
|
|
|
|
gimp_layer_get_effective_mode (GIMP_LAYER (drawable),
|
|
|
|
&mode, NULL, NULL, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mode != GIMP_LAYER_MODE_PASS_THROUGH)
|
|
|
|
{
|
2020-01-18 21:11:51 +08:00
|
|
|
filter = filter_new (data->tg_tool, drawable, data->root_drawable, TRUE);
|
2020-01-16 06:17:56 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GimpContainer *container;
|
|
|
|
|
2020-01-18 21:11:51 +08:00
|
|
|
filter = filter_new (data->tg_tool, drawable, data->root_drawable, FALSE);
|
2020-01-16 06:17:56 +08:00
|
|
|
|
|
|
|
container = gimp_viewable_get_children (GIMP_VIEWABLE (drawable));
|
|
|
|
|
|
|
|
gimp_container_foreach (container,
|
|
|
|
(GFunc) gimp_transform_grid_tool_add_filter,
|
2020-01-18 21:11:51 +08:00
|
|
|
data);
|
2020-01-16 06:17:56 +08:00
|
|
|
}
|
|
|
|
|
2020-01-18 21:11:51 +08:00
|
|
|
g_hash_table_insert (data->tg_tool->filters, drawable, filter);
|
2020-01-16 06:17:56 +08:00
|
|
|
|
|
|
|
if (GIMP_IS_LAYER (drawable))
|
|
|
|
{
|
|
|
|
GimpLayerMask *mask = gimp_layer_get_mask (GIMP_LAYER (drawable));
|
|
|
|
|
|
|
|
if (mask)
|
2020-01-18 21:11:51 +08:00
|
|
|
gimp_transform_grid_tool_add_filter (GIMP_DRAWABLE (mask), data);
|
2020-01-16 06:17:56 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_remove_filter (GimpDrawable *drawable,
|
|
|
|
GimpTransformGridTool *tg_tool)
|
|
|
|
{
|
|
|
|
Filter *filter = g_hash_table_lookup (tg_tool->filters, drawable);
|
|
|
|
|
|
|
|
if (GIMP_IS_LAYER (drawable))
|
|
|
|
{
|
|
|
|
GimpLayerMask *mask = gimp_layer_get_mask (GIMP_LAYER (drawable));
|
|
|
|
|
|
|
|
if (mask)
|
|
|
|
gimp_transform_grid_tool_remove_filter (GIMP_DRAWABLE (mask), tg_tool);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (! filter->filter)
|
|
|
|
{
|
|
|
|
GimpContainer *container;
|
|
|
|
|
|
|
|
container = gimp_viewable_get_children (GIMP_VIEWABLE (drawable));
|
|
|
|
|
|
|
|
gimp_container_foreach (container,
|
|
|
|
(GFunc) gimp_transform_grid_tool_remove_filter,
|
|
|
|
tg_tool);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_hash_table_remove (tg_tool->filters, drawable);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_transform_grid_tool_effective_mode_changed (GimpLayer *layer,
|
|
|
|
GimpTransformGridTool *tg_tool)
|
|
|
|
{
|
|
|
|
Filter *filter = g_hash_table_lookup (tg_tool->filters, layer);
|
|
|
|
GimpLayerMode mode;
|
|
|
|
gboolean old_pass_through;
|
|
|
|
gboolean new_pass_through;
|
|
|
|
|
|
|
|
gimp_layer_get_effective_mode (layer, &mode, NULL, NULL, NULL);
|
|
|
|
|
|
|
|
old_pass_through = ! filter->filter;
|
|
|
|
new_pass_through = mode == GIMP_LAYER_MODE_PASS_THROUGH;
|
|
|
|
|
|
|
|
if (old_pass_through != new_pass_through)
|
|
|
|
{
|
2020-01-18 21:11:51 +08:00
|
|
|
AddFilterData data;
|
|
|
|
|
|
|
|
data.tg_tool = tg_tool;
|
|
|
|
data.root_drawable = filter->root_drawable;
|
|
|
|
|
2020-01-16 06:17:56 +08:00
|
|
|
gimp_transform_grid_tool_remove_filter (GIMP_DRAWABLE (layer), tg_tool);
|
2020-01-18 21:11:51 +08:00
|
|
|
gimp_transform_grid_tool_add_filter (GIMP_DRAWABLE (layer), &data);
|
2020-01-16 06:17:56 +08:00
|
|
|
|
|
|
|
gimp_transform_grid_tool_update_preview (tg_tool);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static Filter *
|
|
|
|
filter_new (GimpTransformGridTool *tg_tool,
|
|
|
|
GimpDrawable *drawable,
|
2020-01-18 21:11:51 +08:00
|
|
|
GimpDrawable *root_drawable,
|
2020-01-16 06:17:56 +08:00
|
|
|
gboolean add_filter)
|
|
|
|
{
|
|
|
|
Filter *filter = g_slice_new0 (Filter);
|
|
|
|
GeglNode *node;
|
|
|
|
GeglNode *input_node;
|
|
|
|
GeglNode *output_node;
|
|
|
|
|
2020-01-18 21:11:51 +08:00
|
|
|
filter->tg_tool = tg_tool;
|
|
|
|
filter->drawable = drawable;
|
|
|
|
filter->root_drawable = root_drawable;
|
2020-01-16 06:17:56 +08:00
|
|
|
|
|
|
|
if (add_filter)
|
|
|
|
{
|
|
|
|
node = gegl_node_new ();
|
|
|
|
|
|
|
|
input_node = gegl_node_get_input_proxy (node, "input");
|
|
|
|
output_node = gegl_node_get_input_proxy (node, "output");
|
|
|
|
|
|
|
|
filter->transform_node = gegl_node_new_child (
|
|
|
|
node,
|
|
|
|
"operation", "gegl:transform",
|
|
|
|
"near-z", GIMP_TRANSFORM_NEAR_Z,
|
|
|
|
"sampler", GEGL_SAMPLER_NEAREST,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
filter->crop_node = gegl_node_new_child (
|
|
|
|
node,
|
|
|
|
"operation", "gegl:crop",
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
gegl_node_link_many (input_node,
|
|
|
|
filter->transform_node,
|
|
|
|
filter->crop_node,
|
|
|
|
output_node,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
gimp_gegl_node_set_underlying_operation (node, filter->transform_node);
|
|
|
|
|
|
|
|
filter->filter = gimp_drawable_filter_new (
|
|
|
|
drawable,
|
|
|
|
GIMP_TRANSFORM_TOOL_GET_CLASS (tg_tool)->undo_desc,
|
|
|
|
node,
|
|
|
|
gimp_tool_get_icon_name (GIMP_TOOL (tg_tool)));
|
|
|
|
|
|
|
|
gimp_drawable_filter_set_clip (filter->filter, FALSE);
|
|
|
|
gimp_drawable_filter_set_override_constraints (filter->filter, TRUE);
|
|
|
|
|
|
|
|
g_signal_connect (
|
|
|
|
filter->filter, "flush",
|
|
|
|
G_CALLBACK (gimp_transform_grid_tool_filter_flush),
|
|
|
|
tg_tool);
|
|
|
|
|
|
|
|
g_object_unref (node);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GIMP_IS_GROUP_LAYER (drawable))
|
|
|
|
{
|
|
|
|
g_signal_connect (
|
|
|
|
drawable, "effective-mode-changed",
|
|
|
|
G_CALLBACK (gimp_transform_grid_tool_effective_mode_changed),
|
|
|
|
tg_tool);
|
|
|
|
}
|
|
|
|
|
|
|
|
return filter;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
filter_free (Filter *filter)
|
|
|
|
{
|
|
|
|
if (filter->filter)
|
|
|
|
{
|
|
|
|
gimp_drawable_filter_abort (filter->filter);
|
|
|
|
|
|
|
|
g_object_unref (filter->filter);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GIMP_IS_GROUP_LAYER (filter->drawable))
|
|
|
|
{
|
|
|
|
g_signal_handlers_disconnect_by_func (
|
|
|
|
filter->drawable,
|
|
|
|
gimp_transform_grid_tool_effective_mode_changed,
|
|
|
|
filter->tg_tool);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_slice_free (Filter, filter);
|
|
|
|
}
|
|
|
|
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
static UndoInfo *
|
|
|
|
undo_info_new (void)
|
2018-06-10 04:25:03 +08:00
|
|
|
{
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
return g_slice_new0 (UndoInfo);
|
2018-06-10 04:25:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
undo_info_free (UndoInfo *info)
|
2018-06-10 04:25:03 +08:00
|
|
|
{
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
g_slice_free (UndoInfo, info);
|
|
|
|
}
|
|
|
|
|
2019-03-13 17:20:51 +08:00
|
|
|
static gboolean
|
|
|
|
trans_info_equal (const TransInfo trans_info1,
|
|
|
|
const TransInfo trans_info2)
|
|
|
|
{
|
|
|
|
gint i;
|
|
|
|
|
|
|
|
for (i = 0; i < TRANS_INFO_SIZE; i++)
|
|
|
|
{
|
|
|
|
if (fabs (trans_info1[i] - trans_info2[i]) > EPSILON)
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
trans_infos_equal (const TransInfo *trans_infos1,
|
|
|
|
const TransInfo *trans_infos2)
|
|
|
|
{
|
|
|
|
return trans_info_equal (trans_infos1[GIMP_TRANSFORM_FORWARD],
|
|
|
|
trans_infos2[GIMP_TRANSFORM_FORWARD]) &&
|
|
|
|
trans_info_equal (trans_infos1[GIMP_TRANSFORM_BACKWARD],
|
|
|
|
trans_infos2[GIMP_TRANSFORM_BACKWARD]);
|
|
|
|
}
|
|
|
|
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
gboolean
|
|
|
|
gimp_transform_grid_tool_info_to_matrix (GimpTransformGridTool *tg_tool,
|
|
|
|
GimpMatrix3 *transform)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_TRANSFORM_GRID_TOOL (tg_tool), FALSE);
|
|
|
|
g_return_val_if_fail (transform != NULL, FALSE);
|
|
|
|
|
|
|
|
if (GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->info_to_matrix)
|
|
|
|
{
|
|
|
|
return GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->info_to_matrix (
|
|
|
|
tg_tool, transform);
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
2018-06-10 04:25:03 +08:00
|
|
|
}
|
|
|
|
|
app: in GimpTransformGridTool, allow linking forward/backward transforms
Add a GimpTransformGridTool::matrix_to_info() virtual function,
which should extract the tool-specific transformation parameters
given a transformation matrix, and the old parameter set (which is
needed in some tools, to derive the parameters that aren't encoded
in the matrix, such as the pivot point). The transformation matrix
can be any combination of matrices calculated by the tool, and
their inverses. Subclasses should only implement this function if
every such matrix can be mapped back to transformation parameters.
This is currently the case for all the transform-grid tools, except
for the shear tool (since it only supports shearing along one of
the horizontal or the vertical directions, however, the combined
matrix may require shearing in both directions).
When a transform-grid tool implements this function, show a chain-
button between the two transform-direction radio-buttons in the
tool options. When the chain-button is linked, whenever the
transform corresponding to the active direction is modified, adjust
the transform corresponding to the non-active direction such that
the overall transform remains the same.
One notable workflow that this enables is transforming a layer
while adjusting a different area than its boundary, by first
defining the area while the transform-directions are linked, and
then transforming the area while the transform-directions are
unlinked.
2019-02-05 04:33:44 +08:00
|
|
|
void
|
|
|
|
gimp_transform_grid_tool_matrix_to_info (GimpTransformGridTool *tg_tool,
|
|
|
|
const GimpMatrix3 *transform)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_TRANSFORM_GRID_TOOL (tg_tool));
|
|
|
|
g_return_if_fail (transform != NULL);
|
|
|
|
|
|
|
|
if (GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->matrix_to_info)
|
|
|
|
{
|
|
|
|
return GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->matrix_to_info (
|
|
|
|
tg_tool, transform);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-10 04:25:03 +08:00
|
|
|
void
|
2020-01-06 18:00:27 +08:00
|
|
|
gimp_transform_grid_tool_push_internal_undo (GimpTransformGridTool *tg_tool,
|
|
|
|
gboolean compress)
|
2018-06-10 04:25:03 +08:00
|
|
|
{
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
UndoInfo *undo_info;
|
|
|
|
|
2018-06-10 04:25:03 +08:00
|
|
|
g_return_if_fail (GIMP_IS_TRANSFORM_GRID_TOOL (tg_tool));
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
g_return_if_fail (tg_tool->undo_list != NULL);
|
|
|
|
|
|
|
|
undo_info = tg_tool->undo_list->data;
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
/* push current state on the undo list and set this state as the
|
|
|
|
* current state, but avoid doing this if there were no changes
|
|
|
|
*/
|
2019-03-13 17:20:51 +08:00
|
|
|
if (! trans_infos_equal (undo_info->trans_infos, tg_tool->trans_infos))
|
2018-06-10 04:25:03 +08:00
|
|
|
{
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
GimpTransformOptions *tr_options = GIMP_TRANSFORM_TOOL_GET_OPTIONS (tg_tool);
|
2020-01-06 18:00:27 +08:00
|
|
|
gint64 time = 0;
|
2020-01-06 17:57:17 +08:00
|
|
|
gboolean flush = FALSE;
|
|
|
|
|
|
|
|
if (tg_tool->undo_list->next == NULL)
|
|
|
|
flush = TRUE;
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
|
2020-01-06 18:00:27 +08:00
|
|
|
if (compress)
|
|
|
|
time = g_get_monotonic_time ();
|
|
|
|
|
|
|
|
if (! compress || time - undo_info->time >= UNDO_COMPRESS_TIME)
|
|
|
|
{
|
|
|
|
undo_info = undo_info_new ();
|
|
|
|
|
|
|
|
tg_tool->undo_list = g_list_prepend (tg_tool->undo_list, undo_info);
|
|
|
|
}
|
|
|
|
|
|
|
|
undo_info->time = time;
|
app: in GimpTransformGridTool, allow simultaneous forward and backward transforms
In GimpTransformGridTool, allow performing simultaneous forward
(normal) and backward (corrective) transforms, by having each
transform direction operate on an independent set of parameters.
In other words, whereas the transform-grid tools previously had a
single transform, which could be applied either normally or
correctively using the "direction" tool-option, they now have two
independent transforms, one applied normally and the other
applied correctively, which are toggled using the "direction"
option. The overall transform is the combination of the backward
transform, followed by the forward transform.
Another way to think about it, is that the tool transforms a source
shape into a destination shape. The source shape is defined by the
backward transform, and the destination shape is defined by the
forward transform. Wherewas previously only one of these shapes
could be controlled (the other shape always being the item bounds),
it's now possible to control both shapes in a single transform.
The next commit will allow modifying both shapes simultaneously,
making this even more useful.
Note that since both transforms start off as the identity, using
only one of the transform directions has the same behavior as
before.
2019-02-04 23:30:18 +08:00
|
|
|
undo_info->direction = tr_options->direction;
|
|
|
|
memcpy (undo_info->trans_infos, tg_tool->trans_infos,
|
|
|
|
sizeof (tg_tool->trans_infos));
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
/* If we undid anything and started interacting, we have to
|
|
|
|
* discard the redo history
|
|
|
|
*/
|
2020-01-06 17:57:17 +08:00
|
|
|
if (tg_tool->redo_list)
|
|
|
|
{
|
|
|
|
g_list_free_full (tg_tool->redo_list,
|
|
|
|
(GDestroyNotify) undo_info_free);
|
|
|
|
tg_tool->redo_list = NULL;
|
|
|
|
|
|
|
|
flush = TRUE;
|
|
|
|
}
|
2018-06-10 04:25:03 +08:00
|
|
|
|
|
|
|
gimp_transform_grid_tool_update_sensitivity (tg_tool);
|
|
|
|
|
|
|
|
/* update the undo actions / menu items */
|
2020-01-06 17:57:17 +08:00
|
|
|
if (flush)
|
|
|
|
{
|
|
|
|
gimp_image_flush (
|
|
|
|
gimp_display_get_image (GIMP_TOOL (tg_tool)->display));
|
|
|
|
}
|
2018-06-10 04:25:03 +08:00
|
|
|
}
|
|
|
|
}
|