Commit 8769bbb4 authored by Garry R. Osgood's avatar Garry R. Osgood Committed by Garry R. Osgood
Browse files

app/commands.c app/gimpimage.c app/layer.c app/layer.h app/resize.c

2000-02-26 Garry R. Osgood <gosgood@idt.net>
* app/commands.c
* app/gimpimage.c
* app/layer.c
* app/layer.h
* app/resize.c
* app/resize.h

Aliasing artifacts that changed relative positions
of layers under scaling, giving rise to #5271, are
minimized by a new layer.c function,
layer_scale_by_factors(). Closes #5271. See
http://idt.net/~gosgood/gimp-patch/patch07.html for
further detail. See also usage documentation for
layer_scale() and layer_scale_by_factors() in
layer.c.

Provided logic for the Scale Image dialog box to
pre-check an image's layers for the possibility that
a particular scaling, s: 0 < s < 1, reduces a layer
dimension to zero. Should this case prevail, a
boolean dialog box warns the user of the
possibility. The user may (1) Cancel, returning
focus to Scale Image and the possibility of
corrective adjustment, or (2) OK the scaling. The
layers that will vanish upon the new scaling are
culled from the GimpImage::layers list first.
parent 882c240a
2000-02-26 Garry R. Osgood <gosgood@idt.net>
* app/commands.c
* app/gimpimage.c
* app/layer.c
* app/layer.h
* app/resize.c
* app/resize.h
* help/C/dialogs/Makefile.am
* help/C/dialogs/scale_layer_warn.html (new: placeholder)
Aliasing artifacts that changed relative positions
of layers under scaling, giving rise to #5271, are
minimized by a new layer.c function,
layer_scale_by_factors(). Closes #5271. See
http://idt.net/~gosgood/gimp-patch/patch07.html
for further detail. See also usage documentation
for layer_scale() and layer_scale_by_factors()
in layer.c.
Provided logic for the Scale Image dialog box
<Image->Scale Image...>
to pre-check an image's layers for the possibility
that a particular scaling, s: 0 < s < 1, reduces
a layer dimension to zero. Should this case prevail,
a boolean dialog box warns the user of the possibility.
The user may (1) Cancel, returning focus to Scale
Image and the possibility of corrective adjustment, or
(2) OK the scaling. The layers that will vanish upon
the new scaling are culled from the GimpImage::layers
list first. >>Please Test This!<< I've tested it
fairly thoroughly, but my physician reports that I
suffer from hubris. ;)
2000-02-26 Michael Natterer <mitch@gimp.org>
 
