[gimp] app: in GimpTransformGridTool, allow linking forward/backward transforms



commit 39e23267f7ac76030f02e5f68bf7994a02bb81a1
Author: Ell <ell_se yahoo com>
Date:   Mon Feb 4 15:33:44 2019 -0500

    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.

 app/tools/gimphandletransformtool.c  | 29 ++++++++++++
 app/tools/gimpperspectivetool.c      | 31 ++++++++++++
 app/tools/gimprotatetool.c           | 44 +++++++++++++++++
 app/tools/gimpscaletool.c            | 26 ++++++++++
 app/tools/gimptransformgridoptions.c | 66 ++++++++++++++++++++++----
 app/tools/gimptransformgridoptions.h |  1 +
 app/tools/gimptransformgridtool.c    | 92 +++++++++++++++++++++++++++++++-----
 app/tools/gimptransformgridtool.h    |  4 ++
 app/tools/gimptransformoptions.c     |  2 +
 app/tools/gimptransformoptions.h     |  1 +
 app/tools/gimpunifiedtransformtool.c | 42 ++++++++++++++++
 11 files changed, 319 insertions(+), 19 deletions(-)
---
diff --git a/app/tools/gimphandletransformtool.c b/app/tools/gimphandletransformtool.c
index bedbe6aefc..1a20e182c5 100644
--- a/app/tools/gimphandletransformtool.c
+++ b/app/tools/gimphandletransformtool.c
@@ -83,6 +83,8 @@ static void             gimp_handle_transform_tool_modifier_key   (GimpTool
                                                                    GdkModifierType           state,
                                                                    GimpDisplay              *display);
 
+static void             gimp_handle_transform_tool_matrix_to_info (GimpTransformGridTool    *tg_tool,
+                                                                   const GimpMatrix3        *transform);
 static void             gimp_handle_transform_tool_prepare        (GimpTransformGridTool    *tg_tool);
 static GimpToolWidget * gimp_handle_transform_tool_get_widget     (GimpTransformGridTool    *tg_tool);
 static void             gimp_handle_transform_tool_update_widget  (GimpTransformGridTool    *tg_tool);
@@ -125,6 +127,7 @@ gimp_handle_transform_tool_class_init (GimpHandleTransformToolClass *klass)
 
   tool_class->modifier_key      = gimp_handle_transform_tool_modifier_key;
 
+  tg_class->matrix_to_info      = gimp_handle_transform_tool_matrix_to_info;
   tg_class->prepare             = gimp_handle_transform_tool_prepare;
   tg_class->get_widget          = gimp_handle_transform_tool_get_widget;
   tg_class->update_widget       = gimp_handle_transform_tool_update_widget;
@@ -196,6 +199,32 @@ gimp_handle_transform_tool_modifier_key (GimpTool        *tool,
                                                 state, display);
 }
 
