[gimp/gimp-2-8] Bug 735906 - Transform tools give unexpected results when transforming...
- From: Michael Natterer <mitch src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp/gimp-2-8] Bug 735906 - Transform tools give unexpected results when transforming...
- Date: Sun, 28 Jun 2015 20:34:47 +0000 (UTC)
commit b3e0e8327434cc8110e56f85530be100096ab38a
Author: Michael Natterer <mitch gimp org>
Date: Sat Jun 27 12:34:19 2015 +0200
Bug 735906 - Transform tools give unexpected results when transforming...
...certain sets of linked layers
Fix the move tool (GimpEditSelectionTool) using the same principle
as the other "linked item" features, just a bit more complicated...
Never translate the active item and its linked items separately,
always translate the entire list at once.
The linked logic was distributed across the entire file. Changed the
code to prepare lists of items that are translated live (layers and
vectors), and items that are translated at the end (channels, masks
and the selection). In the motion and button release functions, simply
use the prepared lists without any further duplicated checking.
Also clean up the stuff a bit, there is more cleanup needed but first
the fix...
(cherry picked from commit 358f13f5b89249ca9bac4857f3ce37bc454b5929)
app/tools/gimpeditselectiontool.c | 348 ++++++++++++++++--------------------
1 files changed, 155 insertions(+), 193 deletions(-)
---
diff --git a/app/tools/gimpeditselectiontool.c b/app/tools/gimpeditselectiontool.c
index 9851789..7be51db 100644
--- a/app/tools/gimpeditselectiontool.c
+++ b/app/tools/gimpeditselectiontool.c
@@ -88,6 +88,9 @@ struct _GimpEditSelectionTool
GimpTranslateMode edit_mode; /* Translate the mask or layer? */
+ GList *live_items; /* Items that are transformed live */
+ GList *delayed_items; /* Items that are transformed later */
+
gboolean first_move; /* Don't push undos after the first */
gboolean propagate_release;
@@ -103,26 +106,26 @@ struct _GimpEditSelectionToolClass
};
-static void gimp_edit_selection_tool_button_release (GimpTool *tool,
- const GimpCoords *coords,
- guint32 time,
- GdkModifierType state,
- GimpButtonReleaseType release_type,
- GimpDisplay *display);
-static void gimp_edit_selection_tool_motion (GimpTool *tool,
- const GimpCoords *coords,
- guint32 time,
- GdkModifierType state,
- GimpDisplay *display);
-static void gimp_edit_selection_tool_active_modifier_key (GimpTool *tool,
- GdkModifierType key,
- gboolean press,
- GdkModifierType state,
- GimpDisplay *display);
-static void gimp_edit_selection_tool_draw (GimpDrawTool *tool);
-
-static GimpItem * gimp_edit_selection_tool_get_active_item (const GimpEditSelectionTool *edit_select,
- const GimpImage *image);
+static void gimp_edit_selection_tool_button_release (GimpTool *tool,
+ const GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state,
+ GimpButtonReleaseType release_type,
+ GimpDisplay *display);
+static void gimp_edit_selection_tool_motion (GimpTool *tool,
+ const GimpCoords *coords,
+ guint32 time,
+ GdkModifierType state,
+ GimpDisplay *display);
+static void gimp_edit_selection_tool_active_modifier_key (GimpTool *tool,
+ GdkModifierType key,
+ gboolean press,
+ GdkModifierType state,
+ GimpDisplay *display);
+static void gimp_edit_selection_tool_draw (GimpDrawTool *tool);
+
+static GimpItem * gimp_edit_selection_tool_get_active_item (GimpEditSelectionTool *edit_select,
+ GimpImage *image);
G_DEFINE_TYPE (GimpEditSelectionTool, gimp_edit_selection_tool,
@@ -145,21 +148,13 @@ gimp_edit_selection_tool_class_init (GimpEditSelectionToolClass *klass)
}
static void
-gimp_edit_selection_tool_init (GimpEditSelectionTool *edit_selection_tool)
+gimp_edit_selection_tool_init (GimpEditSelectionTool *edit_select)
{
- GimpTool *tool = GIMP_TOOL (edit_selection_tool);
+ GimpTool *tool = GIMP_TOOL (edit_select);
gimp_tool_control_set_motion_mode (tool->control, GIMP_MOTION_MODE_COMPRESS);
- edit_selection_tool->origx = 0;
- edit_selection_tool->origy = 0;
-
- edit_selection_tool->cumlx = 0;
- edit_selection_tool->cumly = 0;
-
- edit_selection_tool->first_move = TRUE;
-
- edit_selection_tool->constrain = FALSE;
+ edit_select->first_move = TRUE;
}
static void
@@ -196,7 +191,7 @@ gimp_edit_selection_tool_start (GimpTool *parent_tool,
gint off_x, off_y;
const BoundSeg *segs_in;
const BoundSeg *segs_out;
- const gchar *undo_desc;
+ const gchar *undo_desc = NULL;
edit_select = g_object_new (GIMP_TYPE_EDIT_SELECTION_TOOL,
"tool-info", parent_tool->tool_info,
@@ -234,17 +229,19 @@ gimp_edit_selection_tool_start (GimpTool *parent_tool,
case GIMP_TRANSLATE_MODE_VECTORS:
case GIMP_TRANSLATE_MODE_CHANNEL:
case GIMP_TRANSLATE_MODE_LAYER_MASK:
+ case GIMP_TRANSLATE_MODE_MASK:
case GIMP_TRANSLATE_MODE_LAYER:
undo_desc = GIMP_ITEM_GET_CLASS (active_item)->translate_desc;
break;
- case GIMP_TRANSLATE_MODE_MASK:
- undo_desc = _("Move Selection");
+ case GIMP_TRANSLATE_MODE_MASK_TO_LAYER:
+ case GIMP_TRANSLATE_MODE_MASK_COPY_TO_LAYER:
+ case GIMP_TRANSLATE_MODE_FLOATING_SEL:
+ undo_desc = _("Move Floating Selection");
break;
default:
- undo_desc = _("Move Floating Selection");
- break;
+ g_return_if_reached ();
}
gimp_image_undo_group_start (image,
@@ -265,17 +262,10 @@ gimp_edit_selection_tool_start (GimpTool *parent_tool,
edit_select->constrain = FALSE;
- switch (edit_select->edit_mode)
- {
- case GIMP_TRANSLATE_MODE_CHANNEL:
- case GIMP_TRANSLATE_MODE_LAYER_MASK:
- channel = GIMP_CHANNEL (active_item);
- break;
-
- default:
- channel = gimp_image_get_mask (image);
- break;
- }
+ if (GIMP_IS_CHANNEL (active_item))
+ channel = GIMP_CHANNEL (active_item);
+ else
+ channel = gimp_image_get_mask (image);
gimp_channel_boundary (channel,
&segs_in, &segs_out,
@@ -283,10 +273,12 @@ gimp_edit_selection_tool_start (GimpTool *parent_tool,
0, 0, 0, 0);
edit_select->segs_in = g_memdup (segs_in,
- edit_select->num_segs_in * sizeof (BoundSeg));
+ edit_select->num_segs_in *
+ sizeof (BoundSeg));
edit_select->segs_out = g_memdup (segs_out,
- edit_select->num_segs_out * sizeof (BoundSeg));
+ edit_select->num_segs_out *
+ sizeof (BoundSeg));
if (edit_select->edit_mode == GIMP_TRANSLATE_MODE_VECTORS)
{
@@ -317,10 +309,7 @@ gimp_edit_selection_tool_start (GimpTool *parent_tool,
switch (edit_select->edit_mode)
{
case GIMP_TRANSLATE_MODE_CHANNEL:
- gimp_channel_bounds (GIMP_CHANNEL (active_item),
- &x1, &y1, &x2, &y2);
- break;
-
+ case GIMP_TRANSLATE_MODE_MASK:
case GIMP_TRANSLATE_MODE_LAYER_MASK:
gimp_channel_bounds (GIMP_CHANNEL (active_item),
&x1, &y1, &x2, &y2);
@@ -330,11 +319,6 @@ gimp_edit_selection_tool_start (GimpTool *parent_tool,
y2 += off_y;
break;
- case GIMP_TRANSLATE_MODE_MASK:
- gimp_channel_bounds (gimp_image_get_mask (image),
- &x1, &y1, &x2, &y2);
- break;
-
case GIMP_TRANSLATE_MODE_MASK_TO_LAYER:
case GIMP_TRANSLATE_MODE_MASK_COPY_TO_LAYER:
x1 = edit_select->x1 + off_x;
@@ -352,17 +336,17 @@ gimp_edit_selection_tool_start (GimpTool *parent_tool,
if (gimp_item_get_linked (active_item))
{
+ /* Expand the rectangle to include all linked layers as well */
+
GList *linked;
GList *list;
- linked = gimp_image_item_list_get_list (image,
- active_item,
+ linked = gimp_image_item_list_get_list (image, NULL,
GIMP_ITEM_TYPE_LAYERS,
GIMP_ITEM_SET_LINKED);
- linked = gimp_image_item_list_filter (active_item, linked);
+ linked = gimp_image_item_list_filter (NULL, linked);
- /* Expand the rectangle to include all linked layers as well */
for (list = linked; list; list = g_list_next (list))
{
GimpItem *item = list->data;
@@ -393,17 +377,16 @@ gimp_edit_selection_tool_start (GimpTool *parent_tool,
if (gimp_item_get_linked (active_item))
{
- /* Expand the rectangle to include all linked layers as well */
+ /* Expand the rectangle to include all linked vectors as well */
GList *linked;
GList *list;
- linked = gimp_image_item_list_get_list (image,
- active_item,
+ linked = gimp_image_item_list_get_list (image, NULL,
GIMP_ITEM_TYPE_VECTORS,
GIMP_ITEM_SET_LINKED);
- linked = gimp_image_item_list_filter (active_item, linked);
+ linked = gimp_image_item_list_filter (NULL, linked);
for (list = linked; list; list = g_list_next (list))
{
@@ -439,6 +422,56 @@ gimp_edit_selection_tool_start (GimpTool *parent_tool,
edit_select->center_y = (y1 + y2) / 2.0;
}
+ if (gimp_item_get_linked (active_item))
+ {
+ switch (edit_select->edit_mode)
+ {
+ case GIMP_TRANSLATE_MODE_CHANNEL:
+ case GIMP_TRANSLATE_MODE_LAYER:
+ case GIMP_TRANSLATE_MODE_VECTORS:
+ edit_select->live_items =
+ gimp_image_item_list_get_list (image, NULL,
+ GIMP_ITEM_TYPE_LAYERS |
+ GIMP_ITEM_TYPE_VECTORS,
+ GIMP_ITEM_SET_LINKED);
+ edit_select->live_items =
+ gimp_image_item_list_filter (NULL, edit_select->live_items);
+
+ edit_select->delayed_items =
+ gimp_image_item_list_get_list (image, NULL,
+ GIMP_ITEM_TYPE_CHANNELS,
+ GIMP_ITEM_SET_LINKED);
+ edit_select->delayed_items =
+ gimp_image_item_list_filter (NULL, edit_select->delayed_items);
+ break;
+
+ default:
+ /* other stuff can't be linked so don't bother */
+ break;
+ }
+ }
+ else
+ {
+ switch (edit_select->edit_mode)
+ {
+ case GIMP_TRANSLATE_MODE_VECTORS:
+ case GIMP_TRANSLATE_MODE_LAYER:
+ case GIMP_TRANSLATE_MODE_FLOATING_SEL:
+ edit_select->live_items = g_list_append (NULL, active_item);
+ break;
+
+ case GIMP_TRANSLATE_MODE_CHANNEL:
+ case GIMP_TRANSLATE_MODE_LAYER_MASK:
+ case GIMP_TRANSLATE_MODE_MASK:
+ edit_select->delayed_items = g_list_append (NULL, active_item);
+ break;
+
+ default:
+ /* MASK_TO_LAYER and MASK_COPY_TO_LAYER create a live_item later */
+ break;
+ }
+ }
+
tool_manager_push_tool (display->gimp, tool);
gimp_tool_control_activate (tool->control);
@@ -467,7 +500,6 @@ gimp_edit_selection_tool_button_release (GimpTool *tool,
GimpEditSelectionTool *edit_select = GIMP_EDIT_SELECTION_TOOL (tool);
GimpDisplayShell *shell = gimp_display_get_shell (display);
GimpImage *image = gimp_display_get_image (display);
- GimpItem *active_item;
/* resume the current selection */
gimp_display_shell_selection_resume (shell);
@@ -481,72 +513,18 @@ gimp_edit_selection_tool_button_release (GimpTool *tool,
tool_manager_pop_tool (display->gimp);
- active_item = gimp_edit_selection_tool_get_active_item (edit_select, image);
-
gimp_edit_selection_tool_calc_coords (edit_select,
coords->x,
coords->y);
- /* GIMP_TRANSLATE_MODE_MASK is performed here at movement end, not 'live' like
- * the other translation types.
+ /* move the items -- whether there has been movement or not!
+ * (to ensure that there's something on the undo stack)
*/
- if (edit_select->edit_mode == GIMP_TRANSLATE_MODE_MASK)
- {
- /* move the selection -- whether there has been movement or not!
- * (to ensure that there's something on the undo stack)
- */
- gimp_item_translate (GIMP_ITEM (gimp_image_get_mask (image)),
- edit_select->cumlx,
- edit_select->cumly,
- TRUE);
- }
-
- /* GIMP_TRANSLATE_MODE_CHANNEL and GIMP_TRANSLATE_MODE_LAYER_MASK
- * need to be preformed after thawing the undo.
- */
- if (edit_select->edit_mode == GIMP_TRANSLATE_MODE_CHANNEL ||
- edit_select->edit_mode == GIMP_TRANSLATE_MODE_LAYER_MASK)
- {
- /* move the channel -- whether there has been movement or not!
- * (to ensure that there's something on the undo stack)
- */
- gimp_item_translate (active_item,
- edit_select->cumlx,
- edit_select->cumly,
- TRUE);
- }
-
- if (edit_select->edit_mode == GIMP_TRANSLATE_MODE_VECTORS ||
- edit_select->edit_mode == GIMP_TRANSLATE_MODE_CHANNEL ||
- edit_select->edit_mode == GIMP_TRANSLATE_MODE_LAYER)
- {
- if ((release_type != GIMP_BUTTON_RELEASE_CANCEL) &&
- (edit_select->cumlx != 0 ||
- edit_select->cumly != 0))
- {
- if (gimp_item_get_linked (active_item))
- {
- /* translate all linked channels as well */
-
- GList *linked;
-
- linked = gimp_image_item_list_get_list (image,
- active_item,
- GIMP_ITEM_TYPE_CHANNELS,
- GIMP_ITEM_SET_LINKED);
-
- linked = gimp_image_item_list_filter (active_item, linked);
-
- gimp_image_item_list_translate (image,
- linked,
- edit_select->cumlx,
- edit_select->cumly,
- TRUE);
-
- g_list_free (linked);
- }
- }
- }
+ gimp_image_item_list_translate (image,
+ edit_select->delayed_items,
+ edit_select->cumlx,
+ edit_select->cumly,
+ TRUE);
gimp_image_undo_group_end (image);
@@ -566,6 +544,12 @@ gimp_edit_selection_tool_button_release (GimpTool *tool,
edit_select->num_segs_in = 0;
edit_select->num_segs_out = 0;
+ g_list_free (edit_select->live_items);
+ g_list_free (edit_select->delayed_items);
+
+ edit_select->live_items = NULL;
+ edit_select->delayed_items = NULL;
+
if (edit_select->propagate_release &&
tool_manager_get_active (display->gimp))
{
@@ -634,11 +618,6 @@ gimp_edit_selection_tool_update_motion (GimpEditSelectionTool *edit_select,
{
case GIMP_TRANSLATE_MODE_LAYER_MASK:
case GIMP_TRANSLATE_MODE_MASK:
- /* we don't do the actual edit selection move here. */
- edit_select->origx = x;
- edit_select->origy = y;
- break;
-
case GIMP_TRANSLATE_MODE_VECTORS:
case GIMP_TRANSLATE_MODE_CHANNEL:
edit_select->origx = x;
@@ -647,35 +626,10 @@ gimp_edit_selection_tool_update_motion (GimpEditSelectionTool *edit_select,
/* fallthru */
case GIMP_TRANSLATE_MODE_LAYER:
- /* for CHANNEL_TRANSLATE, only translate the linked layers
- * and vectors on-the-fly, the channel is translated
- * on button_release.
- */
- if (edit_select->edit_mode != GIMP_TRANSLATE_MODE_CHANNEL)
- gimp_item_translate (active_item, xoffset, yoffset,
- edit_select->first_move);
-
- if (gimp_item_get_linked (active_item))
- {
- /* translate all linked layers & vectors as well */
-
- GList *linked;
-
- linked = gimp_image_item_list_get_list (image,
- active_item,
- GIMP_ITEM_TYPE_LAYERS |
- GIMP_ITEM_TYPE_VECTORS,
- GIMP_ITEM_SET_LINKED);
-
- linked = gimp_image_item_list_filter (active_item, linked);
-
- gimp_image_item_list_translate (image,
- linked,
- xoffset, yoffset,
- edit_select->first_move);
-
- g_list_free (linked);
- }
+ gimp_image_item_list_translate (image,
+ edit_select->live_items,
+ xoffset, yoffset,
+ edit_select->first_move);
break;
case GIMP_TRANSLATE_MODE_MASK_TO_LAYER:
@@ -706,14 +660,18 @@ gimp_edit_selection_tool_update_motion (GimpEditSelectionTool *edit_select,
edit_select->edit_mode = GIMP_TRANSLATE_MODE_FLOATING_SEL;
- active_item =
- GIMP_ITEM (gimp_image_get_active_drawable (image));
+ active_item = gimp_edit_selection_tool_get_active_item (edit_select,
+ image);
- /* fall through */
+ edit_select->live_items = g_list_prepend (NULL, active_item);
+
+ /* fallthru */
case GIMP_TRANSLATE_MODE_FLOATING_SEL:
- gimp_item_translate (active_item, xoffset, yoffset,
- edit_select->first_move);
+ gimp_image_item_list_translate (image,
+ edit_select->live_items,
+ xoffset, yoffset,
+ edit_select->first_move);
break;
}
@@ -793,8 +751,10 @@ gimp_edit_selection_tool_draw (GimpDrawTool *draw_tool)
case GIMP_TRANSLATE_MODE_MASK:
{
gboolean floating_sel = FALSE;
- gint off_x = 0;
- gint off_y = 0;
+ gint off_x;
+ gint off_y;
+
+ gimp_item_get_offset (active_item, &off_x, &off_y);
if (edit_select->edit_mode == GIMP_TRANSLATE_MODE_MASK)
{
@@ -803,10 +763,6 @@ gimp_edit_selection_tool_draw (GimpDrawTool *draw_tool)
if (layer)
floating_sel = gimp_layer_is_floating_sel (layer);
}
- else
- {
- gimp_item_get_offset (active_item, &off_x, &off_y);
- }
if (! floating_sel && edit_select->segs_in)
{
@@ -858,10 +814,7 @@ gimp_edit_selection_tool_draw (GimpDrawTool *draw_tool)
case GIMP_TRANSLATE_MODE_LAYER:
{
- GimpItem *active_item;
- gint x1, y1, x2, y2;
-
- active_item = GIMP_ITEM (gimp_image_get_active_layer (image));
+ gint x1, y1, x2, y2;
gimp_item_get_offset (active_item, &x1, &y1);
@@ -875,12 +828,11 @@ gimp_edit_selection_tool_draw (GimpDrawTool *draw_tool)
GList *linked;
GList *list;
- linked = gimp_image_item_list_get_list (image,
- active_item,
+ linked = gimp_image_item_list_get_list (image, NULL,
GIMP_ITEM_TYPE_LAYERS,
GIMP_ITEM_SET_LINKED);
- linked = gimp_image_item_list_filter (active_item, linked);
+ linked = gimp_image_item_list_filter (NULL, linked);
for (list = linked; list; list = g_list_next (list))
{
@@ -910,10 +862,7 @@ gimp_edit_selection_tool_draw (GimpDrawTool *draw_tool)
case GIMP_TRANSLATE_MODE_VECTORS:
{
- GimpItem *active_item;
- gdouble x1, y1, x2, y2;
-
- active_item = GIMP_ITEM (gimp_image_get_active_vectors (image));
+ gdouble x1, y1, x2, y2;
gimp_vectors_bounds (GIMP_VECTORS (active_item), &x1, &y1, &x2, &y2);
@@ -924,12 +873,11 @@ gimp_edit_selection_tool_draw (GimpDrawTool *draw_tool)
GList *linked;
GList *list;
- linked = gimp_image_item_list_get_list (image,
- active_item,
+ linked = gimp_image_item_list_get_list (image, NULL,
GIMP_ITEM_TYPE_VECTORS,
GIMP_ITEM_SET_LINKED);
- linked = gimp_image_item_list_filter (active_item, linked);
+ linked = gimp_image_item_list_filter (NULL, linked);
for (list = linked; list; list = g_list_next (list))
{
@@ -982,15 +930,29 @@ gimp_edit_selection_tool_draw (GimpDrawTool *draw_tool)
}
static GimpItem *
-gimp_edit_selection_tool_get_active_item (const GimpEditSelectionTool *edit_select,
- const GimpImage *image)
+gimp_edit_selection_tool_get_active_item (GimpEditSelectionTool *edit_select,
+ GimpImage *image)
{
GimpItem *active_item;
- if (edit_select->edit_mode == GIMP_TRANSLATE_MODE_VECTORS)
- active_item = GIMP_ITEM (gimp_image_get_active_vectors (image));
- else
- active_item = GIMP_ITEM (gimp_image_get_active_drawable (image));
+ switch (edit_select->edit_mode)
+ {
+ case GIMP_TRANSLATE_MODE_VECTORS:
+ active_item = GIMP_ITEM (gimp_image_get_active_vectors (image));
+ break;
+
+ case GIMP_TRANSLATE_MODE_LAYER:
+ active_item = GIMP_ITEM (gimp_image_get_active_layer (image));
+ break;
+
+ case GIMP_TRANSLATE_MODE_MASK:
+ active_item = GIMP_ITEM (gimp_image_get_mask (image));
+ break;
+
+ default:
+ active_item = GIMP_ITEM (gimp_image_get_active_drawable (image));
+ break;
+ }
return active_item;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]