mirror of https://github.com/GNOME/gimp.git
Applied the transform tool UI patch from Tor Lillqvist <tml@iki.fi>.
It still has a few problems, but I guess there are easier to solve, if the patch is applied. --Sven
This commit is contained in:
parent
fb8a4ebeed
commit
844a3481ee
40
ChangeLog
40
ChangeLog
|
@ -1,3 +1,43 @@
|
|||
Thu Aug 13 22:16:42 MEST 1998 Sven Neumann <sven@gimp.org>
|
||||
|
||||
Applied the patch from Tor Lillqvist <tml@iki.fi>:
|
||||
|
||||
* app/transform_core.c app/transform_core.h: Further changes in
|
||||
the look-and-feel. Now we have a info_dialog window for each
|
||||
transformation tool, with an action and cancel button. The use of
|
||||
shift-clicking to approve the transform introduced in
|
||||
gimp-tml-980724-1 is still there. The old immediate transformation
|
||||
on button release is gone.
|
||||
|
||||
For use by the rotate tool we have a center-of-rotation point
|
||||
which is draggable. Its coordinates are kept in the TransformCore
|
||||
struct.
|
||||
|
||||
As there no longer are several related transformations done after
|
||||
each other as in the old look-and-feel, we don't need the _first_
|
||||
field in TransformUndo.
|
||||
|
||||
Added the function _transform_core_grid_density_changed_ called
|
||||
from transform_tool.c when the grid density spinbutton has been
|
||||
changed. The grid is instantaneously redrawn in the new
|
||||
density. Neat, huh?
|
||||
|
||||
* transform_tool.c transform_tool.h: More options: a toggle to
|
||||
clip the result of a perspective transform, and a spinbutton for
|
||||
the rubber-band grid density. The toggle for "new" vs. "old" UI is
|
||||
now for "corrective" vs. "traditional" paradigm.
|
||||
|
||||
* rotate_tool.c: Show also the center point coordinates in the
|
||||
info dialog. If dragging the center point, update TransformCore
|
||||
accordingly. Use the center point coordinates from TransformCore
|
||||
where appropriate.
|
||||
|
||||
* perspective_tool.c: Show the transformation matrix in the info
|
||||
dialog.
|
||||
|
||||
* undo.c: TransformUndo no longed has the _first_ field, code
|
||||
simplified thusly.
|
||||
|
||||
Thu Aug 13 20:48:48 MEST 1998 Sven Neumann <sven@gimp.org>
|
||||
|
||||
* app/color_area.c: Add event-masks so the tooltip is shown.
|
||||
|
|
|
@ -937,21 +937,17 @@ undo_pop_transform (GImage *gimage,
|
|||
tc->trans_info[i] = d;
|
||||
}
|
||||
|
||||
/* if this is the first transform in a string, swap the
|
||||
* original buffer--the source buffer for repeated transforms
|
||||
/* swap the original buffer--the source buffer for repeated transforms
|
||||
*/
|
||||
if (tu->first)
|
||||
{
|
||||
temp = tu->original;
|
||||
tu->original = tc->original;
|
||||
tc->original = temp;
|
||||
temp = tu->original;
|
||||
tu->original = tc->original;
|
||||
tc->original = temp;
|
||||
|
||||
/* If we're re-implementing the first transform, reactivate tool */
|
||||
if (state == REDO && tc->original)
|
||||
{
|
||||
active_tool->state = ACTIVE;
|
||||
draw_core_resume (tc->core, active_tool);
|
||||
}
|
||||
/* If we're re-implementing the first transform, reactivate tool */
|
||||
if (state == REDO && tc->original)
|
||||
{
|
||||
active_tool->state = ACTIVE;
|
||||
draw_core_resume (tc->core, active_tool);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "appenv.h"
|
||||
#include "drawable.h"
|
||||
#include "gdisplay.h"
|
||||
|
@ -40,9 +41,7 @@
|
|||
#define Y3 7
|
||||
|
||||
/* storage for information dialog fields */
|
||||
char matrix_row1_buf [256];
|
||||
char matrix_row2_buf [256];
|
||||
char matrix_row3_buf [256];
|
||||
static char matrix_row_buf [3][MAX_INFO_BUF];
|
||||
|
||||
/* forward function declarations */
|
||||
static void * perspective_tool_perspective (GImage *, GimpDrawable *, TileManager *, int, Matrix);
|
||||
|
@ -67,7 +66,16 @@ perspective_tool_transform (tool, gdisp_ptr, state)
|
|||
switch (state)
|
||||
{
|
||||
case INIT :
|
||||
transform_info = NULL;
|
||||
if (!transform_info)
|
||||
{
|
||||
transform_info = info_dialog_new ("Perspective Transform Information");
|
||||
info_dialog_add_field (transform_info, "Matrix: ",
|
||||
matrix_row_buf[0]);
|
||||
info_dialog_add_field (transform_info, " ",
|
||||
matrix_row_buf[1]);
|
||||
info_dialog_add_field (transform_info, " ",
|
||||
matrix_row_buf[2]);
|
||||
}
|
||||
|
||||
transform_core->trans_info [X0] = (double) transform_core->x1;
|
||||
transform_core->trans_info [Y0] = (double) transform_core->y1;
|
||||
|
@ -143,6 +151,25 @@ static void
|
|||
perspective_info_update (tool)
|
||||
Tool * tool;
|
||||
{
|
||||
TransformCore * transform_core;
|
||||
int i;
|
||||
|
||||
transform_core = (TransformCore *) tool->private;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
char *p = matrix_row_buf[i];
|
||||
int j;
|
||||
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
p += sprintf (p, "%10.3g", transform_core->transform[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
info_dialog_update (transform_info);
|
||||
info_dialog_popup (transform_info);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,11 +40,16 @@
|
|||
/* index into trans_info array */
|
||||
#define ANGLE 0
|
||||
#define REAL_ANGLE 1
|
||||
#define CENTER_X 2
|
||||
#define CENTER_Y 3
|
||||
|
||||
#define EPSILON 0.018 /* ~ 1 degree */
|
||||
#define FIFTEEN_DEG (M_PI / 12.0)
|
||||
|
||||
/* variables local to this file */
|
||||
char angle_buf [MAX_INFO_BUF];
|
||||
static char angle_buf [MAX_INFO_BUF];
|
||||
static char center_x_buf [MAX_INFO_BUF];
|
||||
static char center_y_buf [MAX_INFO_BUF];
|
||||
|
||||
/* forward function declarations */
|
||||
static void * rotate_tool_rotate (GImage *, GimpDrawable *, double, TileManager *, int, Matrix);
|
||||
|
@ -72,10 +77,16 @@ rotate_tool_transform (tool, gdisp_ptr, state)
|
|||
{
|
||||
transform_info = info_dialog_new ("Rotation Information");
|
||||
info_dialog_add_field (transform_info, "Angle: ", angle_buf);
|
||||
info_dialog_add_field (transform_info, "Center X: ", center_x_buf);
|
||||
info_dialog_add_field (transform_info, "Center Y: ", center_y_buf);
|
||||
}
|
||||
|
||||
transform_core->trans_info[ANGLE] = 0.0;
|
||||
transform_core->trans_info[REAL_ANGLE] = 0.0;
|
||||
transform_core->trans_info[CENTER_X] =
|
||||
(transform_core->x1 + transform_core->x2) / 2;
|
||||
transform_core->trans_info[CENTER_Y] =
|
||||
(transform_core->y1 + transform_core->y2) / 2;
|
||||
|
||||
return NULL;
|
||||
break;
|
||||
|
@ -114,6 +125,8 @@ tools_new_rotate_tool ()
|
|||
private->trans_func = rotate_tool_transform;
|
||||
private->trans_info[ANGLE] = 0.0;
|
||||
private->trans_info[REAL_ANGLE] = 0.0;
|
||||
private->trans_info[CENTER_X] = (private->x1 + private->x2) / 2;
|
||||
private->trans_info[CENTER_Y] = (private->y1 + private->y2) / 2;
|
||||
|
||||
/* assemble the transformation matrix */
|
||||
identity_matrix (private->transform);
|
||||
|
@ -135,13 +148,18 @@ rotate_info_update (tool)
|
|||
GDisplay * gdisp;
|
||||
TransformCore * transform_core;
|
||||
double angle;
|
||||
int cx, cy;
|
||||
|
||||
gdisp = (GDisplay *) tool->gdisp_ptr;
|
||||
transform_core = (TransformCore *) tool->private;
|
||||
|
||||
angle = (transform_core->trans_info[ANGLE] * 180.0) / M_PI;
|
||||
cx = transform_core->cx;
|
||||
cy = transform_core->cy;
|
||||
|
||||
sprintf (angle_buf, "%0.2f", angle);
|
||||
sprintf (center_x_buf, "%d", cx);
|
||||
sprintf (center_y_buf, "%d", cy);
|
||||
|
||||
info_dialog_update (transform_info);
|
||||
info_dialog_popup (transform_info);
|
||||
|
@ -159,8 +177,16 @@ rotate_tool_motion (tool, gdisp_ptr)
|
|||
|
||||
transform_core = (TransformCore *) tool->private;
|
||||
|
||||
cx = (transform_core->x1 + transform_core->x2) / 2.0;
|
||||
cy = (transform_core->y1 + transform_core->y2) / 2.0;
|
||||
if (transform_core->function == HANDLE_CENTER)
|
||||
{
|
||||
transform_core->cx = transform_core->curx;
|
||||
transform_core->cy = transform_core->cury;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
cx = transform_core->cx;
|
||||
cy = transform_core->cy;
|
||||
|
||||
x1 = transform_core->curx - cx;
|
||||
x2 = transform_core->lastx - cx;
|
||||
|
@ -209,8 +235,8 @@ rotate_tool_recalc (tool, gdisp_ptr)
|
|||
gdisp = (GDisplay *) tool->gdisp_ptr;
|
||||
transform_core = (TransformCore *) tool->private;
|
||||
|
||||
cx = (transform_core->x1 + transform_core->x2) / 2.0;
|
||||
cy = (transform_core->y1 + transform_core->y2) / 2.0;
|
||||
cx = transform_core->cx;
|
||||
cy = transform_core->cy;
|
||||
|
||||
/* assemble the transformation matrix */
|
||||
identity_matrix (transform_core->transform);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "appenv.h"
|
||||
#include "drawable.h"
|
||||
#include "gdisplay.h"
|
||||
|
@ -40,9 +41,7 @@
|
|||
#define Y3 7
|
||||
|
||||
/* storage for information dialog fields */
|
||||
char matrix_row1_buf [256];
|
||||
char matrix_row2_buf [256];
|
||||
char matrix_row3_buf [256];
|
||||
static char matrix_row_buf [3][MAX_INFO_BUF];
|
||||
|
||||
/* forward function declarations */
|
||||
static void * perspective_tool_perspective (GImage *, GimpDrawable *, TileManager *, int, Matrix);
|
||||
|
@ -67,7 +66,16 @@ perspective_tool_transform (tool, gdisp_ptr, state)
|
|||
switch (state)
|
||||
{
|
||||
case INIT :
|
||||
transform_info = NULL;
|
||||
if (!transform_info)
|
||||
{
|
||||
transform_info = info_dialog_new ("Perspective Transform Information");
|
||||
info_dialog_add_field (transform_info, "Matrix: ",
|
||||
matrix_row_buf[0]);
|
||||
info_dialog_add_field (transform_info, " ",
|
||||
matrix_row_buf[1]);
|
||||
info_dialog_add_field (transform_info, " ",
|
||||
matrix_row_buf[2]);
|
||||
}
|
||||
|
||||
transform_core->trans_info [X0] = (double) transform_core->x1;
|
||||
transform_core->trans_info [Y0] = (double) transform_core->y1;
|
||||
|
@ -143,6 +151,25 @@ static void
|
|||
perspective_info_update (tool)
|
||||
Tool * tool;
|
||||
{
|
||||
TransformCore * transform_core;
|
||||
int i;
|
||||
|
||||
transform_core = (TransformCore *) tool->private;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
char *p = matrix_row_buf[i];
|
||||
int j;
|
||||
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
p += sprintf (p, "%10.3g", transform_core->transform[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
info_dialog_update (transform_info);
|
||||
info_dialog_popup (transform_info);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,11 +40,16 @@
|
|||
/* index into trans_info array */
|
||||
#define ANGLE 0
|
||||
#define REAL_ANGLE 1
|
||||
#define CENTER_X 2
|
||||
#define CENTER_Y 3
|
||||
|
||||
#define EPSILON 0.018 /* ~ 1 degree */
|
||||
#define FIFTEEN_DEG (M_PI / 12.0)
|
||||
|
||||
/* variables local to this file */
|
||||
char angle_buf [MAX_INFO_BUF];
|
||||
static char angle_buf [MAX_INFO_BUF];
|
||||
static char center_x_buf [MAX_INFO_BUF];
|
||||
static char center_y_buf [MAX_INFO_BUF];
|
||||
|
||||
/* forward function declarations */
|
||||
static void * rotate_tool_rotate (GImage *, GimpDrawable *, double, TileManager *, int, Matrix);
|
||||
|
@ -72,10 +77,16 @@ rotate_tool_transform (tool, gdisp_ptr, state)
|
|||
{
|
||||
transform_info = info_dialog_new ("Rotation Information");
|
||||
info_dialog_add_field (transform_info, "Angle: ", angle_buf);
|
||||
info_dialog_add_field (transform_info, "Center X: ", center_x_buf);
|
||||
info_dialog_add_field (transform_info, "Center Y: ", center_y_buf);
|
||||
}
|
||||
|
||||
transform_core->trans_info[ANGLE] = 0.0;
|
||||
transform_core->trans_info[REAL_ANGLE] = 0.0;
|
||||
transform_core->trans_info[CENTER_X] =
|
||||
(transform_core->x1 + transform_core->x2) / 2;
|
||||
transform_core->trans_info[CENTER_Y] =
|
||||
(transform_core->y1 + transform_core->y2) / 2;
|
||||
|
||||
return NULL;
|
||||
break;
|
||||
|
@ -114,6 +125,8 @@ tools_new_rotate_tool ()
|
|||
private->trans_func = rotate_tool_transform;
|
||||
private->trans_info[ANGLE] = 0.0;
|
||||
private->trans_info[REAL_ANGLE] = 0.0;
|
||||
private->trans_info[CENTER_X] = (private->x1 + private->x2) / 2;
|
||||
private->trans_info[CENTER_Y] = (private->y1 + private->y2) / 2;
|
||||
|
||||
/* assemble the transformation matrix */
|
||||
identity_matrix (private->transform);
|
||||
|
@ -135,13 +148,18 @@ rotate_info_update (tool)
|
|||
GDisplay * gdisp;
|
||||
TransformCore * transform_core;
|
||||
double angle;
|
||||
int cx, cy;
|
||||
|
||||
gdisp = (GDisplay *) tool->gdisp_ptr;
|
||||
transform_core = (TransformCore *) tool->private;
|
||||
|
||||
angle = (transform_core->trans_info[ANGLE] * 180.0) / M_PI;
|
||||
cx = transform_core->cx;
|
||||
cy = transform_core->cy;
|
||||
|
||||
sprintf (angle_buf, "%0.2f", angle);
|
||||
sprintf (center_x_buf, "%d", cx);
|
||||
sprintf (center_y_buf, "%d", cy);
|
||||
|
||||
info_dialog_update (transform_info);
|
||||
info_dialog_popup (transform_info);
|
||||
|
@ -159,8 +177,16 @@ rotate_tool_motion (tool, gdisp_ptr)
|
|||
|
||||
transform_core = (TransformCore *) tool->private;
|
||||
|
||||
cx = (transform_core->x1 + transform_core->x2) / 2.0;
|
||||
cy = (transform_core->y1 + transform_core->y2) / 2.0;
|
||||
if (transform_core->function == HANDLE_CENTER)
|
||||
{
|
||||
transform_core->cx = transform_core->curx;
|
||||
transform_core->cy = transform_core->cury;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
cx = transform_core->cx;
|
||||
cy = transform_core->cy;
|
||||
|
||||
x1 = transform_core->curx - cx;
|
||||
x2 = transform_core->lastx - cx;
|
||||
|
@ -209,8 +235,8 @@ rotate_tool_recalc (tool, gdisp_ptr)
|
|||
gdisp = (GDisplay *) tool->gdisp_ptr;
|
||||
transform_core = (TransformCore *) tool->private;
|
||||
|
||||
cx = (transform_core->x1 + transform_core->x2) / 2.0;
|
||||
cy = (transform_core->y1 + transform_core->y2) / 2.0;
|
||||
cx = transform_core->cx;
|
||||
cy = transform_core->cy;
|
||||
|
||||
/* assemble the transformation matrix */
|
||||
identity_matrix (transform_core->transform);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "appenv.h"
|
||||
#include "drawable.h"
|
||||
#include "gdisplay.h"
|
||||
|
@ -40,9 +41,7 @@
|
|||
#define Y3 7
|
||||
|
||||
/* storage for information dialog fields */
|
||||
char matrix_row1_buf [256];
|
||||
char matrix_row2_buf [256];
|
||||
char matrix_row3_buf [256];
|
||||
static char matrix_row_buf [3][MAX_INFO_BUF];
|
||||
|
||||
/* forward function declarations */
|
||||
static void * perspective_tool_perspective (GImage *, GimpDrawable *, TileManager *, int, Matrix);
|
||||
|
@ -67,7 +66,16 @@ perspective_tool_transform (tool, gdisp_ptr, state)
|
|||
switch (state)
|
||||
{
|
||||
case INIT :
|
||||
transform_info = NULL;
|
||||
if (!transform_info)
|
||||
{
|
||||
transform_info = info_dialog_new ("Perspective Transform Information");
|
||||
info_dialog_add_field (transform_info, "Matrix: ",
|
||||
matrix_row_buf[0]);
|
||||
info_dialog_add_field (transform_info, " ",
|
||||
matrix_row_buf[1]);
|
||||
info_dialog_add_field (transform_info, " ",
|
||||
matrix_row_buf[2]);
|
||||
}
|
||||
|
||||
transform_core->trans_info [X0] = (double) transform_core->x1;
|
||||
transform_core->trans_info [Y0] = (double) transform_core->y1;
|
||||
|
@ -143,6 +151,25 @@ static void
|
|||
perspective_info_update (tool)
|
||||
Tool * tool;
|
||||
{
|
||||
TransformCore * transform_core;
|
||||
int i;
|
||||
|
||||
transform_core = (TransformCore *) tool->private;
|
||||
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
char *p = matrix_row_buf[i];
|
||||
int j;
|
||||
|
||||
for (j = 0; j < 3; j++)
|
||||
{
|
||||
p += sprintf (p, "%10.3g", transform_core->transform[i][j]);
|
||||
}
|
||||
}
|
||||
|
||||
info_dialog_update (transform_info);
|
||||
info_dialog_popup (transform_info);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,11 +40,16 @@
|
|||
/* index into trans_info array */
|
||||
#define ANGLE 0
|
||||
#define REAL_ANGLE 1
|
||||
#define CENTER_X 2
|
||||
#define CENTER_Y 3
|
||||
|
||||
#define EPSILON 0.018 /* ~ 1 degree */
|
||||
#define FIFTEEN_DEG (M_PI / 12.0)
|
||||
|
||||
/* variables local to this file */
|
||||
char angle_buf [MAX_INFO_BUF];
|
||||
static char angle_buf [MAX_INFO_BUF];
|
||||
static char center_x_buf [MAX_INFO_BUF];
|
||||
static char center_y_buf [MAX_INFO_BUF];
|
||||
|
||||
/* forward function declarations */
|
||||
static void * rotate_tool_rotate (GImage *, GimpDrawable *, double, TileManager *, int, Matrix);
|
||||
|
@ -72,10 +77,16 @@ rotate_tool_transform (tool, gdisp_ptr, state)
|
|||
{
|
||||
transform_info = info_dialog_new ("Rotation Information");
|
||||
info_dialog_add_field (transform_info, "Angle: ", angle_buf);
|
||||
info_dialog_add_field (transform_info, "Center X: ", center_x_buf);
|
||||
info_dialog_add_field (transform_info, "Center Y: ", center_y_buf);
|
||||
}
|
||||
|
||||
transform_core->trans_info[ANGLE] = 0.0;
|
||||
transform_core->trans_info[REAL_ANGLE] = 0.0;
|
||||
transform_core->trans_info[CENTER_X] =
|
||||
(transform_core->x1 + transform_core->x2) / 2;
|
||||
transform_core->trans_info[CENTER_Y] =
|
||||
(transform_core->y1 + transform_core->y2) / 2;
|
||||
|
||||
return NULL;
|
||||
break;
|
||||
|
@ -114,6 +125,8 @@ tools_new_rotate_tool ()
|
|||
private->trans_func = rotate_tool_transform;
|
||||
private->trans_info[ANGLE] = 0.0;
|
||||
private->trans_info[REAL_ANGLE] = 0.0;
|
||||
private->trans_info[CENTER_X] = (private->x1 + private->x2) / 2;
|
||||
private->trans_info[CENTER_Y] = (private->y1 + private->y2) / 2;
|
||||
|
||||
/* assemble the transformation matrix */
|
||||
identity_matrix (private->transform);
|
||||
|
@ -135,13 +148,18 @@ rotate_info_update (tool)
|
|||
GDisplay * gdisp;
|
||||
TransformCore * transform_core;
|
||||
double angle;
|
||||
int cx, cy;
|
||||
|
||||
gdisp = (GDisplay *) tool->gdisp_ptr;
|
||||
transform_core = (TransformCore *) tool->private;
|
||||
|
||||
angle = (transform_core->trans_info[ANGLE] * 180.0) / M_PI;
|
||||
cx = transform_core->cx;
|
||||
cy = transform_core->cy;
|
||||
|
||||
sprintf (angle_buf, "%0.2f", angle);
|
||||
sprintf (center_x_buf, "%d", cx);
|
||||
sprintf (center_y_buf, "%d", cy);
|
||||
|
||||
info_dialog_update (transform_info);
|
||||
info_dialog_popup (transform_info);
|
||||
|
@ -159,8 +177,16 @@ rotate_tool_motion (tool, gdisp_ptr)
|
|||
|
||||
transform_core = (TransformCore *) tool->private;
|
||||
|
||||
cx = (transform_core->x1 + transform_core->x2) / 2.0;
|
||||
cy = (transform_core->y1 + transform_core->y2) / 2.0;
|
||||
if (transform_core->function == HANDLE_CENTER)
|
||||
{
|
||||
transform_core->cx = transform_core->curx;
|
||||
transform_core->cy = transform_core->cury;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
cx = transform_core->cx;
|
||||
cy = transform_core->cy;
|
||||
|
||||
x1 = transform_core->curx - cx;
|
||||
x2 = transform_core->lastx - cx;
|
||||
|
@ -209,8 +235,8 @@ rotate_tool_recalc (tool, gdisp_ptr)
|
|||
gdisp = (GDisplay *) tool->gdisp_ptr;
|
||||
transform_core = (TransformCore *) tool->private;
|
||||
|
||||
cx = (transform_core->x1 + transform_core->x2) / 2.0;
|
||||
cy = (transform_core->y1 + transform_core->y2) / 2.0;
|
||||
cx = transform_core->cx;
|
||||
cy = transform_core->cy;
|
||||
|
||||
/* assemble the transformation matrix */
|
||||
identity_matrix (transform_core->transform);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "appenv.h"
|
||||
#include "actionarea.h"
|
||||
#include "drawable.h"
|
||||
#include "errors.h"
|
||||
#include "floating_sel.h"
|
||||
|
@ -48,7 +49,6 @@
|
|||
|
||||
/* variables */
|
||||
static TranInfo old_trans_info;
|
||||
static int new_ui;
|
||||
InfoDialog * transform_info = NULL;
|
||||
|
||||
/* forward function declarations */
|
||||
|
@ -68,6 +68,52 @@ static void invert (Matrix, Matrix);
|
|||
src[i] = tile_data_pointer (tile[i], (x) % TILE_WIDTH, (y) % TILE_HEIGHT);
|
||||
|
||||
|
||||
static void
|
||||
transform_ok_callback (GtkWidget *w,
|
||||
gpointer client_data)
|
||||
{
|
||||
Tool *tool;
|
||||
|
||||
tool = (Tool *) client_data;
|
||||
transform_core_doit (tool, tool->gdisp_ptr);
|
||||
}
|
||||
|
||||
static void
|
||||
transform_cancel_callback (GtkWidget *w,
|
||||
gpointer client_data)
|
||||
{
|
||||
Tool *tool;
|
||||
TransformCore *transform_core;
|
||||
int i;
|
||||
|
||||
tool = (Tool *) client_data;
|
||||
transform_core = (TransformCore *) tool->private;
|
||||
|
||||
/* stop the current tool drawing process */
|
||||
draw_core_pause (transform_core->core, tool);
|
||||
|
||||
/* Restore the previous transformation info */
|
||||
for (i = 0; i < TRAN_INFO_SIZE; i++)
|
||||
transform_core->trans_info [i] = old_trans_info [i];
|
||||
/* recalculate the tool's transformation matrix */
|
||||
transform_core_recalc (tool, tool->gdisp_ptr);
|
||||
|
||||
/* resume drawing the current tool */
|
||||
draw_core_resume (transform_core->core, tool);
|
||||
}
|
||||
|
||||
|
||||
static ActionAreaItem action_items[2] =
|
||||
{
|
||||
{ NULL, transform_ok_callback, NULL, NULL },
|
||||
{ "Cancel", transform_cancel_callback, NULL, NULL },
|
||||
};
|
||||
|
||||
static char *action_labels[4] =
|
||||
{
|
||||
"Rotate", "Scale", "Shear", "Transform"
|
||||
};
|
||||
|
||||
void
|
||||
transform_core_button_press (tool, bevent, gdisp_ptr)
|
||||
Tool *tool;
|
||||
|
@ -90,7 +136,7 @@ transform_core_button_press (tool, bevent, gdisp_ptr)
|
|||
|
||||
tool->drawable = gimage_active_drawable (gdisp->gimage);
|
||||
|
||||
if (transform_core->function == CREATING)
|
||||
if (transform_core->function == CREATING && tool->state == ACTIVE)
|
||||
{
|
||||
/* Save the current transformation info */
|
||||
for (i = 0; i < TRAN_INFO_SIZE; i++)
|
||||
|
@ -105,6 +151,9 @@ transform_core_button_press (tool, bevent, gdisp_ptr)
|
|||
if ((transform_core->function >= CREATING) && (gdisp_ptr == tool->gdisp_ptr) &&
|
||||
transform_core->interactive)
|
||||
{
|
||||
/* start drawing the bounding box and handles... */
|
||||
draw_core_start (transform_core->core, gdisp->canvas->window, tool);
|
||||
|
||||
x = bevent->x;
|
||||
y = bevent->y;
|
||||
|
||||
|
@ -132,6 +181,13 @@ transform_core_button_press (tool, bevent, gdisp_ptr)
|
|||
transform_core->function = HANDLE_4;
|
||||
}
|
||||
|
||||
if (tool->type == ROTATE
|
||||
&& (SQR (x - transform_core->scx) +
|
||||
SQR (y - transform_core->scy)) <= 100)
|
||||
{
|
||||
transform_core->function = HANDLE_CENTER;
|
||||
}
|
||||
|
||||
/* Save the current pointer position */
|
||||
gdisplay_untransform_coords (gdisp, bevent->x, bevent->y,
|
||||
&transform_core->startx,
|
||||
|
@ -143,10 +199,6 @@ transform_core_button_press (tool, bevent, gdisp_ptr)
|
|||
GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
|
||||
NULL, NULL, bevent->time);
|
||||
|
||||
/* start drawing the bounding box and handles... */
|
||||
if (new_ui)
|
||||
draw_core_start (transform_core->core, gdisp->canvas->window, tool);
|
||||
|
||||
tool->state = ACTIVE;
|
||||
return;
|
||||
}
|
||||
|
@ -192,20 +244,24 @@ transform_core_button_press (tool, bevent, gdisp_ptr)
|
|||
*/
|
||||
transform_core_bounds (tool, gdisp_ptr);
|
||||
|
||||
/* If new UI, calculate the grid line endpoints */
|
||||
if (new_ui)
|
||||
transform_core_setup_grid (tool);
|
||||
/* Calculate the grid line endpoints */
|
||||
transform_core_setup_grid (tool);
|
||||
|
||||
/* Initialize the transform tool */
|
||||
(* transform_core->trans_func) (tool, gdisp_ptr, INIT);
|
||||
|
||||
if (transform_info != NULL)
|
||||
{
|
||||
action_items[0].label = action_labels[tool->type - ROTATE];
|
||||
action_items[0].user_data = tool;
|
||||
action_items[1].user_data = tool;
|
||||
build_action_area (GTK_DIALOG (transform_info->shell),
|
||||
action_items, 2, 0);
|
||||
}
|
||||
|
||||
/* Recalculate the transform tool */
|
||||
transform_core_recalc (tool, gdisp_ptr);
|
||||
|
||||
/* start drawing the bounding box and handles... */
|
||||
if (!new_ui)
|
||||
draw_core_start (transform_core->core, gdisp->canvas->window, tool);
|
||||
|
||||
/* recall this function to find which handle we're dragging */
|
||||
if (transform_core->interactive)
|
||||
transform_core_button_press (tool, bevent, gdisp_ptr);
|
||||
|
@ -239,23 +295,16 @@ transform_core_button_release (tool, bevent, gdisp_ptr)
|
|||
/* if the 3rd button isn't pressed, transform the selected mask */
|
||||
if (! (bevent->state & GDK_BUTTON3_MASK))
|
||||
{
|
||||
if (new_ui)
|
||||
/* Shift-clicking is another way to approve the transform */
|
||||
if ((bevent->state & GDK_SHIFT_MASK)
|
||||
|| (tool->type == FLIP_HORZ)
|
||||
|| (tool->type == FLIP_VERT))
|
||||
{
|
||||
/* In the new UI, shift-clicking means perform the transform */
|
||||
if ((bevent->state & GDK_SHIFT_MASK)
|
||||
|| (tool->type == FLIP_HORZ)
|
||||
|| (tool->type == FLIP_VERT))
|
||||
{
|
||||
transform_core_doit (tool, gdisp_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Do nothing, keep the grid visible */
|
||||
}
|
||||
transform_core_doit (tool, gdisp_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
transform_core_doit (tool, gdisp_ptr);
|
||||
/* Do nothing, keep the grid visible */
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -266,7 +315,6 @@ transform_core_button_release (tool, bevent, gdisp_ptr)
|
|||
/* Restore the previous transformation info */
|
||||
for (i = 0; i < TRAN_INFO_SIZE; i++)
|
||||
transform_core->trans_info [i] = old_trans_info [i];
|
||||
|
||||
/* recalculate the tool's transformation matrix */
|
||||
transform_core_recalc (tool, gdisp_ptr);
|
||||
|
||||
|
@ -288,7 +336,6 @@ transform_core_doit (tool, gdisp_ptr)
|
|||
TransformCore *transform_core;
|
||||
TileManager *new_tiles;
|
||||
TransformUndo *tu;
|
||||
int first_transform;
|
||||
int new_layer;
|
||||
int i, x, y;
|
||||
|
||||
|
@ -304,35 +351,25 @@ transform_core_doit (tool, gdisp_ptr)
|
|||
/* Start a transform undo group */
|
||||
undo_push_group_start (gdisp->gimage, TRANSFORM_CORE_UNDO);
|
||||
|
||||
/* If original is NULL, then this is the first transformation */
|
||||
first_transform = (transform_core->original) ? FALSE : TRUE;
|
||||
/* With the old UI, if original is NULL, then this is the
|
||||
first transformation. In the new UI, it is always so, yes? */
|
||||
g_assert (transform_core->original == NULL);
|
||||
|
||||
/* If we're in interactive mode, and haven't yet done any
|
||||
* transformations, we need to copy the current selection to
|
||||
* the transform tool's private selection pointer, so that the
|
||||
* original source can be repeatedly modified.
|
||||
/* If we're in interactive mode, we need to copy the current
|
||||
* selection to the transform tool's private selection pointer, so
|
||||
* that the original source can be repeatedly modified.
|
||||
*/
|
||||
if (first_transform)
|
||||
transform_core->original = transform_core_cut (gdisp->gimage,
|
||||
gimage_active_drawable (gdisp->gimage),
|
||||
&new_layer);
|
||||
else
|
||||
new_layer = FALSE;
|
||||
transform_core->original = transform_core_cut (gdisp->gimage,
|
||||
gimage_active_drawable (gdisp->gimage),
|
||||
&new_layer);
|
||||
|
||||
/* Send the request for the transformation to the tool...
|
||||
*/
|
||||
new_tiles = (* transform_core->trans_func) (tool, gdisp_ptr, FINISH);
|
||||
|
||||
/* If new UI, reset the transformation */
|
||||
if (new_ui)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < TRAN_INFO_SIZE; i++)
|
||||
transform_core->trans_info [i] = 0;
|
||||
|
||||
transform_core_recalc (tool, gdisp_ptr);
|
||||
}
|
||||
(* transform_core->trans_func) (tool, gdisp_ptr, INIT);
|
||||
|
||||
transform_core_recalc (tool, gdisp_ptr);
|
||||
|
||||
if (new_tiles)
|
||||
{
|
||||
|
@ -348,7 +385,6 @@ transform_core_doit (tool, gdisp_ptr)
|
|||
tu->tool_type = tool->type;
|
||||
for (i = 0; i < TRAN_INFO_SIZE; i++)
|
||||
tu->trans_info[i] = old_trans_info[i];
|
||||
tu->first = first_transform;
|
||||
tu->original = NULL;
|
||||
|
||||
/* Make a note of the new current drawable (since we may have
|
||||
|
@ -389,10 +425,7 @@ transform_core_doit (tool, gdisp_ptr)
|
|||
}
|
||||
gdisplays_flush ();
|
||||
|
||||
if (new_ui)
|
||||
{
|
||||
transform_core_reset (tool, gdisp_ptr);
|
||||
}
|
||||
transform_core_reset (tool, gdisp_ptr);
|
||||
|
||||
/* if this tool is non-interactive, make it inactive after use */
|
||||
if (!transform_core->interactive)
|
||||
|
@ -534,6 +567,8 @@ transform_core_draw (tool)
|
|||
TransformCore * transform_core;
|
||||
GDisplay * gdisp;
|
||||
int srw, srh;
|
||||
int i, k, gci;
|
||||
int xa, ya, xb, yb;
|
||||
|
||||
gdisp = tool->gdisp_ptr;
|
||||
transform_core = (TransformCore *) tool->private;
|
||||
|
@ -566,27 +601,22 @@ transform_core_draw (tool)
|
|||
gdk_draw_line (transform_core->core->win, transform_core->core->gc,
|
||||
x3, y3, x1, y1);
|
||||
|
||||
/* if new UI, draw the grid */
|
||||
if (new_ui)
|
||||
{
|
||||
int i, k, gci;
|
||||
int xa, ya, xb, yb;
|
||||
/* Draw the grid */
|
||||
|
||||
gci = 0;
|
||||
k = transform_core->ngx + transform_core->ngy;
|
||||
for (i = 0; i < k; i++)
|
||||
{
|
||||
gdisplay_transform_coords (gdisp, transform_core->tgrid_coords[gci],
|
||||
transform_core->tgrid_coords[gci+1],
|
||||
&xa, &ya, 0);
|
||||
gdisplay_transform_coords (gdisp, transform_core->tgrid_coords[gci+2],
|
||||
transform_core->tgrid_coords[gci+3],
|
||||
&xb, &yb, 0);
|
||||
|
||||
gdk_draw_line (transform_core->core->win, transform_core->core->gc,
|
||||
xa, ya, xb, yb);
|
||||
gci += 4;
|
||||
}
|
||||
gci = 0;
|
||||
k = transform_core->ngx + transform_core->ngy;
|
||||
for (i = 0; i < k; i++)
|
||||
{
|
||||
gdisplay_transform_coords (gdisp, transform_core->tgrid_coords[gci],
|
||||
transform_core->tgrid_coords[gci+1],
|
||||
&xa, &ya, 0);
|
||||
gdisplay_transform_coords (gdisp, transform_core->tgrid_coords[gci+2],
|
||||
transform_core->tgrid_coords[gci+3],
|
||||
&xb, &yb, 0);
|
||||
|
||||
gdk_draw_line (transform_core->core->win, transform_core->core->gc,
|
||||
xa, ya, xb, yb);
|
||||
gci += 4;
|
||||
}
|
||||
|
||||
/* draw the tool handles */
|
||||
|
@ -598,6 +628,18 @@ transform_core_draw (tool)
|
|||
x3 - (srw >> 1), y3 - (srh >> 1), srw, srh);
|
||||
gdk_draw_rectangle (transform_core->core->win, transform_core->core->gc, 0,
|
||||
x4 - (srw >> 1), y4 - (srh >> 1), srw, srh);
|
||||
|
||||
/* draw the center */
|
||||
if (tool->type == ROTATE)
|
||||
{
|
||||
gdisplay_transform_coords (gdisp, transform_core->tcx, transform_core->tcy,
|
||||
&transform_core->scx, &transform_core->scy, 0);
|
||||
|
||||
gdk_draw_arc (transform_core->core->win, transform_core->core->gc, 1,
|
||||
transform_core->scx - (srw >> 1),
|
||||
transform_core->scy - (srh >> 1),
|
||||
srw, srh, 0, 23040);
|
||||
}
|
||||
}
|
||||
|
||||
Tool *
|
||||
|
@ -629,15 +671,6 @@ transform_core_new (type, interactive)
|
|||
|
||||
private->grid_coords = private->tgrid_coords = NULL;
|
||||
|
||||
/* We must save this setting so that the user won't screw us if he
|
||||
* changes the UI to "old" style in the middle of a "new" UI operation.
|
||||
* We can't keep this info in the transform_core, as it is needed
|
||||
* in transform_core_do, which doesn't have access to any TransformCore.
|
||||
* I hope it's OK to use a static variable... (there already is
|
||||
* old_trans_info, so?).
|
||||
*/
|
||||
new_ui = transform_tool_new_ui ();
|
||||
|
||||
tool->type = type;
|
||||
tool->state = INACTIVE;
|
||||
tool->scroll_lock = 1; /* Do not allow scrolling */
|
||||
|
@ -693,6 +726,8 @@ transform_bounding_box (tool)
|
|||
Tool * tool;
|
||||
{
|
||||
TransformCore * transform_core;
|
||||
int i, k;
|
||||
int gci;
|
||||
|
||||
transform_core = (TransformCore *) tool->private;
|
||||
|
||||
|
@ -709,22 +744,21 @@ transform_bounding_box (tool)
|
|||
transform_core->x2, transform_core->y2,
|
||||
&transform_core->tx4, &transform_core->ty4);
|
||||
|
||||
if (new_ui)
|
||||
if (tool->type == ROTATE)
|
||||
transform_point (transform_core->transform,
|
||||
transform_core->cx, transform_core->cy,
|
||||
&transform_core->tcx, &transform_core->tcy);
|
||||
|
||||
gci = 0;
|
||||
k = (transform_core->ngx + transform_core->ngy) * 2;
|
||||
for (i = 0; i < k; i++)
|
||||
{
|
||||
int i, k;
|
||||
int gci;
|
||||
|
||||
gci = 0;
|
||||
k = (transform_core->ngx + transform_core->ngy) * 2;
|
||||
for (i = 0; i < k; i++)
|
||||
{
|
||||
transform_point (transform_core->transform,
|
||||
transform_core->grid_coords[gci],
|
||||
transform_core->grid_coords[gci+1],
|
||||
&(transform_core->tgrid_coords[gci]),
|
||||
&(transform_core->tgrid_coords[gci+1]));
|
||||
gci += 2;
|
||||
}
|
||||
transform_point (transform_core->transform,
|
||||
transform_core->grid_coords[gci],
|
||||
transform_core->grid_coords[gci+1],
|
||||
&(transform_core->tgrid_coords[gci]),
|
||||
&(transform_core->tgrid_coords[gci+1]));
|
||||
gci += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -973,10 +1007,26 @@ transform_core_bounds (tool, gdisp_ptr)
|
|||
transform_core->x2 += offset_x;
|
||||
transform_core->y2 += offset_y;
|
||||
}
|
||||
transform_core->cx = (transform_core->x1 + transform_core->x2) / 2;
|
||||
transform_core->cy = (transform_core->y1 + transform_core->y2) / 2;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
transform_core_grid_density_changed ()
|
||||
{
|
||||
TransformCore * transform_core;
|
||||
|
||||
transform_core = (TransformCore *) active_tool->private;
|
||||
draw_core_pause (transform_core->core, active_tool);
|
||||
g_free (transform_core->grid_coords);
|
||||
g_free (transform_core->tgrid_coords);
|
||||
transform_core_setup_grid (active_tool);
|
||||
transform_bounding_box (active_tool);
|
||||
draw_core_resume (transform_core->core, active_tool);
|
||||
}
|
||||
|
||||
static void
|
||||
transform_core_setup_grid (tool)
|
||||
Tool *tool;
|
||||
|
@ -988,7 +1038,7 @@ transform_core_setup_grid (tool)
|
|||
transform_core = (TransformCore *) tool->private;
|
||||
|
||||
/* We use the transform_tool_grid_size function only here, even if the
|
||||
* user changes the grid size in the middle of a "new" UI
|
||||
* user changes the grid size in the middle of a
|
||||
* operation, nothing happens.
|
||||
*/
|
||||
transform_core->ngx =
|
||||
|
@ -1066,7 +1116,6 @@ transform_core_do (gimage, drawable, float_tiles, interpolation, matrix)
|
|||
int plus2_x, plus2_y;
|
||||
int minus_x, minus_y;
|
||||
int x1, y1, x2, y2;
|
||||
double dx1, dy1, dx2, dy2, dx3, dy3, dx4, dy4;
|
||||
double xinc, yinc, winc;
|
||||
double tx, ty, tw;
|
||||
double ttx = 0.0, tty = 0.0;
|
||||
|
@ -1104,7 +1153,7 @@ transform_core_do (gimage, drawable, float_tiles, interpolation, matrix)
|
|||
break;
|
||||
}
|
||||
|
||||
if (new_ui)
|
||||
if (transform_tool_direction () == TRANSFORM_CORRECTIVE)
|
||||
{
|
||||
invert (matrix, im);
|
||||
matrix = im;
|
||||
|
@ -1118,24 +1167,36 @@ transform_core_do (gimage, drawable, float_tiles, interpolation, matrix)
|
|||
x2 = x1 + float_tiles->levels[0].width;
|
||||
y2 = y1 + float_tiles->levels[0].height;
|
||||
|
||||
transform_point (matrix, x1, y1, &dx1, &dy1);
|
||||
transform_point (matrix, x2, y1, &dx2, &dy2);
|
||||
transform_point (matrix, x1, y2, &dx3, &dy3);
|
||||
transform_point (matrix, x2, y2, &dx4, &dy4);
|
||||
|
||||
/* Find the bounding coordinates */
|
||||
tx1 = MINIMUM (dx1, dx2);
|
||||
tx1 = MINIMUM (tx1, dx3);
|
||||
tx1 = MINIMUM (tx1, dx4);
|
||||
ty1 = MINIMUM (dy1, dy2);
|
||||
ty1 = MINIMUM (ty1, dy3);
|
||||
ty1 = MINIMUM (ty1, dy4);
|
||||
tx2 = MAXIMUM (dx1, dx2);
|
||||
tx2 = MAXIMUM (tx2, dx3);
|
||||
tx2 = MAXIMUM (tx2, dx4);
|
||||
ty2 = MAXIMUM (dy1, dy2);
|
||||
ty2 = MAXIMUM (ty2, dy3);
|
||||
ty2 = MAXIMUM (ty2, dy4);
|
||||
if (active_tool && active_tool->type == PERSPECTIVE && transform_tool_clip ())
|
||||
{
|
||||
tx1 = x1;
|
||||
ty1 = y1;
|
||||
tx2 = x2;
|
||||
ty2 = y2;
|
||||
}
|
||||
else
|
||||
{
|
||||
double dx1, dy1, dx2, dy2, dx3, dy3, dx4, dy4;
|
||||
|
||||
transform_point (matrix, x1, y1, &dx1, &dy1);
|
||||
transform_point (matrix, x2, y1, &dx2, &dy2);
|
||||
transform_point (matrix, x1, y2, &dx3, &dy3);
|
||||
transform_point (matrix, x2, y2, &dx4, &dy4);
|
||||
|
||||
tx1 = MINIMUM (dx1, dx2);
|
||||
tx1 = MINIMUM (tx1, dx3);
|
||||
tx1 = MINIMUM (tx1, dx4);
|
||||
ty1 = MINIMUM (dy1, dy2);
|
||||
ty1 = MINIMUM (ty1, dy3);
|
||||
ty1 = MINIMUM (ty1, dy4);
|
||||
tx2 = MAXIMUM (dx1, dx2);
|
||||
tx2 = MAXIMUM (tx2, dx3);
|
||||
tx2 = MAXIMUM (tx2, dx4);
|
||||
ty2 = MAXIMUM (dy1, dy2);
|
||||
ty2 = MAXIMUM (ty2, dy3);
|
||||
ty2 = MAXIMUM (ty2, dy4);
|
||||
}
|
||||
|
||||
/* Get the new temporary buffer for the transformed result */
|
||||
tiles = tile_manager_new ((tx2 - tx1), (ty2 - ty1), float_tiles->levels[0].bpp);
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#define HANDLE_2 2
|
||||
#define HANDLE_3 3
|
||||
#define HANDLE_4 4
|
||||
#define HANDLE_CENTER 5
|
||||
|
||||
/* the different states that the transformation function can be called with */
|
||||
#define INIT 0
|
||||
|
@ -36,7 +37,7 @@
|
|||
#define FINISH 3
|
||||
|
||||
/* buffer sizes for scaling information strings (for the info dialog) */
|
||||
#define MAX_INFO_BUF 12
|
||||
#define MAX_INFO_BUF 40
|
||||
#define TRAN_INFO_SIZE 8
|
||||
|
||||
/* control whether the transform tool draws a bounding box */
|
||||
|
@ -68,16 +69,19 @@ struct _transform_core
|
|||
|
||||
int x1, y1; /* upper left hand coordinate */
|
||||
int x2, y2; /* lower right hand coords */
|
||||
int cx, cy; /* center point (for rotation) */
|
||||
|
||||
double tx1, ty1; /* transformed coords */
|
||||
double tx2, ty2; /* */
|
||||
double tx3, ty3; /* */
|
||||
double tx4, ty4; /* */
|
||||
double tcx, tcy; /* */
|
||||
|
||||
int sx1, sy1; /* transformed screen coords */
|
||||
int sx2, sy2; /* position of four handles */
|
||||
int sx3, sy3; /* */
|
||||
int sx4, sy4; /* */
|
||||
int scx, scy; /* and center for rotation */
|
||||
|
||||
Matrix transform; /* transformation matrix */
|
||||
TranInfo trans_info; /* transformation info */
|
||||
|
@ -93,8 +97,6 @@ struct _transform_core
|
|||
* a button pressed before we deal with
|
||||
* motion events. ALT.
|
||||
*/
|
||||
/* The following fields are used by
|
||||
the "new UI". */
|
||||
int ngx, ngy; /* number of grid lines in original
|
||||
x and y directions */
|
||||
double *grid_coords; /* x and y coordinates of the grid
|
||||
|
@ -112,7 +114,6 @@ struct _transform_undo
|
|||
int tool_ID;
|
||||
int tool_type;
|
||||
TranInfo trans_info;
|
||||
int first;
|
||||
TileManager * original;
|
||||
};
|
||||
|
||||
|
@ -133,6 +134,7 @@ void transform_core_no_draw (Tool *);
|
|||
Tool * transform_core_new (int, int);
|
||||
void transform_core_free (Tool *);
|
||||
void transform_core_reset (Tool *, void *);
|
||||
void transform_core_grid_density_changed (void);
|
||||
|
||||
/* transform functions */
|
||||
TileManager * transform_core_do (GImage *, GimpDrawable *, TileManager *, int, Matrix);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "appenv.h"
|
||||
#include "gdisplay.h"
|
||||
#include "tools.h"
|
||||
|
@ -23,14 +24,16 @@
|
|||
#include "rotate_tool.h"
|
||||
#include "scale_tool.h"
|
||||
#include "shear_tool.h"
|
||||
#include "transform_core.h"
|
||||
#include "transform_tool.h"
|
||||
|
||||
typedef struct _TransformOptions TransformOptions;
|
||||
|
||||
struct _TransformOptions
|
||||
{
|
||||
int direction;
|
||||
int smoothing;
|
||||
int new_ui;
|
||||
int clip;
|
||||
int grid_size;
|
||||
ToolType type;
|
||||
};
|
||||
|
@ -41,7 +44,6 @@ static void transform_change_type (int);
|
|||
/* Static variables */
|
||||
static TransformOptions *transform_options = NULL;
|
||||
|
||||
|
||||
static void
|
||||
transform_toggle_update (GtkWidget *w,
|
||||
gpointer data)
|
||||
|
@ -63,31 +65,62 @@ transform_type_callback (GtkWidget *w,
|
|||
transform_change_type ((long) client_data);
|
||||
}
|
||||
|
||||
static void
|
||||
transform_direction_callback (GtkWidget *w,
|
||||
gpointer client_data)
|
||||
{
|
||||
long dir = (long) client_data;
|
||||
|
||||
if (dir == TRANSFORM_TRADITIONAL)
|
||||
transform_options->direction = TRANSFORM_TRADITIONAL;
|
||||
else
|
||||
transform_options->direction = TRANSFORM_CORRECTIVE;
|
||||
}
|
||||
|
||||
static void
|
||||
transform_grid_density_callback (GtkWidget *w,
|
||||
GtkSpinButton *spin)
|
||||
{
|
||||
transform_options->grid_size =
|
||||
(int) pow (2.0, 7.0 - gtk_spin_button_get_value_as_int (spin));
|
||||
transform_core_grid_density_changed ();
|
||||
}
|
||||
|
||||
static TransformOptions *
|
||||
create_transform_options (void)
|
||||
{
|
||||
TransformOptions *options;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *vbox, *hbox;
|
||||
GtkWidget *label;
|
||||
GtkWidget *radio_frame;
|
||||
GtkWidget *radio_box;
|
||||
GtkWidget *radio_button;
|
||||
GtkWidget *smoothing_toggle;
|
||||
GtkWidget *new_ui_toggle;
|
||||
GSList *group = NULL;
|
||||
GtkWidget *clip_toggle;
|
||||
GtkAdjustment *grid_adj;
|
||||
GtkWidget *grid_density;
|
||||
GSList *group;
|
||||
int i;
|
||||
char *button_names[4] =
|
||||
char *transform_button_names[4] =
|
||||
{
|
||||
"Rotation",
|
||||
"Scaling",
|
||||
"Shearing",
|
||||
"Perspective"
|
||||
};
|
||||
char *direction_button_names[2] =
|
||||
{
|
||||
"Corrective",
|
||||
"Traditional"
|
||||
};
|
||||
|
||||
/* the new options structure */
|
||||
options = (TransformOptions *) g_malloc (sizeof (TransformOptions));
|
||||
options->smoothing = 1;
|
||||
options->type = ROTATE;
|
||||
options->smoothing = 1;
|
||||
options->clip = 1;
|
||||
options->direction = TRANSFORM_CORRECTIVE;
|
||||
options->grid_size = 32;
|
||||
|
||||
/* the main vbox */
|
||||
vbox = gtk_vbox_new (FALSE, 1);
|
||||
|
@ -97,22 +130,47 @@ create_transform_options (void)
|
|||
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
/* the radio frame and box */
|
||||
/* the first radio frame and box, for transform type */
|
||||
radio_frame = gtk_frame_new ("Transform");
|
||||
gtk_box_pack_start (GTK_BOX (vbox), radio_frame, FALSE, FALSE, 0);
|
||||
|
||||
radio_box = gtk_vbox_new (FALSE, 1);
|
||||
gtk_container_add (GTK_CONTAINER (radio_frame), radio_box);
|
||||
|
||||
/* the radio buttons */
|
||||
group = NULL;
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
radio_button =
|
||||
gtk_radio_button_new_with_label (group, transform_button_names[i]);
|
||||
group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio_button));
|
||||
gtk_box_pack_start (GTK_BOX (radio_box), radio_button, FALSE, FALSE, 0);
|
||||
gtk_signal_connect (GTK_OBJECT (radio_button), "toggled",
|
||||
(GtkSignalFunc) transform_type_callback,
|
||||
(gpointer) ((long) ROTATE + i));
|
||||
gtk_widget_show (radio_button);
|
||||
}
|
||||
gtk_widget_show (radio_box);
|
||||
gtk_widget_show (radio_frame);
|
||||
|
||||
/* the second radio frame and box, for transform direction */
|
||||
radio_frame = gtk_frame_new ("Tool paradigm");
|
||||
gtk_box_pack_start (GTK_BOX (vbox), radio_frame, FALSE, FALSE, 0);
|
||||
|
||||
radio_box = gtk_vbox_new (FALSE, 1);
|
||||
gtk_container_add (GTK_CONTAINER (radio_frame), radio_box);
|
||||
|
||||
/* the radio buttons */
|
||||
for (i = 0; i < 4; i++)
|
||||
group = NULL;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
radio_button = gtk_radio_button_new_with_label (group, button_names[i]);
|
||||
radio_button =
|
||||
gtk_radio_button_new_with_label (group, direction_button_names[i]);
|
||||
group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio_button));
|
||||
gtk_box_pack_start (GTK_BOX (radio_box), radio_button, FALSE, FALSE, 0);
|
||||
gtk_signal_connect (GTK_OBJECT (radio_button), "toggled",
|
||||
(GtkSignalFunc) transform_type_callback,
|
||||
(gpointer) ((long) ROTATE + i));
|
||||
(GtkSignalFunc) transform_direction_callback,
|
||||
(gpointer) ((long) i));
|
||||
gtk_widget_show (radio_button);
|
||||
}
|
||||
gtk_widget_show (radio_box);
|
||||
|
@ -128,19 +186,32 @@ create_transform_options (void)
|
|||
options->smoothing);
|
||||
gtk_widget_show (smoothing_toggle);
|
||||
|
||||
|
||||
/* the new UI toggle button */
|
||||
new_ui_toggle = gtk_check_button_new_with_label ("New user interface");
|
||||
gtk_box_pack_start (GTK_BOX (vbox), new_ui_toggle, FALSE, FALSE, 0);
|
||||
gtk_signal_connect (GTK_OBJECT (new_ui_toggle), "toggled",
|
||||
/* the clip resulting image toggle button */
|
||||
clip_toggle = gtk_check_button_new_with_label ("Clip perspective");
|
||||
gtk_box_pack_start (GTK_BOX (vbox), clip_toggle, FALSE, FALSE, 0);
|
||||
gtk_signal_connect (GTK_OBJECT (clip_toggle), "toggled",
|
||||
(GtkSignalFunc) transform_toggle_update,
|
||||
&options->new_ui);
|
||||
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (new_ui_toggle),
|
||||
options->new_ui);
|
||||
gtk_widget_show (new_ui_toggle);
|
||||
&options->clip);
|
||||
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (clip_toggle),
|
||||
options->clip);
|
||||
gtk_widget_show (clip_toggle);
|
||||
|
||||
/* the grid size entry */
|
||||
options->grid_size = 32; /* XXX */
|
||||
/* the grid density entry */
|
||||
hbox = gtk_hbox_new (FALSE, 1);
|
||||
gtk_widget_show (hbox);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
||||
label = gtk_label_new ("Grid density: ");
|
||||
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
grid_adj = (GtkAdjustment *) gtk_adjustment_new (2.0, 0.0, 5.0, 1.0, 1.0, 0.0);
|
||||
grid_density = gtk_spin_button_new (grid_adj, 0, 0);
|
||||
gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (grid_density), TRUE);
|
||||
gtk_signal_connect (GTK_OBJECT (grid_adj), "value_changed",
|
||||
(GtkSignalFunc) transform_grid_density_callback,
|
||||
grid_density);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), grid_density, FALSE, FALSE, 0);
|
||||
gtk_widget_show (grid_density);
|
||||
|
||||
|
||||
/* Register this selection options widget with the main tools options dialog */
|
||||
tools_register_options (ROTATE, vbox);
|
||||
|
@ -221,12 +292,21 @@ transform_tool_smoothing ()
|
|||
}
|
||||
|
||||
int
|
||||
transform_tool_new_ui ()
|
||||
transform_tool_clip ()
|
||||
{
|
||||
if (!transform_options)
|
||||
return 1;
|
||||
return 0;
|
||||
else
|
||||
return transform_options->new_ui;
|
||||
return transform_options->clip;
|
||||
}
|
||||
|
||||
int
|
||||
transform_tool_direction ()
|
||||
{
|
||||
if (!transform_options)
|
||||
return TRANSFORM_TRADITIONAL;
|
||||
else
|
||||
return transform_options->direction;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -22,7 +22,12 @@
|
|||
Tool * tools_new_transform_tool (void);
|
||||
void tools_free_transform_tool (Tool *);
|
||||
int transform_tool_smoothing (void);
|
||||
int transform_tool_new_ui (void);
|
||||
int transform_tool_clip (void);
|
||||
int transform_tool_direction (void);
|
||||
int transform_tool_grid_size (void);
|
||||
|
||||
/* transform directions */
|
||||
#define TRANSFORM_CORRECTIVE 0
|
||||
#define TRANSFORM_TRADITIONAL 1
|
||||
|
||||
#endif /* __TRANSFORM_TOOL_H__ */
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "appenv.h"
|
||||
#include "actionarea.h"
|
||||
#include "drawable.h"
|
||||
#include "errors.h"
|
||||
#include "floating_sel.h"
|
||||
|
@ -48,7 +49,6 @@
|
|||
|
||||
/* variables */
|
||||
static TranInfo old_trans_info;
|
||||
static int new_ui;
|
||||
InfoDialog * transform_info = NULL;
|
||||
|
||||
/* forward function declarations */
|
||||
|
@ -68,6 +68,52 @@ static void invert (Matrix, Matrix);
|
|||
src[i] = tile_data_pointer (tile[i], (x) % TILE_WIDTH, (y) % TILE_HEIGHT);
|
||||
|
||||
|
||||
static void
|
||||
transform_ok_callback (GtkWidget *w,
|
||||
gpointer client_data)
|
||||
{
|
||||
Tool *tool;
|
||||
|
||||
tool = (Tool *) client_data;
|
||||
transform_core_doit (tool, tool->gdisp_ptr);
|
||||
}
|
||||
|
||||
static void
|
||||
transform_cancel_callback (GtkWidget *w,
|
||||
gpointer client_data)
|
||||
{
|
||||
Tool *tool;
|
||||
TransformCore *transform_core;
|
||||
int i;
|
||||
|
||||
tool = (Tool *) client_data;
|
||||
transform_core = (TransformCore *) tool->private;
|
||||
|
||||
/* stop the current tool drawing process */
|
||||
draw_core_pause (transform_core->core, tool);
|
||||
|
||||
/* Restore the previous transformation info */
|
||||
for (i = 0; i < TRAN_INFO_SIZE; i++)
|
||||
transform_core->trans_info [i] = old_trans_info [i];
|
||||
/* recalculate the tool's transformation matrix */
|
||||
transform_core_recalc (tool, tool->gdisp_ptr);
|
||||
|
||||
/* resume drawing the current tool */
|
||||
draw_core_resume (transform_core->core, tool);
|
||||
}
|
||||
|
||||
|
||||
static ActionAreaItem action_items[2] =
|
||||
{
|
||||
{ NULL, transform_ok_callback, NULL, NULL },
|
||||
{ "Cancel", transform_cancel_callback, NULL, NULL },
|
||||
};
|
||||
|
||||
static char *action_labels[4] =
|
||||
{
|
||||
"Rotate", "Scale", "Shear", "Transform"
|
||||
};
|
||||
|
||||
void
|
||||
transform_core_button_press (tool, bevent, gdisp_ptr)
|
||||
Tool *tool;
|
||||
|
@ -90,7 +136,7 @@ transform_core_button_press (tool, bevent, gdisp_ptr)
|
|||
|
||||
tool->drawable = gimage_active_drawable (gdisp->gimage);
|
||||
|
||||
if (transform_core->function == CREATING)
|
||||
if (transform_core->function == CREATING && tool->state == ACTIVE)
|
||||
{
|
||||
/* Save the current transformation info */
|
||||
for (i = 0; i < TRAN_INFO_SIZE; i++)
|
||||
|
@ -105,6 +151,9 @@ transform_core_button_press (tool, bevent, gdisp_ptr)
|
|||
if ((transform_core->function >= CREATING) && (gdisp_ptr == tool->gdisp_ptr) &&
|
||||
transform_core->interactive)
|
||||
{
|
||||
/* start drawing the bounding box and handles... */
|
||||
draw_core_start (transform_core->core, gdisp->canvas->window, tool);
|
||||
|
||||
x = bevent->x;
|
||||
y = bevent->y;
|
||||
|
||||
|
@ -132,6 +181,13 @@ transform_core_button_press (tool, bevent, gdisp_ptr)
|
|||
transform_core->function = HANDLE_4;
|
||||
}
|
||||
|
||||
if (tool->type == ROTATE
|
||||
&& (SQR (x - transform_core->scx) +
|
||||
SQR (y - transform_core->scy)) <= 100)
|
||||
{
|
||||
transform_core->function = HANDLE_CENTER;
|
||||
}
|
||||
|
||||
/* Save the current pointer position */
|
||||
gdisplay_untransform_coords (gdisp, bevent->x, bevent->y,
|
||||
&transform_core->startx,
|
||||
|
@ -143,10 +199,6 @@ transform_core_button_press (tool, bevent, gdisp_ptr)
|
|||
GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON1_MOTION_MASK | GDK_BUTTON_RELEASE_MASK,
|
||||
NULL, NULL, bevent->time);
|
||||
|
||||
/* start drawing the bounding box and handles... */
|
||||
if (new_ui)
|
||||
draw_core_start (transform_core->core, gdisp->canvas->window, tool);
|
||||
|
||||
tool->state = ACTIVE;
|
||||
return;
|
||||
}
|
||||
|
@ -192,20 +244,24 @@ transform_core_button_press (tool, bevent, gdisp_ptr)
|
|||
*/
|
||||
transform_core_bounds (tool, gdisp_ptr);
|
||||
|
||||
/* If new UI, calculate the grid line endpoints */
|
||||
if (new_ui)
|
||||
transform_core_setup_grid (tool);
|
||||
/* Calculate the grid line endpoints */
|
||||
transform_core_setup_grid (tool);
|
||||
|
||||
/* Initialize the transform tool */
|
||||
(* transform_core->trans_func) (tool, gdisp_ptr, INIT);
|
||||
|
||||
if (transform_info != NULL)
|
||||
{
|
||||
action_items[0].label = action_labels[tool->type - ROTATE];
|
||||
action_items[0].user_data = tool;
|
||||
action_items[1].user_data = tool;
|
||||
build_action_area (GTK_DIALOG (transform_info->shell),
|
||||
action_items, 2, 0);
|
||||
}
|
||||
|
||||
/* Recalculate the transform tool */
|
||||
transform_core_recalc (tool, gdisp_ptr);
|
||||
|
||||
/* start drawing the bounding box and handles... */
|
||||
if (!new_ui)
|
||||
draw_core_start (transform_core->core, gdisp->canvas->window, tool);
|
||||
|
||||
/* recall this function to find which handle we're dragging */
|
||||
if (transform_core->interactive)
|
||||
transform_core_button_press (tool, bevent, gdisp_ptr);
|
||||
|
@ -239,23 +295,16 @@ transform_core_button_release (tool, bevent, gdisp_ptr)
|
|||
/* if the 3rd button isn't pressed, transform the selected mask */
|
||||
if (! (bevent->state & GDK_BUTTON3_MASK))
|
||||
{
|
||||
if (new_ui)
|
||||
/* Shift-clicking is another way to approve the transform */
|
||||
if ((bevent->state & GDK_SHIFT_MASK)
|
||||
|| (tool->type == FLIP_HORZ)
|
||||
|| (tool->type == FLIP_VERT))
|
||||
{
|
||||
/* In the new UI, shift-clicking means perform the transform */
|
||||
if ((bevent->state & GDK_SHIFT_MASK)
|
||||
|| (tool->type == FLIP_HORZ)
|
||||
|| (tool->type == FLIP_VERT))
|
||||
{
|
||||
transform_core_doit (tool, gdisp_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Do nothing, keep the grid visible */
|
||||
}
|
||||
transform_core_doit (tool, gdisp_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
transform_core_doit (tool, gdisp_ptr);
|
||||
/* Do nothing, keep the grid visible */
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -266,7 +315,6 @@ transform_core_button_release (tool, bevent, gdisp_ptr)
|
|||
/* Restore the previous transformation info */
|
||||
for (i = 0; i < TRAN_INFO_SIZE; i++)
|
||||
transform_core->trans_info [i] = old_trans_info [i];
|
||||
|
||||
/* recalculate the tool's transformation matrix */
|
||||
transform_core_recalc (tool, gdisp_ptr);
|
||||
|
||||
|
@ -288,7 +336,6 @@ transform_core_doit (tool, gdisp_ptr)
|
|||
TransformCore *transform_core;
|
||||
TileManager *new_tiles;
|
||||
TransformUndo *tu;
|
||||
int first_transform;
|
||||
int new_layer;
|
||||
int i, x, y;
|
||||
|
||||
|
@ -304,35 +351,25 @@ transform_core_doit (tool, gdisp_ptr)
|
|||
/* Start a transform undo group */
|
||||
undo_push_group_start (gdisp->gimage, TRANSFORM_CORE_UNDO);
|
||||
|
||||
/* If original is NULL, then this is the first transformation */
|
||||
first_transform = (transform_core->original) ? FALSE : TRUE;
|
||||
/* With the old UI, if original is NULL, then this is the
|
||||
first transformation. In the new UI, it is always so, yes? */
|
||||
g_assert (transform_core->original == NULL);
|
||||
|
||||
/* If we're in interactive mode, and haven't yet done any
|
||||
* transformations, we need to copy the current selection to
|
||||
* the transform tool's private selection pointer, so that the
|
||||
* original source can be repeatedly modified.
|
||||
/* If we're in interactive mode, we need to copy the current
|
||||
* selection to the transform tool's private selection pointer, so
|
||||
* that the original source can be repeatedly modified.
|
||||
*/
|
||||
if (first_transform)
|
||||
transform_core->original = transform_core_cut (gdisp->gimage,
|
||||
gimage_active_drawable (gdisp->gimage),
|
||||
&new_layer);
|
||||
else
|
||||
new_layer = FALSE;
|
||||
transform_core->original = transform_core_cut (gdisp->gimage,
|
||||
gimage_active_drawable (gdisp->gimage),
|
||||
&new_layer);
|
||||
|
||||
/* Send the request for the transformation to the tool...
|
||||
*/
|
||||
new_tiles = (* transform_core->trans_func) (tool, gdisp_ptr, FINISH);
|
||||
|
||||
/* If new UI, reset the transformation */
|
||||
if (new_ui)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < TRAN_INFO_SIZE; i++)
|
||||
transform_core->trans_info [i] = 0;
|
||||
|
||||
transform_core_recalc (tool, gdisp_ptr);
|
||||
}
|
||||
(* transform_core->trans_func) (tool, gdisp_ptr, INIT);
|
||||
|
||||
transform_core_recalc (tool, gdisp_ptr);
|
||||
|
||||
if (new_tiles)
|
||||
{
|
||||
|
@ -348,7 +385,6 @@ transform_core_doit (tool, gdisp_ptr)
|
|||
tu->tool_type = tool->type;
|
||||
for (i = 0; i < TRAN_INFO_SIZE; i++)
|
||||
tu->trans_info[i] = old_trans_info[i];
|
||||
tu->first = first_transform;
|
||||
tu->original = NULL;
|
||||
|
||||
/* Make a note of the new current drawable (since we may have
|
||||
|
@ -389,10 +425,7 @@ transform_core_doit (tool, gdisp_ptr)
|
|||
}
|
||||
gdisplays_flush ();
|
||||
|
||||
if (new_ui)
|
||||
{
|
||||
transform_core_reset (tool, gdisp_ptr);
|
||||
}
|
||||
transform_core_reset (tool, gdisp_ptr);
|
||||
|
||||
/* if this tool is non-interactive, make it inactive after use */
|
||||
if (!transform_core->interactive)
|
||||
|
@ -534,6 +567,8 @@ transform_core_draw (tool)
|
|||
TransformCore * transform_core;
|
||||
GDisplay * gdisp;
|
||||
int srw, srh;
|
||||
int i, k, gci;
|
||||
int xa, ya, xb, yb;
|
||||
|
||||
gdisp = tool->gdisp_ptr;
|
||||
transform_core = (TransformCore *) tool->private;
|
||||
|
@ -566,27 +601,22 @@ transform_core_draw (tool)
|
|||
gdk_draw_line (transform_core->core->win, transform_core->core->gc,
|
||||
x3, y3, x1, y1);
|
||||
|
||||
/* if new UI, draw the grid */
|
||||
if (new_ui)
|
||||
{
|
||||
int i, k, gci;
|
||||
int xa, ya, xb, yb;
|
||||
/* Draw the grid */
|
||||
|
||||
gci = 0;
|
||||
k = transform_core->ngx + transform_core->ngy;
|
||||
for (i = 0; i < k; i++)
|
||||
{
|
||||
gdisplay_transform_coords (gdisp, transform_core->tgrid_coords[gci],
|
||||
transform_core->tgrid_coords[gci+1],
|
||||
&xa, &ya, 0);
|
||||
gdisplay_transform_coords (gdisp, transform_core->tgrid_coords[gci+2],
|
||||
transform_core->tgrid_coords[gci+3],
|
||||
&xb, &yb, 0);
|
||||
|
||||
gdk_draw_line (transform_core->core->win, transform_core->core->gc,
|
||||
xa, ya, xb, yb);
|
||||
gci += 4;
|
||||
}
|
||||
gci = 0;
|
||||
k = transform_core->ngx + transform_core->ngy;
|
||||
for (i = 0; i < k; i++)
|
||||
{
|
||||
gdisplay_transform_coords (gdisp, transform_core->tgrid_coords[gci],
|
||||
transform_core->tgrid_coords[gci+1],
|
||||
&xa, &ya, 0);
|
||||
gdisplay_transform_coords (gdisp, transform_core->tgrid_coords[gci+2],
|
||||
transform_core->tgrid_coords[gci+3],
|
||||
&xb, &yb, 0);
|
||||
|
||||
gdk_draw_line (transform_core->core->win, transform_core->core->gc,
|
||||
xa, ya, xb, yb);
|
||||
gci += 4;
|
||||
}
|
||||
|
||||
/* draw the tool handles */
|
||||
|
@ -598,6 +628,18 @@ transform_core_draw (tool)
|
|||
x3 - (srw >> 1), y3 - (srh >> 1), srw, srh);
|
||||
gdk_draw_rectangle (transform_core->core->win, transform_core->core->gc, 0,
|
||||
x4 - (srw >> 1), y4 - (srh >> 1), srw, srh);
|
||||
|
||||
/* draw the center */
|
||||
if (tool->type == ROTATE)
|
||||
{
|
||||
gdisplay_transform_coords (gdisp, transform_core->tcx, transform_core->tcy,
|
||||
&transform_core->scx, &transform_core->scy, 0);
|
||||
|
||||
gdk_draw_arc (transform_core->core->win, transform_core->core->gc, 1,
|
||||
transform_core->scx - (srw >> 1),
|
||||
transform_core->scy - (srh >> 1),
|
||||
srw, srh, 0, 23040);
|
||||
}
|
||||
}
|
||||
|
||||
Tool *
|
||||
|
@ -629,15 +671,6 @@ transform_core_new (type, interactive)
|
|||
|
||||
private->grid_coords = private->tgrid_coords = NULL;
|
||||
|
||||
/* We must save this setting so that the user won't screw us if he
|
||||
* changes the UI to "old" style in the middle of a "new" UI operation.
|
||||
* We can't keep this info in the transform_core, as it is needed
|
||||
* in transform_core_do, which doesn't have access to any TransformCore.
|
||||
* I hope it's OK to use a static variable... (there already is
|
||||
* old_trans_info, so?).
|
||||
*/
|
||||
new_ui = transform_tool_new_ui ();
|
||||
|
||||
tool->type = type;
|
||||
tool->state = INACTIVE;
|
||||
tool->scroll_lock = 1; /* Do not allow scrolling */
|
||||
|
@ -693,6 +726,8 @@ transform_bounding_box (tool)
|
|||
Tool * tool;
|
||||
{
|
||||
TransformCore * transform_core;
|
||||
int i, k;
|
||||
int gci;
|
||||
|
||||
transform_core = (TransformCore *) tool->private;
|
||||
|
||||
|
@ -709,22 +744,21 @@ transform_bounding_box (tool)
|
|||
transform_core->x2, transform_core->y2,
|
||||
&transform_core->tx4, &transform_core->ty4);
|
||||
|
||||
if (new_ui)
|
||||
if (tool->type == ROTATE)
|
||||
transform_point (transform_core->transform,
|
||||
transform_core->cx, transform_core->cy,
|
||||
&transform_core->tcx, &transform_core->tcy);
|
||||
|
||||
gci = 0;
|
||||
k = (transform_core->ngx + transform_core->ngy) * 2;
|
||||
for (i = 0; i < k; i++)
|
||||
{
|
||||
int i, k;
|
||||
int gci;
|
||||
|
||||
gci = 0;
|
||||
k = (transform_core->ngx + transform_core->ngy) * 2;
|
||||
for (i = 0; i < k; i++)
|
||||
{
|
||||
transform_point (transform_core->transform,
|
||||
transform_core->grid_coords[gci],
|
||||
transform_core->grid_coords[gci+1],
|
||||
&(transform_core->tgrid_coords[gci]),
|
||||
&(transform_core->tgrid_coords[gci+1]));
|
||||
gci += 2;
|
||||
}
|
||||
transform_point (transform_core->transform,
|
||||
transform_core->grid_coords[gci],
|
||||
transform_core->grid_coords[gci+1],
|
||||
&(transform_core->tgrid_coords[gci]),
|
||||
&(transform_core->tgrid_coords[gci+1]));
|
||||
gci += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -973,10 +1007,26 @@ transform_core_bounds (tool, gdisp_ptr)
|
|||
transform_core->x2 += offset_x;
|
||||
transform_core->y2 += offset_y;
|
||||
}
|
||||
transform_core->cx = (transform_core->x1 + transform_core->x2) / 2;
|
||||
transform_core->cy = (transform_core->y1 + transform_core->y2) / 2;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
transform_core_grid_density_changed ()
|
||||
{
|
||||
TransformCore * transform_core;
|
||||
|
||||
transform_core = (TransformCore *) active_tool->private;
|
||||
draw_core_pause (transform_core->core, active_tool);
|
||||
g_free (transform_core->grid_coords);
|
||||
g_free (transform_core->tgrid_coords);
|
||||
transform_core_setup_grid (active_tool);
|
||||
transform_bounding_box (active_tool);
|
||||
draw_core_resume (transform_core->core, active_tool);
|
||||
}
|
||||
|
||||
static void
|
||||
transform_core_setup_grid (tool)
|
||||
Tool *tool;
|
||||
|
@ -988,7 +1038,7 @@ transform_core_setup_grid (tool)
|
|||
transform_core = (TransformCore *) tool->private;
|
||||
|
||||
/* We use the transform_tool_grid_size function only here, even if the
|
||||
* user changes the grid size in the middle of a "new" UI
|
||||
* user changes the grid size in the middle of a
|
||||
* operation, nothing happens.
|
||||
*/
|
||||
transform_core->ngx =
|
||||
|
@ -1066,7 +1116,6 @@ transform_core_do (gimage, drawable, float_tiles, interpolation, matrix)
|
|||
int plus2_x, plus2_y;
|
||||
int minus_x, minus_y;
|
||||
int x1, y1, x2, y2;
|
||||
double dx1, dy1, dx2, dy2, dx3, dy3, dx4, dy4;
|
||||
double xinc, yinc, winc;
|
||||
double tx, ty, tw;
|
||||
double ttx = 0.0, tty = 0.0;
|
||||
|
@ -1104,7 +1153,7 @@ transform_core_do (gimage, drawable, float_tiles, interpolation, matrix)
|
|||
break;
|
||||
}
|
||||
|
||||
if (new_ui)
|
||||
if (transform_tool_direction () == TRANSFORM_CORRECTIVE)
|
||||
{
|
||||
invert (matrix, im);
|
||||
matrix = im;
|
||||
|
@ -1118,24 +1167,36 @@ transform_core_do (gimage, drawable, float_tiles, interpolation, matrix)
|
|||
x2 = x1 + float_tiles->levels[0].width;
|
||||
y2 = y1 + float_tiles->levels[0].height;
|
||||
|
||||
transform_point (matrix, x1, y1, &dx1, &dy1);
|
||||
transform_point (matrix, x2, y1, &dx2, &dy2);
|
||||
transform_point (matrix, x1, y2, &dx3, &dy3);
|
||||
transform_point (matrix, x2, y2, &dx4, &dy4);
|
||||
|
||||
/* Find the bounding coordinates */
|
||||
tx1 = MINIMUM (dx1, dx2);
|
||||
tx1 = MINIMUM (tx1, dx3);
|
||||
tx1 = MINIMUM (tx1, dx4);
|
||||
ty1 = MINIMUM (dy1, dy2);
|
||||
ty1 = MINIMUM (ty1, dy3);
|
||||
ty1 = MINIMUM (ty1, dy4);
|
||||
tx2 = MAXIMUM (dx1, dx2);
|
||||
tx2 = MAXIMUM (tx2, dx3);
|
||||
tx2 = MAXIMUM (tx2, dx4);
|
||||
ty2 = MAXIMUM (dy1, dy2);
|
||||
ty2 = MAXIMUM (ty2, dy3);
|
||||
ty2 = MAXIMUM (ty2, dy4);
|
||||
if (active_tool && active_tool->type == PERSPECTIVE && transform_tool_clip ())
|
||||
{
|
||||
tx1 = x1;
|
||||
ty1 = y1;
|
||||
tx2 = x2;
|
||||
ty2 = y2;
|
||||
}
|
||||
else
|
||||
{
|
||||
double dx1, dy1, dx2, dy2, dx3, dy3, dx4, dy4;
|
||||
|
||||
transform_point (matrix, x1, y1, &dx1, &dy1);
|
||||
transform_point (matrix, x2, y1, &dx2, &dy2);
|
||||
transform_point (matrix, x1, y2, &dx3, &dy3);
|
||||
transform_point (matrix, x2, y2, &dx4, &dy4);
|
||||
|
||||
tx1 = MINIMUM (dx1, dx2);
|
||||
tx1 = MINIMUM (tx1, dx3);
|
||||
tx1 = MINIMUM (tx1, dx4);
|
||||
ty1 = MINIMUM (dy1, dy2);
|
||||
ty1 = MINIMUM (ty1, dy3);
|
||||
ty1 = MINIMUM (ty1, dy4);
|
||||
tx2 = MAXIMUM (dx1, dx2);
|
||||
tx2 = MAXIMUM (tx2, dx3);
|
||||
tx2 = MAXIMUM (tx2, dx4);
|
||||
ty2 = MAXIMUM (dy1, dy2);
|
||||
ty2 = MAXIMUM (ty2, dy3);
|
||||
ty2 = MAXIMUM (ty2, dy4);
|
||||
}
|
||||
|
||||
/* Get the new temporary buffer for the transformed result */
|
||||
tiles = tile_manager_new ((tx2 - tx1), (ty2 - ty1), float_tiles->levels[0].bpp);
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#define HANDLE_2 2
|
||||
#define HANDLE_3 3
|
||||
#define HANDLE_4 4
|
||||
#define HANDLE_CENTER 5
|
||||
|
||||
/* the different states that the transformation function can be called with */
|
||||
#define INIT 0
|
||||
|
@ -36,7 +37,7 @@
|
|||
#define FINISH 3
|
||||
|
||||
/* buffer sizes for scaling information strings (for the info dialog) */
|
||||
#define MAX_INFO_BUF 12
|
||||
#define MAX_INFO_BUF 40
|
||||
#define TRAN_INFO_SIZE 8
|
||||
|
||||
/* control whether the transform tool draws a bounding box */
|
||||
|
@ -68,16 +69,19 @@ struct _transform_core
|
|||
|
||||
int x1, y1; /* upper left hand coordinate */
|
||||
int x2, y2; /* lower right hand coords */
|
||||
int cx, cy; /* center point (for rotation) */
|
||||
|
||||
double tx1, ty1; /* transformed coords */
|
||||
double tx2, ty2; /* */
|
||||
double tx3, ty3; /* */
|
||||
double tx4, ty4; /* */
|
||||
double tcx, tcy; /* */
|
||||
|
||||
int sx1, sy1; /* transformed screen coords */
|
||||
int sx2, sy2; /* position of four handles */
|
||||
int sx3, sy3; /* */
|
||||
int sx4, sy4; /* */
|
||||
int scx, scy; /* and center for rotation */
|
||||
|
||||
Matrix transform; /* transformation matrix */
|
||||
TranInfo trans_info; /* transformation info */
|
||||
|
@ -93,8 +97,6 @@ struct _transform_core
|
|||
* a button pressed before we deal with
|
||||
* motion events. ALT.
|
||||
*/
|
||||
/* The following fields are used by
|
||||
the "new UI". */
|
||||
int ngx, ngy; /* number of grid lines in original
|
||||
x and y directions */
|
||||
double *grid_coords; /* x and y coordinates of the grid
|
||||
|
@ -112,7 +114,6 @@ struct _transform_undo
|
|||
int tool_ID;
|
||||
int tool_type;
|
||||
TranInfo trans_info;
|
||||
int first;
|
||||
TileManager * original;
|
||||
};
|
||||
|
||||
|
@ -133,6 +134,7 @@ void transform_core_no_draw (Tool *);
|
|||
Tool * transform_core_new (int, int);
|
||||
void transform_core_free (Tool *);
|
||||
void transform_core_reset (Tool *, void *);
|
||||
void transform_core_grid_density_changed (void);
|
||||
|
||||
/* transform functions */
|
||||
TileManager * transform_core_do (GImage *, GimpDrawable *, TileManager *, int, Matrix);
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "appenv.h"
|
||||
#include "gdisplay.h"
|
||||
#include "tools.h"
|
||||
|
@ -23,14 +24,16 @@
|
|||
#include "rotate_tool.h"
|
||||
#include "scale_tool.h"
|
||||
#include "shear_tool.h"
|
||||
#include "transform_core.h"
|
||||
#include "transform_tool.h"
|
||||
|
||||
typedef struct _TransformOptions TransformOptions;
|
||||
|
||||
struct _TransformOptions
|
||||
{
|
||||
int direction;
|
||||
int smoothing;
|
||||
int new_ui;
|
||||
int clip;
|
||||
int grid_size;
|
||||
ToolType type;
|
||||
};
|
||||
|
@ -41,7 +44,6 @@ static void transform_change_type (int);
|
|||
/* Static variables */
|
||||
static TransformOptions *transform_options = NULL;
|
||||
|
||||
|
||||
static void
|
||||
transform_toggle_update (GtkWidget *w,
|
||||
gpointer data)
|
||||
|
@ -63,31 +65,62 @@ transform_type_callback (GtkWidget *w,
|
|||
transform_change_type ((long) client_data);
|
||||
}
|
||||
|
||||
static void
|
||||
transform_direction_callback (GtkWidget *w,
|
||||
gpointer client_data)
|
||||
{
|
||||
long dir = (long) client_data;
|
||||
|
||||
if (dir == TRANSFORM_TRADITIONAL)
|
||||
transform_options->direction = TRANSFORM_TRADITIONAL;
|
||||
else
|
||||
transform_options->direction = TRANSFORM_CORRECTIVE;
|
||||
}
|
||||
|
||||
static void
|
||||
transform_grid_density_callback (GtkWidget *w,
|
||||
GtkSpinButton *spin)
|
||||
{
|
||||
transform_options->grid_size =
|
||||
(int) pow (2.0, 7.0 - gtk_spin_button_get_value_as_int (spin));
|
||||
transform_core_grid_density_changed ();
|
||||
}
|
||||
|
||||
static TransformOptions *
|
||||
create_transform_options (void)
|
||||
{
|
||||
TransformOptions *options;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *vbox, *hbox;
|
||||
GtkWidget *label;
|
||||
GtkWidget *radio_frame;
|
||||
GtkWidget *radio_box;
|
||||
GtkWidget *radio_button;
|
||||
GtkWidget *smoothing_toggle;
|
||||
GtkWidget *new_ui_toggle;
|
||||
GSList *group = NULL;
|
||||
GtkWidget *clip_toggle;
|
||||
GtkAdjustment *grid_adj;
|
||||
GtkWidget *grid_density;
|
||||
GSList *group;
|
||||
int i;
|
||||
char *button_names[4] =
|
||||
char *transform_button_names[4] =
|
||||
{
|
||||
"Rotation",
|
||||
"Scaling",
|
||||
"Shearing",
|
||||
"Perspective"
|
||||
};
|
||||
char *direction_button_names[2] =
|
||||
{
|
||||
"Corrective",
|
||||
"Traditional"
|
||||
};
|
||||
|
||||
/* the new options structure */
|
||||
options = (TransformOptions *) g_malloc (sizeof (TransformOptions));
|
||||
options->smoothing = 1;
|
||||
options->type = ROTATE;
|
||||
options->smoothing = 1;
|
||||
options->clip = 1;
|
||||
options->direction = TRANSFORM_CORRECTIVE;
|
||||
options->grid_size = 32;
|
||||
|
||||
/* the main vbox */
|
||||
vbox = gtk_vbox_new (FALSE, 1);
|
||||
|
@ -97,22 +130,47 @@ create_transform_options (void)
|
|||
gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
|
||||
/* the radio frame and box */
|
||||
/* the first radio frame and box, for transform type */
|
||||
radio_frame = gtk_frame_new ("Transform");
|
||||
gtk_box_pack_start (GTK_BOX (vbox), radio_frame, FALSE, FALSE, 0);
|
||||
|
||||
radio_box = gtk_vbox_new (FALSE, 1);
|
||||
gtk_container_add (GTK_CONTAINER (radio_frame), radio_box);
|
||||
|
||||
/* the radio buttons */
|
||||
group = NULL;
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
radio_button =
|
||||
gtk_radio_button_new_with_label (group, transform_button_names[i]);
|
||||
group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio_button));
|
||||
gtk_box_pack_start (GTK_BOX (radio_box), radio_button, FALSE, FALSE, 0);
|
||||
gtk_signal_connect (GTK_OBJECT (radio_button), "toggled",
|
||||
(GtkSignalFunc) transform_type_callback,
|
||||
(gpointer) ((long) ROTATE + i));
|
||||
gtk_widget_show (radio_button);
|
||||
}
|
||||
gtk_widget_show (radio_box);
|
||||
gtk_widget_show (radio_frame);
|
||||
|
||||
/* the second radio frame and box, for transform direction */
|
||||
radio_frame = gtk_frame_new ("Tool paradigm");
|
||||
gtk_box_pack_start (GTK_BOX (vbox), radio_frame, FALSE, FALSE, 0);
|
||||
|
||||
radio_box = gtk_vbox_new (FALSE, 1);
|
||||
gtk_container_add (GTK_CONTAINER (radio_frame), radio_box);
|
||||
|
||||
/* the radio buttons */
|
||||
for (i = 0; i < 4; i++)
|
||||
group = NULL;
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
radio_button = gtk_radio_button_new_with_label (group, button_names[i]);
|
||||
radio_button =
|
||||
gtk_radio_button_new_with_label (group, direction_button_names[i]);
|
||||
group = gtk_radio_button_group (GTK_RADIO_BUTTON (radio_button));
|
||||
gtk_box_pack_start (GTK_BOX (radio_box), radio_button, FALSE, FALSE, 0);
|
||||
gtk_signal_connect (GTK_OBJECT (radio_button), "toggled",
|
||||
(GtkSignalFunc) transform_type_callback,
|
||||
(gpointer) ((long) ROTATE + i));
|
||||
(GtkSignalFunc) transform_direction_callback,
|
||||
(gpointer) ((long) i));
|
||||
gtk_widget_show (radio_button);
|
||||
}
|
||||
gtk_widget_show (radio_box);
|
||||
|
@ -128,19 +186,32 @@ create_transform_options (void)
|
|||
options->smoothing);
|
||||
gtk_widget_show (smoothing_toggle);
|
||||
|
||||
|
||||
/* the new UI toggle button */
|
||||
new_ui_toggle = gtk_check_button_new_with_label ("New user interface");
|
||||
gtk_box_pack_start (GTK_BOX (vbox), new_ui_toggle, FALSE, FALSE, 0);
|
||||
gtk_signal_connect (GTK_OBJECT (new_ui_toggle), "toggled",
|
||||
/* the clip resulting image toggle button */
|
||||
clip_toggle = gtk_check_button_new_with_label ("Clip perspective");
|
||||
gtk_box_pack_start (GTK_BOX (vbox), clip_toggle, FALSE, FALSE, 0);
|
||||
gtk_signal_connect (GTK_OBJECT (clip_toggle), "toggled",
|
||||
(GtkSignalFunc) transform_toggle_update,
|
||||
&options->new_ui);
|
||||
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (new_ui_toggle),
|
||||
options->new_ui);
|
||||
gtk_widget_show (new_ui_toggle);
|
||||
&options->clip);
|
||||
gtk_toggle_button_set_state (GTK_TOGGLE_BUTTON (clip_toggle),
|
||||
options->clip);
|
||||
gtk_widget_show (clip_toggle);
|
||||
|
||||
/* the grid size entry */
|
||||
options->grid_size = 32; /* XXX */
|
||||
/* the grid density entry */
|
||||
hbox = gtk_hbox_new (FALSE, 1);
|
||||
gtk_widget_show (hbox);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
|
||||
label = gtk_label_new ("Grid density: ");
|
||||
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
|
||||
gtk_widget_show (label);
|
||||
grid_adj = (GtkAdjustment *) gtk_adjustment_new (2.0, 0.0, 5.0, 1.0, 1.0, 0.0);
|
||||
grid_density = gtk_spin_button_new (grid_adj, 0, 0);
|
||||
gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (grid_density), TRUE);
|
||||
gtk_signal_connect (GTK_OBJECT (grid_adj), "value_changed",
|
||||
(GtkSignalFunc) transform_grid_density_callback,
|
||||
grid_density);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), grid_density, FALSE, FALSE, 0);
|
||||
gtk_widget_show (grid_density);
|
||||
|
||||
|
||||
/* Register this selection options widget with the main tools options dialog */
|
||||
tools_register_options (ROTATE, vbox);
|
||||
|
@ -221,12 +292,21 @@ transform_tool_smoothing ()
|
|||
}
|
||||
|
||||
int
|
||||
transform_tool_new_ui ()
|
||||
transform_tool_clip ()
|
||||
{
|
||||
if (!transform_options)
|
||||
return 1;
|
||||
return 0;
|
||||
else
|
||||
return transform_options->new_ui;
|
||||
return transform_options->clip;
|
||||
}
|
||||
|
||||
int
|
||||
transform_tool_direction ()
|
||||
{
|
||||
if (!transform_options)
|
||||
return TRANSFORM_TRADITIONAL;
|
||||
else
|
||||
return transform_options->direction;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -22,7 +22,12 @@
|
|||
Tool * tools_new_transform_tool (void);
|
||||
void tools_free_transform_tool (Tool *);
|
||||
int transform_tool_smoothing (void);
|
||||
int transform_tool_new_ui (void);
|
||||
int transform_tool_clip (void);
|
||||
int transform_tool_direction (void);
|
||||
int transform_tool_grid_size (void);
|
||||
|
||||
/* transform directions */
|
||||
#define TRANSFORM_CORRECTIVE 0
|
||||
#define TRANSFORM_TRADITIONAL 1
|
||||
|
||||
#endif /* __TRANSFORM_TOOL_H__ */
|
||||
|
|
22
app/undo.c
22
app/undo.c
|
@ -937,21 +937,17 @@ undo_pop_transform (GImage *gimage,
|
|||
tc->trans_info[i] = d;
|
||||
}
|
||||
|
||||
/* if this is the first transform in a string, swap the
|
||||
* original buffer--the source buffer for repeated transforms
|
||||
/* swap the original buffer--the source buffer for repeated transforms
|
||||
*/
|
||||
if (tu->first)
|
||||
{
|
||||
temp = tu->original;
|
||||
tu->original = tc->original;
|
||||
tc->original = temp;
|
||||
temp = tu->original;
|
||||
tu->original = tc->original;
|
||||
tc->original = temp;
|
||||
|
||||
/* If we're re-implementing the first transform, reactivate tool */
|
||||
if (state == REDO && tc->original)
|
||||
{
|
||||
active_tool->state = ACTIVE;
|
||||
draw_core_resume (tc->core, active_tool);
|
||||
}
|
||||
/* If we're re-implementing the first transform, reactivate tool */
|
||||
if (state == REDO && tc->original)
|
||||
{
|
||||
active_tool->state = ACTIVE;
|
||||
draw_core_resume (tc->core, active_tool);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
|
Loading…
Reference in New Issue