+static void
+gimp_handle_transform_tool_matrix_to_info (GimpTransformGridTool *tg_tool,
+                                           const GimpMatrix3     *transform)
+{
+  gimp_matrix3_transform_point (transform,
+                                tg_tool->trans_info[OX0],
+                                tg_tool->trans_info[OY0],
+                                &tg_tool->trans_info[X0],
+                                &tg_tool->trans_info[Y0]);
+  gimp_matrix3_transform_point (transform,
+                                tg_tool->trans_info[OX1],
+                                tg_tool->trans_info[OY1],
+                                &tg_tool->trans_info[X1],
+                                &tg_tool->trans_info[Y1]);
+  gimp_matrix3_transform_point (transform,
+                                tg_tool->trans_info[OX2],
+                                tg_tool->trans_info[OY2],
+                                &tg_tool->trans_info[X2],
+                                &tg_tool->trans_info[Y2]);
+  gimp_matrix3_transform_point (transform,
+                                tg_tool->trans_info[OX3],
+                                tg_tool->trans_info[OY3],
+                                &tg_tool->trans_info[X3],
+                                &tg_tool->trans_info[Y3]);
+}
+
 static void
 gimp_handle_transform_tool_prepare (GimpTransformGridTool *tg_tool)
 {
diff --git a/app/tools/gimpperspectivetool.c b/app/tools/gimpperspectivetool.c
index 0599433618..185227cb73 100644
--- a/app/tools/gimpperspectivetool.c
+++ b/app/tools/gimpperspectivetool.c
@@ -54,6 +54,8 @@ enum
 
 /*  local function prototypes  */
 
+static void             gimp_perspective_tool_matrix_to_info (GimpTransformGridTool    *tg_tool,
+                                                              const GimpMatrix3        *transform);
 static void             gimp_perspective_tool_prepare        (GimpTransformGridTool    *tg_tool);
 static GimpToolWidget * gimp_perspective_tool_get_widget     (GimpTransformGridTool    *tg_tool);
 static void             gimp_perspective_tool_update_widget  (GimpTransformGridTool    *tg_tool);
@@ -93,6 +95,7 @@ gimp_perspective_tool_class_init (GimpPerspectiveToolClass *klass)
   GimpTransformGridToolClass    *tg_class      = GIMP_TRANSFORM_GRID_TOOL_CLASS (klass);
   GimpGenericTransformToolClass *generic_class = GIMP_GENERIC_TRANSFORM_TOOL_CLASS (klass);
 
+  tg_class->matrix_to_info      = gimp_perspective_tool_matrix_to_info;
   tg_class->prepare             = gimp_perspective_tool_prepare;
   tg_class->get_widget          = gimp_perspective_tool_get_widget;
   tg_class->update_widget       = gimp_perspective_tool_update_widget;
@@ -113,6 +116,34 @@ gimp_perspective_tool_init (GimpPerspectiveTool *perspective_tool)
                                      GIMP_TOOL_CURSOR_PERSPECTIVE);
 }
 
