Total crop-tool massacre.

--Sven
This commit is contained in:
Sven Neumann 1999-04-08 05:20:37 +00:00
parent 9a4edab746
commit 4dca1d5640
7 changed files with 761 additions and 150 deletions

View File

@ -1,3 +1,17 @@
Thu Apr 8 07:12:10 MEST 1999 Sven Neumann <sven@gimp.org>
* app/crop.[ch]: Ok, this is a little bit more than what we
discussed on the list: Basically, it allows to use the crop
tool as usual or as a resize-tool for layers and the image.
The defaults are the new behaviour. Holding the <Alt>-Key
when creating the selection toggles the "Allow-expand" mode,
holding the <Shift>-key when cropping, gives you the opposite
of your default setting for "Crop layers".
The button for "Selection" is gone, but will reappear somewhere
else soon. But first, I need some sleep...
Wed Apr 7 23:53:22 BST 1999 Andy Thomas <alt@gimp.org> Wed Apr 7 23:53:22 BST 1999 Andy Thomas <alt@gimp.org>
Changed:- Changed:-

View File

@ -63,6 +63,7 @@ struct _crop
#define RESIZING_LEFT 2 #define RESIZING_LEFT 2
#define RESIZING_RIGHT 3 #define RESIZING_RIGHT 3
#define CROPPING 4 #define CROPPING 4
#define REFRAMING 5
/* speed of key movement */ /* speed of key movement */
#define ARROW_VELOCITY 25 #define ARROW_VELOCITY 25
@ -84,7 +85,7 @@ static void crop_arrow_keys_func (Tool *, GdkEventKey *, gpointer);
/* Crop helper functions */ /* Crop helper functions */
static void crop_image (GImage *gimage, int, int, int, int); static void crop_image (GImage *gimage, int, int, int, int, int, int);
static void crop_recalc (Tool *, Crop *); static void crop_recalc (Tool *, Crop *);
static void crop_start (Tool *, Crop *); static void crop_start (Tool *, Crop *);
static void crop_adjust_guides (GImage *, int, int, int, int); static void crop_adjust_guides (GImage *, int, int, int, int);
@ -93,6 +94,7 @@ static void crop_adjust_guides (GImage *, int, int, int, int);
static void crop_info_update (Tool *); static void crop_info_update (Tool *);
static void crop_info_create (Tool *); static void crop_info_create (Tool *);
static void crop_ok_callback (GtkWidget *, gpointer); static void crop_ok_callback (GtkWidget *, gpointer);
static void crop_resize_callback (GtkWidget *, gpointer);
static void crop_selection_callback (GtkWidget *, gpointer); static void crop_selection_callback (GtkWidget *, gpointer);
static void crop_close_callback (GtkWidget *, gpointer); static void crop_close_callback (GtkWidget *, gpointer);
@ -117,6 +119,12 @@ init_crop_options()
GtkWidget *vbox; GtkWidget *vbox;
GtkWidget *label; GtkWidget *label;
GtkWidget *checkbutton; GtkWidget *checkbutton;
GtkWidget *defaults_frame;
GtkWidget *defaults_box;
options.layer_only = FALSE;
options.default_to_enlarge = TRUE;
options.default_to_crop = FALSE;
/* the main vbox */ /* the main vbox */
vbox = gtk_vbox_new (FALSE, 2); vbox = gtk_vbox_new (FALSE, 2);
@ -137,6 +145,38 @@ init_crop_options()
options.layer_only); options.layer_only);
gtk_widget_show(checkbutton); gtk_widget_show(checkbutton);
/* defaults */
defaults_frame = gtk_frame_new (_("Defaults"));
gtk_box_pack_start (GTK_BOX (vbox), defaults_frame, FALSE, FALSE, 0);
defaults_box = gtk_vbox_new (FALSE, 1);
gtk_container_add (GTK_CONTAINER (defaults_frame), defaults_box);
/* enlarge toggle */
checkbutton = gtk_check_button_new_with_label(_("Allow Enlarging"));
gtk_box_pack_start(GTK_BOX(defaults_box), checkbutton,
FALSE, FALSE, 0);
gtk_signal_connect(GTK_OBJECT(checkbutton), "toggled",
(GtkSignalFunc) crop_checkbutton_update,
&options.default_to_enlarge);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton),
options.default_to_enlarge);
gtk_widget_show(checkbutton);
/* crop toggle */
checkbutton = gtk_check_button_new_with_label(_("Crop Layers"));
gtk_box_pack_start(GTK_BOX(defaults_box), checkbutton,
FALSE, FALSE, 0);
gtk_signal_connect(GTK_OBJECT(checkbutton), "toggled",
(GtkSignalFunc) crop_checkbutton_update,
&options.default_to_crop);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton),
options.default_to_crop);
gtk_widget_show(checkbutton);
gtk_widget_show (defaults_box);
gtk_widget_show (defaults_frame);
/* Register this selection options widget with the main tools /* Register this selection options widget with the main tools
* options dialog */ * options dialog */
@ -157,7 +197,6 @@ crop_checkbutton_update (GtkWidget *w,
*toggle_val = FALSE; *toggle_val = FALSE;
} }
static void static void
crop_button_press (Tool *tool, crop_button_press (Tool *tool,
GdkEventButton *bevent, GdkEventButton *bevent,
@ -192,11 +231,25 @@ crop_button_press (Tool *tool,
bevent->y == BOUNDS (bevent->y, crop->y1, crop->y1 + crop->srh))) bevent->y == BOUNDS (bevent->y, crop->y1, crop->y1 + crop->srh)))
crop->function = MOVING; crop->function = MOVING;
/* If the pointer is in the rectangular region, crop it! */ /* If the pointer is in the rectangular region, crop or resize it! */
else if (bevent->x > crop->x1 && bevent->x < crop->x2 && else if (bevent->x > crop->x1 && bevent->x < crop->x2 &&
bevent->y > crop->y1 && bevent->y < crop->y2) bevent->y > crop->y1 && bevent->y < crop->y2)
{
if ( options.default_to_crop )
{
if ( bevent->state & GDK_SHIFT_MASK )
crop->function = REFRAMING;
else
crop->function = CROPPING; crop->function = CROPPING;
}
else
{
if ( bevent->state & GDK_SHIFT_MASK )
crop->function = CROPPING;
else
crop->function = REFRAMING;
}
}
/* otherwise, the new function will be creating, since we want to start anew */ /* otherwise, the new function will be creating, since we want to start anew */
else else
crop->function = CREATING; crop->function = CREATING;
@ -247,10 +300,17 @@ crop_button_release (Tool *tool,
if (! (bevent->state & GDK_BUTTON3_MASK)) if (! (bevent->state & GDK_BUTTON3_MASK))
{ {
if (crop->function == CROPPING) switch (crop->function)
crop_image (gdisp->gimage, crop->tx1, crop->ty1, crop->tx2, crop->ty2);
else
{ {
case CROPPING:
crop_image (gdisp->gimage, crop->tx1, crop->ty1, crop->tx2, crop->ty2,
options.layer_only, TRUE);
break;
case REFRAMING:
crop_image (gdisp->gimage, crop->tx1, crop->ty1, crop->tx2, crop->ty2,
options.layer_only, FALSE);
break;
default:
crop_info_update (tool); crop_info_update (tool);
return; return;
} }
@ -316,17 +376,19 @@ crop_motion (Tool *tool,
{ {
Crop * crop; Crop * crop;
GDisplay * gdisp; GDisplay * gdisp;
Layer * layer;
int x1, y1, x2, y2; int x1, y1, x2, y2;
int curx, cury; int curx, cury;
int inc_x, inc_y; int inc_x, inc_y;
gchar size[STATUSBAR_SIZE]; gchar size[STATUSBAR_SIZE];
int clamp;
int min_x, min_y, max_x, max_y;
crop = (Crop *) tool->private; crop = (Crop *) tool->private;
gdisp = (GDisplay *) gdisp_ptr; gdisp = (GDisplay *) gdisp_ptr;
/* This is the only case when the motion events should be ignored-- /* This is the only case when the motion events should be ignored--
we're just waiting for the button release event to crop the image */ we're just waiting for the button release event to crop the image */
if (crop->function == CROPPING) if (crop->function == CROPPING || crop->function == REFRAMING)
return; return;
gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &curx, &cury, TRUE, FALSE); gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &curx, &cury, TRUE, FALSE);
@ -344,18 +406,56 @@ crop_motion (Tool *tool,
draw_core_pause (crop->core, tool); draw_core_pause (crop->core, tool);
/* shall we clamp the coordinates to the image dimensions? */
if (options.default_to_enlarge)
{
if (mevent->state & GDK_MOD1_MASK)
clamp = TRUE;
else
clamp = FALSE;
}
else
{
if (mevent->state & GDK_MOD1_MASK)
clamp = FALSE;
else
clamp = TRUE;
}
if (options.layer_only)
{
layer = (gdisp->gimage)->active_layer;
drawable_offsets (GIMP_DRAWABLE(layer), &min_x, &min_y);
max_x = drawable_width (GIMP_DRAWABLE(layer)) + min_x;
max_y = drawable_height (GIMP_DRAWABLE(layer)) + min_y;
}
else
{
min_x = min_y = 0;
max_x = gdisp->gimage->width;
max_y = gdisp->gimage->height;
}
switch (crop->function) switch (crop->function)
{ {
case CREATING : case CREATING :
x1 = BOUNDS (x1, 0, gdisp->gimage->width); if (clamp)
y1 = BOUNDS (y1, 0, gdisp->gimage->height); {
x2 = BOUNDS (x2, 0, gdisp->gimage->width); x1 = BOUNDS (x1, min_x, max_x);
y2 = BOUNDS (y2, 0, gdisp->gimage->height); y1 = BOUNDS (y1, min_y, max_y);
x2 = BOUNDS (x2, min_x, max_x);
y2 = BOUNDS (y2, min_y, max_y);
}
break; break;
case RESIZING_LEFT : case RESIZING_LEFT :
x1 = BOUNDS (crop->tx1 + inc_x, 0, gdisp->gimage->width); x1 = crop->tx1 + inc_x;
y1 = BOUNDS (crop->ty1 + inc_y, 0, gdisp->gimage->height); y1 = crop->ty1 + inc_y;
if (clamp)
{
x1 = BOUNDS (x1, min_x, max_x);
y1 = BOUNDS (y1, min_y, max_y);
}
x2 = MAXIMUM (x1, crop->tx2); x2 = MAXIMUM (x1, crop->tx2);
y2 = MAXIMUM (y1, crop->ty2); y2 = MAXIMUM (y1, crop->ty2);
crop->startx = curx; crop->startx = curx;
@ -363,8 +463,13 @@ crop_motion (Tool *tool,
break; break;
case RESIZING_RIGHT : case RESIZING_RIGHT :
x2 = BOUNDS (crop->tx2 + inc_x, 0, gdisp->gimage->width); x2 = crop->tx2 + inc_x;
y2 = BOUNDS (crop->ty2 + inc_y, 0, gdisp->gimage->height); y2 = crop->ty2 + inc_y;
if (clamp)
{
x2 = BOUNDS (x2, min_x, max_x);
y2 = BOUNDS (y2, min_y, max_y);
}
x1 = MINIMUM (crop->tx1, x2); x1 = MINIMUM (crop->tx1, x2);
y1 = MINIMUM (crop->ty1, y2); y1 = MINIMUM (crop->ty1, y2);
crop->startx = curx; crop->startx = curx;
@ -372,8 +477,11 @@ crop_motion (Tool *tool,
break; break;
case MOVING : case MOVING :
inc_x = BOUNDS (inc_x, -crop->tx1, gdisp->gimage->width - crop->tx2); if (clamp)
inc_y = BOUNDS (inc_y, -crop->ty1, gdisp->gimage->height - crop->ty2); {
inc_x = BOUNDS (inc_x, min_x - crop->tx1, max_x - crop->tx2);
inc_y = BOUNDS (inc_y, min_y - crop->ty1, max_y - crop->ty2);
}
x1 = crop->tx1 + inc_x; x1 = crop->tx1 + inc_x;
x2 = crop->tx2 + inc_x; x2 = crop->tx2 + inc_x;
y1 = crop->ty1 + inc_y; y1 = crop->ty1 + inc_y;
@ -456,7 +564,22 @@ crop_cursor_update (Tool *tool,
ctype = GDK_FLEUR; ctype = GDK_FLEUR;
else if (mevent->x > crop->x1 && mevent->x < crop->x2 && else if (mevent->x > crop->x1 && mevent->x < crop->x2 &&
mevent->y > crop->y1 && mevent->y < crop->y2) mevent->y > crop->y1 && mevent->y < crop->y2)
{
if ( options.default_to_crop )
{
if ( mevent->state & GDK_SHIFT_MASK )
ctype = GDK_SIZING;
else
ctype = GDK_ICON; ctype = GDK_ICON;
}
else
{
if ( mevent->state & GDK_SHIFT_MASK )
ctype = GDK_ICON;
else
ctype = GDK_SIZING;
}
}
else else
ctype = GDK_CROSS; ctype = GDK_CROSS;
@ -470,7 +593,10 @@ crop_arrow_keys_func (Tool *tool,
{ {
int inc_x, inc_y; int inc_x, inc_y;
GDisplay * gdisp; GDisplay * gdisp;
Layer * layer;
Crop * crop; Crop * crop;
int clamp;
int min_x, min_y, max_x, max_y;
gdisp = (GDisplay *) gdisp_ptr; gdisp = (GDisplay *) gdisp_ptr;
@ -496,17 +622,55 @@ crop_arrow_keys_func (Tool *tool,
draw_core_pause (crop->core, tool); draw_core_pause (crop->core, tool);
/* shall we clamp the coordinates to the image dimensions? */
if (options.default_to_enlarge)
{
if (kevent->state & GDK_MOD1_MASK)
clamp = TRUE;
else
clamp = FALSE;
}
else
{
if (kevent->state & GDK_MOD1_MASK)
clamp = FALSE;
else
clamp = TRUE;
}
if (options.layer_only)
{
layer = (gdisp->gimage)->active_layer;
drawable_offsets (GIMP_DRAWABLE(layer), &min_x, &min_y);
max_x = drawable_width (GIMP_DRAWABLE(layer)) + min_x;
max_y = drawable_height (GIMP_DRAWABLE(layer)) + min_y;
}
else
{
min_x = min_y = 0;
max_x = gdisp->gimage->width;
max_y = gdisp->gimage->height;
}
if (kevent->state & GDK_CONTROL_MASK) /* RESIZING */ if (kevent->state & GDK_CONTROL_MASK) /* RESIZING */
{ {
crop->tx2 = BOUNDS (crop->tx2 + inc_x, 0, gdisp->gimage->width); crop->tx2 = crop->tx2 + inc_x;
crop->ty2 = BOUNDS (crop->ty2 + inc_y, 0, gdisp->gimage->height); crop->ty2 = crop->ty2 + inc_y;
if (clamp)
{
crop->tx2 = BOUNDS (crop->tx2, min_x, max_x);
crop->ty2 = BOUNDS (crop->ty2, min_y, max_y);
}
crop->tx1 = MINIMUM (crop->tx1, crop->tx2); crop->tx1 = MINIMUM (crop->tx1, crop->tx2);
crop->ty1 = MINIMUM (crop->ty1, crop->ty2); crop->ty1 = MINIMUM (crop->ty1, crop->ty2);
} }
else else
{
if (clamp)
{ {
inc_x = BOUNDS (inc_x, -crop->tx1, gdisp->gimage->width - crop->tx2); inc_x = BOUNDS (inc_x, -crop->tx1, gdisp->gimage->width - crop->tx2);
inc_y = BOUNDS (inc_y, -crop->ty1, gdisp->gimage->height - crop->ty2); inc_y = BOUNDS (inc_y, -crop->ty1, gdisp->gimage->height - crop->ty2);
}
crop->tx1 += inc_x; crop->tx1 += inc_x;
crop->tx2 += inc_x; crop->tx2 += inc_x;
crop->ty1 += inc_y; crop->ty1 += inc_y;
@ -638,7 +802,9 @@ crop_image (GImage *gimage,
int x1, int x1,
int y1, int y1,
int x2, int x2,
int y2) int y2,
int layer_only,
int crop_layers)
{ {
Layer *layer; Layer *layer;
Layer *floating_layer; Layer *floating_layer;
@ -659,7 +825,7 @@ crop_image (GImage *gimage,
{ {
gimp_add_busy_cursors(); gimp_add_busy_cursors();
if (options.layer_only) if (layer_only)
{ {
undo_push_group_start (gimage, LAYER_RESIZE_UNDO); undo_push_group_start (gimage, LAYER_RESIZE_UNDO);
@ -718,6 +884,8 @@ crop_image (GImage *gimage,
layer_translate (layer, -x1, -y1); layer_translate (layer, -x1, -y1);
if (crop_layers)
{
drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y); drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y);
lx1 = BOUNDS (off_x, 0, gimage->width); lx1 = BOUNDS (off_x, 0, gimage->width);
@ -727,8 +895,6 @@ crop_image (GImage *gimage,
width = lx2 - lx1; width = lx2 - lx1;
height = ly2 - ly1; height = ly2 - ly1;
list = g_slist_next (list);
if (width && height) if (width && height)
layer_resize (layer, width, height, layer_resize (layer, width, height,
-(lx1 - off_x), -(lx1 - off_x),
@ -737,6 +903,9 @@ crop_image (GImage *gimage,
gimage_remove_layer (gimage, layer); gimage_remove_layer (gimage, layer);
} }
list = g_slist_next (list);
}
/* Make sure the projection matches the gimage size */ /* Make sure the projection matches the gimage size */
gimage_projection_realloc (gimage); gimage_projection_realloc (gimage);
@ -839,10 +1008,11 @@ crop_start (Tool *tool,
/* Crop dialog functions */ /* Crop dialog functions */
/*******************************************************/ /*******************************************************/
static ActionAreaItem action_items[3] = static ActionAreaItem action_items[4] =
{ {
{ N_("Crop"), crop_ok_callback, NULL, NULL }, { N_("Crop"), crop_ok_callback, NULL, NULL },
{ N_("Selection"), crop_selection_callback, NULL, NULL }, { N_("Resize"), crop_resize_callback, NULL, NULL },
/* { N_("Selection"), crop_selection_callback, NULL, NULL }, */
{ N_("Close"), crop_close_callback, NULL, NULL }, { N_("Close"), crop_close_callback, NULL, NULL },
}; };
@ -949,7 +1119,28 @@ crop_ok_callback (GtkWidget *w,
tool = active_tool; tool = active_tool;
crop = (Crop *) tool->private; crop = (Crop *) tool->private;
gdisp = (GDisplay *) tool->gdisp_ptr; gdisp = (GDisplay *) tool->gdisp_ptr;
crop_image (gdisp->gimage, crop->tx1, crop->ty1, crop->tx2, crop->ty2); crop_image (gdisp->gimage, crop->tx1, crop->ty1, crop->tx2, crop->ty2,
options.layer_only, TRUE);
/* Finish the tool */
draw_core_stop (crop->core, tool);
info_dialog_popdown (crop_info);
tool->state = INACTIVE;
}
static void
crop_resize_callback (GtkWidget *w,
gpointer client_data)
{
Tool * tool;
Crop * crop;
GDisplay * gdisp;
tool = active_tool;
crop = (Crop *) tool->private;
gdisp = (GDisplay *) tool->gdisp_ptr;
crop_image (gdisp->gimage, crop->tx1, crop->ty1, crop->tx2, crop->ty2,
options.layer_only, FALSE);
/* Finish the tool */ /* Finish the tool */
draw_core_stop (crop->core, tool); draw_core_stop (crop->core, tool);
@ -1113,11 +1304,14 @@ crop_invoker (Argument *args)
int int_value; int int_value;
int new_width, new_height; int new_width, new_height;
int offx, offy; int offx, offy;
int layer_only, crop_layers ;
new_width = 1; new_width = 1;
new_height = 1; new_height = 1;
offx = 0; offx = 0;
offy = 0; offy = 0;
layer_only = FALSE;
crop_layers = TRUE;
success = TRUE; success = TRUE;
if (success) if (success)
@ -1147,7 +1341,8 @@ crop_invoker (Argument *args)
success = FALSE; success = FALSE;
if (success) if (success)
crop_image (gimage, offx, offy, offx + new_width, offy + new_height); crop_image (gimage, offx, offy, offx + new_width, offy + new_height,
layer_only, crop_layers);
return procedural_db_return_args (&crop_proc, success); return procedural_db_return_args (&crop_proc, success);
} }

View File

@ -29,6 +29,8 @@ void tools_free_crop (Tool *);
/* tool options */ /* tool options */
typedef struct { typedef struct {
int layer_only; int layer_only;
int default_to_enlarge;
int default_to_crop;
} CropToolOptions; } CropToolOptions;
@ -36,3 +38,5 @@ typedef struct {
extern ProcRecord crop_proc; extern ProcRecord crop_proc;
#endif /* __CROP_H__ */ #endif /* __CROP_H__ */

View File

@ -63,6 +63,7 @@ struct _crop
#define RESIZING_LEFT 2 #define RESIZING_LEFT 2
#define RESIZING_RIGHT 3 #define RESIZING_RIGHT 3
#define CROPPING 4 #define CROPPING 4
#define REFRAMING 5
/* speed of key movement */ /* speed of key movement */
#define ARROW_VELOCITY 25 #define ARROW_VELOCITY 25
@ -84,7 +85,7 @@ static void crop_arrow_keys_func (Tool *, GdkEventKey *, gpointer);
/* Crop helper functions */ /* Crop helper functions */
static void crop_image (GImage *gimage, int, int, int, int); static void crop_image (GImage *gimage, int, int, int, int, int, int);
static void crop_recalc (Tool *, Crop *); static void crop_recalc (Tool *, Crop *);
static void crop_start (Tool *, Crop *); static void crop_start (Tool *, Crop *);
static void crop_adjust_guides (GImage *, int, int, int, int); static void crop_adjust_guides (GImage *, int, int, int, int);
@ -93,6 +94,7 @@ static void crop_adjust_guides (GImage *, int, int, int, int);
static void crop_info_update (Tool *); static void crop_info_update (Tool *);
static void crop_info_create (Tool *); static void crop_info_create (Tool *);
static void crop_ok_callback (GtkWidget *, gpointer); static void crop_ok_callback (GtkWidget *, gpointer);
static void crop_resize_callback (GtkWidget *, gpointer);
static void crop_selection_callback (GtkWidget *, gpointer); static void crop_selection_callback (GtkWidget *, gpointer);
static void crop_close_callback (GtkWidget *, gpointer); static void crop_close_callback (GtkWidget *, gpointer);
@ -117,6 +119,12 @@ init_crop_options()
GtkWidget *vbox; GtkWidget *vbox;
GtkWidget *label; GtkWidget *label;
GtkWidget *checkbutton; GtkWidget *checkbutton;
GtkWidget *defaults_frame;
GtkWidget *defaults_box;
options.layer_only = FALSE;
options.default_to_enlarge = TRUE;
options.default_to_crop = FALSE;
/* the main vbox */ /* the main vbox */
vbox = gtk_vbox_new (FALSE, 2); vbox = gtk_vbox_new (FALSE, 2);
@ -137,6 +145,38 @@ init_crop_options()
options.layer_only); options.layer_only);
gtk_widget_show(checkbutton); gtk_widget_show(checkbutton);
/* defaults */
defaults_frame = gtk_frame_new (_("Defaults"));
gtk_box_pack_start (GTK_BOX (vbox), defaults_frame, FALSE, FALSE, 0);
defaults_box = gtk_vbox_new (FALSE, 1);
gtk_container_add (GTK_CONTAINER (defaults_frame), defaults_box);
/* enlarge toggle */
checkbutton = gtk_check_button_new_with_label(_("Allow Enlarging"));
gtk_box_pack_start(GTK_BOX(defaults_box), checkbutton,
FALSE, FALSE, 0);
gtk_signal_connect(GTK_OBJECT(checkbutton), "toggled",
(GtkSignalFunc) crop_checkbutton_update,
&options.default_to_enlarge);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton),
options.default_to_enlarge);
gtk_widget_show(checkbutton);
/* crop toggle */
checkbutton = gtk_check_button_new_with_label(_("Crop Layers"));
gtk_box_pack_start(GTK_BOX(defaults_box), checkbutton,
FALSE, FALSE, 0);
gtk_signal_connect(GTK_OBJECT(checkbutton), "toggled",
(GtkSignalFunc) crop_checkbutton_update,
&options.default_to_crop);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton),
options.default_to_crop);
gtk_widget_show(checkbutton);
gtk_widget_show (defaults_box);
gtk_widget_show (defaults_frame);
/* Register this selection options widget with the main tools /* Register this selection options widget with the main tools
* options dialog */ * options dialog */
@ -157,7 +197,6 @@ crop_checkbutton_update (GtkWidget *w,
*toggle_val = FALSE; *toggle_val = FALSE;
} }
static void static void
crop_button_press (Tool *tool, crop_button_press (Tool *tool,
GdkEventButton *bevent, GdkEventButton *bevent,
@ -192,11 +231,25 @@ crop_button_press (Tool *tool,
bevent->y == BOUNDS (bevent->y, crop->y1, crop->y1 + crop->srh))) bevent->y == BOUNDS (bevent->y, crop->y1, crop->y1 + crop->srh)))
crop->function = MOVING; crop->function = MOVING;
/* If the pointer is in the rectangular region, crop it! */ /* If the pointer is in the rectangular region, crop or resize it! */
else if (bevent->x > crop->x1 && bevent->x < crop->x2 && else if (bevent->x > crop->x1 && bevent->x < crop->x2 &&
bevent->y > crop->y1 && bevent->y < crop->y2) bevent->y > crop->y1 && bevent->y < crop->y2)
{
if ( options.default_to_crop )
{
if ( bevent->state & GDK_SHIFT_MASK )
crop->function = REFRAMING;
else
crop->function = CROPPING; crop->function = CROPPING;
}
else
{
if ( bevent->state & GDK_SHIFT_MASK )
crop->function = CROPPING;
else
crop->function = REFRAMING;
}
}
/* otherwise, the new function will be creating, since we want to start anew */ /* otherwise, the new function will be creating, since we want to start anew */
else else
crop->function = CREATING; crop->function = CREATING;
@ -247,10 +300,17 @@ crop_button_release (Tool *tool,
if (! (bevent->state & GDK_BUTTON3_MASK)) if (! (bevent->state & GDK_BUTTON3_MASK))
{ {
if (crop->function == CROPPING) switch (crop->function)
crop_image (gdisp->gimage, crop->tx1, crop->ty1, crop->tx2, crop->ty2);
else
{ {
case CROPPING:
crop_image (gdisp->gimage, crop->tx1, crop->ty1, crop->tx2, crop->ty2,
options.layer_only, TRUE);
break;
case REFRAMING:
crop_image (gdisp->gimage, crop->tx1, crop->ty1, crop->tx2, crop->ty2,
options.layer_only, FALSE);
break;
default:
crop_info_update (tool); crop_info_update (tool);
return; return;
} }
@ -316,17 +376,19 @@ crop_motion (Tool *tool,
{ {
Crop * crop; Crop * crop;
GDisplay * gdisp; GDisplay * gdisp;
Layer * layer;
int x1, y1, x2, y2; int x1, y1, x2, y2;
int curx, cury; int curx, cury;
int inc_x, inc_y; int inc_x, inc_y;
gchar size[STATUSBAR_SIZE]; gchar size[STATUSBAR_SIZE];
int clamp;
int min_x, min_y, max_x, max_y;
crop = (Crop *) tool->private; crop = (Crop *) tool->private;
gdisp = (GDisplay *) gdisp_ptr; gdisp = (GDisplay *) gdisp_ptr;
/* This is the only case when the motion events should be ignored-- /* This is the only case when the motion events should be ignored--
we're just waiting for the button release event to crop the image */ we're just waiting for the button release event to crop the image */
if (crop->function == CROPPING) if (crop->function == CROPPING || crop->function == REFRAMING)
return; return;
gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &curx, &cury, TRUE, FALSE); gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &curx, &cury, TRUE, FALSE);
@ -344,18 +406,56 @@ crop_motion (Tool *tool,
draw_core_pause (crop->core, tool); draw_core_pause (crop->core, tool);
/* shall we clamp the coordinates to the image dimensions? */
if (options.default_to_enlarge)
{
if (mevent->state & GDK_MOD1_MASK)
clamp = TRUE;
else
clamp = FALSE;
}
else
{
if (mevent->state & GDK_MOD1_MASK)
clamp = FALSE;
else
clamp = TRUE;
}
if (options.layer_only)
{
layer = (gdisp->gimage)->active_layer;
drawable_offsets (GIMP_DRAWABLE(layer), &min_x, &min_y);
max_x = drawable_width (GIMP_DRAWABLE(layer)) + min_x;
max_y = drawable_height (GIMP_DRAWABLE(layer)) + min_y;
}
else
{
min_x = min_y = 0;
max_x = gdisp->gimage->width;
max_y = gdisp->gimage->height;
}
switch (crop->function) switch (crop->function)
{ {
case CREATING : case CREATING :
x1 = BOUNDS (x1, 0, gdisp->gimage->width); if (clamp)
y1 = BOUNDS (y1, 0, gdisp->gimage->height); {
x2 = BOUNDS (x2, 0, gdisp->gimage->width); x1 = BOUNDS (x1, min_x, max_x);
y2 = BOUNDS (y2, 0, gdisp->gimage->height); y1 = BOUNDS (y1, min_y, max_y);
x2 = BOUNDS (x2, min_x, max_x);
y2 = BOUNDS (y2, min_y, max_y);
}
break; break;
case RESIZING_LEFT : case RESIZING_LEFT :
x1 = BOUNDS (crop->tx1 + inc_x, 0, gdisp->gimage->width); x1 = crop->tx1 + inc_x;
y1 = BOUNDS (crop->ty1 + inc_y, 0, gdisp->gimage->height); y1 = crop->ty1 + inc_y;
if (clamp)
{
x1 = BOUNDS (x1, min_x, max_x);
y1 = BOUNDS (y1, min_y, max_y);
}
x2 = MAXIMUM (x1, crop->tx2); x2 = MAXIMUM (x1, crop->tx2);
y2 = MAXIMUM (y1, crop->ty2); y2 = MAXIMUM (y1, crop->ty2);
crop->startx = curx; crop->startx = curx;
@ -363,8 +463,13 @@ crop_motion (Tool *tool,
break; break;
case RESIZING_RIGHT : case RESIZING_RIGHT :
x2 = BOUNDS (crop->tx2 + inc_x, 0, gdisp->gimage->width); x2 = crop->tx2 + inc_x;
y2 = BOUNDS (crop->ty2 + inc_y, 0, gdisp->gimage->height); y2 = crop->ty2 + inc_y;
if (clamp)
{
x2 = BOUNDS (x2, min_x, max_x);
y2 = BOUNDS (y2, min_y, max_y);
}
x1 = MINIMUM (crop->tx1, x2); x1 = MINIMUM (crop->tx1, x2);
y1 = MINIMUM (crop->ty1, y2); y1 = MINIMUM (crop->ty1, y2);
crop->startx = curx; crop->startx = curx;
@ -372,8 +477,11 @@ crop_motion (Tool *tool,
break; break;
case MOVING : case MOVING :
inc_x = BOUNDS (inc_x, -crop->tx1, gdisp->gimage->width - crop->tx2); if (clamp)
inc_y = BOUNDS (inc_y, -crop->ty1, gdisp->gimage->height - crop->ty2); {
inc_x = BOUNDS (inc_x, min_x - crop->tx1, max_x - crop->tx2);
inc_y = BOUNDS (inc_y, min_y - crop->ty1, max_y - crop->ty2);
}
x1 = crop->tx1 + inc_x; x1 = crop->tx1 + inc_x;
x2 = crop->tx2 + inc_x; x2 = crop->tx2 + inc_x;
y1 = crop->ty1 + inc_y; y1 = crop->ty1 + inc_y;
@ -456,7 +564,22 @@ crop_cursor_update (Tool *tool,
ctype = GDK_FLEUR; ctype = GDK_FLEUR;
else if (mevent->x > crop->x1 && mevent->x < crop->x2 && else if (mevent->x > crop->x1 && mevent->x < crop->x2 &&
mevent->y > crop->y1 && mevent->y < crop->y2) mevent->y > crop->y1 && mevent->y < crop->y2)
{
if ( options.default_to_crop )
{
if ( mevent->state & GDK_SHIFT_MASK )
ctype = GDK_SIZING;
else
ctype = GDK_ICON; ctype = GDK_ICON;
}
else
{
if ( mevent->state & GDK_SHIFT_MASK )
ctype = GDK_ICON;
else
ctype = GDK_SIZING;
}
}
else else
ctype = GDK_CROSS; ctype = GDK_CROSS;
@ -470,7 +593,10 @@ crop_arrow_keys_func (Tool *tool,
{ {
int inc_x, inc_y; int inc_x, inc_y;
GDisplay * gdisp; GDisplay * gdisp;
Layer * layer;
Crop * crop; Crop * crop;
int clamp;
int min_x, min_y, max_x, max_y;
gdisp = (GDisplay *) gdisp_ptr; gdisp = (GDisplay *) gdisp_ptr;
@ -496,17 +622,55 @@ crop_arrow_keys_func (Tool *tool,
draw_core_pause (crop->core, tool); draw_core_pause (crop->core, tool);
/* shall we clamp the coordinates to the image dimensions? */
if (options.default_to_enlarge)
{
if (kevent->state & GDK_MOD1_MASK)
clamp = TRUE;
else
clamp = FALSE;
}
else
{
if (kevent->state & GDK_MOD1_MASK)
clamp = FALSE;
else
clamp = TRUE;
}
if (options.layer_only)
{
layer = (gdisp->gimage)->active_layer;
drawable_offsets (GIMP_DRAWABLE(layer), &min_x, &min_y);
max_x = drawable_width (GIMP_DRAWABLE(layer)) + min_x;
max_y = drawable_height (GIMP_DRAWABLE(layer)) + min_y;
}
else
{
min_x = min_y = 0;
max_x = gdisp->gimage->width;
max_y = gdisp->gimage->height;
}
if (kevent->state & GDK_CONTROL_MASK) /* RESIZING */ if (kevent->state & GDK_CONTROL_MASK) /* RESIZING */
{ {
crop->tx2 = BOUNDS (crop->tx2 + inc_x, 0, gdisp->gimage->width); crop->tx2 = crop->tx2 + inc_x;
crop->ty2 = BOUNDS (crop->ty2 + inc_y, 0, gdisp->gimage->height); crop->ty2 = crop->ty2 + inc_y;
if (clamp)
{
crop->tx2 = BOUNDS (crop->tx2, min_x, max_x);
crop->ty2 = BOUNDS (crop->ty2, min_y, max_y);
}
crop->tx1 = MINIMUM (crop->tx1, crop->tx2); crop->tx1 = MINIMUM (crop->tx1, crop->tx2);
crop->ty1 = MINIMUM (crop->ty1, crop->ty2); crop->ty1 = MINIMUM (crop->ty1, crop->ty2);
} }
else else
{
if (clamp)
{ {
inc_x = BOUNDS (inc_x, -crop->tx1, gdisp->gimage->width - crop->tx2); inc_x = BOUNDS (inc_x, -crop->tx1, gdisp->gimage->width - crop->tx2);
inc_y = BOUNDS (inc_y, -crop->ty1, gdisp->gimage->height - crop->ty2); inc_y = BOUNDS (inc_y, -crop->ty1, gdisp->gimage->height - crop->ty2);
}
crop->tx1 += inc_x; crop->tx1 += inc_x;
crop->tx2 += inc_x; crop->tx2 += inc_x;
crop->ty1 += inc_y; crop->ty1 += inc_y;
@ -638,7 +802,9 @@ crop_image (GImage *gimage,
int x1, int x1,
int y1, int y1,
int x2, int x2,
int y2) int y2,
int layer_only,
int crop_layers)
{ {
Layer *layer; Layer *layer;
Layer *floating_layer; Layer *floating_layer;
@ -659,7 +825,7 @@ crop_image (GImage *gimage,
{ {
gimp_add_busy_cursors(); gimp_add_busy_cursors();
if (options.layer_only) if (layer_only)
{ {
undo_push_group_start (gimage, LAYER_RESIZE_UNDO); undo_push_group_start (gimage, LAYER_RESIZE_UNDO);
@ -718,6 +884,8 @@ crop_image (GImage *gimage,
layer_translate (layer, -x1, -y1); layer_translate (layer, -x1, -y1);
if (crop_layers)
{
drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y); drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y);
lx1 = BOUNDS (off_x, 0, gimage->width); lx1 = BOUNDS (off_x, 0, gimage->width);
@ -727,8 +895,6 @@ crop_image (GImage *gimage,
width = lx2 - lx1; width = lx2 - lx1;
height = ly2 - ly1; height = ly2 - ly1;
list = g_slist_next (list);
if (width && height) if (width && height)
layer_resize (layer, width, height, layer_resize (layer, width, height,
-(lx1 - off_x), -(lx1 - off_x),
@ -737,6 +903,9 @@ crop_image (GImage *gimage,
gimage_remove_layer (gimage, layer); gimage_remove_layer (gimage, layer);
} }
list = g_slist_next (list);
}
/* Make sure the projection matches the gimage size */ /* Make sure the projection matches the gimage size */
gimage_projection_realloc (gimage); gimage_projection_realloc (gimage);
@ -839,10 +1008,11 @@ crop_start (Tool *tool,
/* Crop dialog functions */ /* Crop dialog functions */
/*******************************************************/ /*******************************************************/
static ActionAreaItem action_items[3] = static ActionAreaItem action_items[4] =
{ {
{ N_("Crop"), crop_ok_callback, NULL, NULL }, { N_("Crop"), crop_ok_callback, NULL, NULL },
{ N_("Selection"), crop_selection_callback, NULL, NULL }, { N_("Resize"), crop_resize_callback, NULL, NULL },
/* { N_("Selection"), crop_selection_callback, NULL, NULL }, */
{ N_("Close"), crop_close_callback, NULL, NULL }, { N_("Close"), crop_close_callback, NULL, NULL },
}; };
@ -949,7 +1119,28 @@ crop_ok_callback (GtkWidget *w,
tool = active_tool; tool = active_tool;
crop = (Crop *) tool->private; crop = (Crop *) tool->private;
gdisp = (GDisplay *) tool->gdisp_ptr; gdisp = (GDisplay *) tool->gdisp_ptr;
crop_image (gdisp->gimage, crop->tx1, crop->ty1, crop->tx2, crop->ty2); crop_image (gdisp->gimage, crop->tx1, crop->ty1, crop->tx2, crop->ty2,
options.layer_only, TRUE);
/* Finish the tool */
draw_core_stop (crop->core, tool);
info_dialog_popdown (crop_info);
tool->state = INACTIVE;
}
static void
crop_resize_callback (GtkWidget *w,
gpointer client_data)
{
Tool * tool;
Crop * crop;
GDisplay * gdisp;
tool = active_tool;
crop = (Crop *) tool->private;
gdisp = (GDisplay *) tool->gdisp_ptr;
crop_image (gdisp->gimage, crop->tx1, crop->ty1, crop->tx2, crop->ty2,
options.layer_only, FALSE);
/* Finish the tool */ /* Finish the tool */
draw_core_stop (crop->core, tool); draw_core_stop (crop->core, tool);
@ -1113,11 +1304,14 @@ crop_invoker (Argument *args)
int int_value; int int_value;
int new_width, new_height; int new_width, new_height;
int offx, offy; int offx, offy;
int layer_only, crop_layers ;
new_width = 1; new_width = 1;
new_height = 1; new_height = 1;
offx = 0; offx = 0;
offy = 0; offy = 0;
layer_only = FALSE;
crop_layers = TRUE;
success = TRUE; success = TRUE;
if (success) if (success)
@ -1147,7 +1341,8 @@ crop_invoker (Argument *args)
success = FALSE; success = FALSE;
if (success) if (success)
crop_image (gimage, offx, offy, offx + new_width, offy + new_height); crop_image (gimage, offx, offy, offx + new_width, offy + new_height,
layer_only, crop_layers);
return procedural_db_return_args (&crop_proc, success); return procedural_db_return_args (&crop_proc, success);
} }

View File

@ -29,6 +29,8 @@ void tools_free_crop (Tool *);
/* tool options */ /* tool options */
typedef struct { typedef struct {
int layer_only; int layer_only;
int default_to_enlarge;
int default_to_crop;
} CropToolOptions; } CropToolOptions;
@ -36,3 +38,5 @@ typedef struct {
extern ProcRecord crop_proc; extern ProcRecord crop_proc;
#endif /* __CROP_H__ */ #endif /* __CROP_H__ */

View File

@ -63,6 +63,7 @@ struct _crop
#define RESIZING_LEFT 2 #define RESIZING_LEFT 2
#define RESIZING_RIGHT 3 #define RESIZING_RIGHT 3
#define CROPPING 4 #define CROPPING 4
#define REFRAMING 5
/* speed of key movement */ /* speed of key movement */
#define ARROW_VELOCITY 25 #define ARROW_VELOCITY 25
@ -84,7 +85,7 @@ static void crop_arrow_keys_func (Tool *, GdkEventKey *, gpointer);
/* Crop helper functions */ /* Crop helper functions */
static void crop_image (GImage *gimage, int, int, int, int); static void crop_image (GImage *gimage, int, int, int, int, int, int);
static void crop_recalc (Tool *, Crop *); static void crop_recalc (Tool *, Crop *);
static void crop_start (Tool *, Crop *); static void crop_start (Tool *, Crop *);
static void crop_adjust_guides (GImage *, int, int, int, int); static void crop_adjust_guides (GImage *, int, int, int, int);
@ -93,6 +94,7 @@ static void crop_adjust_guides (GImage *, int, int, int, int);
static void crop_info_update (Tool *); static void crop_info_update (Tool *);
static void crop_info_create (Tool *); static void crop_info_create (Tool *);
static void crop_ok_callback (GtkWidget *, gpointer); static void crop_ok_callback (GtkWidget *, gpointer);
static void crop_resize_callback (GtkWidget *, gpointer);
static void crop_selection_callback (GtkWidget *, gpointer); static void crop_selection_callback (GtkWidget *, gpointer);
static void crop_close_callback (GtkWidget *, gpointer); static void crop_close_callback (GtkWidget *, gpointer);
@ -117,6 +119,12 @@ init_crop_options()
GtkWidget *vbox; GtkWidget *vbox;
GtkWidget *label; GtkWidget *label;
GtkWidget *checkbutton; GtkWidget *checkbutton;
GtkWidget *defaults_frame;
GtkWidget *defaults_box;
options.layer_only = FALSE;
options.default_to_enlarge = TRUE;
options.default_to_crop = FALSE;
/* the main vbox */ /* the main vbox */
vbox = gtk_vbox_new (FALSE, 2); vbox = gtk_vbox_new (FALSE, 2);
@ -137,6 +145,38 @@ init_crop_options()
options.layer_only); options.layer_only);
gtk_widget_show(checkbutton); gtk_widget_show(checkbutton);
/* defaults */
defaults_frame = gtk_frame_new (_("Defaults"));
gtk_box_pack_start (GTK_BOX (vbox), defaults_frame, FALSE, FALSE, 0);
defaults_box = gtk_vbox_new (FALSE, 1);
gtk_container_add (GTK_CONTAINER (defaults_frame), defaults_box);
/* enlarge toggle */
checkbutton = gtk_check_button_new_with_label(_("Allow Enlarging"));
gtk_box_pack_start(GTK_BOX(defaults_box), checkbutton,
FALSE, FALSE, 0);
gtk_signal_connect(GTK_OBJECT(checkbutton), "toggled",
(GtkSignalFunc) crop_checkbutton_update,
&options.default_to_enlarge);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton),
options.default_to_enlarge);
gtk_widget_show(checkbutton);
/* crop toggle */
checkbutton = gtk_check_button_new_with_label(_("Crop Layers"));
gtk_box_pack_start(GTK_BOX(defaults_box), checkbutton,
FALSE, FALSE, 0);
gtk_signal_connect(GTK_OBJECT(checkbutton), "toggled",
(GtkSignalFunc) crop_checkbutton_update,
&options.default_to_crop);
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton),
options.default_to_crop);
gtk_widget_show(checkbutton);
gtk_widget_show (defaults_box);
gtk_widget_show (defaults_frame);
/* Register this selection options widget with the main tools /* Register this selection options widget with the main tools
* options dialog */ * options dialog */
@ -157,7 +197,6 @@ crop_checkbutton_update (GtkWidget *w,
*toggle_val = FALSE; *toggle_val = FALSE;
} }
static void static void
crop_button_press (Tool *tool, crop_button_press (Tool *tool,
GdkEventButton *bevent, GdkEventButton *bevent,
@ -192,11 +231,25 @@ crop_button_press (Tool *tool,
bevent->y == BOUNDS (bevent->y, crop->y1, crop->y1 + crop->srh))) bevent->y == BOUNDS (bevent->y, crop->y1, crop->y1 + crop->srh)))
crop->function = MOVING; crop->function = MOVING;
/* If the pointer is in the rectangular region, crop it! */ /* If the pointer is in the rectangular region, crop or resize it! */
else if (bevent->x > crop->x1 && bevent->x < crop->x2 && else if (bevent->x > crop->x1 && bevent->x < crop->x2 &&
bevent->y > crop->y1 && bevent->y < crop->y2) bevent->y > crop->y1 && bevent->y < crop->y2)
{
if ( options.default_to_crop )
{
if ( bevent->state & GDK_SHIFT_MASK )
crop->function = REFRAMING;
else
crop->function = CROPPING; crop->function = CROPPING;
}
else
{
if ( bevent->state & GDK_SHIFT_MASK )
crop->function = CROPPING;
else
crop->function = REFRAMING;
}
}
/* otherwise, the new function will be creating, since we want to start anew */ /* otherwise, the new function will be creating, since we want to start anew */
else else
crop->function = CREATING; crop->function = CREATING;
@ -247,10 +300,17 @@ crop_button_release (Tool *tool,
if (! (bevent->state & GDK_BUTTON3_MASK)) if (! (bevent->state & GDK_BUTTON3_MASK))
{ {
if (crop->function == CROPPING) switch (crop->function)
crop_image (gdisp->gimage, crop->tx1, crop->ty1, crop->tx2, crop->ty2);
else
{ {
case CROPPING:
crop_image (gdisp->gimage, crop->tx1, crop->ty1, crop->tx2, crop->ty2,
options.layer_only, TRUE);
break;
case REFRAMING:
crop_image (gdisp->gimage, crop->tx1, crop->ty1, crop->tx2, crop->ty2,
options.layer_only, FALSE);
break;
default:
crop_info_update (tool); crop_info_update (tool);
return; return;
} }
@ -316,17 +376,19 @@ crop_motion (Tool *tool,
{ {
Crop * crop; Crop * crop;
GDisplay * gdisp; GDisplay * gdisp;
Layer * layer;
int x1, y1, x2, y2; int x1, y1, x2, y2;
int curx, cury; int curx, cury;
int inc_x, inc_y; int inc_x, inc_y;
gchar size[STATUSBAR_SIZE]; gchar size[STATUSBAR_SIZE];
int clamp;
int min_x, min_y, max_x, max_y;
crop = (Crop *) tool->private; crop = (Crop *) tool->private;
gdisp = (GDisplay *) gdisp_ptr; gdisp = (GDisplay *) gdisp_ptr;
/* This is the only case when the motion events should be ignored-- /* This is the only case when the motion events should be ignored--
we're just waiting for the button release event to crop the image */ we're just waiting for the button release event to crop the image */
if (crop->function == CROPPING) if (crop->function == CROPPING || crop->function == REFRAMING)
return; return;
gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &curx, &cury, TRUE, FALSE); gdisplay_untransform_coords (gdisp, mevent->x, mevent->y, &curx, &cury, TRUE, FALSE);
@ -344,18 +406,56 @@ crop_motion (Tool *tool,
draw_core_pause (crop->core, tool); draw_core_pause (crop->core, tool);
/* shall we clamp the coordinates to the image dimensions? */
if (options.default_to_enlarge)
{
if (mevent->state & GDK_MOD1_MASK)
clamp = TRUE;
else
clamp = FALSE;
}
else
{
if (mevent->state & GDK_MOD1_MASK)
clamp = FALSE;
else
clamp = TRUE;
}
if (options.layer_only)
{
layer = (gdisp->gimage)->active_layer;
drawable_offsets (GIMP_DRAWABLE(layer), &min_x, &min_y);
max_x = drawable_width (GIMP_DRAWABLE(layer)) + min_x;
max_y = drawable_height (GIMP_DRAWABLE(layer)) + min_y;
}
else
{
min_x = min_y = 0;
max_x = gdisp->gimage->width;
max_y = gdisp->gimage->height;
}
switch (crop->function) switch (crop->function)
{ {
case CREATING : case CREATING :
x1 = BOUNDS (x1, 0, gdisp->gimage->width); if (clamp)
y1 = BOUNDS (y1, 0, gdisp->gimage->height); {
x2 = BOUNDS (x2, 0, gdisp->gimage->width); x1 = BOUNDS (x1, min_x, max_x);
y2 = BOUNDS (y2, 0, gdisp->gimage->height); y1 = BOUNDS (y1, min_y, max_y);
x2 = BOUNDS (x2, min_x, max_x);
y2 = BOUNDS (y2, min_y, max_y);
}
break; break;
case RESIZING_LEFT : case RESIZING_LEFT :
x1 = BOUNDS (crop->tx1 + inc_x, 0, gdisp->gimage->width); x1 = crop->tx1 + inc_x;
y1 = BOUNDS (crop->ty1 + inc_y, 0, gdisp->gimage->height); y1 = crop->ty1 + inc_y;
if (clamp)
{
x1 = BOUNDS (x1, min_x, max_x);
y1 = BOUNDS (y1, min_y, max_y);
}
x2 = MAXIMUM (x1, crop->tx2); x2 = MAXIMUM (x1, crop->tx2);
y2 = MAXIMUM (y1, crop->ty2); y2 = MAXIMUM (y1, crop->ty2);
crop->startx = curx; crop->startx = curx;
@ -363,8 +463,13 @@ crop_motion (Tool *tool,
break; break;
case RESIZING_RIGHT : case RESIZING_RIGHT :
x2 = BOUNDS (crop->tx2 + inc_x, 0, gdisp->gimage->width); x2 = crop->tx2 + inc_x;
y2 = BOUNDS (crop->ty2 + inc_y, 0, gdisp->gimage->height); y2 = crop->ty2 + inc_y;
if (clamp)
{
x2 = BOUNDS (x2, min_x, max_x);
y2 = BOUNDS (y2, min_y, max_y);
}
x1 = MINIMUM (crop->tx1, x2); x1 = MINIMUM (crop->tx1, x2);
y1 = MINIMUM (crop->ty1, y2); y1 = MINIMUM (crop->ty1, y2);
crop->startx = curx; crop->startx = curx;
@ -372,8 +477,11 @@ crop_motion (Tool *tool,
break; break;
case MOVING : case MOVING :
inc_x = BOUNDS (inc_x, -crop->tx1, gdisp->gimage->width - crop->tx2); if (clamp)
inc_y = BOUNDS (inc_y, -crop->ty1, gdisp->gimage->height - crop->ty2); {
inc_x = BOUNDS (inc_x, min_x - crop->tx1, max_x - crop->tx2);
inc_y = BOUNDS (inc_y, min_y - crop->ty1, max_y - crop->ty2);
}
x1 = crop->tx1 + inc_x; x1 = crop->tx1 + inc_x;
x2 = crop->tx2 + inc_x; x2 = crop->tx2 + inc_x;
y1 = crop->ty1 + inc_y; y1 = crop->ty1 + inc_y;
@ -456,7 +564,22 @@ crop_cursor_update (Tool *tool,
ctype = GDK_FLEUR; ctype = GDK_FLEUR;
else if (mevent->x > crop->x1 && mevent->x < crop->x2 && else if (mevent->x > crop->x1 && mevent->x < crop->x2 &&
mevent->y > crop->y1 && mevent->y < crop->y2) mevent->y > crop->y1 && mevent->y < crop->y2)
{
if ( options.default_to_crop )
{
if ( mevent->state & GDK_SHIFT_MASK )
ctype = GDK_SIZING;
else
ctype = GDK_ICON; ctype = GDK_ICON;
}
else
{
if ( mevent->state & GDK_SHIFT_MASK )
ctype = GDK_ICON;
else
ctype = GDK_SIZING;
}
}
else else
ctype = GDK_CROSS; ctype = GDK_CROSS;
@ -470,7 +593,10 @@ crop_arrow_keys_func (Tool *tool,
{ {
int inc_x, inc_y; int inc_x, inc_y;
GDisplay * gdisp; GDisplay * gdisp;
Layer * layer;
Crop * crop; Crop * crop;
int clamp;
int min_x, min_y, max_x, max_y;
gdisp = (GDisplay *) gdisp_ptr; gdisp = (GDisplay *) gdisp_ptr;
@ -496,17 +622,55 @@ crop_arrow_keys_func (Tool *tool,
draw_core_pause (crop->core, tool); draw_core_pause (crop->core, tool);
/* shall we clamp the coordinates to the image dimensions? */
if (options.default_to_enlarge)
{
if (kevent->state & GDK_MOD1_MASK)
clamp = TRUE;
else
clamp = FALSE;
}
else
{
if (kevent->state & GDK_MOD1_MASK)
clamp = FALSE;
else
clamp = TRUE;
}
if (options.layer_only)
{
layer = (gdisp->gimage)->active_layer;
drawable_offsets (GIMP_DRAWABLE(layer), &min_x, &min_y);
max_x = drawable_width (GIMP_DRAWABLE(layer)) + min_x;
max_y = drawable_height (GIMP_DRAWABLE(layer)) + min_y;
}
else
{
min_x = min_y = 0;
max_x = gdisp->gimage->width;
max_y = gdisp->gimage->height;
}
if (kevent->state & GDK_CONTROL_MASK) /* RESIZING */ if (kevent->state & GDK_CONTROL_MASK) /* RESIZING */
{ {
crop->tx2 = BOUNDS (crop->tx2 + inc_x, 0, gdisp->gimage->width); crop->tx2 = crop->tx2 + inc_x;
crop->ty2 = BOUNDS (crop->ty2 + inc_y, 0, gdisp->gimage->height); crop->ty2 = crop->ty2 + inc_y;
if (clamp)
{
crop->tx2 = BOUNDS (crop->tx2, min_x, max_x);
crop->ty2 = BOUNDS (crop->ty2, min_y, max_y);
}
crop->tx1 = MINIMUM (crop->tx1, crop->tx2); crop->tx1 = MINIMUM (crop->tx1, crop->tx2);
crop->ty1 = MINIMUM (crop->ty1, crop->ty2); crop->ty1 = MINIMUM (crop->ty1, crop->ty2);
} }
else else
{
if (clamp)
{ {
inc_x = BOUNDS (inc_x, -crop->tx1, gdisp->gimage->width - crop->tx2); inc_x = BOUNDS (inc_x, -crop->tx1, gdisp->gimage->width - crop->tx2);
inc_y = BOUNDS (inc_y, -crop->ty1, gdisp->gimage->height - crop->ty2); inc_y = BOUNDS (inc_y, -crop->ty1, gdisp->gimage->height - crop->ty2);
}
crop->tx1 += inc_x; crop->tx1 += inc_x;
crop->tx2 += inc_x; crop->tx2 += inc_x;
crop->ty1 += inc_y; crop->ty1 += inc_y;
@ -638,7 +802,9 @@ crop_image (GImage *gimage,
int x1, int x1,
int y1, int y1,
int x2, int x2,
int y2) int y2,
int layer_only,
int crop_layers)
{ {
Layer *layer; Layer *layer;
Layer *floating_layer; Layer *floating_layer;
@ -659,7 +825,7 @@ crop_image (GImage *gimage,
{ {
gimp_add_busy_cursors(); gimp_add_busy_cursors();
if (options.layer_only) if (layer_only)
{ {
undo_push_group_start (gimage, LAYER_RESIZE_UNDO); undo_push_group_start (gimage, LAYER_RESIZE_UNDO);
@ -718,6 +884,8 @@ crop_image (GImage *gimage,
layer_translate (layer, -x1, -y1); layer_translate (layer, -x1, -y1);
if (crop_layers)
{
drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y); drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y);
lx1 = BOUNDS (off_x, 0, gimage->width); lx1 = BOUNDS (off_x, 0, gimage->width);
@ -727,8 +895,6 @@ crop_image (GImage *gimage,
width = lx2 - lx1; width = lx2 - lx1;
height = ly2 - ly1; height = ly2 - ly1;
list = g_slist_next (list);
if (width && height) if (width && height)
layer_resize (layer, width, height, layer_resize (layer, width, height,
-(lx1 - off_x), -(lx1 - off_x),
@ -737,6 +903,9 @@ crop_image (GImage *gimage,
gimage_remove_layer (gimage, layer); gimage_remove_layer (gimage, layer);
} }
list = g_slist_next (list);
}
/* Make sure the projection matches the gimage size */ /* Make sure the projection matches the gimage size */
gimage_projection_realloc (gimage); gimage_projection_realloc (gimage);
@ -839,10 +1008,11 @@ crop_start (Tool *tool,
/* Crop dialog functions */ /* Crop dialog functions */
/*******************************************************/ /*******************************************************/
static ActionAreaItem action_items[3] = static ActionAreaItem action_items[4] =
{ {
{ N_("Crop"), crop_ok_callback, NULL, NULL }, { N_("Crop"), crop_ok_callback, NULL, NULL },
{ N_("Selection"), crop_selection_callback, NULL, NULL }, { N_("Resize"), crop_resize_callback, NULL, NULL },
/* { N_("Selection"), crop_selection_callback, NULL, NULL }, */
{ N_("Close"), crop_close_callback, NULL, NULL }, { N_("Close"), crop_close_callback, NULL, NULL },
}; };
@ -949,7 +1119,28 @@ crop_ok_callback (GtkWidget *w,
tool = active_tool; tool = active_tool;
crop = (Crop *) tool->private; crop = (Crop *) tool->private;
gdisp = (GDisplay *) tool->gdisp_ptr; gdisp = (GDisplay *) tool->gdisp_ptr;
crop_image (gdisp->gimage, crop->tx1, crop->ty1, crop->tx2, crop->ty2); crop_image (gdisp->gimage, crop->tx1, crop->ty1, crop->tx2, crop->ty2,
options.layer_only, TRUE);
/* Finish the tool */
draw_core_stop (crop->core, tool);
info_dialog_popdown (crop_info);
tool->state = INACTIVE;
}
static void
crop_resize_callback (GtkWidget *w,
gpointer client_data)
{
Tool * tool;
Crop * crop;
GDisplay * gdisp;
tool = active_tool;
crop = (Crop *) tool->private;
gdisp = (GDisplay *) tool->gdisp_ptr;
crop_image (gdisp->gimage, crop->tx1, crop->ty1, crop->tx2, crop->ty2,
options.layer_only, FALSE);
/* Finish the tool */ /* Finish the tool */
draw_core_stop (crop->core, tool); draw_core_stop (crop->core, tool);
@ -1113,11 +1304,14 @@ crop_invoker (Argument *args)
int int_value; int int_value;
int new_width, new_height; int new_width, new_height;
int offx, offy; int offx, offy;
int layer_only, crop_layers ;
new_width = 1; new_width = 1;
new_height = 1; new_height = 1;
offx = 0; offx = 0;
offy = 0; offy = 0;
layer_only = FALSE;
crop_layers = TRUE;
success = TRUE; success = TRUE;
if (success) if (success)
@ -1147,7 +1341,8 @@ crop_invoker (Argument *args)
success = FALSE; success = FALSE;
if (success) if (success)
crop_image (gimage, offx, offy, offx + new_width, offy + new_height); crop_image (gimage, offx, offy, offx + new_width, offy + new_height,
layer_only, crop_layers);
return procedural_db_return_args (&crop_proc, success); return procedural_db_return_args (&crop_proc, success);
} }

View File

@ -29,6 +29,8 @@ void tools_free_crop (Tool *);
/* tool options */ /* tool options */
typedef struct { typedef struct {
int layer_only; int layer_only;
int default_to_enlarge;
int default_to_crop;
} CropToolOptions; } CropToolOptions;
@ -36,3 +38,5 @@ typedef struct {
extern ProcRecord crop_proc; extern ProcRecord crop_proc;
#endif /* __CROP_H__ */ #endif /* __CROP_H__ */