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.
This commit is contained in:
Ell 2019-02-04 15:33:44 -05:00
parent de8e81f81f
commit 39e23267f7
11 changed files with 319 additions and 19 deletions

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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);

View File

@ -37,6 +37,7 @@ struct _GimpTransformGridOptions
{
GimpTransformOptions parent_instance;
gboolean direction_linked;
gboolean show_preview;
gdouble preview_opacity;
GimpGuidesType grid_type;

View File

@ -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)
{

View File

@ -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);

View File

@ -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 */

View File

@ -44,6 +44,7 @@ struct _GimpTransformOptions
/* options gui */
GtkWidget *type_box;
GtkWidget *direction_frame;
};
struct _GimpTransformOptionsClass

View File

@ -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)
{