app: improve transform-tools readjustment

In GimpTransformGridTool, extend the functionality of the
"Readjust" button, such that if the transformation is already
adjusted to the view (i.e., when the button is clicked the second
time), readjust the transformation to the item bounds (as when
using the tool "normally"), and vice versa.  This allows switching
back and forth between "normal" mode, and "adjusted-to-view" mode.

Additionally, disable readjustment when the current transforamtion
is invalid, and show an error when readjustment results in an
invalid transformation.
This commit is contained in:
Ell 2019-03-13 05:20:51 -04:00
parent 92216a635a
commit a3fa3b6181
1 changed files with 115 additions and 17 deletions

View File

@ -56,6 +56,9 @@
#include "gimp-intl.h" #include "gimp-intl.h"
#define EPSILON 1e-6
#define RESPONSE_RESET 1 #define RESPONSE_RESET 1
#define RESPONSE_READJUST 2 #define RESPONSE_READJUST 2
@ -169,6 +172,11 @@ static void gimp_transform_grid_tool_show_active_item (GimpTransformGridT
static UndoInfo * undo_info_new (void); static UndoInfo * undo_info_new (void);
static void undo_info_free (UndoInfo *info); static void undo_info_free (UndoInfo *info);
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);
G_DEFINE_TYPE (GimpTransformGridTool, gimp_transform_grid_tool, GIMP_TYPE_TRANSFORM_TOOL) G_DEFINE_TYPE (GimpTransformGridTool, gimp_transform_grid_tool, GIMP_TYPE_TRANSFORM_TOOL)
@ -857,15 +865,15 @@ gimp_transform_grid_tool_get_undo_desc (GimpTransformTool *tr_tool)
result = GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->get_undo_desc ( result = GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->get_undo_desc (
tg_tool); tg_tool);
} }
else if (! memcmp (tg_tool->trans_infos[GIMP_TRANSFORM_BACKWARD], else if (trans_info_equal (tg_tool->trans_infos[GIMP_TRANSFORM_BACKWARD],
tg_tool->init_trans_info, sizeof (TransInfo))) tg_tool->init_trans_info))
{ {
tg_tool->trans_info = tg_tool->trans_infos[GIMP_TRANSFORM_FORWARD]; tg_tool->trans_info = tg_tool->trans_infos[GIMP_TRANSFORM_FORWARD];
result = GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->get_undo_desc ( result = GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->get_undo_desc (
tg_tool); tg_tool);
} }
else if (! memcmp (tg_tool->trans_infos[GIMP_TRANSFORM_FORWARD], else if (trans_info_equal (tg_tool->trans_infos[GIMP_TRANSFORM_FORWARD],
tg_tool->init_trans_info, sizeof (TransInfo))) tg_tool->init_trans_info))
{ {
gchar *desc; gchar *desc;
@ -1236,6 +1244,7 @@ gimp_transform_grid_tool_response (GimpToolGui *gui,
{ {
GimpTool *tool = GIMP_TOOL (tg_tool); GimpTool *tool = GIMP_TOOL (tg_tool);
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tg_tool); 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); GimpTransformGridOptions *tg_options = GIMP_TRANSFORM_GRID_TOOL_GET_OPTIONS (tg_tool);
GimpDisplay *display = tool->display; GimpDisplay *display = tool->display;
@ -1265,11 +1274,19 @@ gimp_transform_grid_tool_response (GimpToolGui *gui,
break; break;
case RESPONSE_READJUST: case RESPONSE_READJUST:
if (GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->readjust) 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)
{ {
gboolean direction_linked; TransInfo old_trans_infos[2];
gboolean direction_linked;
gboolean transform_valid;
/* readjust the transformation info */ /* save the current transformation info */
memcpy (old_trans_infos, tg_tool->trans_infos,
sizeof (old_trans_infos));
/* readjust the transformation info to view */
GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->readjust (tg_tool); GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->readjust (tg_tool);
/* recalculate the tool's transformation matrix, preserving the /* recalculate the tool's transformation matrix, preserving the
@ -1280,8 +1297,63 @@ gimp_transform_grid_tool_response (GimpToolGui *gui,
gimp_transform_tool_recalc_matrix (tr_tool, display); gimp_transform_tool_recalc_matrix (tr_tool, display);
tg_options->direction_linked = direction_linked; tg_options->direction_linked = direction_linked;
/* push the new info to the undo stack */ transform_valid = tr_tool->transform_valid;
gimp_transform_grid_tool_push_internal_undo (tg_tool);
/* 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);
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_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->matrix_to_info (
tg_tool, &transform);
/* 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;
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 */
gimp_transform_grid_tool_push_internal_undo (tg_tool);
}
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"));
}
} }
break; break;
@ -1314,12 +1386,14 @@ gimp_transform_grid_tool_update_sensitivity (GimpTransformGridTool *tg_tool)
gimp_tool_gui_set_response_sensitive ( gimp_tool_gui_set_response_sensitive (
tg_tool->gui, RESPONSE_RESET, tg_tool->gui, RESPONSE_RESET,
memcmp (tg_tool->trans_infos[GIMP_TRANSFORM_FORWARD], ! (trans_info_equal (tg_tool->trans_infos[GIMP_TRANSFORM_FORWARD],
tg_tool->init_trans_info, tg_tool->init_trans_info) &&
sizeof (TransInfo)) || trans_info_equal (tg_tool->trans_infos[GIMP_TRANSFORM_BACKWARD],
memcmp (tg_tool->trans_infos[GIMP_TRANSFORM_BACKWARD], tg_tool->init_trans_info)));
tg_tool->init_trans_info,
sizeof (TransInfo))); gimp_tool_gui_set_response_sensitive (
tg_tool->gui, RESPONSE_READJUST,
tr_tool->transform_valid);
} }
static void static void
@ -1428,6 +1502,31 @@ undo_info_free (UndoInfo *info)
g_slice_free (UndoInfo, info); g_slice_free (UndoInfo, info);
} }
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]);
}
gboolean gboolean
gimp_transform_grid_tool_info_to_matrix (GimpTransformGridTool *tg_tool, gimp_transform_grid_tool_info_to_matrix (GimpTransformGridTool *tg_tool,
GimpMatrix3 *transform) GimpMatrix3 *transform)
@ -1471,8 +1570,7 @@ gimp_transform_grid_tool_push_internal_undo (GimpTransformGridTool *tg_tool)
/* push current state on the undo list and set this state as the /* push current state on the undo list and set this state as the
* current state, but avoid doing this if there were no changes * current state, but avoid doing this if there were no changes
*/ */
if (memcmp (undo_info->trans_infos, tg_tool->trans_infos, if (! trans_infos_equal (undo_info->trans_infos, tg_tool->trans_infos))
sizeof (tg_tool->trans_infos)) != 0)
{ {
GimpTransformOptions *tr_options = GIMP_TRANSFORM_TOOL_GET_OPTIONS (tg_tool); GimpTransformOptions *tr_options = GIMP_TRANSFORM_TOOL_GET_OPTIONS (tg_tool);