* libgimp/gimphelpui.[ch]
......
......@@ -65,27 +65,21 @@
gdisp = gdisplay_active (); \
if (!gdisp) return
typedef struct
{
Resize *resize;
GimpImage *gimage;
} ImageResize;
/* external functions */
extern void layers_dialog_layer_merge_query (GImage *, gboolean);
/* local functions */
static void image_resize_callback (GtkWidget *, gpointer);
static void image_scale_callback (GtkWidget *, gpointer);
static void image_cancel_callback (GtkWidget *, gpointer);
static void gimage_mask_feather_callback (GtkWidget *, gdouble, GimpUnit,
gpointer);
static void gimage_mask_border_callback (GtkWidget *, gdouble, GimpUnit,
gpointer);
static void gimage_mask_grow_callback (GtkWidget *, gdouble, GimpUnit,
gpointer);
static void gimage_mask_shrink_callback (GtkWidget *, gdouble, GimpUnit,
gpointer);
static void image_resize_callback (GtkWidget *, gpointer);
static void image_scale_callback (GtkWidget *, gpointer);
static void image_cancel_callback (GtkWidget *, gpointer);
static void gimage_mask_feather_callback (GtkWidget *, gdouble, GimpUnit,
gpointer);
static void gimage_mask_border_callback (GtkWidget *, gdouble, GimpUnit,
gpointer);
static void gimage_mask_grow_callback (GtkWidget *, gdouble, GimpUnit,
gpointer);
static void gimage_mask_shrink_callback (GtkWidget *, gdouble, GimpUnit,
gpointer);
/* local variables */
static gdouble selection_feather_radius = 5.0;
......@@ -1318,94 +1312,29 @@ static void
image_scale_callback (GtkWidget *widget,
gpointer client_data)
{
ImageResize *image_scale;
GImage *gimage;
gboolean rulers_flush = FALSE;
gboolean display_flush = FALSE; /* this is a bit ugly:
we hijack the flush variable
to check if an undo_group was
already started */
ImageResize *image_scale = NULL;
image_scale = (ImageResize *) client_data;
if ((gimage = image_scale->gimage) != NULL)
g_assert((image_scale = (ImageResize *) client_data) != NULL);
g_assert(image_scale->gimage != NULL);
if(TRUE == resize_check_layer_scaling(image_scale))
{
if (image_scale->resize->resolution_x != gimage->xresolution ||
image_scale->resize->resolution_y != gimage->yresolution)
{
undo_push_group_start (gimage, IMAGE_SCALE_UNDO);
gimage_set_resolution (gimage,
image_scale->resize->resolution_x,
image_scale->resize->resolution_y);
rulers_flush = TRUE;
display_flush = TRUE;
}
if (image_scale->resize->unit != gimage->unit)
{
if (!display_flush)
undo_push_group_start (gimage, IMAGE_SCALE_UNDO);
gimage_set_unit (gimage, image_scale->resize->unit);
gdisplays_setup_scale (gimage);
gdisplays_resize_cursor_label (gimage);
rulers_flush = TRUE;
display_flush = TRUE;
}
if (image_scale->resize->width != gimage->width ||
image_scale->resize->height != gimage->height)
{
if (image_scale->resize->width > 0 &&
image_scale->resize->height > 0)
{
if (!display_flush)
undo_push_group_start (gimage, IMAGE_SCALE_UNDO);
gimage_scale (gimage,
image_scale->resize->width,
image_scale->resize->height);
display_flush = TRUE;
}
else
{
g_message (_("Scale Error: Both width and height must be "
"greater than zero."));
return;
}
}
if (rulers_flush)
{
gdisplays_setup_scale (gimage);
gdisplays_resize_cursor_label (gimage);
}
if (display_flush)
{
undo_push_group_end (gimage);
gdisplays_flush ();
}
resize_scale_implement(image_scale);
resize_widget_free (image_scale->resize);
g_free (image_scale);
}
resize_widget_free (image_scale->resize);
g_free (image_scale);
}
static void
image_cancel_callback (GtkWidget *widget,
gpointer client_data)
{
ImageResize *image_resize;
ImageResize *image_scale;
image_resize = (ImageResize *) client_data;
image_scale = (ImageResize *) client_data;
resize_widget_free (image_resize->resize);
g_free (image_resize);
resize_widget_free (image_scale->resize);
g_free (image_scale);
}
static void
......
......@@ -65,27 +65,21 @@
gdisp = gdisplay_active (); \
if (!gdisp) return
typedef struct
{
Resize *resize;
GimpImage *gimage;
} ImageResize;
/* external functions */
extern void layers_dialog_layer_merge_query (GImage *, gboolean);
/* local functions */
static void image_resize_callback (GtkWidget *, gpointer);
static void image_scale_callback (GtkWidget *, gpointer);
static void image_cancel_callback (GtkWidget *, gpointer);
static void gimage_mask_feather_callback (GtkWidget *, gdouble, GimpUnit,
gpointer);
static void gimage_mask_border_callback (GtkWidget *, gdouble, GimpUnit,
gpointer);
static void gimage_mask_grow_callback (GtkWidget *, gdouble, GimpUnit,
gpointer);
static void gimage_mask_shrink_callback (GtkWidget *, gdouble, GimpUnit,
gpointer);
static void image_resize_callback (GtkWidget *, gpointer);
static void image_scale_callback (GtkWidget *, gpointer);
static void image_cancel_callback (GtkWidget *, gpointer);
static void gimage_mask_feather_callback (GtkWidget *, gdouble, GimpUnit,
gpointer);
static void gimage_mask_border_callback (GtkWidget *, gdouble, GimpUnit,
gpointer);
static void gimage_mask_grow_callback (GtkWidget *, gdouble, GimpUnit,
gpointer);
static void gimage_mask_shrink_callback (GtkWidget *, gdouble, GimpUnit,
gpointer);
/* local variables */
static gdouble selection_feather_radius = 5.0;
......@@ -1318,94 +1312,29 @@ static void
image_scale_callback (GtkWidget *widget,
gpointer client_data)
{
ImageResize *image_scale;
GImage *gimage;
gboolean rulers_flush = FALSE;
gboolean display_flush = FALSE; /* this is a bit ugly:
we hijack the flush variable
to check if an undo_group was
already started */
ImageResize *image_scale = NULL;
image_scale = (ImageResize *) client_data;
if ((gimage = image_scale->gimage) != NULL)
g_assert((image_scale = (ImageResize *) client_data) != NULL);
g_assert(image_scale->gimage != NULL);
if(TRUE == resize_check_layer_scaling(image_scale))
{
if (image_scale->resize->resolution_x != gimage->xresolution ||
image_scale->resize->resolution_y != gimage->yresolution)
{
undo_push_group_start (gimage, IMAGE_SCALE_UNDO);
gimage_set_resolution (gimage,
image_scale->resize->resolution_x,
image_scale->resize->resolution_y);
rulers_flush = TRUE;
display_flush = TRUE;
}
if (image_scale->resize->unit != gimage->unit)
{
if (!display_flush)
undo_push_group_start (gimage, IMAGE_SCALE_UNDO);
gimage_set_unit (gimage, image_scale->resize->unit);
gdisplays_setup_scale (gimage);
gdisplays_resize_cursor_label (gimage);
rulers_flush = TRUE;
display_flush = TRUE;
}
if (image_scale->resize->width != gimage->width ||
image_scale->resize->height != gimage->height)
{
if (image_scale->resize->width > 0 &&
image_scale->resize->height > 0)
{
if (!display_flush)
undo_push_group_start (gimage, IMAGE_SCALE_UNDO);
gimage_scale (gimage,
image_scale->resize->width,
image_scale->resize->height);
display_flush = TRUE;
}
else
{
g_message (_("Scale Error: Both width and height must be "
"greater than zero."));
return;
}
}
if (rulers_flush)
{
gdisplays_setup_scale (gimage);
gdisplays_resize_cursor_label (gimage);
}
if (display_flush)
{
undo_push_group_end (gimage);
gdisplays_flush ();
}
resize_scale_implement(image_scale);
resize_widget_free (image_scale->resize);
g_free (image_scale);
}
resize_widget_free (image_scale->resize);
g_free (image_scale);
}
static void
image_cancel_callback (GtkWidget *widget,
gpointer client_data)
{
ImageResize *image_resize;
ImageResize *image_scale;
image_resize = (ImageResize *) client_data;
image_scale = (ImageResize *) client_data;
resize_widget_free (image_resize->resize);
g_free (image_resize);
resize_widget_free (image_scale->resize);
g_free (image_scale);
}
static void
......
......@@ -532,10 +532,20 @@ gimp_image_scale (GimpImage *gimage,
Layer *layer;
Layer *floating_layer;
GSList *list;
GSList *marklist = NULL;
GList *glist;
Guide *guide;
gint old_width, old_height;
gint layer_width, layer_height;
gint old_width, old_height;
gint old_offset_x, old_offset_y;
gint layer_width, layer_height;
gdouble img_scale_w = 1.0;
gdouble img_scale_h = 1.0;
if((new_width == 0) || (new_height == 0))
{
g_message(_("gimp_image_scale: Layer with zero width or height has been rejected."));
return;
}
gimp_add_busy_cursors ();
......@@ -552,11 +562,14 @@ gimp_image_scale (GimpImage *gimage,
undo_push_gimage_mod (gimage);
/* Set the new width and height */
old_width = gimage->width;
old_height = gimage->height;
old_width = gimage->width;
old_height = gimage->height;
gimage->width = new_width;
gimage->height = new_height;
img_scale_w = (gdouble)new_width/(gdouble)old_width;
img_scale_h = (gdouble)new_height/(gdouble)old_height;
/* Scale all channels */
list = gimage->channels;
while (list)
......@@ -574,14 +587,30 @@ gimp_image_scale (GimpImage *gimage,
list = gimage->layers;
while (list)
{
layer = (Layer *) list->data;
layer_width = (new_width *
drawable_width (GIMP_DRAWABLE(layer))) / old_width;
layer_height = (new_height *
drawable_height (GIMP_DRAWABLE(layer))) / old_height;
layer_scale (layer, layer_width, layer_height, FALSE);
list = g_slist_next (list);
layer = (Layer *) list->data;
if(FALSE == layer_scale_by_factors(layer, img_scale_w, img_scale_h))
{
/* Since 0 < img_scale_w, img_scale_h, failure due to one or more */
/* vanishing scaled layer dimensions. Implicit delete implemented */
/* here. Upstream warning implemented in resize_check_layer_scaling() */
/* [resize.c line 1295], which offers the user the chance to bail out.*/
marklist = g_list_append(marklist, layer);
}
list = g_slist_next (list);
}
/* We defer removing layers lost to scaling until now */
/* so as not to mix the operations of iterating over and removal */
/* from gimage->layers. */
if(marklist != NULL)
{
while(marklist)
{
layer = marklist->data;
gimage_remove_layer(gimage, layer);
marklist = g_slist_remove(marklist, layer);
}
}
/* Scale any Guides */
......
......@@ -532,10 +532,20 @@ gimp_image_scale (GimpImage *gimage,
Layer *layer;
Layer *floating_layer;
GSList *list;
GSList *marklist = NULL;
GList *glist;
Guide *guide;
gint old_width, old_height;
gint layer_width, layer_height;
gint old_width, old_height;
gint old_offset_x, old_offset_y;
gint layer_width, layer_height;
gdouble img_scale_w = 1.0;
gdouble img_scale_h = 1.0;
if((new_width == 0) || (new_height == 0))
{
g_message(_("gimp_image_scale: Layer with zero width or height has been rejected."));
return;
}
gimp_add_busy_cursors ();
......@@ -552,11 +562,14 @@ gimp_image_scale (GimpImage *gimage,
undo_push_gimage_mod (gimage);
/* Set the new width and height */
old_width = gimage->width;
old_height = gimage->height;
old_width = gimage->width;
old_height = gimage->height;
gimage->width = new_width;
gimage->height = new_height;
img_scale_w = (gdouble)new_width/(gdouble)old_width;
img_scale_h = (gdouble)new_height/(gdouble)old_height;
/* Scale all channels */
list = gimage->channels;
while (list)
......@@ -574,14 +587,30 @@ gimp_image_scale (GimpImage *gimage,
list = gimage->layers;
while (list)
{
layer = (Layer *) list->data;
layer_width = (new_width *
drawable_width (GIMP_DRAWABLE(layer))) / old_width;
layer_height = (new_height *
drawable_height (GIMP_DRAWABLE(layer))) / old_height;
layer_scale (layer, layer_width, layer_height, FALSE);
list = g_slist_next (list);
layer = (Layer *) list->data;
if(FALSE == layer_scale_by_factors(layer, img_scale_w, img_scale_h))
{
/* Since 0 < img_scale_w, img_scale_h, failure due to one or more */
/* vanishing scaled layer dimensions. Implicit delete implemented */
/* here. Upstream warning implemented in resize_check_layer_scaling() */
/* [resize.c line 1295], which offers the user the chance to bail out.*/
marklist = g_list_append(marklist, layer);
}
list = g_slist_next (list);
}
/* We defer removing layers lost to scaling until now */
/* so as not to mix the operations of iterating over and removal */
/* from gimage->layers. */
if(marklist != NULL)
{
while(marklist)
{
layer = marklist->data;
gimage_remove_layer(gimage, layer);
marklist = g_slist_remove(marklist, layer);
}
}
/* Scale any Guides */
......
......@@ -532,10 +532,20 @@ gimp_image_scale (GimpImage *gimage,
Layer *layer;
Layer *floating_layer;
GSList *list;
GSList *marklist = NULL;
GList *glist;
Guide *guide;
gint old_width, old_height;
gint layer_width, layer_height;
gint old_width, old_height;
gint old_offset_x, old_offset_y;
gint layer_width, layer_height;
gdouble img_scale_w = 1.0;
gdouble img_scale_h = 1.0;
if((new_width == 0) || (new_height == 0))
{
g_message(_("gimp_image_scale: Layer with zero width or height has been rejected."));
return;
}
gimp_add_busy_cursors ();
......@@ -552,11 +562,14 @@ gimp_image_scale (GimpImage *gimage,
undo_push_gimage_mod (gimage);
/* Set the new width and height */
old_width = gimage->width;
old_height = gimage->height;
old_width = gimage->width;
old_height = gimage->height;
gimage->width = new_width;
gimage->height = new_height;
img_scale_w = (gdouble)new_width/(gdouble)old_width;
img_scale_h = (gdouble)new_height/(gdouble)old_height;
/* Scale all channels */
list = gimage->channels;
while (list)
......@@ -574,14 +587,30 @@ gimp_image_scale (GimpImage *gimage,
list = gimage->layers;
while (list)
{
layer = (Layer *) list->data;
layer_width = (new_width *
drawable_width (GIMP_DRAWABLE(layer))) / old_width;
layer_height = (new_height *
drawable_height (GIMP_DRAWABLE(layer))) / old_height;
layer_scale (layer, layer_width, layer_height, FALSE);
list = g_slist_next (list);
layer = (Layer *) list->data;
if(FALSE == layer_scale_by_factors(layer, img_scale_w, img_scale_h))
{
/* Since 0 < img_scale_w, img_scale_h, failure due to one or more */
/* vanishing scaled layer dimensions. Implicit delete implemented */
/* here. Upstream warning implemented in resize_check_layer_scaling() */
/* [resize.c line 1295], which offers the user the chance to bail out.*/
marklist = g_list_append(marklist, layer);
}
list = g_slist_next (list);
}
/* We defer removing layers lost to scaling until now */
/* so as not to mix the operations of iterating over and removal */
/* from gimage->layers. */
if(marklist != NULL)
{
while(marklist)
{
layer = marklist->data;
gimage_remove_layer(gimage, layer);
marklist = g_slist_remove(marklist, layer);
}
}
/* Scale any Guides */
......
......@@ -532,10 +532,20 @@ gimp_image_scale (GimpImage *gimage,
Layer *layer;
Layer *floating_layer;
GSList *list;
GSList *marklist = NULL;
GList *glist;
Guide *guide;
gint old_width, old_height;
gint layer_width, layer_height;
gint old_width, old_height;
gint old_offset_x, old_offset_y;
gint layer_width, layer_height;
gdouble img_scale_w = 1.0;
gdouble img_scale_h = 1.0;
if((new_width == 0) || (new_height == 0))
{
g_message(_("gimp_image_scale: Layer with zero width or height has been rejected."));
return;
}
gimp_add_busy_cursors ();
......@@ -552,11 +562,14 @@ gimp_image_scale (GimpImage *gimage,
undo_push_gimage_mod (gimage);
/* Set the new width and height */
old_width = gimage->width;
old_height = gimage->height;
old_width = gimage->width;
old_height = gimage->height;
gimage->width = new_width;
gimage->height = new_height;
img_scale_w = (gdouble)new_width/(gdouble)old_width;
img_scale_h = (gdouble)new_height/(gdouble)old_height;
/* Scale all channels */