+static void
+gimp_perspective_tool_matrix_to_info (GimpTransformGridTool *tg_tool,
+                                      const GimpMatrix3     *transform)
+{
+  GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tg_tool);
+
+  gimp_matrix3_transform_point (transform,
+                                tr_tool->x1,
+                                tr_tool->y1,
+                                &tg_tool->trans_info[X0],
+                                &tg_tool->trans_info[Y0]);
+  gimp_matrix3_transform_point (transform,
+                                tr_tool->x2,
+                                tr_tool->y1,
+                                &tg_tool->trans_info[X1],
+                                &tg_tool->trans_info[Y1]);
+  gimp_matrix3_transform_point (transform,
+                                tr_tool->x1,
+                                tr_tool->y2,
+                                &tg_tool->trans_info[X2],
+                                &tg_tool->trans_info[Y2]);
+  gimp_matrix3_transform_point (transform,
+                                tr_tool->x2,
+                                tr_tool->y2,
+                                &tg_tool->trans_info[X3],
+                                &tg_tool->trans_info[Y3]);
+}
+
 static void
 gimp_perspective_tool_prepare (GimpTransformGridTool *tg_tool)
 {
diff --git a/app/tools/gimprotatetool.c b/app/tools/gimprotatetool.c
index 6cf75e2a1f..7199fb8144 100644
--- a/app/tools/gimprotatetool.c
+++ b/app/tools/gimprotatetool.c
@@ -53,6 +53,7 @@ enum
 
 
 #define SB_WIDTH 10
+#define EPSILON  1e-6
 
 
 /*  local function prototypes  */
@@ -63,6 +64,8 @@ static gboolean         gimp_rotate_tool_key_press      (GimpTool              *
 
 static gboolean         gimp_rotate_tool_info_to_matrix (GimpTransformGridTool *tg_tool,
                                                          GimpMatrix3           *transform);
+static void             gimp_rotate_tool_matrix_to_info (GimpTransformGridTool *tg_tool,
+                                                         const GimpMatrix3     *transform);
 static gchar          * gimp_rotate_tool_get_undo_desc  (GimpTransformGridTool *tg_tool);
 static void             gimp_rotate_tool_dialog         (GimpTransformGridTool *tg_tool);
 static void             gimp_rotate_tool_dialog_update  (GimpTransformGridTool *tg_tool);
@@ -109,6 +112,7 @@ gimp_rotate_tool_class_init (GimpRotateToolClass *klass)
   tool_class->key_press     = gimp_rotate_tool_key_press;
 
   tg_class->info_to_matrix  = gimp_rotate_tool_info_to_matrix;
+  tg_class->matrix_to_info  = gimp_rotate_tool_matrix_to_info;
   tg_class->get_undo_desc   = gimp_rotate_tool_get_undo_desc;
   tg_class->dialog          = gimp_rotate_tool_dialog;
   tg_class->dialog_update   = gimp_rotate_tool_dialog_update;
@@ -181,6 +185,46 @@ gimp_rotate_tool_info_to_matrix (GimpTransformGridTool *tg_tool,
   return TRUE;
 }
 
+static void
+gimp_rotate_tool_matrix_to_info (GimpTransformGridTool *tg_tool,
+                                 const GimpMatrix3     *transform)
+{
+  gdouble c;
+  gdouble s;
+  gdouble x;
+  gdouble y;
+  gdouble q;
+
+  c = transform->coeff[0][0];
+  s = transform->coeff[1][0];
+  x = transform->coeff[0][2];
+  y = transform->coeff[1][2];
+
+  tg_tool->trans_info[ANGLE] = atan2 (s, c);
+
+  q = 2.0 * (1.0 - transform->coeff[0][0]);
+
+  if (q > EPSILON)
+    {
+      tg_tool->trans_info[PIVOT_X] = ((1.0 - c) * x - s * y) / q;
+      tg_tool->trans_info[PIVOT_Y] = (s * x + (1.0 - c) * y) / q;
+    }
+  else
+    {
+      GimpMatrix3 transfer;
+
+      gimp_transform_grid_tool_info_to_matrix (tg_tool, &transfer);
+      gimp_matrix3_invert (&transfer);
+      gimp_matrix3_mult (transform, &transfer);
+
+      gimp_matrix3_transform_point (&transfer,
+                                    tg_tool->trans_info[PIVOT_X],
+                                    tg_tool->trans_info[PIVOT_Y],
+                                    &tg_tool->trans_info[PIVOT_X],
+                                    &tg_tool->trans_info[PIVOT_Y]);
+    }
+}
+
 static gchar *
 gimp_rotate_tool_get_undo_desc (GimpTransformGridTool *tg_tool)
 {
diff --git a/app/tools/gimpscaletool.c b/app/tools/gimpscaletool.c
index 987ffb0ab8..10bbe18a0e 100644
--- a/app/tools/gimpscaletool.c
+++ b/app/tools/gimpscaletool.c
@@ -62,6 +62,8 @@ enum
 
 static gboolean         gimp_scale_tool_info_to_matrix (GimpTransformGridTool *tg_tool,
                                                         GimpMatrix3           *transform);
+static void             gimp_scale_tool_matrix_to_info (GimpTransformGridTool *tg_tool,
+                                                        const GimpMatrix3     *transform);
 static gchar          * gimp_scale_tool_get_undo_desc  (GimpTransformGridTool *tg_tool);
 static void             gimp_scale_tool_dialog         (GimpTransformGridTool *tg_tool);
 static void             gimp_scale_tool_dialog_update  (GimpTransformGridTool *tg_tool);
@@ -104,6 +106,7 @@ gimp_scale_tool_class_init (GimpScaleToolClass *klass)
   GimpTransformGridToolClass *tg_class = GIMP_TRANSFORM_GRID_TOOL_CLASS (klass);
 
   tg_class->info_to_matrix  = gimp_scale_tool_info_to_matrix;
+  tg_class->matrix_to_info  = gimp_scale_tool_matrix_to_info;
   tg_class->get_undo_desc   = gimp_scale_tool_get_undo_desc;
   tg_class->dialog          = gimp_scale_tool_dialog;
   tg_class->dialog_update   = gimp_scale_tool_dialog_update;
@@ -145,6 +148,29 @@ gimp_scale_tool_info_to_matrix  (GimpTransformGridTool *tg_tool,
   return TRUE;
 }
 
+static void
+gimp_scale_tool_matrix_to_info  (GimpTransformGridTool *tg_tool,
+                                 const GimpMatrix3     *transform)
+{
+  GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tg_tool);
+  gdouble            x;
+  gdouble            y;
+  gdouble            w;
+  gdouble            h;
+
+  x = transform->coeff[0][2];
+  y = transform->coeff[1][2];
+  w = transform->coeff[0][0];
+  h = transform->coeff[1][1];
+
+  tg_tool->trans_info[X0] = x + w * tr_tool->x1;
+  tg_tool->trans_info[Y0] = y + h * tr_tool->y1;
+  tg_tool->trans_info[X1] = tg_tool->trans_info[X0] +
+                            w * (tr_tool->x2 - tr_tool->x1);
+  tg_tool->trans_info[Y1] = tg_tool->trans_info[Y0] +
+                            h * (tr_tool->y2 - tr_tool->y1);
+}
+
 static gchar *
 gimp_scale_tool_get_undo_desc (GimpTransformGridTool *tg_tool)
 {
diff --git a/app/tools/gimptransformgridoptions.c b/app/tools/gimptransformgridoptions.c
index 69f19240bd..631bbe7b12 100644
--- a/app/tools/gimptransformgridoptions.c
+++ b/app/tools/gimptransformgridoptions.c
@@ -37,6 +37,7 @@
 #include "gimpunifiedtransformtool.h"
 #include "gimptooloptions-gui.h"
 #include "gimptransformgridoptions.h"
+#include "gimptransformgridtool.h"
 
 #include "gimp-intl.h"
 
@@ -45,6 +46,7 @@ enum
 {
   PROP_0,
   PROP_DIRECTION,
+  PROP_DIRECTION_LINKED,
   PROP_SHOW_PREVIEW,
   PROP_PREVIEW_OPACITY,
   PROP_GRID_TYPE,
@@ -94,6 +96,12 @@ gimp_transform_grid_options_class_init (GimpTransformGridOptionsClass *klass)
   g_object_class_override_property (object_class, PROP_DIRECTION,
                                     "direction");
 
+  GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_DIRECTION_LINKED,
+                            "direction-linked",
+                            NULL, NULL,
+                            FALSE,
+                            GIMP_PARAM_STATIC_STRINGS);
+
   GIMP_CONFIG_PROP_BOOLEAN (object_class, PROP_SHOW_PREVIEW,
                             "show-preview",
                             _("Show image preview"),
@@ -212,6 +220,9 @@ gimp_transform_grid_options_set_property (GObject      *object,
                     transform_options->direction != GIMP_TRANSFORM_BACKWARD,
                     NULL);
       break;
+    case PROP_DIRECTION_LINKED:
+      options->direction_linked = g_value_get_boolean (value);
+      break;
     case PROP_SHOW_PREVIEW:
       options->show_preview = g_value_get_boolean (value);
       break;
@@ -274,6 +285,9 @@ gimp_transform_grid_options_get_property (GObject    *object,
     case PROP_DIRECTION:
       g_value_set_enum (value, transform_options->direction);
       break;
+    case PROP_DIRECTION_LINKED:
+      g_value_set_boolean (value, options->direction_linked);
+      break;
     case PROP_SHOW_PREVIEW:
       g_value_set_boolean (value, options->show_preview);
       break;
@@ -333,17 +347,53 @@ gimp_transform_grid_options_get_property (GObject    *object,
 GtkWidget *
 gimp_transform_grid_options_gui (GimpToolOptions *tool_options)
 {
-  GObject         *config = G_OBJECT (tool_options);
-  GtkWidget       *vbox;
-  GtkWidget       *frame;
-  GtkWidget       *combo;
-  GtkWidget       *scale;
-  GtkWidget       *grid_box;
-  GdkModifierType  extend_mask    = gimp_get_extend_selection_mask ();
-  GdkModifierType  constrain_mask = gimp_get_constrain_behavior_mask ();
+  GObject                    *config = G_OBJECT (tool_options);
+  GimpTransformGridToolClass *tg_class;
+  GtkWidget                  *vbox;
+  GtkWidget                  *frame;
+  GtkWidget                  *combo;
+  GtkWidget                  *scale;
+  GtkWidget                  *grid_box;
+  GdkModifierType             extend_mask    = gimp_get_extend_selection_mask ();
+  GdkModifierType             constrain_mask = gimp_get_constrain_behavior_mask ();
 
   vbox = gimp_transform_options_gui (tool_options, TRUE, TRUE, TRUE);
 
+  tg_class  = g_type_class_ref (tool_options->tool_info->tool_type);
+
+  /* the direction-link button */
+  if (tg_class->matrix_to_info)
+    {
+      GimpTransformOptions *tr_options = GIMP_TRANSFORM_OPTIONS (tool_options);
+      GtkWidget            *vbox2;
+      GtkWidget            *hbox;
+      GtkWidget            *button;
+
+      vbox2 = gtk_bin_get_child (GTK_BIN (tr_options->direction_frame));
+      g_object_ref (vbox2);
+      gtk_container_remove (GTK_CONTAINER (tr_options->direction_frame), vbox2);
+
+      hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 1);
+      gtk_container_add (GTK_CONTAINER (tr_options->direction_frame), hbox);
+      gtk_widget_show (hbox);
+
+      gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 0);
+      g_object_unref (vbox2);
+
+      button = gimp_chain_button_new (GIMP_CHAIN_RIGHT);
+      gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
+      gimp_chain_button_set_icon_size (GIMP_CHAIN_BUTTON (button),
+                                       GTK_ICON_SIZE_MENU);
+      gtk_widget_show (button);
+
+      g_object_bind_property (config, "direction-linked",
+                              button, "active",
+                              G_BINDING_BIDIRECTIONAL |
+                              G_BINDING_SYNC_CREATE);
+    }
+
+  g_type_class_unref (tg_class);
+
   /*  the preview frame  */
   scale = gimp_prop_spin_scale_new (config, "preview-opacity", NULL,
                                     0.01, 0.1, 0);
diff --git a/app/tools/gimptransformgridoptions.h b/app/tools/gimptransformgridoptions.h
index dc959e5998..91d46bde09 100644
--- a/app/tools/gimptransformgridoptions.h
+++ b/app/tools/gimptransformgridoptions.h
@@ -37,6 +37,7 @@ struct _GimpTransformGridOptions
 {
   GimpTransformOptions  parent_instance;
 
+  gboolean              direction_linked;
   gboolean              show_preview;
   gdouble               preview_opacity;
   GimpGuidesType        grid_type;
diff --git a/app/tools/gimptransformgridtool.c b/app/tools/gimptransformgridtool.c
index 75d3872e2b..b54eec59e1 100644
--- a/app/tools/gimptransformgridtool.c
+++ b/app/tools/gimptransformgridtool.c
@@ -205,6 +205,7 @@ gimp_transform_grid_tool_class_init (GimpTransformGridToolClass *klass)
   tr_class->transform        = gimp_transform_grid_tool_transform;
 
   klass->info_to_matrix      = NULL;
+  klass->matrix_to_info      = NULL;
   klass->get_undo_desc       = gimp_transform_grid_tool_real_get_undo_desc;
   klass->dialog              = NULL;
   klass->dialog_update       = NULL;
@@ -753,32 +754,76 @@ gimp_transform_grid_tool_draw (GimpDrawTool *draw_tool)
 static void
 gimp_transform_grid_tool_recalc_matrix (GimpTransformTool *tr_tool)
 {
-  GimpTransformGridTool *tg_tool    = GIMP_TRANSFORM_GRID_TOOL (tr_tool);
-  GimpTransformOptions  *tr_options = GIMP_TRANSFORM_TOOL_GET_OPTIONS (tr_tool);
+  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);
 
   if (GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->info_to_matrix)
     {
       GimpMatrix3 forward_transform;
       GimpMatrix3 backward_transform;
-
-      tr_tool->transform_valid = TRUE;
+      gboolean    forward_transform_valid;
+      gboolean    backward_transform_valid;
 
       tg_tool->trans_info      = tg_tool->trans_infos[GIMP_TRANSFORM_FORWARD];
-      tr_tool->transform_valid = tr_tool->transform_valid &&
-                                 gimp_transform_grid_tool_info_to_matrix (
+      forward_transform_valid  = gimp_transform_grid_tool_info_to_matrix (
                                    tg_tool, &forward_transform);
 
       tg_tool->trans_info      = tg_tool->trans_infos[GIMP_TRANSFORM_BACKWARD];
-      tr_tool->transform_valid = tr_tool->transform_valid &&
-                                 gimp_transform_grid_tool_info_to_matrix (
+      backward_transform_valid = gimp_transform_grid_tool_info_to_matrix (
                                    tg_tool, &backward_transform);
 
-      if (tr_tool->transform_valid)
+      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)
         {
           tr_tool->transform = backward_transform;
           gimp_matrix3_invert (&tr_tool->transform);
           gimp_matrix3_mult (&forward_transform, &tr_tool->transform);
         }
+
+      tr_tool->transform_valid = forward_transform_valid &&
+                                 backward_transform_valid;
     }
 
   tg_tool->trans_info = tg_tool->trans_infos[tr_options->direction];
@@ -799,8 +844,19 @@ gimp_transform_grid_tool_get_undo_desc (GimpTransformTool *tr_tool)
   GimpTransformOptions  *tr_options = GIMP_TRANSFORM_TOOL_GET_OPTIONS (tr_tool);
   gchar                 *result;
 
-  if (! memcmp (tg_tool->trans_infos[GIMP_TRANSFORM_BACKWARD],
-                tg_tool->init_trans_info, sizeof (TransInfo)))
+  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);
+    }
+  else if (! memcmp (tg_tool->trans_infos[GIMP_TRANSFORM_BACKWARD],
+                     tg_tool->init_trans_info, sizeof (TransInfo)))
     {
       tg_tool->trans_info = tg_tool->trans_infos[GIMP_TRANSFORM_FORWARD];
       result = GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->get_undo_desc (
@@ -1345,6 +1401,20 @@ gimp_transform_grid_tool_info_to_matrix (GimpTransformGridTool *tg_tool,
   return FALSE;
 }
 
+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);
+    }
+}
+
 void
 gimp_transform_grid_tool_push_internal_undo (GimpTransformGridTool *tg_tool)
 {
diff --git a/app/tools/gimptransformgridtool.h b/app/tools/gimptransformgridtool.h
index 401baaf456..ab31111ec8 100644
--- a/app/tools/gimptransformgridtool.h
+++ b/app/tools/gimptransformgridtool.h
@@ -76,6 +76,8 @@ struct _GimpTransformGridToolClass
   /*  virtual functions  */
   gboolean         (* info_to_matrix) (GimpTransformGridTool  *tg_tool,
                                        GimpMatrix3            *transform);
+  void             (* matrix_to_info) (GimpTransformGridTool  *tg_tool,
+                                       const GimpMatrix3      *transform);
   gchar          * (* get_undo_desc)  (GimpTransformGridTool  *tg_tool);
   void             (* dialog)         (GimpTransformGridTool  *tg_tool);
   void             (* dialog_update)  (GimpTransformGridTool  *tg_tool);
@@ -100,6 +102,8 @@ GType      gimp_transform_grid_tool_get_type           (void) G_GNUC_CONST;
 
 gboolean   gimp_transform_grid_tool_info_to_matrix     (GimpTransformGridTool *tg_tool,
                                                         GimpMatrix3           *transform);
+void       gimp_transform_grid_tool_matrix_to_info     (GimpTransformGridTool *tg_tool,
+                                                        const GimpMatrix3     *transform);
 
 void       gimp_transform_grid_tool_push_internal_undo (GimpTransformGridTool *tg_tool);
 
diff --git a/app/tools/gimptransformoptions.c b/app/tools/gimptransformoptions.c
index a9311c98f7..d1c75e649c 100644
--- a/app/tools/gimptransformoptions.c
+++ b/app/tools/gimptransformoptions.c
@@ -243,6 +243,8 @@ gimp_transform_options_gui (GimpToolOptions *tool_options,
                                               0, 0);
       gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
       gtk_widget_show (frame);
+
+      options->direction_frame = frame;
     }
 
   /*  the interpolation menu  */
diff --git a/app/tools/gimptransformoptions.h b/app/tools/gimptransformoptions.h
index e5a42acd96..ca8d032fcb 100644
--- a/app/tools/gimptransformoptions.h
+++ b/app/tools/gimptransformoptions.h
@@ -44,6 +44,7 @@ struct _GimpTransformOptions
 
   /*  options gui  */
   GtkWidget              *type_box;
+  GtkWidget              *direction_frame;
 };
 
 struct _GimpTransformOptionsClass
diff --git a/app/tools/gimpunifiedtransformtool.c b/app/tools/gimpunifiedtransformtool.c
index 0c8ded9fc1..00a1934efa 100644
--- a/app/tools/gimpunifiedtransformtool.c
+++ b/app/tools/gimpunifiedtransformtool.c
@@ -56,6 +56,8 @@ enum
 
 /*  local function prototypes  */
 
+static void             gimp_unified_transform_tool_matrix_to_info (GimpTransformGridTool    *tg_tool,
+                                                                    const GimpMatrix3        *transform);
 static void             gimp_unified_transform_tool_prepare        (GimpTransformGridTool    *tg_tool);
 static GimpToolWidget * gimp_unified_transform_tool_get_widget     (GimpTransformGridTool    *tg_tool);
 static void             gimp_unified_transform_tool_update_widget  (GimpTransformGridTool    *tg_tool);
@@ -95,6 +97,7 @@ gimp_unified_transform_tool_class_init (GimpUnifiedTransformToolClass *klass)
   GimpTransformGridToolClass    *tg_class      = GIMP_TRANSFORM_GRID_TOOL_CLASS (klass);
   GimpGenericTransformToolClass *generic_class = GIMP_GENERIC_TRANSFORM_TOOL_CLASS (klass);
 
+  tg_class->matrix_to_info      = gimp_unified_transform_tool_matrix_to_info;
   tg_class->prepare             = gimp_unified_transform_tool_prepare;
   tg_class->get_widget          = gimp_unified_transform_tool_get_widget;
   tg_class->update_widget       = gimp_unified_transform_tool_update_widget;
@@ -111,6 +114,45 @@ gimp_unified_transform_tool_init (GimpUnifiedTransformTool *unified_tool)
 {
 }
 
+static void
+gimp_unified_transform_tool_matrix_to_info (GimpTransformGridTool *tg_tool,
+                                            const GimpMatrix3     *transform)
+{
+  GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tg_tool);
+  GimpMatrix3        transfer;
+
+  gimp_transform_grid_tool_info_to_matrix (tg_tool, &transfer);
+  gimp_matrix3_invert (&transfer);
+  gimp_matrix3_mult (transform, &transfer);
+
+  gimp_matrix3_transform_point (&transfer,
+                                tg_tool->trans_info[PIVOT_X],
+                                tg_tool->trans_info[PIVOT_Y],
+                                &tg_tool->trans_info[PIVOT_X],
+                                &tg_tool->trans_info[PIVOT_Y]);
+
+  gimp_matrix3_transform_point (transform,
+                                tr_tool->x1,
+                                tr_tool->y1,
+                                &tg_tool->trans_info[X0],
+                                &tg_tool->trans_info[Y0]);
+  gimp_matrix3_transform_point (transform,
+                                tr_tool->x2,
+                                tr_tool->y1,
+                                &tg_tool->trans_info[X1],
+                                &tg_tool->trans_info[Y1]);
+  gimp_matrix3_transform_point (transform,
+                                tr_tool->x1,
+                                tr_tool->y2,
+                                &tg_tool->trans_info[X2],
+                                &tg_tool->trans_info[Y2]);
+  gimp_matrix3_transform_point (transform,
+                                tr_tool->x2,
+                                tr_tool->y2,
+                                &tg_tool->trans_info[X3],
+                                &tg_tool->trans_info[Y3]);
+}
+
 static void
 gimp_unified_transform_tool_prepare (GimpTransformGridTool *tg_tool)
 {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]