app: add "Image" transform type to transform tools

Add a new "Image" transform type to the transform tools, in
addition to the existing "Layer", "Selection", and "Path" transform
types.  The "Image" mode transforms the entire image, rather than a
single item.  In tools with a preview, the preview shows the
transformed image projection.  The clipping mode controls how the
canvas is clipped during the transform; in particular, the ADJUST
clipping mode resizes the canvas to fit its transformed size.

(cherry picked from commit e4990bee7b)
This commit is contained in:
Ell
2019-08-10 22:57:55 +03:00
parent cd4eaf6e54
commit 5903c9c71d
11 changed files with 342 additions and 161 deletions

View File

@ -1166,6 +1166,9 @@ gimp_edit_selection_tool_translate (GimpTool *tool,
}
break;
case GIMP_TRANSFORM_TYPE_IMAGE:
g_return_val_if_reached (FALSE);
}
}

View File

@ -31,11 +31,13 @@
#include "core/gimpdrawable-transform.h"
#include "core/gimpguide.h"
#include "core/gimpimage.h"
#include "core/gimpimage-flip.h"
#include "core/gimpimage-pick-item.h"
#include "core/gimpitem-linked.h"
#include "core/gimplayer.h"
#include "core/gimplayermask.h"
#include "core/gimppickable.h"
#include "core/gimpprogress.h"
#include "widgets/gimphelp-ids.h"
#include "widgets/gimpwidgets-utils.h"
@ -79,7 +81,7 @@ static void gimp_flip_tool_draw (GimpDrawTool *draw_too
static gchar * gimp_flip_tool_get_undo_desc (GimpTransformTool *tr_tool);
static GeglBuffer * gimp_flip_tool_transform (GimpTransformTool *tr_tool,
GimpItem *item,
GimpObject *object,
GeglBuffer *orig_buffer,
gint orig_offset_x,
gint orig_offset_y,
@ -162,7 +164,11 @@ gimp_flip_tool_button_press (GimpTool *tool,
{
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tool);
tool->display = display;
gimp_transform_tool_transform (tr_tool, display);
gimp_tool_control (tool, GIMP_TOOL_ACTION_HALT, display);
}
static void
@ -253,7 +259,7 @@ gimp_flip_tool_cursor_update (GimpTool *tool,
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tool);
GimpFlipTool *flip = GIMP_FLIP_TOOL (tool);
if (! gimp_transform_tool_check_active_item (tr_tool, display, NULL))
if (! gimp_transform_tool_check_active_object (tr_tool, display, NULL))
{
gimp_tool_set_cursor (tool, display,
gimp_tool_control_get_cursor (tool->control),
@ -312,7 +318,7 @@ gimp_flip_tool_get_undo_desc (GimpTransformTool *tr_tool)
static GeglBuffer *
gimp_flip_tool_transform (GimpTransformTool *tr_tool,
GimpItem *active_item,
GimpObject *object,
GeglBuffer *orig_buffer,
gint orig_offset_x,
gint orig_offset_y,
@ -374,7 +380,9 @@ gimp_flip_tool_transform (GimpTransformTool *tr_tool,
* normal drawable
*/
ret = gimp_drawable_transform_buffer_flip (GIMP_DRAWABLE (active_item),
g_return_val_if_fail (GIMP_IS_DRAWABLE (object), NULL);
ret = gimp_drawable_transform_buffer_flip (GIMP_DRAWABLE (object),
context,
orig_buffer,
orig_offset_x,
@ -385,23 +393,43 @@ gimp_flip_tool_transform (GimpTransformTool *tr_tool,
new_offset_x,
new_offset_y);
}
else
else if (GIMP_IS_ITEM (object))
{
/* this happens for entire drawables, paths and layer groups */
if (gimp_item_get_linked (active_item))
GimpItem *item = GIMP_ITEM (object);
if (gimp_item_get_linked (item))
{
gimp_item_linked_flip (active_item, context,
gimp_item_linked_flip (item, context,
flip_type, axis, clip_result);
}
else
{
clip_result = gimp_item_get_clip (active_item, clip_result);
clip_result = gimp_item_get_clip (item, clip_result);
gimp_item_flip (active_item, context,
gimp_item_flip (item, context,
flip_type, axis, clip_result);
}
}
else
{
/* this happens for images */
GimpTransformToolClass *tr_class = GIMP_TRANSFORM_TOOL_GET_CLASS (tr_tool);
GimpProgress *progress;
g_return_val_if_fail (GIMP_IS_IMAGE (object), NULL);
progress = gimp_progress_start (GIMP_PROGRESS (tr_tool), FALSE,
"%s", tr_class->progress_text);
gimp_image_flip_full (GIMP_IMAGE (object), context,
flip_type, axis, clip_result,
progress);
if (progress)
gimp_progress_end (progress);
}
return ret;
}

View File

@ -198,7 +198,9 @@ gimp_move_options_gui (GimpToolOptions *tool_options)
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
gtk_widget_show (label);
box = gimp_prop_enum_icon_box_new (config, "move-type", "gimp", 0, 0);
box = gimp_prop_enum_icon_box_new (config, "move-type", "gimp",
GIMP_TRANSFORM_TYPE_LAYER,
GIMP_TRANSFORM_TYPE_PATH);
gtk_box_pack_start (GTK_BOX (hbox), box, FALSE, FALSE, 0);
gtk_widget_show (box);

View File

@ -343,6 +343,9 @@ gimp_move_tool_button_press (GimpTool *tool,
}
}
break;
case GIMP_TRANSFORM_TYPE_IMAGE:
g_return_if_reached ();
}
if (! active_item)

View File

@ -606,8 +606,21 @@ gimp_transform_grid_options_show_preview (GimpTransformGridOptions *options)
transform_options = GIMP_TRANSFORM_OPTIONS (options);
return (options->show_preview &&
transform_options->type == GIMP_TRANSFORM_TYPE_LAYER);
if (options->show_preview)
{
switch (transform_options->type)
{
case GIMP_TRANSFORM_TYPE_LAYER:
case GIMP_TRANSFORM_TYPE_IMAGE:
return TRUE;
case GIMP_TRANSFORM_TYPE_SELECTION:
case GIMP_TRANSFORM_TYPE_PATH:
return FALSE;
}
}
return FALSE;
}

View File

@ -45,6 +45,7 @@
#include "display/gimpcanvasitem.h"
#include "display/gimpdisplay.h"
#include "display/gimpdisplayshell.h"
#include "display/gimptoolgui.h"
#include "display/gimptoolwidget.h"
@ -124,7 +125,7 @@ static gchar * gimp_transform_grid_tool_get_undo_desc (GimpTransformTool
static GimpTransformDirection gimp_transform_grid_tool_get_direction
(GimpTransformTool *tr_tool);
static GeglBuffer * gimp_transform_grid_tool_transform (GimpTransformTool *tr_tool,
GimpItem *item,
GimpObject *object,
GeglBuffer *orig_buffer,
gint orig_offset_x,
gint orig_offset_y,
@ -136,7 +137,7 @@ static gchar * gimp_transform_grid_tool_real_get_undo_desc (GimpTransformGridT
static void gimp_transform_grid_tool_real_update_widget (GimpTransformGridTool *tg_tool);
static void gimp_transform_grid_tool_real_widget_changed (GimpTransformGridTool *tg_tool);
static GeglBuffer * gimp_transform_grid_tool_real_transform (GimpTransformGridTool *tg_tool,
GimpItem *item,
GimpObject *object,
GeglBuffer *orig_buffer,
gint orig_offset_x,
gint orig_offset_y,
@ -166,9 +167,9 @@ static void gimp_transform_grid_tool_response (GimpToolGui
static void gimp_transform_grid_tool_update_sensitivity (GimpTransformGridTool *tg_tool);
static void gimp_transform_grid_tool_update_preview (GimpTransformGridTool *tg_tool);
static void gimp_transform_grid_tool_hide_active_item (GimpTransformGridTool *tg_tool,
GimpItem *item);
static void gimp_transform_grid_tool_show_active_item (GimpTransformGridTool *tg_tool);
static void gimp_transform_grid_tool_hide_active_object (GimpTransformGridTool *tg_tool,
GimpObject *object);
static void gimp_transform_grid_tool_show_active_object (GimpTransformGridTool *tg_tool);
static UndoInfo * undo_info_new (void);
static void undo_info_free (UndoInfo *info);
@ -273,18 +274,18 @@ gimp_transform_grid_tool_initialize (GimpTool *tool,
GimpTransformGridTool *tg_tool = GIMP_TRANSFORM_GRID_TOOL (tool);
GimpImage *image = gimp_display_get_image (display);
GimpDrawable *drawable = gimp_image_get_active_drawable (image);
GimpItem *item;
GimpObject *object;
UndoInfo *undo_info;
item = gimp_transform_tool_check_active_item (tr_tool, display, error);
object = gimp_transform_tool_check_active_object (tr_tool, display, error);
if (! item)
if (! object)
return FALSE;
tool->display = display;
tool->drawable = drawable;
tool->display = display;
tool->drawable = drawable;
tr_tool->item = item;
tr_tool->object = object;
/* Initialize the transform_grid tool dialog */
if (! tg_tool->gui)
@ -304,7 +305,7 @@ gimp_transform_grid_tool_initialize (GimpTool *tool,
/* Get the on-canvas gui */
tg_tool->widget = gimp_transform_grid_tool_get_widget (tg_tool);
gimp_transform_grid_tool_hide_active_item (tg_tool, item);
gimp_transform_grid_tool_hide_active_object (tg_tool, object);
/* start drawing the bounding box and handles... */
gimp_draw_tool_start (GIMP_DRAW_TOOL (tool), display);
@ -477,7 +478,7 @@ gimp_transform_grid_tool_cursor_update (GimpTool *tool,
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tool);
if (display != tool->display &&
! gimp_transform_tool_check_active_item (tr_tool, display, NULL))
! gimp_transform_tool_check_active_object (tr_tool, display, NULL))
{
gimp_tool_set_cursor (tool, display,
gimp_tool_control_get_cursor (tool->control),
@ -615,7 +616,7 @@ gimp_transform_grid_tool_options_notify (GimpTool *tool,
if (tg_tool->preview)
{
GimpDisplay *display;
GimpItem *item;
GimpObject *object;
gboolean show_preview;
show_preview = gimp_transform_grid_options_show_preview (tg_options) &&
@ -624,13 +625,14 @@ gimp_transform_grid_tool_options_notify (GimpTool *tool,
gimp_canvas_item_set_visible (tg_tool->preview, show_preview);
display = tool->display;
item = gimp_transform_tool_get_active_item (tr_tool, display);
if (item)
object = gimp_transform_tool_get_active_object (tr_tool, display);
if (object)
{
if (gimp_transform_grid_options_show_preview (tg_options))
gimp_transform_grid_tool_hide_active_item (tg_tool, item);
gimp_transform_grid_tool_hide_active_object (tg_tool, object);
else
gimp_transform_grid_tool_show_active_item (tg_tool);
gimp_transform_grid_tool_show_active_object (tg_tool);
}
}
}
@ -660,12 +662,20 @@ gimp_transform_grid_tool_draw (GimpDrawTool *draw_tool)
if (tg_tool->widget)
{
gboolean show_preview = gimp_transform_grid_options_show_preview (options) &&
tr_tool->transform_valid;
GimpPickable *pickable;
gboolean show_preview;
if (tr_options->type == GIMP_TRANSFORM_TYPE_IMAGE)
pickable = GIMP_PICKABLE (image);
else
pickable = GIMP_PICKABLE (tool->drawable);
show_preview = gimp_transform_grid_options_show_preview (options) &&
tr_tool->transform_valid;
tg_tool->preview =
gimp_draw_tool_add_transform_preview (draw_tool,
GIMP_PICKABLE (tool->drawable),
pickable,
&matrix,
tr_tool->x1,
tr_tool->y1,
@ -905,7 +915,7 @@ gimp_transform_grid_tool_get_direction (GimpTransformTool *tr_tool)
static GeglBuffer *
gimp_transform_grid_tool_transform (GimpTransformTool *tr_tool,
GimpItem *item,
GimpObject *object,
GeglBuffer *orig_buffer,
gint orig_offset_x,
gint orig_offset_y,
@ -923,7 +933,7 @@ gimp_transform_grid_tool_transform (GimpTransformTool *tr_tool,
*/
new_buffer =
GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->transform (tg_tool,
item,
object,
orig_buffer,
orig_offset_x,
orig_offset_y,
@ -982,7 +992,7 @@ gimp_transform_grid_tool_real_widget_changed (GimpTransformGridTool *tg_tool)
static GeglBuffer *
gimp_transform_grid_tool_real_transform (GimpTransformGridTool *tg_tool,
GimpItem *item,
GimpObject *object,
GeglBuffer *orig_buffer,
gint orig_offset_x,
gint orig_offset_y,
@ -993,7 +1003,7 @@ gimp_transform_grid_tool_real_transform (GimpTransformGridTool *tg_tool,
GimpTransformTool *tr_tool = GIMP_TRANSFORM_TOOL (tg_tool);
return GIMP_TRANSFORM_TOOL_CLASS (parent_class)->transform (tr_tool,
item,
object,
orig_buffer,
orig_offset_x,
orig_offset_y,
@ -1058,12 +1068,12 @@ gimp_transform_grid_tool_halt (GimpTransformGridTool *tg_tool)
tg_tool->undo_list = NULL;
}
gimp_transform_grid_tool_show_active_item (tg_tool);
gimp_transform_grid_tool_show_active_object (tg_tool);
tool->display = NULL;
tool->drawable = NULL;
tool->display = NULL;
tool->drawable = NULL;
tr_tool->item = NULL;
tr_tool->object = NULL;
}
static void
@ -1144,10 +1154,11 @@ gimp_transform_grid_tool_prepare (GimpTransformGridTool *tg_tool,
if (tg_tool->gui)
{
GimpItem *item = gimp_transform_tool_get_active_item (tr_tool, display);
GimpObject *object = gimp_transform_tool_get_active_object (tr_tool,
display);
gimp_tool_gui_set_shell (tg_tool->gui, gimp_display_get_shell (display));
gimp_tool_gui_set_viewable (tg_tool->gui, GIMP_VIEWABLE (item));
gimp_tool_gui_set_viewable (tg_tool->gui, GIMP_VIEWABLE (object));
}
if (GIMP_TRANSFORM_GRID_TOOL_GET_CLASS (tg_tool)->prepare)
@ -1452,39 +1463,61 @@ gimp_transform_grid_tool_update_preview (GimpTransformGridTool *tg_tool)
}
static void
gimp_transform_grid_tool_hide_active_item (GimpTransformGridTool *tg_tool,
GimpItem *item)
gimp_transform_grid_tool_hide_active_object (GimpTransformGridTool *tg_tool,
GimpObject *object)
{
GimpTransformGridOptions *options = GIMP_TRANSFORM_GRID_TOOL_GET_OPTIONS (tg_tool);
GimpTransformOptions *tr_options = GIMP_TRANSFORM_OPTIONS (options);
GimpDisplay *display = GIMP_TOOL (tg_tool)->display;
GimpImage *image = gimp_display_get_image (display);
/* hide only complete layers and channels, not layer masks */
if (tr_options->type == GIMP_TRANSFORM_TYPE_LAYER &&
options->show_preview &&
GIMP_IS_DRAWABLE (item) &&
! GIMP_IS_LAYER_MASK (item) &&
gimp_item_get_visible (item) &&
gimp_channel_is_empty (gimp_image_get_mask (image)))
if (options->show_preview)
{
tg_tool->hidden_item = item;
gimp_item_set_visible (item, FALSE, FALSE);
/* hide only complete layers and channels, not layer masks */
if (tr_options->type == GIMP_TRANSFORM_TYPE_LAYER &&
GIMP_IS_DRAWABLE (object) &&
! GIMP_IS_LAYER_MASK (object) &&
gimp_item_get_visible (GIMP_ITEM (object)) &&
gimp_channel_is_empty (gimp_image_get_mask (image)))
{
tg_tool->hidden_object = object;
gimp_projection_flush (gimp_image_get_projection (image));
gimp_item_set_visible (GIMP_ITEM (object), FALSE, FALSE);
gimp_projection_flush (gimp_image_get_projection (image));
}
else if (tr_options->type == GIMP_TRANSFORM_TYPE_IMAGE)
{
tg_tool->hidden_object = object;
gimp_display_shell_set_show_image (gimp_display_get_shell (display),
FALSE);
}
}
}
static void
gimp_transform_grid_tool_show_active_item (GimpTransformGridTool *tg_tool)
gimp_transform_grid_tool_show_active_object (GimpTransformGridTool *tg_tool)
{
if (tg_tool->hidden_item)
if (tg_tool->hidden_object)
{
GimpDisplay *display = GIMP_TOOL (tg_tool)->display;
GimpImage *image = gimp_display_get_image (display);
gimp_item_set_visible (tg_tool->hidden_item, TRUE, FALSE);
tg_tool->hidden_item = NULL;
if (GIMP_IS_ITEM (tg_tool->hidden_object))
{
gimp_item_set_visible (GIMP_ITEM (tg_tool->hidden_object), TRUE,
FALSE);
}
else
{
g_return_if_fail (GIMP_IS_IMAGE (tg_tool->hidden_object));
gimp_display_shell_set_show_image (gimp_display_get_shell (display),
TRUE);
}
tg_tool->hidden_object = NULL;
gimp_image_flush (image);
}

View File

@ -56,7 +56,7 @@ struct _GimpTransformGridTool
GList *redo_list; /* list of all undone states,
NULL when nothing undone */
GimpItem *hidden_item; /* the item that was hidden during
GimpObject *hidden_object; /* the object that was hidden during
the transform */
GimpToolWidget *widget;
@ -87,7 +87,7 @@ struct _GimpTransformGridToolClass
void (* update_widget) (GimpTransformGridTool *tg_tool);
void (* widget_changed) (GimpTransformGridTool *tg_tool);
GeglBuffer * (* transform) (GimpTransformGridTool *tg_tool,
GimpItem *item,
GimpObject *object,
GeglBuffer *orig_buffer,
gint orig_offset_x,
gint orig_offset_y,

View File

@ -32,6 +32,7 @@
#include "core/gimperror.h"
#include "core/gimpimage.h"
#include "core/gimpimage-item-list.h"
#include "core/gimpimage-transform.h"
#include "core/gimpimage-undo.h"
#include "core/gimpitem-linked.h"
#include "core/gimplayer.h"
@ -66,7 +67,7 @@
static gchar * gimp_transform_tool_real_get_undo_desc (GimpTransformTool *tr_tool);
static GimpTransformDirection gimp_transform_tool_real_get_direction (GimpTransformTool *tr_tool);
static GeglBuffer * gimp_transform_tool_real_transform (GimpTransformTool *tr_tool,
GimpItem *item,
GimpObject *object,
GeglBuffer *orig_buffer,
gint orig_offset_x,
gint orig_offset_y,
@ -121,7 +122,7 @@ gimp_transform_tool_real_get_direction (GimpTransformTool *tr_tool)
static GeglBuffer *
gimp_transform_tool_real_transform (GimpTransformTool *tr_tool,
GimpItem *active_item,
GimpObject *object,
GeglBuffer *orig_buffer,
gint orig_offset_x,
gint orig_offset_y,
@ -149,7 +150,9 @@ gimp_transform_tool_real_transform (GimpTransformTool *tr_tool,
* normal drawable
*/
ret = gimp_drawable_transform_buffer_affine (GIMP_DRAWABLE (active_item),
g_return_val_if_fail (GIMP_IS_DRAWABLE (object), NULL);
ret = gimp_drawable_transform_buffer_affine (GIMP_DRAWABLE (object),
context,
orig_buffer,
orig_offset_x,
@ -163,13 +166,15 @@ gimp_transform_tool_real_transform (GimpTransformTool *tr_tool,
new_offset_y,
progress);
}
else
else if (GIMP_IS_ITEM (object))
{
/* this happens for entire drawables, paths and layer groups */
if (gimp_item_get_linked (active_item))
GimpItem *item = GIMP_ITEM (object);
if (gimp_item_get_linked (item))
{
gimp_item_linked_transform (active_item, context,
gimp_item_linked_transform (item, context,
&tr_tool->transform,
direction,
options->interpolation,
@ -178,9 +183,9 @@ gimp_transform_tool_real_transform (GimpTransformTool *tr_tool,
}
else
{
clip = gimp_item_get_clip (active_item, clip);
clip = gimp_item_get_clip (item, clip);
gimp_item_transform (active_item, context,
gimp_item_transform (item, context,
&tr_tool->transform,
direction,
options->interpolation,
@ -188,6 +193,19 @@ gimp_transform_tool_real_transform (GimpTransformTool *tr_tool,
progress);
}
}
else
{
/* this happens for images */
g_return_val_if_fail (GIMP_IS_IMAGE (object), NULL);
gimp_image_transform (GIMP_IMAGE (object), context,
&tr_tool->transform,
direction,
options->interpolation,
clip,
progress);
}
if (progress)
gimp_progress_end (progress);
@ -199,13 +217,14 @@ static gboolean
gimp_transform_tool_confirm (GimpTransformTool *tr_tool,
GimpDisplay *display)
{
GimpTransformOptions *options = GIMP_TRANSFORM_TOOL_GET_OPTIONS (tr_tool);
GimpDisplayShell *shell = gimp_display_get_shell (display);
GimpImage *image = gimp_display_get_image (display);
GimpItem *active_item;
gdouble max_ratio = 0.0;
GimpTransformOptions *options = GIMP_TRANSFORM_TOOL_GET_OPTIONS (tr_tool);
GimpDisplayShell *shell = gimp_display_get_shell (display);
GimpImage *image = gimp_display_get_image (display);
GimpObject *active_object;
gdouble max_ratio = 0.0;
GimpObject *max_ratio_object = NULL;
active_item = gimp_transform_tool_get_active_item (tr_tool, display);
active_object = gimp_transform_tool_get_active_object (tr_tool, display);
if (GIMP_TRANSFORM_TOOL_GET_CLASS (tr_tool)->recalc_matrix)
{
@ -213,7 +232,7 @@ gimp_transform_tool_confirm (GimpTransformTool *tr_tool,
GimpTransformDirection direction;
GeglRectangle selection_bounds;
gboolean selection_empty = TRUE;
GList *items;
GList *objects;
GList *iter;
transform = tr_tool->transform;
@ -224,7 +243,7 @@ gimp_transform_tool_confirm (GimpTransformTool *tr_tool,
gimp_matrix3_invert (&transform);
if (options->type == GIMP_TRANSFORM_TYPE_LAYER &&
! gimp_viewable_get_children (GIMP_VIEWABLE (active_item)))
! gimp_viewable_get_children (GIMP_VIEWABLE (active_object)))
{
selection_empty = ! gimp_item_bounds (
GIMP_ITEM (gimp_image_get_mask (image)),
@ -232,28 +251,42 @@ gimp_transform_tool_confirm (GimpTransformTool *tr_tool,
&selection_bounds.width, &selection_bounds.height);
}
if (selection_empty && gimp_item_get_linked (active_item))
if (selection_empty &&
GIMP_IS_ITEM (active_object) &&
gimp_item_get_linked (GIMP_ITEM (active_object)))
{
items = gimp_image_item_list_get_list (image,
GIMP_ITEM_TYPE_ALL,
GIMP_ITEM_SET_LINKED);
objects = gimp_image_item_list_get_list (image,
GIMP_ITEM_TYPE_ALL,
GIMP_ITEM_SET_LINKED);
}
else
{
items = g_list_append (NULL, active_item);
objects = g_list_append (NULL, active_object);
}
for (iter = items; iter; iter = g_list_next (iter))
if (options->type == GIMP_TRANSFORM_TYPE_IMAGE)
{
GimpItem *item = iter->data;
GimpTransformResize clip = options->clip;
objects = g_list_concat (
objects,
gimp_image_item_list_get_list (image,
GIMP_ITEM_TYPE_ALL,
GIMP_ITEM_SET_ALL));
}
for (iter = objects; iter; iter = g_list_next (iter))
{
GimpObject *object = iter->data;
GimpTransformResize clip = options->clip;
GeglRectangle orig_bounds;
GeglRectangle new_bounds;
gdouble ratio = 0.0;
if (GIMP_IS_DRAWABLE (item))
if (GIMP_IS_DRAWABLE (object))
{
if (selection_empty)
{
GimpItem *item = GIMP_ITEM (object);
gimp_item_get_offset (item, &orig_bounds.x, &orig_bounds.y);
orig_bounds.width = gimp_item_get_width (item);
@ -266,14 +299,29 @@ gimp_transform_tool_confirm (GimpTransformTool *tr_tool,
orig_bounds = selection_bounds;
}
}
else
else if (GIMP_IS_ITEM (object))
{
GimpItem *item = GIMP_ITEM (object);
gimp_item_bounds (item,
&orig_bounds.x, &orig_bounds.y,
&orig_bounds.width, &orig_bounds.height);
clip = gimp_item_get_clip (item, clip);
}
else
{
GimpImage *image;
g_return_val_if_fail (GIMP_IS_IMAGE (object), FALSE);
image = GIMP_IMAGE (object);
orig_bounds.x = 0;
orig_bounds.y = 0;
orig_bounds.width = gimp_image_get_width (image);
orig_bounds.height = gimp_image_get_height (image);
}
gimp_transform_resize_boundary (&transform, clip,
@ -292,20 +340,26 @@ gimp_transform_tool_confirm (GimpTransformTool *tr_tool,
if (new_bounds.width > orig_bounds.width)
{
max_ratio = MAX (max_ratio,
(gdouble) new_bounds.width /
(gdouble) gimp_image_get_width (image));
ratio = MAX (ratio,
(gdouble) new_bounds.width /
(gdouble) gimp_image_get_width (image));
}
if (new_bounds.height > orig_bounds.height)
{
max_ratio = MAX (max_ratio,
(gdouble) new_bounds.height /
(gdouble) gimp_image_get_height (image));
ratio = MAX (ratio,
(gdouble) new_bounds.height /
(gdouble) gimp_image_get_height (image));
}
if (ratio > max_ratio)
{
max_ratio = ratio;
max_ratio_object = object;
}
}
g_list_free (items);
g_list_free (objects);
}
if (max_ratio > MIN_CONFIRMATION_RATIO)
@ -330,15 +384,31 @@ gimp_transform_tool_confirm (GimpTransformTool *tr_tool,
GTK_RESPONSE_CANCEL,
-1);
gimp_message_box_set_primary_text (GIMP_MESSAGE_DIALOG (dialog)->box,
_("Transformation creates "
"a very large item."));
if (GIMP_IS_ITEM (max_ratio_object))
{
gimp_message_box_set_primary_text (GIMP_MESSAGE_DIALOG (dialog)->box,
_("Transformation creates "
"a very large item."));
gimp_message_box_set_text (GIMP_MESSAGE_DIALOG (dialog)->box,
_("Applying the transformation will result "
"in an item that is over %g times larger "
"than the image."),
floor (max_ratio));
gimp_message_box_set_text (
GIMP_MESSAGE_DIALOG (dialog)->box,
_("Applying the transformation will result "
"in an item that is over %g times larger "
"than the image."),
floor (max_ratio));
}
else
{
gimp_message_box_set_primary_text (GIMP_MESSAGE_DIALOG (dialog)->box,
_("Transformation creates "
"a very large image."));
gimp_message_box_set_text (
GIMP_MESSAGE_DIALOG (dialog)->box,
_("Applying the transformation will enlarge "
"the image by a factor of %g."),
floor (max_ratio));
}
response = gtk_dialog_run (GTK_DIALOG (dialog));
@ -440,6 +510,13 @@ gimp_transform_tool_bounds (GimpTransformTool *tr_tool,
}
break;
case GIMP_TRANSFORM_TYPE_IMAGE:
tr_tool->x1 = 0;
tr_tool->y1 = 0;
tr_tool->x2 = gimp_image_get_width (image);
tr_tool->y2 = gimp_image_get_height (image);
break;
}
return non_empty;
@ -458,13 +535,13 @@ gimp_transform_tool_recalc_matrix (GimpTransformTool *tr_tool,
GIMP_TRANSFORM_TOOL_GET_CLASS (tr_tool)->recalc_matrix (tr_tool);
}
GimpItem *
gimp_transform_tool_get_active_item (GimpTransformTool *tr_tool,
GimpDisplay *display)
GimpObject *
gimp_transform_tool_get_active_object (GimpTransformTool *tr_tool,
GimpDisplay *display)
{
GimpTransformOptions *options;
GimpImage *image;
GimpItem *item = NULL;
GimpObject *object = NULL;
g_return_val_if_fail (GIMP_IS_TRANSFORM_TOOL (tr_tool), NULL);
g_return_val_if_fail (GIMP_IS_DISPLAY (display), NULL);
@ -475,37 +552,41 @@ gimp_transform_tool_get_active_item (GimpTransformTool *tr_tool,
g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
if (tr_tool->item)
return tr_tool->item;
if (tr_tool->object)
return tr_tool->object;
switch (options->type)
{
case GIMP_TRANSFORM_TYPE_LAYER:
item = GIMP_ITEM (gimp_image_get_active_drawable (image));
object = GIMP_OBJECT (gimp_image_get_active_drawable (image));
break;
case GIMP_TRANSFORM_TYPE_SELECTION:
item = GIMP_ITEM (gimp_image_get_mask (image));
object = GIMP_OBJECT (gimp_image_get_mask (image));
if (gimp_channel_is_empty (GIMP_CHANNEL (item)))
item = NULL;
if (gimp_channel_is_empty (GIMP_CHANNEL (object)))
object = NULL;
break;
case GIMP_TRANSFORM_TYPE_PATH:
item = GIMP_ITEM (gimp_image_get_active_vectors (image));
object = GIMP_OBJECT (gimp_image_get_active_vectors (image));
break;
case GIMP_TRANSFORM_TYPE_IMAGE:
object = GIMP_OBJECT (image);
break;
}
return item;
return object;
}
GimpItem *
gimp_transform_tool_check_active_item (GimpTransformTool *tr_tool,
GimpDisplay *display,
GError **error)
GimpObject *
gimp_transform_tool_check_active_object (GimpTransformTool *tr_tool,
GimpDisplay *display,
GError **error)
{
GimpTransformOptions *options;
GimpItem *item;
GimpObject *object;
const gchar *null_message = NULL;
const gchar *locked_message = NULL;
GimpGuiConfig *config = GIMP_GUI_CONFIG (display->gimp->config);
@ -516,15 +597,17 @@ gimp_transform_tool_check_active_item (GimpTransformTool *tr_tool,
options = GIMP_TRANSFORM_TOOL_GET_OPTIONS (tr_tool);
item = gimp_transform_tool_get_active_item (tr_tool, display);
object = gimp_transform_tool_get_active_object (tr_tool, display);
switch (options->type)
{
case GIMP_TRANSFORM_TYPE_LAYER:
null_message = _("There is no layer to transform.");
if (item)
if (object)
{
GimpItem *item = GIMP_ITEM (object);
if (gimp_item_is_content_locked (item))
locked_message = _("The active layer's pixels are locked.");
else if (gimp_item_is_position_locked (item))
@ -532,7 +615,7 @@ gimp_transform_tool_check_active_item (GimpTransformTool *tr_tool,
if (! gimp_item_is_visible (item) &&
! config->edit_non_visible &&
item != tr_tool->item) /* see bug #759194 */
object != tr_tool->object) /* see bug #759194 */
{
g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
_("The active layer is not visible."));
@ -551,8 +634,10 @@ gimp_transform_tool_check_active_item (GimpTransformTool *tr_tool,
case GIMP_TRANSFORM_TYPE_SELECTION:
null_message = _("There is no selection to transform.");
if (item)
if (object)
{
GimpItem *item = GIMP_ITEM (object);
/* cannot happen, so don't translate these messages */
if (gimp_item_is_content_locked (item))
locked_message = "The selection's pixels are locked.";
@ -564,8 +649,10 @@ gimp_transform_tool_check_active_item (GimpTransformTool *tr_tool,
case GIMP_TRANSFORM_TYPE_PATH:
null_message = _("There is no path to transform.");
if (item)
if (object)
{
GimpItem *item = GIMP_ITEM (object);
if (gimp_item_is_content_locked (item))
locked_message = _("The active path's strokes are locked.");
else if (gimp_item_is_position_locked (item))
@ -574,9 +661,14 @@ gimp_transform_tool_check_active_item (GimpTransformTool *tr_tool,
locked_message = _("The active path has no strokes.");
}
break;
case GIMP_TRANSFORM_TYPE_IMAGE:
/* cannot happen, so don't translate this message */
null_message = "There is no image to transform.";
break;
}
if (! item)
if (! object)
{
g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED, null_message);
if (error)
@ -588,11 +680,11 @@ gimp_transform_tool_check_active_item (GimpTransformTool *tr_tool,
{
g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED, locked_message);
if (error)
gimp_tools_blink_lock_box (display->gimp, item);
gimp_tools_blink_lock_box (display->gimp, GIMP_ITEM (object));
return NULL;
}
return item;
return object;
}
gboolean
@ -603,7 +695,7 @@ gimp_transform_tool_transform (GimpTransformTool *tr_tool,
GimpTransformOptions *options;
GimpContext *context;
GimpImage *image;
GimpItem *active_item;
GimpObject *active_object;
GeglBuffer *orig_buffer = NULL;
gint orig_offset_x = 0;
gint orig_offset_y = 0;
@ -625,10 +717,10 @@ gimp_transform_tool_transform (GimpTransformTool *tr_tool,
g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
active_item = gimp_transform_tool_check_active_item (tr_tool, display,
&error);
active_object = gimp_transform_tool_check_active_object (tr_tool, display,
&error);
if (! active_item)
if (! active_object)
{
gimp_tool_message_literal (tool, display, error->message);
g_clear_error (&error);
@ -666,32 +758,35 @@ gimp_transform_tool_transform (GimpTransformTool *tr_tool,
switch (options->type)
{
case GIMP_TRANSFORM_TYPE_LAYER:
if (! gimp_viewable_get_children (GIMP_VIEWABLE (active_item)) &&
if (! gimp_viewable_get_children (GIMP_VIEWABLE (active_object)) &&
! gimp_channel_is_empty (gimp_image_get_mask (image)))
{
orig_buffer = gimp_drawable_transform_cut (GIMP_DRAWABLE (active_item),
context,
&orig_offset_x,
&orig_offset_y,
&new_layer);
orig_buffer = gimp_drawable_transform_cut (
GIMP_DRAWABLE (active_object),
context,
&orig_offset_x,
&orig_offset_y,
&new_layer);
}
break;
case GIMP_TRANSFORM_TYPE_SELECTION:
case GIMP_TRANSFORM_TYPE_PATH:
case GIMP_TRANSFORM_TYPE_IMAGE:
break;
}
/* Send the request for the transformation to the tool...
*/
new_buffer = GIMP_TRANSFORM_TOOL_GET_CLASS (tr_tool)->transform (tr_tool,
active_item,
orig_buffer,
orig_offset_x,
orig_offset_y,
&buffer_profile,
&new_offset_x,
&new_offset_y);
new_buffer = GIMP_TRANSFORM_TOOL_GET_CLASS (tr_tool)->transform (
tr_tool,
active_object,
orig_buffer,
orig_offset_x,
orig_offset_y,
&buffer_profile,
&new_offset_x,
&new_offset_y);
if (orig_buffer)
g_object_unref (orig_buffer);
@ -704,7 +799,7 @@ gimp_transform_tool_transform (GimpTransformTool *tr_tool,
/* paste the new transformed image to the image...also implement
* undo...
*/
gimp_drawable_transform_paste (GIMP_DRAWABLE (active_item),
gimp_drawable_transform_paste (GIMP_DRAWABLE (active_object),
new_buffer, buffer_profile,
new_offset_x, new_offset_y,
new_layer);
@ -714,6 +809,7 @@ gimp_transform_tool_transform (GimpTransformTool *tr_tool,
case GIMP_TRANSFORM_TYPE_SELECTION:
case GIMP_TRANSFORM_TYPE_PATH:
case GIMP_TRANSFORM_TYPE_IMAGE:
/* Nothing to be done */
break;
}

View File

@ -47,7 +47,7 @@ struct _GimpTransformTool
{
GimpDrawTool parent_instance;
GimpItem *item;
GimpObject *object;
gint x1, y1; /* upper left hand coordinate */
gint x2, y2; /* lower right hand coords */
@ -65,7 +65,7 @@ struct _GimpTransformToolClass
gchar * (* get_undo_desc) (GimpTransformTool *tr_tool);
GimpTransformDirection (* get_direction) (GimpTransformTool *tr_tool);
GeglBuffer * (* transform) (GimpTransformTool *tr_tool,
GimpItem *item,
GimpObject *object,
GeglBuffer *orig_buffer,
gint orig_offset_x,
gint orig_offset_y,
@ -78,21 +78,21 @@ struct _GimpTransformToolClass
};
GType gimp_transform_tool_get_type (void) G_GNUC_CONST;
GType gimp_transform_tool_get_type (void) G_GNUC_CONST;
GimpItem * gimp_transform_tool_get_active_item (GimpTransformTool *tr_tool,
GimpDisplay *display);
GimpItem * gimp_transform_tool_check_active_item (GimpTransformTool *tr_tool,
GimpDisplay *display,
GError **error);
GimpObject * gimp_transform_tool_get_active_object (GimpTransformTool *tr_tool,
GimpDisplay *display);
GimpObject * gimp_transform_tool_check_active_object (GimpTransformTool *tr_tool,
GimpDisplay *display,
GError **error);
gboolean gimp_transform_tool_bounds (GimpTransformTool *tr_tool,
GimpDisplay *display);
void gimp_transform_tool_recalc_matrix (GimpTransformTool *tr_tool,
GimpDisplay *display);
gboolean gimp_transform_tool_bounds (GimpTransformTool *tr_tool,
GimpDisplay *display);
void gimp_transform_tool_recalc_matrix (GimpTransformTool *tr_tool,
GimpDisplay *display);
gboolean gimp_transform_tool_transform (GimpTransformTool *tr_tool,
GimpDisplay *display);
gboolean gimp_transform_tool_transform (GimpTransformTool *tr_tool,
GimpDisplay *display);
#endif /* __GIMP_TRANSFORM_TOOL_H__ */

View File

@ -112,6 +112,7 @@ gimp_transform_type_get_type (void)
{ GIMP_TRANSFORM_TYPE_LAYER, "GIMP_TRANSFORM_TYPE_LAYER", "layer" },
{ GIMP_TRANSFORM_TYPE_SELECTION, "GIMP_TRANSFORM_TYPE_SELECTION", "selection" },
{ GIMP_TRANSFORM_TYPE_PATH, "GIMP_TRANSFORM_TYPE_PATH", "path" },
{ GIMP_TRANSFORM_TYPE_IMAGE, "GIMP_TRANSFORM_TYPE_IMAGE", "image" },
{ 0, NULL, NULL }
};
@ -120,6 +121,7 @@ gimp_transform_type_get_type (void)
{ GIMP_TRANSFORM_TYPE_LAYER, NC_("transform-type", "Layer"), NULL },
{ GIMP_TRANSFORM_TYPE_SELECTION, NC_("transform-type", "Selection"), NULL },
{ GIMP_TRANSFORM_TYPE_PATH, NC_("transform-type", "Path"), NULL },
{ GIMP_TRANSFORM_TYPE_IMAGE, NC_("transform-type", "Image"), NULL },
{ 0, NULL, NULL }
};

View File

@ -85,7 +85,8 @@ typedef enum
{
GIMP_TRANSFORM_TYPE_LAYER, /*< desc="Layer" >*/
GIMP_TRANSFORM_TYPE_SELECTION, /*< desc="Selection" >*/
GIMP_TRANSFORM_TYPE_PATH /*< desc="Path" >*/
GIMP_TRANSFORM_TYPE_PATH, /*< desc="Path" >*/
GIMP_TRANSFORM_TYPE_IMAGE /*< desc="Image" >*/
} GimpTransformType;