Commit 2a17435e authored by Michael Natterer's avatar Michael Natterer 😴 Committed by Michael Natterer

Started to abstract item transformation so we can easily transform

2003-05-07  Michael Natterer  <mitch@gimp.org>

	Started to abstract item transformation so we can easily
	transform multiple linked items later:

	* app/core/gimpitem.[ch]: added new virtual function
	GimpItem::scale() with the same signature as the former
	gimp_layer_scale_lowlevel().

	* app/core/gimpdrawable.c: implement scale() and do the
	common parts of layer/channel scaling here.

	* app/core/gimpchannel.[ch]
	* app/core/gimplayer.[ch]: implement scale() for the
	channel/layer specific parts of scaling.

	* app/core/gimplayer.[ch]: renamed gimp_layer_scale() to
	gimp_layer_scale_by_origin().

	* app/vectors/gimpvectors.c: added empty scale() implementation.

	* app/core/gimpimage-scale.c
	* app/core/gimpimage-undo-push.c
	* app/gui/layers-commands.c
	* tools/pdbgen/pdb/layer.pdb: changed accordingly.

	* app/pdb/layer_cmds.c: regenerated.

	Unrelated:

	* app/core/gimpimage-undo-push.c: fixed item rename undo to
	take the size of the saved name into account. Removed old
	path_undo stuff.
