mirror of https://github.com/GNOME/gimp.git
applied gimp-tml-980724-1 for new transform tool ui. It's still a little
rough, needs fixes -Yosh
This commit is contained in:
parent
e6c92b1b22
commit
5007176bba
|
@ -1,3 +1,8 @@
|
|||
Fri Jul 24 14:03:13 PDT 1998 Manish Singh <yosh@gimp.org>
|
||||
|
||||
* app/transform*.[ch]: applied gimp-tml-980724-1 for new
|
||||
transform tool ui. It's still a little rough, needs fixes
|
||||
|
||||
Fri Jul 24 14:40:55 CDT 1998 Larry Ewing <lewing@gimp.org>
|
||||
|
||||
* app/layers_dialog.c (lc_dialog_create): moved
|
||||
|
|
|
@ -48,13 +48,16 @@
|
|||
|
||||
/* variables */
|
||||
static TranInfo old_trans_info;
|
||||
static int new_ui;
|
||||
InfoDialog * transform_info = NULL;
|
||||
|
||||
/* forward function declarations */
|
||||
static int transform_core_bounds (Tool *, void *);
|
||||
static void * transform_core_recalc (Tool *, void *);
|
||||
static double cubic (double, int, int, int, int);
|
||||
|
||||
static int transform_core_bounds (Tool *, void *);
|
||||
static void * transform_core_recalc (Tool *, void *);
|
||||
static void transform_core_doit (Tool *, gpointer);
|
||||
static double cubic (double, int, int, int, int);
|
||||
static void transform_core_setup_grid (Tool *);
|
||||
static void invert (Matrix, Matrix);
|
||||
|
||||
#define BILINEAR(jk,j1k,jk1,j1k1,dx,dy) \
|
||||
((1-dy) * ((1-dx)*jk + dx*j1k) + \
|
||||
|
@ -87,9 +90,13 @@ transform_core_button_press (tool, bevent, gdisp_ptr)
|
|||
|
||||
tool->drawable = gimage_active_drawable (gdisp->gimage);
|
||||
|
||||
/* Save the current transformation info */
|
||||
for (i = 0; i < TRAN_INFO_SIZE; i++)
|
||||
old_trans_info [i] = transform_core->trans_info [i];
|
||||
if (transform_core->function == CREATING)
|
||||
{
|
||||
/* Save the current transformation info */
|
||||
for (i = 0; i < TRAN_INFO_SIZE; i++)
|
||||
old_trans_info [i] = transform_core->trans_info [i];
|
||||
}
|
||||
|
||||
|
||||
/* if we have already displayed the bounding box and handles,
|
||||
* check to make sure that the display which currently owns the
|
||||
|
@ -136,6 +143,10 @@ 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;
|
||||
}
|
||||
|
@ -180,6 +191,10 @@ transform_core_button_press (tool, bevent, gdisp_ptr)
|
|||
* that actually need the bounds for initializing
|
||||
*/
|
||||
transform_core_bounds (tool, gdisp_ptr);
|
||||
|
||||
/* If new UI, calculate the grid line endpoints */
|
||||
if (new_ui)
|
||||
transform_core_setup_grid (tool);
|
||||
|
||||
/* Initialize the transform tool */
|
||||
(* transform_core->trans_func) (tool, gdisp_ptr, INIT);
|
||||
|
@ -188,7 +203,8 @@ transform_core_button_press (tool, bevent, gdisp_ptr)
|
|||
transform_core_recalc (tool, gdisp_ptr);
|
||||
|
||||
/* start drawing the bounding box and handles... */
|
||||
draw_core_start (transform_core->core, gdisp->canvas->window, tool);
|
||||
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)
|
||||
|
@ -205,11 +221,7 @@ transform_core_button_release (tool, bevent, gdisp_ptr)
|
|||
{
|
||||
GDisplay *gdisp;
|
||||
TransformCore *transform_core;
|
||||
TileManager *new_tiles;
|
||||
TransformUndo *tu;
|
||||
int first_transform;
|
||||
int new_layer;
|
||||
int i, x, y;
|
||||
int i;
|
||||
|
||||
gdisp = (GDisplay *) gdisp_ptr;
|
||||
transform_core = (TransformCore *) tool->private;
|
||||
|
@ -227,88 +239,22 @@ 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))
|
||||
{
|
||||
/* We're going to dirty this image, but we want to keep the tool
|
||||
around
|
||||
*/
|
||||
|
||||
tool->preserve = TRUE;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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 (first_transform)
|
||||
transform_core->original = transform_core_cut (gdisp->gimage,
|
||||
gimage_active_drawable (gdisp->gimage),
|
||||
&new_layer);
|
||||
if (new_ui)
|
||||
{
|
||||
/* In the new UI, shift-clicking means perform the transform */
|
||||
if (bevent->state & GDK_SHIFT_MASK)
|
||||
{
|
||||
transform_core_doit (tool, gdisp_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Do nothing, keep the grid visible */
|
||||
}
|
||||
}
|
||||
else
|
||||
new_layer = FALSE;
|
||||
|
||||
/* Send the request for the transformation to the tool...
|
||||
*/
|
||||
new_tiles = (* transform_core->trans_func) (tool, gdisp_ptr, FINISH);
|
||||
|
||||
if (new_tiles)
|
||||
{
|
||||
/* paste the new transformed image to the gimage...also implement
|
||||
* undo...
|
||||
*/
|
||||
transform_core_paste (gdisp->gimage, gimage_active_drawable (gdisp->gimage),
|
||||
new_tiles, new_layer);
|
||||
|
||||
/* create and initialize the transform_undo structure */
|
||||
tu = (TransformUndo *) g_malloc (sizeof (TransformUndo));
|
||||
tu->tool_ID = tool->ID;
|
||||
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
|
||||
a floating selection, etc now. */
|
||||
|
||||
tool->drawable = gimage_active_drawable (gdisp->gimage);
|
||||
|
||||
undo_push_transform (gdisp->gimage, (void *) tu);
|
||||
transform_core_doit (tool, gdisp_ptr);
|
||||
}
|
||||
|
||||
/* push the undo group end */
|
||||
undo_push_group_end (gdisp->gimage);
|
||||
|
||||
/* We're done dirtying the image, and would like to be restarted
|
||||
if the image gets dirty while the tool exists
|
||||
*/
|
||||
|
||||
tool->preserve = FALSE;
|
||||
|
||||
/* Flush the gdisplays */
|
||||
if (gdisp->disp_xoffset || gdisp->disp_yoffset)
|
||||
{
|
||||
gdk_window_get_size (gdisp->canvas->window, &x, &y);
|
||||
if (gdisp->disp_yoffset)
|
||||
{
|
||||
gdisplay_expose_area (gdisp, 0, 0, gdisp->disp_width,
|
||||
gdisp->disp_yoffset);
|
||||
gdisplay_expose_area (gdisp, 0, gdisp->disp_yoffset + y,
|
||||
gdisp->disp_width, gdisp->disp_height);
|
||||
}
|
||||
if (gdisp->disp_xoffset)
|
||||
{
|
||||
gdisplay_expose_area (gdisp, 0, 0, gdisp->disp_xoffset,
|
||||
gdisp->disp_height);
|
||||
gdisplay_expose_area (gdisp, gdisp->disp_xoffset + x, 0,
|
||||
gdisp->disp_width, gdisp->disp_height);
|
||||
}
|
||||
}
|
||||
gdisplays_flush ();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -331,6 +277,127 @@ transform_core_button_release (tool, bevent, gdisp_ptr)
|
|||
tool->state = INACTIVE;
|
||||
}
|
||||
|
||||
void
|
||||
transform_core_doit (tool, gdisp_ptr)
|
||||
Tool *tool;
|
||||
gpointer gdisp_ptr;
|
||||
{
|
||||
GDisplay *gdisp;
|
||||
TransformCore *transform_core;
|
||||
TileManager *new_tiles;
|
||||
TransformUndo *tu;
|
||||
int first_transform;
|
||||
int new_layer;
|
||||
int i, x, y;
|
||||
|
||||
gdisp = (GDisplay *) gdisp_ptr;
|
||||
transform_core = (TransformCore *) tool->private;
|
||||
|
||||
/* We're going to dirty this image, but we want to keep the tool
|
||||
around
|
||||
*/
|
||||
|
||||
tool->preserve = TRUE;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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 (first_transform)
|
||||
transform_core->original = transform_core_cut (gdisp->gimage,
|
||||
gimage_active_drawable (gdisp->gimage),
|
||||
&new_layer);
|
||||
else
|
||||
new_layer = FALSE;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
if (new_tiles)
|
||||
{
|
||||
/* paste the new transformed image to the gimage...also implement
|
||||
* undo...
|
||||
*/
|
||||
transform_core_paste (gdisp->gimage, gimage_active_drawable (gdisp->gimage),
|
||||
new_tiles, new_layer);
|
||||
|
||||
/* create and initialize the transform_undo structure */
|
||||
tu = (TransformUndo *) g_malloc (sizeof (TransformUndo));
|
||||
tu->tool_ID = tool->ID;
|
||||
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
|
||||
a floating selection, etc now. */
|
||||
|
||||
tool->drawable = gimage_active_drawable (gdisp->gimage);
|
||||
|
||||
undo_push_transform (gdisp->gimage, (void *) tu);
|
||||
}
|
||||
|
||||
/* push the undo group end */
|
||||
undo_push_group_end (gdisp->gimage);
|
||||
|
||||
/* We're done dirtying the image, and would like to be restarted
|
||||
if the image gets dirty while the tool exists
|
||||
*/
|
||||
|
||||
tool->preserve = FALSE;
|
||||
|
||||
/* Flush the gdisplays */
|
||||
if (gdisp->disp_xoffset || gdisp->disp_yoffset)
|
||||
{
|
||||
gdk_window_get_size (gdisp->canvas->window, &x, &y);
|
||||
if (gdisp->disp_yoffset)
|
||||
{
|
||||
gdisplay_expose_area (gdisp, 0, 0, gdisp->disp_width,
|
||||
gdisp->disp_yoffset);
|
||||
gdisplay_expose_area (gdisp, 0, gdisp->disp_yoffset + y,
|
||||
gdisp->disp_width, gdisp->disp_height);
|
||||
}
|
||||
if (gdisp->disp_xoffset)
|
||||
{
|
||||
gdisplay_expose_area (gdisp, 0, 0, gdisp->disp_xoffset,
|
||||
gdisp->disp_height);
|
||||
gdisplay_expose_area (gdisp, gdisp->disp_xoffset + x, 0,
|
||||
gdisp->disp_width, gdisp->disp_height);
|
||||
}
|
||||
}
|
||||
gdisplays_flush ();
|
||||
|
||||
if (new_ui)
|
||||
{
|
||||
transform_core_reset (tool, gdisp_ptr);
|
||||
}
|
||||
|
||||
/* if this tool is non-interactive, make it inactive after use */
|
||||
if (!transform_core->interactive)
|
||||
tool->state = INACTIVE;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
transform_core_motion (tool, mevent, gdisp_ptr)
|
||||
Tool *tool;
|
||||
|
@ -497,6 +564,29 @@ 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;
|
||||
|
||||
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 */
|
||||
gdk_draw_rectangle (transform_core->core->win, transform_core->core->gc, 0,
|
||||
x1 - (srw >> 1), y1 - (srh >> 1), srw, srh);
|
||||
|
@ -535,6 +625,17 @@ transform_core_new (type, interactive)
|
|||
for (i = 0; i < TRAN_INFO_SIZE; i++)
|
||||
private->trans_info[i] = 0;
|
||||
|
||||
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 */
|
||||
|
@ -577,6 +678,10 @@ transform_core_free (tool)
|
|||
info_dialog_free (transform_info);
|
||||
transform_info = NULL;
|
||||
|
||||
/* Free the grid line endpoint arrays */
|
||||
g_free (transform_core->grid_coords);
|
||||
g_free (transform_core->tgrid_coords);
|
||||
|
||||
/* Finally, free the transform tool itself */
|
||||
g_free (transform_core);
|
||||
}
|
||||
|
@ -601,6 +706,24 @@ transform_bounding_box (tool)
|
|||
transform_point (transform_core->transform,
|
||||
transform_core->x2, transform_core->y2,
|
||||
&transform_core->tx4, &transform_core->ty4);
|
||||
|
||||
if (new_ui)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -852,6 +975,58 @@ transform_core_bounds (tool, gdisp_ptr)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
transform_core_setup_grid (tool)
|
||||
Tool *tool;
|
||||
{
|
||||
TransformCore * transform_core;
|
||||
int i, gci;
|
||||
double *coords;
|
||||
|
||||
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
|
||||
* operation, nothing happens.
|
||||
*/
|
||||
transform_core->ngx =
|
||||
(transform_core->x2 - transform_core->x1) / transform_tool_grid_size ();
|
||||
if (transform_core->ngx > 0)
|
||||
transform_core->ngx--;
|
||||
transform_core->ngy =
|
||||
(transform_core->y2 - transform_core->y1) / transform_tool_grid_size ();
|
||||
if (transform_core->ngy > 0)
|
||||
transform_core->ngy--;
|
||||
transform_core->grid_coords = coords = (double *)
|
||||
g_malloc ((transform_core->ngx + transform_core->ngy) * 4
|
||||
* sizeof(double));
|
||||
transform_core->tgrid_coords = (double *)
|
||||
g_malloc ((transform_core->ngx + transform_core->ngy) * 4
|
||||
* sizeof(double));
|
||||
|
||||
gci = 0;
|
||||
for (i = 1; i <= transform_core->ngx; i++)
|
||||
{
|
||||
coords[gci] = transform_core->x1 +
|
||||
((double) i)/(transform_core->ngx + 1) *
|
||||
(transform_core->x2 - transform_core->x1);
|
||||
coords[gci+1] = transform_core->y1;
|
||||
coords[gci+2] = coords[gci];
|
||||
coords[gci+3] = transform_core->y2;
|
||||
gci += 4;
|
||||
}
|
||||
for (i = 1; i <= transform_core->ngy; i++)
|
||||
{
|
||||
coords[gci] = transform_core->x1;
|
||||
coords[gci+1] = transform_core->y1 +
|
||||
((double) i)/(transform_core->ngy + 1) *
|
||||
(transform_core->y2 - transform_core->y1);
|
||||
coords[gci+2] = transform_core->x2;
|
||||
coords[gci+3] = coords[gci+1];
|
||||
gci += 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void *
|
||||
transform_core_recalc (tool, gdisp_ptr)
|
||||
Tool * tool;
|
||||
|
@ -877,6 +1052,7 @@ transform_core_do (gimage, drawable, float_tiles, interpolation, matrix)
|
|||
PixelRegion destPR;
|
||||
TileManager *tiles;
|
||||
Matrix m;
|
||||
Matrix im;
|
||||
int itx, ity;
|
||||
int tx1, ty1, tx2, ty2;
|
||||
int width, height;
|
||||
|
@ -926,6 +1102,12 @@ transform_core_do (gimage, drawable, float_tiles, interpolation, matrix)
|
|||
break;
|
||||
}
|
||||
|
||||
if (new_ui)
|
||||
{
|
||||
invert (matrix, im);
|
||||
matrix = im;
|
||||
}
|
||||
|
||||
/* Find the inverse of the transformation matrix */
|
||||
invert (matrix, m);
|
||||
|
||||
|
|
|
@ -93,6 +93,14 @@ 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
|
||||
endpoints (a total of (ngx+ngy)*2
|
||||
coordinate pairs) */
|
||||
double *tgrid_coords; /* transformed grid_coords */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ typedef struct _TransformOptions TransformOptions;
|
|||
struct _TransformOptions
|
||||
{
|
||||
int smoothing;
|
||||
int new_ui;
|
||||
int grid_size;
|
||||
ToolType type;
|
||||
};
|
||||
|
||||
|
@ -71,6 +73,7 @@ create_transform_options (void)
|
|||
GtkWidget *radio_box;
|
||||
GtkWidget *radio_button;
|
||||
GtkWidget *smoothing_toggle;
|
||||
GtkWidget *new_ui_toggle;
|
||||
GSList *group = NULL;
|
||||
int i;
|
||||
char *button_names[4] =
|
||||
|
@ -126,6 +129,19 @@ create_transform_options (void)
|
|||
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",
|
||||
(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);
|
||||
|
||||
/* the grid size entry */
|
||||
options->grid_size = 32; /* XXX */
|
||||
|
||||
/* Register this selection options widget with the main tools options dialog */
|
||||
tools_register_options (ROTATE, vbox);
|
||||
tools_register_options (SCALE, vbox);
|
||||
|
@ -203,3 +219,21 @@ transform_tool_smoothing ()
|
|||
else
|
||||
return transform_options->smoothing;
|
||||
}
|
||||
|
||||
int
|
||||
transform_tool_new_ui ()
|
||||
{
|
||||
if (!transform_options)
|
||||
return 1;
|
||||
else
|
||||
return transform_options->new_ui;
|
||||
}
|
||||
|
||||
int
|
||||
transform_tool_grid_size ()
|
||||
{
|
||||
if (!transform_options)
|
||||
return 32;
|
||||
else
|
||||
return transform_options->grid_size;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
/* tool functions */
|
||||
Tool * tools_new_transform_tool (void);
|
||||
void tools_free_transform_tool (Tool *);
|
||||
int transform_tool_smoothing (void);
|
||||
int transform_tool_smoothing (void);
|
||||
int transform_tool_new_ui (void);
|
||||
int transform_tool_grid_size (void);
|
||||
|
||||
#endif /* __TRANSFORM_TOOL_H__ */
|
||||
|
|
|
@ -48,13 +48,16 @@
|
|||
|
||||
/* variables */
|
||||
static TranInfo old_trans_info;
|
||||
static int new_ui;
|
||||
InfoDialog * transform_info = NULL;
|
||||
|
||||
/* forward function declarations */
|
||||
static int transform_core_bounds (Tool *, void *);
|
||||
static void * transform_core_recalc (Tool *, void *);
|
||||
static double cubic (double, int, int, int, int);
|
||||
|
||||
static int transform_core_bounds (Tool *, void *);
|
||||
static void * transform_core_recalc (Tool *, void *);
|
||||
static void transform_core_doit (Tool *, gpointer);
|
||||
static double cubic (double, int, int, int, int);
|
||||
static void transform_core_setup_grid (Tool *);
|
||||
static void invert (Matrix, Matrix);
|
||||
|
||||
#define BILINEAR(jk,j1k,jk1,j1k1,dx,dy) \
|
||||
((1-dy) * ((1-dx)*jk + dx*j1k) + \
|
||||
|
@ -87,9 +90,13 @@ transform_core_button_press (tool, bevent, gdisp_ptr)
|
|||
|
||||
tool->drawable = gimage_active_drawable (gdisp->gimage);
|
||||
|
||||
/* Save the current transformation info */
|
||||
for (i = 0; i < TRAN_INFO_SIZE; i++)
|
||||
old_trans_info [i] = transform_core->trans_info [i];
|
||||
if (transform_core->function == CREATING)
|
||||
{
|
||||
/* Save the current transformation info */
|
||||
for (i = 0; i < TRAN_INFO_SIZE; i++)
|
||||
old_trans_info [i] = transform_core->trans_info [i];
|
||||
}
|
||||
|
||||
|
||||
/* if we have already displayed the bounding box and handles,
|
||||
* check to make sure that the display which currently owns the
|
||||
|
@ -136,6 +143,10 @@ 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;
|
||||
}
|
||||
|
@ -180,6 +191,10 @@ transform_core_button_press (tool, bevent, gdisp_ptr)
|
|||
* that actually need the bounds for initializing
|
||||
*/
|
||||
transform_core_bounds (tool, gdisp_ptr);
|
||||
|
||||
/* If new UI, calculate the grid line endpoints */
|
||||
if (new_ui)
|
||||
transform_core_setup_grid (tool);
|
||||
|
||||
/* Initialize the transform tool */
|
||||
(* transform_core->trans_func) (tool, gdisp_ptr, INIT);
|
||||
|
@ -188,7 +203,8 @@ transform_core_button_press (tool, bevent, gdisp_ptr)
|
|||
transform_core_recalc (tool, gdisp_ptr);
|
||||
|
||||
/* start drawing the bounding box and handles... */
|
||||
draw_core_start (transform_core->core, gdisp->canvas->window, tool);
|
||||
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)
|
||||
|
@ -205,11 +221,7 @@ transform_core_button_release (tool, bevent, gdisp_ptr)
|
|||
{
|
||||
GDisplay *gdisp;
|
||||
TransformCore *transform_core;
|
||||
TileManager *new_tiles;
|
||||
TransformUndo *tu;
|
||||
int first_transform;
|
||||
int new_layer;
|
||||
int i, x, y;
|
||||
int i;
|
||||
|
||||
gdisp = (GDisplay *) gdisp_ptr;
|
||||
transform_core = (TransformCore *) tool->private;
|
||||
|
@ -227,88 +239,22 @@ 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))
|
||||
{
|
||||
/* We're going to dirty this image, but we want to keep the tool
|
||||
around
|
||||
*/
|
||||
|
||||
tool->preserve = TRUE;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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 (first_transform)
|
||||
transform_core->original = transform_core_cut (gdisp->gimage,
|
||||
gimage_active_drawable (gdisp->gimage),
|
||||
&new_layer);
|
||||
if (new_ui)
|
||||
{
|
||||
/* In the new UI, shift-clicking means perform the transform */
|
||||
if (bevent->state & GDK_SHIFT_MASK)
|
||||
{
|
||||
transform_core_doit (tool, gdisp_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Do nothing, keep the grid visible */
|
||||
}
|
||||
}
|
||||
else
|
||||
new_layer = FALSE;
|
||||
|
||||
/* Send the request for the transformation to the tool...
|
||||
*/
|
||||
new_tiles = (* transform_core->trans_func) (tool, gdisp_ptr, FINISH);
|
||||
|
||||
if (new_tiles)
|
||||
{
|
||||
/* paste the new transformed image to the gimage...also implement
|
||||
* undo...
|
||||
*/
|
||||
transform_core_paste (gdisp->gimage, gimage_active_drawable (gdisp->gimage),
|
||||
new_tiles, new_layer);
|
||||
|
||||
/* create and initialize the transform_undo structure */
|
||||
tu = (TransformUndo *) g_malloc (sizeof (TransformUndo));
|
||||
tu->tool_ID = tool->ID;
|
||||
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
|
||||
a floating selection, etc now. */
|
||||
|
||||
tool->drawable = gimage_active_drawable (gdisp->gimage);
|
||||
|
||||
undo_push_transform (gdisp->gimage, (void *) tu);
|
||||
transform_core_doit (tool, gdisp_ptr);
|
||||
}
|
||||
|
||||
/* push the undo group end */
|
||||
undo_push_group_end (gdisp->gimage);
|
||||
|
||||
/* We're done dirtying the image, and would like to be restarted
|
||||
if the image gets dirty while the tool exists
|
||||
*/
|
||||
|
||||
tool->preserve = FALSE;
|
||||
|
||||
/* Flush the gdisplays */
|
||||
if (gdisp->disp_xoffset || gdisp->disp_yoffset)
|
||||
{
|
||||
gdk_window_get_size (gdisp->canvas->window, &x, &y);
|
||||
if (gdisp->disp_yoffset)
|
||||
{
|
||||
gdisplay_expose_area (gdisp, 0, 0, gdisp->disp_width,
|
||||
gdisp->disp_yoffset);
|
||||
gdisplay_expose_area (gdisp, 0, gdisp->disp_yoffset + y,
|
||||
gdisp->disp_width, gdisp->disp_height);
|
||||
}
|
||||
if (gdisp->disp_xoffset)
|
||||
{
|
||||
gdisplay_expose_area (gdisp, 0, 0, gdisp->disp_xoffset,
|
||||
gdisp->disp_height);
|
||||
gdisplay_expose_area (gdisp, gdisp->disp_xoffset + x, 0,
|
||||
gdisp->disp_width, gdisp->disp_height);
|
||||
}
|
||||
}
|
||||
gdisplays_flush ();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -331,6 +277,127 @@ transform_core_button_release (tool, bevent, gdisp_ptr)
|
|||
tool->state = INACTIVE;
|
||||
}
|
||||
|
||||
void
|
||||
transform_core_doit (tool, gdisp_ptr)
|
||||
Tool *tool;
|
||||
gpointer gdisp_ptr;
|
||||
{
|
||||
GDisplay *gdisp;
|
||||
TransformCore *transform_core;
|
||||
TileManager *new_tiles;
|
||||
TransformUndo *tu;
|
||||
int first_transform;
|
||||
int new_layer;
|
||||
int i, x, y;
|
||||
|
||||
gdisp = (GDisplay *) gdisp_ptr;
|
||||
transform_core = (TransformCore *) tool->private;
|
||||
|
||||
/* We're going to dirty this image, but we want to keep the tool
|
||||
around
|
||||
*/
|
||||
|
||||
tool->preserve = TRUE;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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 (first_transform)
|
||||
transform_core->original = transform_core_cut (gdisp->gimage,
|
||||
gimage_active_drawable (gdisp->gimage),
|
||||
&new_layer);
|
||||
else
|
||||
new_layer = FALSE;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
if (new_tiles)
|
||||
{
|
||||
/* paste the new transformed image to the gimage...also implement
|
||||
* undo...
|
||||
*/
|
||||
transform_core_paste (gdisp->gimage, gimage_active_drawable (gdisp->gimage),
|
||||
new_tiles, new_layer);
|
||||
|
||||
/* create and initialize the transform_undo structure */
|
||||
tu = (TransformUndo *) g_malloc (sizeof (TransformUndo));
|
||||
tu->tool_ID = tool->ID;
|
||||
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
|
||||
a floating selection, etc now. */
|
||||
|
||||
tool->drawable = gimage_active_drawable (gdisp->gimage);
|
||||
|
||||
undo_push_transform (gdisp->gimage, (void *) tu);
|
||||
}
|
||||
|
||||
/* push the undo group end */
|
||||
undo_push_group_end (gdisp->gimage);
|
||||
|
||||
/* We're done dirtying the image, and would like to be restarted
|
||||
if the image gets dirty while the tool exists
|
||||
*/
|
||||
|
||||
tool->preserve = FALSE;
|
||||
|
||||
/* Flush the gdisplays */
|
||||
if (gdisp->disp_xoffset || gdisp->disp_yoffset)
|
||||
{
|
||||
gdk_window_get_size (gdisp->canvas->window, &x, &y);
|
||||
if (gdisp->disp_yoffset)
|
||||
{
|
||||
gdisplay_expose_area (gdisp, 0, 0, gdisp->disp_width,
|
||||
gdisp->disp_yoffset);
|
||||
gdisplay_expose_area (gdisp, 0, gdisp->disp_yoffset + y,
|
||||
gdisp->disp_width, gdisp->disp_height);
|
||||
}
|
||||
if (gdisp->disp_xoffset)
|
||||
{
|
||||
gdisplay_expose_area (gdisp, 0, 0, gdisp->disp_xoffset,
|
||||
gdisp->disp_height);
|
||||
gdisplay_expose_area (gdisp, gdisp->disp_xoffset + x, 0,
|
||||
gdisp->disp_width, gdisp->disp_height);
|
||||
}
|
||||
}
|
||||
gdisplays_flush ();
|
||||
|
||||
if (new_ui)
|
||||
{
|
||||
transform_core_reset (tool, gdisp_ptr);
|
||||
}
|
||||
|
||||
/* if this tool is non-interactive, make it inactive after use */
|
||||
if (!transform_core->interactive)
|
||||
tool->state = INACTIVE;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
transform_core_motion (tool, mevent, gdisp_ptr)
|
||||
Tool *tool;
|
||||
|
@ -497,6 +564,29 @@ 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;
|
||||
|
||||
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 */
|
||||
gdk_draw_rectangle (transform_core->core->win, transform_core->core->gc, 0,
|
||||
x1 - (srw >> 1), y1 - (srh >> 1), srw, srh);
|
||||
|
@ -535,6 +625,17 @@ transform_core_new (type, interactive)
|
|||
for (i = 0; i < TRAN_INFO_SIZE; i++)
|
||||
private->trans_info[i] = 0;
|
||||
|
||||
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 */
|
||||
|
@ -577,6 +678,10 @@ transform_core_free (tool)
|
|||
info_dialog_free (transform_info);
|
||||
transform_info = NULL;
|
||||
|
||||
/* Free the grid line endpoint arrays */
|
||||
g_free (transform_core->grid_coords);
|
||||
g_free (transform_core->tgrid_coords);
|
||||
|
||||
/* Finally, free the transform tool itself */
|
||||
g_free (transform_core);
|
||||
}
|
||||
|
@ -601,6 +706,24 @@ transform_bounding_box (tool)
|
|||
transform_point (transform_core->transform,
|
||||
transform_core->x2, transform_core->y2,
|
||||
&transform_core->tx4, &transform_core->ty4);
|
||||
|
||||
if (new_ui)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -852,6 +975,58 @@ transform_core_bounds (tool, gdisp_ptr)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
transform_core_setup_grid (tool)
|
||||
Tool *tool;
|
||||
{
|
||||
TransformCore * transform_core;
|
||||
int i, gci;
|
||||
double *coords;
|
||||
|
||||
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
|
||||
* operation, nothing happens.
|
||||
*/
|
||||
transform_core->ngx =
|
||||
(transform_core->x2 - transform_core->x1) / transform_tool_grid_size ();
|
||||
if (transform_core->ngx > 0)
|
||||
transform_core->ngx--;
|
||||
transform_core->ngy =
|
||||
(transform_core->y2 - transform_core->y1) / transform_tool_grid_size ();
|
||||
if (transform_core->ngy > 0)
|
||||
transform_core->ngy--;
|
||||
transform_core->grid_coords = coords = (double *)
|
||||
g_malloc ((transform_core->ngx + transform_core->ngy) * 4
|
||||
* sizeof(double));
|
||||
transform_core->tgrid_coords = (double *)
|
||||
g_malloc ((transform_core->ngx + transform_core->ngy) * 4
|
||||
* sizeof(double));
|
||||
|
||||
gci = 0;
|
||||
for (i = 1; i <= transform_core->ngx; i++)
|
||||
{
|
||||
coords[gci] = transform_core->x1 +
|
||||
((double) i)/(transform_core->ngx + 1) *
|
||||
(transform_core->x2 - transform_core->x1);
|
||||
coords[gci+1] = transform_core->y1;
|
||||
coords[gci+2] = coords[gci];
|
||||
coords[gci+3] = transform_core->y2;
|
||||
gci += 4;
|
||||
}
|
||||
for (i = 1; i <= transform_core->ngy; i++)
|
||||
{
|
||||
coords[gci] = transform_core->x1;
|
||||
coords[gci+1] = transform_core->y1 +
|
||||
((double) i)/(transform_core->ngy + 1) *
|
||||
(transform_core->y2 - transform_core->y1);
|
||||
coords[gci+2] = transform_core->x2;
|
||||
coords[gci+3] = coords[gci+1];
|
||||
gci += 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void *
|
||||
transform_core_recalc (tool, gdisp_ptr)
|
||||
Tool * tool;
|
||||
|
@ -877,6 +1052,7 @@ transform_core_do (gimage, drawable, float_tiles, interpolation, matrix)
|
|||
PixelRegion destPR;
|
||||
TileManager *tiles;
|
||||
Matrix m;
|
||||
Matrix im;
|
||||
int itx, ity;
|
||||
int tx1, ty1, tx2, ty2;
|
||||
int width, height;
|
||||
|
@ -926,6 +1102,12 @@ transform_core_do (gimage, drawable, float_tiles, interpolation, matrix)
|
|||
break;
|
||||
}
|
||||
|
||||
if (new_ui)
|
||||
{
|
||||
invert (matrix, im);
|
||||
matrix = im;
|
||||
}
|
||||
|
||||
/* Find the inverse of the transformation matrix */
|
||||
invert (matrix, m);
|
||||
|
||||
|
|
|
@ -93,6 +93,14 @@ 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
|
||||
endpoints (a total of (ngx+ngy)*2
|
||||
coordinate pairs) */
|
||||
double *tgrid_coords; /* transformed grid_coords */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -30,6 +30,8 @@ typedef struct _TransformOptions TransformOptions;
|
|||
struct _TransformOptions
|
||||
{
|
||||
int smoothing;
|
||||
int new_ui;
|
||||
int grid_size;
|
||||
ToolType type;
|
||||
};
|
||||
|
||||
|
@ -71,6 +73,7 @@ create_transform_options (void)
|
|||
GtkWidget *radio_box;
|
||||
GtkWidget *radio_button;
|
||||
GtkWidget *smoothing_toggle;
|
||||
GtkWidget *new_ui_toggle;
|
||||
GSList *group = NULL;
|
||||
int i;
|
||||
char *button_names[4] =
|
||||
|
@ -126,6 +129,19 @@ create_transform_options (void)
|
|||
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",
|
||||
(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);
|
||||
|
||||
/* the grid size entry */
|
||||
options->grid_size = 32; /* XXX */
|
||||
|
||||
/* Register this selection options widget with the main tools options dialog */
|
||||
tools_register_options (ROTATE, vbox);
|
||||
tools_register_options (SCALE, vbox);
|
||||
|
@ -203,3 +219,21 @@ transform_tool_smoothing ()
|
|||
else
|
||||
return transform_options->smoothing;
|
||||
}
|
||||
|
||||
int
|
||||
transform_tool_new_ui ()
|
||||
{
|
||||
if (!transform_options)
|
||||
return 1;
|
||||
else
|
||||
return transform_options->new_ui;
|
||||
}
|
||||
|
||||
int
|
||||
transform_tool_grid_size ()
|
||||
{
|
||||
if (!transform_options)
|
||||
return 32;
|
||||
else
|
||||
return transform_options->grid_size;
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
/* tool functions */
|
||||
Tool * tools_new_transform_tool (void);
|
||||
void tools_free_transform_tool (Tool *);
|
||||
int transform_tool_smoothing (void);
|
||||
int transform_tool_smoothing (void);
|
||||
int transform_tool_new_ui (void);
|
||||
int transform_tool_grid_size (void);
|
||||
|
||||
#endif /* __TRANSFORM_TOOL_H__ */
|
||||
|
|
Loading…
Reference in New Issue