Commit 1de667f0 authored by Sven Neumann's avatar Sven Neumann Committed by Sven Neumann

added new enum GimpRotationType.

2003-05-20  Sven Neumann  <sven@gimp.org>

	* app/core/core-enums.[ch]: added new enum GimpRotationType.

	* app/core/Makefile.am
	* app/core/gimpimage-rotate.[ch]: new files.

	* app/core/gimpchannel.c
	* app/core/gimpdrawable-transform.[ch]
	* app/core/gimpdrawable.c
	* app/core/gimpitem.[ch]
	* app/core/gimplayer.c
	* app/vectors/gimpvectors.c: added GimpItem::rotate. Still work in
	progress.

	* plug-ins/common/rotate.c: don't install any menu entries. The
	plug-in is only kept around to provide plug_in_rotate for backward
	compatibility.

	* app/gui/drawable-commands.[ch]
	* app/gui/image-commands.[ch]
	* app/gui/image-menu.c: use the new rotate implementation and use
	stock icons for the menu entries. Fixes bug #57797.
parent 470947f9
2003-05-20 Sven Neumann <sven@gimp.org>
* app/core/core-enums.[ch]: added new enum GimpRotationType.
* app/core/Makefile.am
* app/core/gimpimage-rotate.[ch]: new files.
* app/core/gimpchannel.c
* app/core/gimpdrawable-transform.[ch]
* app/core/gimpdrawable.c
* app/core/gimpitem.[ch]
* app/core/gimplayer.c
* app/vectors/gimpvectors.c: added GimpItem::rotate. Still work in
progress.
* plug-ins/common/rotate.c: don't install any menu entries. The
plug-in is only kept around to provide plug_in_rotate for backward
compatibility.
* app/gui/drawable-commands.[ch]
* app/gui/image-commands.[ch]
* app/gui/image-menu.c: use the new rotate implementation and use
stock icons for the menu entries. Fixes bug #57797.
2003-05-20 Michael Natterer <mitch@gimp.org>
Some color API cleanup:
......@@ -154,6 +154,29 @@ drawable_flip_cmd_callback (GtkWidget *widget,
gimp_image_flush (gimage);
}
void
drawable_rotate_cmd_callback (GtkWidget *widget,
gpointer data,
guint action)
{
GimpImage *gimage;
GimpDrawable *active_drawable;
GimpItem *item;
gint off_x, off_y;
gdouble center_x, center_y;
return_if_no_drawable (gimage, active_drawable, data);
item = GIMP_ITEM (active_drawable);
gimp_item_offsets (item, &off_x, &off_y);
center_x = ((gdouble) off_x + (gdouble) gimp_item_width (item) / 2.0);
center_y = ((gdouble) off_y + (gdouble) gimp_item_height (item) / 2.0);
gimp_item_rotate (item, (GimpRotationType) action, center_x, center_y, TRUE);
gimp_image_flush (gimage);
}
void
drawable_offset_cmd_callback (GtkWidget *widget,
gpointer data)
......
......@@ -29,6 +29,9 @@ void drawable_equalize_cmd_callback (GtkWidget *widget,
void drawable_flip_cmd_callback (GtkWidget *widget,
gpointer data,
guint action);
void drawable_rotate_cmd_callback (GtkWidget *widget,
gpointer data,
guint action);
void drawable_offset_cmd_callback (GtkWidget *widget,
gpointer data);
......
......@@ -33,6 +33,7 @@
#include "core/gimpimage-mask.h"
#include "core/gimpimage-merge.h"
#include "core/gimpimage-resize.h"
#include "core/gimpimage-rotate.h"
#include "core/gimpimage-scale.h"
#include "core/gimpimage-undo.h"
......@@ -221,6 +222,25 @@ image_flip_cmd_callback (GtkWidget *widget,
gimp_image_flush (gdisp->gimage);
}
void
image_rotate_cmd_callback (GtkWidget *widget,
gpointer data,
guint action)
{
GimpDisplay *gdisp;
GimpProgress *progress;
return_if_no_display (gdisp, data);
progress = gimp_progress_start (gdisp, _("Rotating..."), TRUE, NULL, NULL);
gimp_image_rotate (gdisp->gimage, (GimpRotationType) action,
gimp_progress_update_and_flush, progress);
gimp_progress_end (progress);
gimp_image_flush (gdisp->gimage);
}
void
image_crop_cmd_callback (GtkWidget *widget,
gpointer data)
......
......@@ -34,6 +34,9 @@ void image_scale_cmd_callback (GtkWidget *widget,
void image_flip_cmd_callback (GtkWidget *widget,
gpointer data,
guint action);
void image_rotate_cmd_callback (GtkWidget *widget,
gpointer data,
guint action);
void image_crop_cmd_callback (GtkWidget *widget,
gpointer data);
......
......@@ -121,6 +121,8 @@ libappcore_a_sources = \
gimpimage-qmask.h \
gimpimage-resize.c \
gimpimage-resize.h \
gimpimage-rotate.c \
gimpimage-rotate.h \
gimpimage-scale.c \
gimpimage-scale.h \
gimpimage-undo.c \
......
......@@ -276,6 +276,26 @@ gimp_orientation_type_get_type (void)
}
static const GEnumValue gimp_rotation_type_enum_values[] =
{
{ GIMP_ROTATE_90, "GIMP_ROTATE_90", "90" },
{ GIMP_ROTATE_180, "GIMP_ROTATE_180", "180" },
{ GIMP_ROTATE_270, "GIMP_ROTATE_270", "270" },
{ 0, NULL, NULL }
};
GType
gimp_rotation_type_get_type (void)
{
static GType enum_type = 0;
if (!enum_type)
enum_type = g_enum_register_static ("GimpRotationType", gimp_rotation_type_enum_values);
return enum_type;
}
static const GEnumValue gimp_preview_size_enum_values[] =
{
{ GIMP_PREVIEW_SIZE_TINY, N_("Tiny"), "tiny" },
......@@ -431,6 +451,7 @@ static const GEnumValue gimp_undo_type_enum_values[] =
{ GIMP_UNDO_GROUP_IMAGE_SCALE, N_("Scale Image"), "group-image-scale" },
{ GIMP_UNDO_GROUP_IMAGE_RESIZE, N_("Resize Image"), "group-image-resize" },
{ GIMP_UNDO_GROUP_IMAGE_FLIP, N_("Flip Image"), "group-image-flip" },
{ GIMP_UNDO_GROUP_IMAGE_ROTATE, N_("Rotate Image"), "group-image-rotate" },
{ GIMP_UNDO_GROUP_IMAGE_CONVERT, N_("Convert Image"), "group-image-convert" },
{ GIMP_UNDO_GROUP_IMAGE_CROP, N_("Crop Image"), "group-image-crop" },
{ GIMP_UNDO_GROUP_IMAGE_LAYERS_MERGE, N_("Merge Layers"), "group-image-layers-merge" },
......
......@@ -209,6 +209,18 @@ typedef enum
} GimpOrientationType;
#define GIMP_TYPE_ROTATION_TYPE (gimp_rotation_type_get_type ())
GType gimp_rotation_type_get_type (void) G_GNUC_CONST;
typedef enum /*< pdb-skip >*/
{
GIMP_ROTATE_90,
GIMP_ROTATE_180,
GIMP_ROTATE_270
} GimpRotationType;
#define GIMP_TYPE_PREVIEW_SIZE (gimp_preview_size_get_type ())
GType gimp_preview_size_get_type (void) G_GNUC_CONST;
......@@ -318,6 +330,7 @@ typedef enum /*< pdb-skip >*/
GIMP_UNDO_GROUP_IMAGE_SCALE, /*< desc="Scale Image" >*/
GIMP_UNDO_GROUP_IMAGE_RESIZE, /*< desc="Resize Image" >*/
GIMP_UNDO_GROUP_IMAGE_FLIP, /*< desc="Flip Image" >*/
GIMP_UNDO_GROUP_IMAGE_ROTATE, /*< desc="Rotate Image" >*/
GIMP_UNDO_GROUP_IMAGE_CONVERT, /*< desc="Convert Image" >*/
GIMP_UNDO_GROUP_IMAGE_CROP, /*< desc="Crop Image" >*/
GIMP_UNDO_GROUP_IMAGE_LAYERS_MERGE, /*< desc="Merge Layers" >*/
......
......@@ -551,6 +551,164 @@ gimp_drawable_transform_tiles_flip (GimpDrawable *drawable,
return new_tiles;
}
TileManager *
gimp_drawable_transform_tiles_rotate (GimpDrawable *drawable,
TileManager *orig_tiles,
GimpRotationType rotate_type,
gdouble center_x,
gdouble center_y,
gboolean clip_result)
{
GimpImage *gimage;
TileManager *new_tiles;
PixelRegion srcPR, destPR;
guchar *buf = NULL;
gint orig_x, orig_y;
gint orig_width, orig_height;
gint orig_bpp;
gint new_x, new_y;
gint new_width, new_height;
gint i, j, k;
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
g_return_val_if_fail (orig_tiles != NULL, NULL);
gimage = gimp_item_get_image (GIMP_ITEM (drawable));
g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL);
orig_width = tile_manager_width (orig_tiles);
orig_height = tile_manager_height (orig_tiles);
orig_bpp = tile_manager_bpp (orig_tiles);
tile_manager_get_offsets (orig_tiles, &orig_x, &orig_y);
switch (rotate_type)
{
case GIMP_ROTATE_90:
new_x = ROUND (center_x + (gdouble) orig_y - center_y);
new_y = ROUND (center_y + (gdouble) orig_x - center_x);
new_width = orig_height;
new_height = orig_width;
break;
case GIMP_ROTATE_180:
new_x = ROUND ((gdouble) orig_x - 2.0 * center_x) + orig_width - 1;
new_y = ROUND ((gdouble) orig_y - 2.0 * center_y) + orig_height - 1;
new_width = orig_width;
new_height = orig_height;
break;
case GIMP_ROTATE_270:
new_x = ROUND (center_x - (gdouble) orig_y - center_y);
new_y = ROUND (center_y - (gdouble) orig_x - center_x);
new_width = orig_height;
new_height = orig_width;
break;
default:
g_assert_not_reached ();
return NULL;
}
new_tiles = tile_manager_new (new_width, new_height, orig_bpp);
if (FALSE && clip_result)
{
guchar bg_color[MAX_CHANNELS];
gint clip_x, clip_y;
gint clip_width, clip_height;
tile_manager_set_offsets (new_tiles, orig_x, orig_y);
gimp_image_get_background (gimage, drawable, bg_color);
/* "Outside" a channel is transparency, not the bg color */
if (GIMP_IS_CHANNEL (drawable))
bg_color[0] = TRANSPARENT_OPACITY;
pixel_region_init (&destPR, new_tiles,
0, 0, new_width, new_height, TRUE);
color_region (&destPR, bg_color);
if (gimp_rectangle_intersect (orig_x, orig_y, orig_width, orig_height,
new_x, new_y, new_width, new_height,
&clip_x, &clip_y,
&clip_width, &clip_height))
{
orig_x = new_x = clip_x - orig_x;
orig_y = new_y = clip_y - orig_y;
}
orig_width = new_width = clip_width;
orig_height = new_height = clip_height;
}
else
{
tile_manager_set_offsets (new_tiles, new_x, new_y);
orig_x = 0;
orig_y = 0;
new_x = 0;
new_y = 0;
}
if (new_width == 0 && new_height == 0)
return new_tiles;
pixel_region_init (&srcPR, orig_tiles,
orig_x, orig_y, orig_width, orig_height, FALSE);
pixel_region_init (&destPR, new_tiles,
new_x, new_y, new_width, new_height, TRUE);
switch (rotate_type)
{
case GIMP_ROTATE_90:
g_assert (new_height == orig_width);
buf = g_new (guchar, new_height * orig_bpp);
for (i = 0; i < orig_height; i++)
{
pixel_region_get_row (&srcPR, orig_x, orig_y + orig_height - 1 - i,
orig_width, buf, 1);
pixel_region_set_col (&destPR, new_x + i, new_y, new_height, buf);
}
break;
case GIMP_ROTATE_180:
g_assert (new_width == orig_width);
buf = g_new (guchar, new_width * orig_bpp);
for (i = 0; i < orig_height; i++)
{
pixel_region_get_row (&srcPR, orig_x, orig_y + orig_height - 1 - i,
orig_width, buf, 1);
for (j = 0; j < orig_width / 2; j++)
for (k = 0; k < orig_bpp; k++)
buf[j * orig_bpp + k] = buf[(orig_width - 1 - j) * orig_bpp + k];
pixel_region_set_row (&destPR, new_x, new_y + i, new_width, buf);
}
break;
case GIMP_ROTATE_270:
g_assert (new_width == orig_height);
buf = g_new (guchar, new_width * orig_bpp);
for (i = 0; i < orig_width; i++)
{
pixel_region_get_col (&srcPR, orig_x + orig_width - 1 - i, orig_y,
orig_height, buf, 1);
pixel_region_set_row (&destPR, new_x, new_y + i, new_width, buf);
}
break;
}
g_free (buf);
return new_tiles;
}
gboolean
gimp_drawable_transform_affine (GimpDrawable *drawable,
GimpMatrix3 matrix,
......@@ -624,8 +782,7 @@ gimp_drawable_transform_flip (GimpDrawable *drawable,
g_return_val_if_fail (GIMP_IS_IMAGE (gimage), FALSE);
/* Start a transform undo group */
gimp_image_undo_group_start (gimage, GIMP_UNDO_GROUP_TRANSFORM,
_("Flip"));
gimp_image_undo_group_start (gimage, GIMP_UNDO_GROUP_TRANSFORM, _("Flip"));
/* Cut/Copy from the specified drawable */
orig_tiles = gimp_drawable_transform_cut (drawable, &new_layer);
......@@ -673,6 +830,61 @@ gimp_drawable_transform_flip (GimpDrawable *drawable,
return success;
}
gboolean
gimp_drawable_transform_rotate (GimpDrawable *drawable,
GimpRotationType rotate_type)
{
GimpImage *gimage;
TileManager *orig_tiles;
gboolean new_layer;
gboolean success = FALSE;
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE);
gimage = gimp_item_get_image (GIMP_ITEM (drawable));
g_return_val_if_fail (GIMP_IS_IMAGE (gimage), FALSE);
/* Start a transform undo group */
gimp_image_undo_group_start (gimage, GIMP_UNDO_GROUP_TRANSFORM, _("Rotate"));
/* Cut/Copy from the specified drawable */
orig_tiles = gimp_drawable_transform_cut (drawable, &new_layer);
if (orig_tiles)
{
TileManager *new_tiles;
gint off_x, off_y;
gint width, height;
gdouble center_x, center_y;
tile_manager_get_offsets (orig_tiles, &off_x, &off_y);
width = tile_manager_width (orig_tiles);
height = tile_manager_height (orig_tiles);
center_x = (gdouble) off_x + (gdouble) width / 2.0;
center_y = (gdouble) off_y + (gdouble) height / 2.0;
/* transform the buffer */
new_tiles = gimp_drawable_transform_tiles_rotate (drawable, orig_tiles,
rotate_type,
center_x, center_y,
FALSE);
/* Free the cut/copied buffer */
tile_manager_destroy (orig_tiles);
if (new_tiles)
success = gimp_drawable_transform_paste (drawable, new_tiles,
new_layer);
}
/* push the undo group end */
gimp_image_undo_group_end (gimage);
return success;
}
TileManager *
gimp_drawable_transform_cut (GimpDrawable *drawable,
gboolean *new_layer)
......
......@@ -78,6 +78,11 @@ static void gimp_channel_flip (GimpItem *item,
GimpOrientationType flip_type,
gdouble axis,
gboolean flip_result);
static void gimp_channel_rotate (GimpItem *item,
GimpRotationType flip_type,
gdouble center_x,
gdouble center_y,
gboolean flip_result);
static void gimp_channel_transform (GimpItem *item,
GimpMatrix3 matrix,
GimpTransformDirection direction,
......@@ -149,6 +154,7 @@ gimp_channel_class_init (GimpChannelClass *klass)
item_class->scale = gimp_channel_scale;
item_class->resize = gimp_channel_resize;
item_class->flip = gimp_channel_flip;
item_class->rotate = gimp_channel_rotate;
item_class->transform = gimp_channel_transform;
item_class->default_name = _("Channel");
item_class->rename_desc = _("Rename Channel");
......@@ -420,6 +426,35 @@ gimp_channel_flip (GimpItem *item,
channel->bounds_known = FALSE;
}
static void
gimp_channel_rotate (GimpItem *item,
GimpRotationType rotate_type,
gdouble center_x,
gdouble center_y,
gboolean clip_result)
{
GimpChannel *channel;
GimpImage *gimage;
channel = GIMP_CHANNEL (item);
gimage = gimp_item_get_image (item);
gimp_image_undo_group_start (gimage, GIMP_UNDO_GROUP_TRANSFORM,
_("Rotate Channel"));
if (G_TYPE_FROM_INSTANCE (item) == GIMP_TYPE_CHANNEL)
clip_result = TRUE;
GIMP_ITEM_CLASS (parent_class)->rotate (item,
rotate_type, center_x, center_y,
clip_result);
gimp_image_undo_group_end (gimage);
/* bounds are now unknown */
channel->bounds_known = FALSE;
}
static void
gimp_channel_transform (GimpItem *item,
GimpMatrix3 matrix,
......
......@@ -78,6 +78,11 @@ static void gimp_channel_flip (GimpItem *item,
GimpOrientationType flip_type,
gdouble axis,
gboolean flip_result);
static void gimp_channel_rotate (GimpItem *item,
GimpRotationType flip_type,
gdouble center_x,
gdouble center_y,
gboolean flip_result);
static void gimp_channel_transform (GimpItem *item,
GimpMatrix3 matrix,
GimpTransformDirection direction,
......@@ -149,6 +154,7 @@ gimp_channel_class_init (GimpChannelClass *klass)
item_class->scale = gimp_channel_scale;
item_class->resize = gimp_channel_resize;
item_class->flip = gimp_channel_flip;
item_class->rotate = gimp_channel_rotate;
item_class->transform = gimp_channel_transform;
item_class->default_name = _("Channel");
item_class->rename_desc = _("Rename Channel");
......@@ -420,6 +426,35 @@ gimp_channel_flip (GimpItem *item,
channel->bounds_known = FALSE;
}
static void
gimp_channel_rotate (GimpItem *item,
GimpRotationType rotate_type,
gdouble center_x,
gdouble center_y,
gboolean clip_result)
{
GimpChannel *channel;
GimpImage *gimage;
channel = GIMP_CHANNEL (item);
gimage = gimp_item_get_image (item);
gimp_image_undo_group_start (gimage, GIMP_UNDO_GROUP_TRANSFORM,
_("Rotate Channel"));
if (G_TYPE_FROM_INSTANCE (item) == GIMP_TYPE_CHANNEL)
clip_result = TRUE;
GIMP_ITEM_CLASS (parent_class)->rotate (item,
rotate_type, center_x, center_y,
clip_result);
gimp_image_undo_group_end (gimage);
/* bounds are now unknown */
channel->bounds_known = FALSE;
}
static void
gimp_channel_transform (GimpItem *item,
GimpMatrix3 matrix,
......
......@@ -551,6 +551,164 @@ gimp_drawable_transform_tiles_flip (GimpDrawable *drawable,
return new_tiles;
}
TileManager *
gimp_drawable_transform_tiles_rotate (GimpDrawable *drawable,
TileManager *orig_tiles,
GimpRotationType rotate_type,
gdouble center_x,
gdouble center_y,
gboolean clip_result)
{
GimpImage *gimage;
TileManager *new_tiles;
PixelRegion srcPR, destPR;
guchar *buf = NULL;
gint orig_x, orig_y;
gint orig_width, orig_height;
gint orig_bpp;
gint new_x, new_y;
gint new_width, new_height;
gint i, j, k;
g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
g_return_val_if_fail (orig_tiles != NULL, NULL);
gimage = gimp_item_get_image (GIMP_ITEM (drawable));
g_return_val_if_fail (GIMP_IS_IMAGE (gimage), NULL);
orig_width = tile_manager_width (orig_tiles);
orig_height = tile_manager_height (orig_tiles);
orig_bpp = tile_manager_bpp (orig_tiles);
tile_manager_get_offsets (orig_tiles, &orig_x, &orig_y);
switch (rotate_type)
{
case GIMP_ROTATE_90:
new_x = ROUND (center_x + (gdouble) orig_y - center_y);
new_y = ROUND (center_y + (gdouble) orig_x - center_x);
new_width = orig_height;
new_height = orig_width;
break;
case GIMP_ROTATE_180:
new_x = ROUND ((gdouble) orig_x - 2.0 * center_x) + orig_width - 1;
new_y = ROUND ((gdouble) orig_y - 2.0 * center_y) + orig_height - 1;
new_width = orig_width;
new_height = orig_height;
break;
case GIMP_ROTATE_270:
new_x = ROUND (center_x - (gdouble) orig_y - center_y);
new_y = ROUND (center_y - (gdouble) orig_x - center_x);
new_width = orig_height;
new_height = orig_width;
break;
default:
g_assert_not_reached ();
return NULL;
}
new_tiles = tile_manager_new (new_width, new_height, orig_bpp);
if (FALSE && clip_result)
{
guchar bg_color[MAX_CHANNELS];
gint clip_x, clip_y;
gint clip_width, clip_height;
tile_manager_set_offsets (new_tiles, orig_x, orig_y);
gimp_image_get_background (gimage, drawable, bg_color);
/* "Outside" a channel is transparency, not the bg color */
if (GIMP_IS_CHANNEL (drawable))
bg_color[0] = TRANSPARENT_OPACITY;
pixel_region_init (&destPR, new_tiles,
0, 0, new_width, new_height, TRUE);
color_region (&destPR, bg_color);
if (gimp_rectangle_intersect (orig_x, orig_y, orig_width, orig_height,
new_x, new_y, new_width, new_height,
&clip_x, &clip_y,
&clip_width, &clip_height))
{
orig_x = new_x = clip_x - orig_x;
orig_y = new_y = clip_y - orig_y;
}
orig_width = new_width = clip_width;
orig_height = new_height = clip_height;
}
else
{
tile_manager_set_offsets (new_tiles, new_x, new_y);
orig_x = 0;
orig_y = 0;
new_x = 0;
new_y = 0;
}
if (new_width == 0 && new_height == 0)
return new_tiles;
pixel_region_init (&srcPR, orig_tiles,
orig_x, orig_y, orig_width, orig_height, FALSE);
pixel_region_init (&destPR, new_tiles,
new_x, new_y, new_width, new_height, TRUE);
switch (rotate_type)
{
case GIMP_ROTATE_90:
g_assert (new_height == orig_width);
buf = g_new (guchar, new_height * orig_bpp);
for (i = 0; i < orig_height; i++)
{
pixel_region_get_row (&srcPR, orig_x, orig_y + orig_height - 1 - i,
orig_width, buf, 1);
pixel_region_set_col (&destPR, new_x + i, new_y, new_height, buf);
}
break;
case GIMP_ROTATE_180:
g_assert (new_width == orig_width);
buf = g_new (guchar, new_width * orig_bpp);
for (i = 0; i < orig_height; i++)
{
pixel_region_get_row (&srcPR, orig_x, orig_y + orig_height - 1 - i,
orig_width, buf, 1);
for (j = 0; j < orig_width / 2; j++)
for (k = 0; k < orig_bpp; k++)
buf[j * orig_bpp + k] = buf[(orig_width - 1 - j) * orig_bpp + k];
pixel_region_set_row (&destPR, new_x, new_y + i, new_width, buf);
}
break;
case GIMP_ROTATE_270:
g_assert (new_width == orig_height);
buf = g_new (guchar, new_width * orig_bpp);
for (i = 0; i < orig_width; i++)
{
pixel_region_get_col (&srcPR, orig_x + orig_width - 1 - i, orig_y,
orig_height, buf, 1);
pixel_region_set_row (&destPR, new_x, new_y + i, new_width, buf);
}
break;
}
g_free (buf);
return new_tiles;
}
gboolean
gimp_drawable_transform_affine (GimpDrawable *drawable,
GimpMatrix3 matrix,
......@@ -624,8 +782,7 @@ gimp_drawable_transform_flip (GimpDrawable *drawable,
g_return_val_if_fail (GIMP_IS_IMAGE (gimage), FALSE);
/* Start a transform undo group */
gimp_image_undo_group_start (gimage, GIMP_UNDO_GROUP_TRANSFORM,
_("Flip"));
gimp_image_undo_group_start (gimage, GIMP_UNDO_GROUP_TRANSFORM, _("Flip"));
/* Cut/Copy from the specified drawable */
orig_tiles = gimp_drawable_transform_cut (drawable, &new_layer);
......@@ -673,6 +830,61 @@ gimp_drawable_transform_flip (GimpDrawable *drawable,
return success;
}
gboolean
gimp_drawable_transform_rotate (GimpDrawable *drawable,
GimpRotationType rotate_type)
{
GimpImage *gimage;
TileManager *orig_tiles;
gboolean new_layer;
gboolean success = FALSE;