parent f3747dba
2003-05-07 Michael Natterer <mitch@gimp.org>
Started to abstract item transformation so we can easily
transform multiple linked items later:
* app/core/gimpitem.[ch]: added new virtual function
GimpItem::scale() with the same signature as the former
gimp_layer_scale_lowlevel().
* app/core/gimpdrawable.c: implement scale() and do the
common parts of layer/channel scaling here.
* app/core/gimpchannel.[ch]
* app/core/gimplayer.[ch]: implement scale() for the
channel/layer specific parts of scaling.
* app/core/gimplayer.[ch]: renamed gimp_layer_scale() to
gimp_layer_scale_by_origin().
* app/vectors/gimpvectors.c: added empty scale() implementation.
* app/core/gimpimage-scale.c
* app/core/gimpimage-undo-push.c
* app/gui/layers-commands.c
* tools/pdbgen/pdb/layer.pdb: changed accordingly.
* app/pdb/layer_cmds.c: regenerated.
Unrelated:
* app/core/gimpimage-undo-push.c: fixed item rename undo to
take the size of the saved name into account. Removed old
path_undo stuff.
2003-05-06 Michael Natterer <mitch@gimp.org>
* app/tools/tools-enums.[ch]: removed GimpToolState (ACTIVE,
......@@ -935,22 +935,26 @@ scale_layer_query_ok_callback (GtkWidget *widget,
if (gimage)
{
gimp_image_undo_group_start (gimage, GIMP_UNDO_GROUP_LAYER_SCALE,
_("Scale Layer"));
if (gimp_layer_is_floating_sel (layer))
floating_sel_relax (layer, TRUE);
{
gimp_image_undo_group_start (gimage, GIMP_UNDO_GROUP_LAYER_SCALE,
_("Scale Layer"));
floating_sel_relax (layer, TRUE);
}
gimp_layer_scale (layer,
options->resize->width,
options->resize->height,
options->resize->interpolation,
TRUE);
gimp_layer_scale_by_origin (layer,
options->resize->width,
options->resize->height,
options->resize->interpolation,
TRUE);
if (gimp_layer_is_floating_sel (layer))
floating_sel_rigor (layer, TRUE);
{
floating_sel_rigor (layer, TRUE);
gimp_image_undo_group_end (gimage);
gimp_image_undo_group_end (gimage);
}
gimp_image_flush (gimage);
}
......
......@@ -58,6 +58,12 @@ static gsize gimp_channel_get_memsize (GimpObject *object);
static GimpItem * gimp_channel_duplicate (GimpItem *item,
GType new_type,
gboolean add_alpha);
static void gimp_channel_scale (GimpItem *item,
gint new_width,
gint new_height,
gint new_offset_x,
gint new_offset_y,
GimpInterpolationType interp_type);
static void gimp_channel_push_undo (GimpChannel *mask,
const gchar *undo_desc);
......@@ -118,6 +124,7 @@ gimp_channel_class_init (GimpChannelClass *klass)
viewable_class->default_stock_id = "gimp-channel";
item_class->duplicate = gimp_channel_duplicate;
item_class->scale = gimp_channel_scale;
item_class->default_name = _("Channel");
item_class->rename_desc = _("Rename Channel");
}
......@@ -218,6 +225,30 @@ gimp_channel_duplicate (GimpItem *item,
return new_item;
}
static void
gimp_channel_scale (GimpItem *item,
gint new_width,
gint new_height,
gint new_offset_x,
gint new_offset_y,
GimpInterpolationType interpolation_type)
{
GimpChannel *channel;
channel = GIMP_CHANNEL (item);
gimp_image_undo_push_channel_mod (gimp_item_get_image (item),
_("Scale Channel"),
channel);
GIMP_ITEM_CLASS (parent_class)->scale (item, new_width, new_height,
new_offset_x, new_offset_y,
interpolation_type);
/* bounds are now unknown */
channel->bounds_known = FALSE;
}
static void
gimp_channel_push_undo (GimpChannel *mask,
const gchar *undo_desc)
......@@ -420,66 +451,6 @@ gimp_channel_set_show_masked (GimpChannel *channel,
}
}
void
gimp_channel_scale (GimpChannel *channel,
gint new_width,
gint new_height,
GimpInterpolationType interpolation_type)
{
PixelRegion srcPR, destPR;
TileManager *new_tiles;
g_return_if_fail (GIMP_IS_CHANNEL (channel));
if (new_width == 0 || new_height == 0)
return;
/* Update the old channel position */
gimp_drawable_update (GIMP_DRAWABLE (channel),
0, 0,
GIMP_DRAWABLE (channel)->width,
GIMP_DRAWABLE (channel)->height);
/* Allocate the new channel */
new_tiles = tile_manager_new (new_width, new_height, 1);
/* Configure the pixel regions */
pixel_region_init (&srcPR, GIMP_DRAWABLE (channel)->tiles,
0, 0,
GIMP_DRAWABLE (channel)->width,
GIMP_DRAWABLE (channel)->height,
FALSE);
pixel_region_init (&destPR, new_tiles,
0, 0,
new_width, new_height,
TRUE);
/* Sclae the channel */
scale_region (&srcPR, &destPR, interpolation_type);
/* Push the channel on the undo stack */
gimp_image_undo_push_channel_mod (gimp_item_get_image (GIMP_ITEM (channel)),
_("Scale Channel"),
channel);
/* Configure the new channel */
GIMP_DRAWABLE (channel)->tiles = new_tiles;
GIMP_DRAWABLE (channel)->width = new_width;
GIMP_DRAWABLE (channel)->height = new_height;
/* bounds are now unknown */
channel->bounds_known = FALSE;
/* Update the new channel position */
gimp_drawable_update (GIMP_DRAWABLE (channel),
0, 0,
GIMP_DRAWABLE (channel)->width,
GIMP_DRAWABLE (channel)->height);
gimp_viewable_size_changed (GIMP_VIEWABLE (channel));
}
void
gimp_channel_resize (GimpChannel *channel,
gint new_width,
......
......@@ -92,10 +92,6 @@ gboolean gimp_channel_get_show_masked (GimpChannel *channel);
void gimp_channel_set_show_masked (GimpChannel *channel,
gboolean show_masked);
void gimp_channel_scale (GimpChannel *channel,
gint new_width,
gint new_height,
GimpInterpolationType interpolation_type);
void gimp_channel_resize (GimpChannel *channel,
gint new_width,
gint new_height,
......
......@@ -58,6 +58,12 @@ static gsize gimp_channel_get_memsize (GimpObject *object);
static GimpItem * gimp_channel_duplicate (GimpItem *item,
GType new_type,
gboolean add_alpha);
static void gimp_channel_scale (GimpItem *item,
gint new_width,
gint new_height,
gint new_offset_x,
gint new_offset_y,
GimpInterpolationType interp_type);
static void gimp_channel_push_undo (GimpChannel *mask,
const gchar *undo_desc);
......@@ -118,6 +124,7 @@ gimp_channel_class_init (GimpChannelClass *klass)
viewable_class->default_stock_id = "gimp-channel";
item_class->duplicate = gimp_channel_duplicate;
item_class->scale = gimp_channel_scale;
item_class->default_name = _("Channel");
item_class->rename_desc = _("Rename Channel");
}
......@@ -218,6 +225,30 @@ gimp_channel_duplicate (GimpItem *item,
return new_item;
}
static void
gimp_channel_scale (GimpItem *item,
gint new_width,
gint new_height,
gint new_offset_x,
gint new_offset_y,
GimpInterpolationType interpolation_type)
{
GimpChannel *channel;
channel = GIMP_CHANNEL (item);
gimp_image_undo_push_channel_mod (gimp_item_get_image (item),
_("Scale Channel"),
channel);
GIMP_ITEM_CLASS (parent_class)->scale (item, new_width, new_height,
new_offset_x, new_offset_y,
interpolation_type);
/* bounds are now unknown */
channel->bounds_known = FALSE;
}
static void
gimp_channel_push_undo (GimpChannel *mask,
const gchar *undo_desc)
......@@ -420,66 +451,6 @@ gimp_channel_set_show_masked (GimpChannel *channel,
}
}
void
gimp_channel_scale (GimpChannel *channel,
gint new_width,
gint new_height,
GimpInterpolationType interpolation_type)
{
PixelRegion srcPR, destPR;
TileManager *new_tiles;
g_return_if_fail (GIMP_IS_CHANNEL (channel));
if (new_width == 0 || new_height == 0)
return;
/* Update the old channel position */
gimp_drawable_update (GIMP_DRAWABLE (channel),
0, 0,
GIMP_DRAWABLE (channel)->width,
GIMP_DRAWABLE (channel)->height);
/* Allocate the new channel */
new_tiles = tile_manager_new (new_width, new_height, 1);
/* Configure the pixel regions */
pixel_region_init (&srcPR, GIMP_DRAWABLE (channel)->tiles,
0, 0,
GIMP_DRAWABLE (channel)->width,
GIMP_DRAWABLE (channel)->height,
FALSE);
pixel_region_init (&destPR, new_tiles,
0, 0,
new_width, new_height,
TRUE);
/* Sclae the channel */
scale_region (&srcPR, &destPR, interpolation_type);
/* Push the channel on the undo stack */
gimp_image_undo_push_channel_mod (gimp_item_get_image (GIMP_ITEM (channel)),
_("Scale Channel"),
channel);
/* Configure the new channel */
GIMP_DRAWABLE (channel)->tiles = new_tiles;
GIMP_DRAWABLE (channel)->width = new_width;
GIMP_DRAWABLE (channel)->height = new_height;
/* bounds are now unknown */
channel->bounds_known = FALSE;
/* Update the new channel position */
gimp_drawable_update (GIMP_DRAWABLE (channel),
0, 0,
GIMP_DRAWABLE (channel)->width,
GIMP_DRAWABLE (channel)->height);
gimp_viewable_size_changed (GIMP_VIEWABLE (channel));
}
void
gimp_channel_resize (GimpChannel *channel,
gint new_width,
......
......@@ -92,10 +92,6 @@ gboolean gimp_channel_get_show_masked (GimpChannel *channel);
void gimp_channel_set_show_masked (GimpChannel *channel,
gboolean show_masked);
void gimp_channel_scale (GimpChannel *channel,
gint new_width,
gint new_height,
GimpInterpolationType interpolation_type);
void gimp_channel_resize (GimpChannel *channel,
gint new_width,
gint new_height,
......
......@@ -74,6 +74,12 @@ static void gimp_drawable_invalidate_preview (GimpViewable *viewable)
static GimpItem * gimp_drawable_duplicate (GimpItem *item,
GType new_type,
gboolean add_alpha);
static void gimp_drawable_scale (GimpItem *item,
gint new_width,
gint new_height,
gint new_offset_x,
gint new_offset_y,
GimpInterpolationType interp_type);
/* private variables */
......@@ -145,6 +151,7 @@ gimp_drawable_class_init (GimpDrawableClass *klass)
viewable_class->get_preview = gimp_drawable_get_preview;
item_class->duplicate = gimp_drawable_duplicate;
item_class->scale = gimp_drawable_scale;
klass->visibility_changed = NULL;
}
......@@ -283,6 +290,61 @@ gimp_drawable_duplicate (GimpItem *item,
return new_item;
}
static void
gimp_drawable_scale (GimpItem *item,
gint new_width,
gint new_height,
gint new_offset_x,
gint new_offset_y,
GimpInterpolationType interpolation_type)
{
GimpDrawable *drawable;
PixelRegion srcPR, destPR;
TileManager *new_tiles;
drawable = GIMP_DRAWABLE (item);
/* Update the old position */
gimp_drawable_update (drawable, 0, 0, drawable->width, drawable->height);
/* Allocate the new channel */
new_tiles = tile_manager_new (new_width, new_height, drawable->bytes);
/* Configure the pixel regions */
pixel_region_init (&srcPR, drawable->tiles,
0, 0,
drawable->width,
drawable->height,
FALSE);
pixel_region_init (&destPR, new_tiles,
0, 0,
new_width, new_height,
TRUE);
/* Scale the drawable -
* If the drawable is indexed, then we don't use pixel-value
* resampling because that doesn't necessarily make sense for indexed
* images.
*/
if (gimp_drawable_is_indexed (drawable))
interpolation_type = GIMP_INTERPOLATION_NONE;
scale_region (&srcPR, &destPR, interpolation_type);
/* Configure the new channel */
drawable->tiles = new_tiles;
drawable->width = new_width;
drawable->height = new_height;
drawable->offset_x = new_offset_x;
drawable->offset_y = new_offset_y;
/* Update the new position */
gimp_drawable_update (drawable, 0, 0, drawable->width, drawable->height);
gimp_viewable_size_changed (GIMP_VIEWABLE (drawable));
}
void
gimp_drawable_configure (GimpDrawable *drawable,
GimpImage *gimage,
......
......@@ -45,7 +45,7 @@ gimp_image_scale (GimpImage *gimage,
GimpProgressFunc progress_func,
gpointer progress_data)
{
GimpChannel *channel;
GimpItem *item;
GimpLayer *layer;
GimpLayer *floating_layer;
GList *list;
......@@ -95,9 +95,9 @@ gimp_image_scale (GimpImage *gimage,
list;
list = g_list_next (list))
{
channel = (GimpChannel *) list->data;
item = (GimpItem *) list->data;
gimp_channel_scale (channel, new_width, new_height, interpolation_type);
gimp_item_scale (item, new_width, new_height, 0, 0, interpolation_type);
if (progress_func)
{
......@@ -113,8 +113,8 @@ gimp_image_scale (GimpImage *gimage,
else
*/
gimp_channel_scale (gimage->selection_mask, new_width, new_height,
interpolation_type);
gimp_item_scale (GIMP_ITEM (gimage->selection_mask), new_width, new_height,
0, 0, interpolation_type);
gimp_image_mask_invalidate (gimage);
/* Scale all layers */
......
......@@ -21,11 +21,11 @@
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include <glib-object.h>
#include "libgimpbase/gimpbase.h"
#include "tools/tools-types.h"
#include "core-types.h"
#include "config/gimpcoreconfig.h"
......@@ -57,8 +57,6 @@
#include "vectors/gimpvectors.h"
#include "path_transform.h"
#include "gimp-intl.h"
......@@ -1014,14 +1012,19 @@ gimp_image_undo_push_item_rename (GimpImage *gimage,
const gchar *undo_desc,
GimpItem *item)
{
GimpUndo *new;
GimpUndo *new;
gsize size;
const gchar *name;
g_return_val_if_fail (GIMP_IS_IMAGE (gimage), FALSE);
g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE);
name = gimp_object_get_name (GIMP_OBJECT (item));
size = sizeof (ItemRenameUndo) + strlen (name) + 1;
if ((new = gimp_image_undo_push_item (gimage, item,
sizeof (ItemRenameUndo),
sizeof (ItemRenameUndo),
size, sizeof (ItemRenameUndo),
GIMP_UNDO_ITEM_RENAME, undo_desc,
TRUE,
undo_pop_item_rename,
......@@ -1031,7 +1034,7 @@ gimp_image_undo_push_item_rename (GimpImage *gimage,
iru = new->data;
iru->old_name = g_strdup (gimp_object_get_name (GIMP_OBJECT (item)));
iru->old_name = g_strdup (name);
return TRUE;
}
......@@ -1694,9 +1697,8 @@ typedef struct _LayerDisplaceUndo LayerDisplaceUndo;
struct _LayerDisplaceUndo
{
gint old_offset_x;
gint old_offset_y;
GSList *path_undo;
gint old_offset_x;
gint old_offset_y;
};
static gboolean undo_pop_layer_displace (GimpUndo *undo,
......@@ -1729,7 +1731,6 @@ gimp_image_undo_push_layer_displace (GimpImage *gimage,
ldu->old_offset_x = GIMP_DRAWABLE (layer)->offset_x;
ldu->old_offset_y = GIMP_DRAWABLE (layer)->offset_y;
ldu->path_undo = path_transform_start_undo (gimage);
return TRUE;
}
......@@ -1761,10 +1762,6 @@ undo_pop_layer_displace (GimpUndo *undo,
ldu->old_offset_x = offset_x;
ldu->old_offset_y = offset_y;
/* Now undo paths bits */
if (ldu->path_undo)
path_transform_do_undo (undo->gimage, ldu->path_undo);
return TRUE;
}
......@@ -1776,9 +1773,6 @@ undo_free_layer_displace (GimpUndo *undo,
ldu = (LayerDisplaceUndo *) undo->data;
if (ldu->path_undo)
path_transform_free_undo (ldu->path_undo);
g_free (ldu);
}
......
......@@ -322,6 +322,27 @@ gimp_item_rename (GimpItem *item,
item_class->rename (item, new_name, item_class->rename_desc);
}
void
gimp_item_scale (GimpItem *item,
gint new_width,
gint new_height,
gint new_offset_x,
gint new_offset_y,
GimpInterpolationType interpolation_type)
{
GimpItemClass *item_class;
g_return_if_fail (GIMP_IS_ITEM (item));
if (new_width == 0 || new_height == 0)
return;
item_class = GIMP_ITEM_GET_CLASS (item);
item_class->scale (item, new_width, new_height, new_offset_x, new_offset_y,
interpolation_type);
}
gint
gimp_item_get_ID (GimpItem *item)
{
......
......@@ -53,15 +53,22 @@ struct _GimpItemClass
void (* removed) (GimpItem *item);
/* virtual functions */
GimpItem * (* duplicate) (GimpItem *item,
GType new_type,
gboolean add_alpha);
void (* rename) (GimpItem *item,
const gchar *new_name,
const gchar *undo_desc);
GimpItem * (* duplicate) (GimpItem *item,
GType new_type,
gboolean add_alpha);
void (* rename) (GimpItem *item,
const gchar *new_name,
const gchar *undo_desc);
void (* scale) (GimpItem *item,
gint new_width,
gint new_height,
gint new_offset_x,
gint new_offset_y,
GimpInterpolationType interpolation_type);
const gchar *default_name;
const gchar *rename_desc;
const gchar *scale_desc;
};
......@@ -79,6 +86,13 @@ GimpItem * gimp_item_duplicate (GimpItem *item,
void gimp_item_rename (GimpItem *item,
const gchar *new_name);
void gimp_item_scale (GimpItem *item,
gint new_width,
gint new_height,
gint new_offset_x,
gint new_offset_y,
GimpInterpolationType interp_type);
gint gimp_item_get_ID (GimpItem *item);
GimpItem * gimp_item_get_by_ID (Gimp *gimp,
gint id);
......
......@@ -75,6 +75,12 @@ static GimpItem * gimp_layer_duplicate (GimpItem *item,
static void gimp_layer_rename (GimpItem *item,
const gchar *new_name,
const gchar *undo_desc);
static void gimp_layer_scale (GimpItem *item,
gint new_width,
gint new_height,
gint new_offset_x,
gint new_offset_y,
GimpInterpolationType interp_type);
static void gimp_layer_transform_color (GimpImage *gimage,
PixelRegion *layerPR,
......@@ -185,6 +191,7 @@ gimp_layer_class_init (GimpLayerClass *klass)
item_class->duplicate = gimp_layer_duplicate;
item_class->rename = gimp_layer_rename;
item_class->scale = gimp_layer_scale;
item_class->default_name = _("Layer");
item_class->rename_desc = _("Rename Layer");
......@@ -344,6 +351,46 @@ gimp_layer_rename (GimpItem *item,
gimp_image_undo_group_end (gimage);
}
static void
gimp_layer_scale (GimpItem *item,
gint new_width,
gint new_height,
gint new_offset_x,
gint new_offset_y,
GimpInterpolationType interpolation_type)
{
GimpLayer *layer;
GimpImage *gimage;
layer = GIMP_LAYER (item);
gimage = gimp_item_get_image (item);
if (layer->mask)
gimp_image_undo_group_start (gimage, GIMP_UNDO_GROUP_LAYER_SCALE,
_("Scale Layer"));
gimp_image_undo_push_layer_mod (gimage, _("Scale Layer"), layer);
GIMP_ITEM_CLASS (parent_class)->scale (item, new_width, new_height,
new_offset_x, new_offset_y,
interpolation_type);
/* If there is a layer mask, make sure it gets scaled also */
if (layer->mask)
{
gimp_item_scale (GIMP_ITEM (layer->mask),
new_width, new_height,
new_offset_x, new_offset_y,
interpolation_type);
gimp_image_undo_group_end (gimage);
}
/* Make sure we're not caching any old selection info */
gimp_layer_invalidate_boundary (layer);
}
static void
gimp_layer_transform_color (GimpImage *gimage,
PixelRegion *layerPR,
......@@ -967,87 +1014,6 @@ gimp_layer_add_alpha (GimpLayer *layer)
}
}
static void
gimp_layer_scale_lowlevel (GimpLayer *layer,
gint new_width,
gint new_height,
gint new_offset_x,
gint new_offset_y,
GimpInterpolationType interpolation_type)
{
PixelRegion srcPR, destPR;
TileManager *new_tiles;
/* Update the old layer position */
gimp_drawable_update (GIMP_DRAWABLE (layer),
0, 0,
GIMP_DRAWABLE (layer)->width,
GIMP_DRAWABLE (layer)->height);
/* Configure the pixel regions */
pixel_region_init (&srcPR, GIMP_DRAWABLE(layer)->tiles,
0, 0,
GIMP_DRAWABLE (layer)->width,
GIMP_DRAWABLE (layer)->height,
FALSE);
/* Allocate the new layer, configure dest region */
new_tiles = tile_manager_new (new_width, new_height,
GIMP_DRAWABLE (layer)->bytes);
pixel_region_init (&destPR, new_tiles,
0, 0,
new_width, new_height,
TRUE);
/* Scale the layer -
* If the layer is of type INDEXED, then we don't use pixel-value
* resampling because that doesn't necessarily make sense for INDEXED
* images.
*/
if (GIMP_IMAGE_TYPE_IS_INDEXED (GIMP_DRAWABLE (layer)->type))
{
scale_region (&srcPR, &destPR, GIMP_INTERPOLATION_NONE);
}
else
{
scale_region (&srcPR, &destPR, interpolation_type);
}
/* Push the layer on the undo stack */
gimp_image_undo_push_layer_mod (gimp_item_get_image (GIMP_ITEM (layer)),
_("Scale Layer"),
layer);
/* Configure the new layer */
GIMP_DRAWABLE (layer)->offset_x = new_offset_x;
GIMP_DRAWABLE (layer)->offset_y = new_offset_y;
GIMP_DRAWABLE (layer)->tiles = new_tiles;