mirror of https://github.com/GNOME/gimp.git
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.
This commit is contained in:
parent
882c240a38
commit
8769bbb456
33
ChangeLog
33
ChangeLog
|
@ -1,3 +1,36 @@
|
|||
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
|
||||
|
|
117
app/commands.c
117
app/commands.c
|
@ -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 = (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.*/
|
||||
|
||||
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);
|
||||
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 = (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.*/
|
||||
|
||||
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);
|
||||
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 = (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.*/
|
||||
|
||||
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);
|
||||
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 = (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.*/
|
||||
|
||||
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);
|
||||
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 = (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.*/
|
||||
|
||||
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);
|
||||
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 = (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.*/
|
||||
|
||||
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);
|
||||
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 */
|
||||
|
|
|
@ -346,7 +346,7 @@ layer_copy (Layer *layer,
|
|||
new_type, layer_name, layer->opacity, layer->mode);
|
||||
if (!new_layer)
|
||||
{
|
||||
g_message ("layer_copy: could not allocate new layer");
|
||||
g_message (_("layer_copy: could not allocate new layer"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
@ -421,7 +421,7 @@ layer_new_from_tiles (GimpImage *gimage,
|
|||
|
||||
if (!new_layer)
|
||||
{
|
||||
g_message ("layer_new_from_tiles: could not allocate new layer");
|
||||
g_message (_("layer_new_from_tiles: could not allocate new layer"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -723,18 +723,16 @@ layer_add_alpha (Layer *layer)
|
|||
"restructure");
|
||||
}
|
||||
|
||||
void
|
||||
layer_scale (Layer *layer,
|
||||
gint new_width,
|
||||
gint new_height,
|
||||
gint local_origin)
|
||||
static void
|
||||
layer_scale_lowlevel(Layer *layer,
|
||||
gint new_width,
|
||||
gint new_height,
|
||||
gint new_offset_x,
|
||||
gint new_offset_y)
|
||||
{
|
||||
PixelRegion srcPR, destPR;
|
||||
TileManager *new_tiles;
|
||||
|
||||
if (new_width == 0 || new_height == 0)
|
||||
return;
|
||||
|
||||
/* Update the old layer position */
|
||||
drawable_update (GIMP_DRAWABLE(layer),
|
||||
0, 0,
|
||||
|
@ -761,29 +759,12 @@ layer_scale (Layer *layer,
|
|||
undo_push_layer_mod (GIMP_DRAWABLE(layer)->gimage, layer);
|
||||
|
||||
/* Configure the new layer */
|
||||
if (local_origin)
|
||||
{
|
||||
int cx, cy;
|
||||
|
||||
cx = GIMP_DRAWABLE(layer)->offset_x + GIMP_DRAWABLE(layer)->width / 2;
|
||||
cy = GIMP_DRAWABLE(layer)->offset_y + GIMP_DRAWABLE(layer)->height / 2;
|
||||
|
||||
GIMP_DRAWABLE(layer)->offset_x = cx - (new_width / 2);
|
||||
GIMP_DRAWABLE(layer)->offset_y = cy - (new_height / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
double xrat, yrat;
|
||||
|
||||
xrat = (double) new_width / (double) GIMP_DRAWABLE(layer)->width;
|
||||
yrat = (double) new_height / (double) GIMP_DRAWABLE(layer)->height;
|
||||
|
||||
GIMP_DRAWABLE(layer)->offset_x = (int) (xrat * GIMP_DRAWABLE(layer)->offset_x);
|
||||
GIMP_DRAWABLE(layer)->offset_y = (int) (yrat * GIMP_DRAWABLE(layer)->offset_y);
|
||||
}
|
||||
GIMP_DRAWABLE(layer)->tiles = new_tiles;
|
||||
GIMP_DRAWABLE(layer)->width = new_width;
|
||||
GIMP_DRAWABLE(layer)->height = new_height;
|
||||
GIMP_DRAWABLE(layer)->offset_x = new_offset_x;
|
||||
GIMP_DRAWABLE(layer)->offset_y = new_offset_y;
|
||||
GIMP_DRAWABLE(layer)->tiles = new_tiles;
|
||||
GIMP_DRAWABLE(layer)->width = new_width;
|
||||
GIMP_DRAWABLE(layer)->height = new_height;
|
||||
|
||||
/* If there is a layer mask, make sure it gets scaled also */
|
||||
if (layer->mask)
|
||||
|
@ -794,11 +775,146 @@ layer_scale (Layer *layer,
|
|||
}
|
||||
|
||||
/* Update the new layer position */
|
||||
|
||||
drawable_update (GIMP_DRAWABLE(layer),
|
||||
0, 0,
|
||||
GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height);
|
||||
}
|
||||
|
||||
/**
|
||||
* layer_check_scaling:
|
||||
* @layer: Layer to check
|
||||
* @new_width: proposed width of layer, in pixels
|
||||
* @new_height: proposed height of layer, in pixels
|
||||
* Scales layer dimensions, then snaps them to pixel centers
|
||||
* Returns FALSE if any dimension reduces to zero as a result
|
||||
* of this; otherwise, returns TRUE.
|
||||
*/
|
||||
|
||||
gboolean layer_check_scaling (Layer *layer,
|
||||
gint new_width,
|
||||
gint new_height)
|
||||
{
|
||||
GImage *gimage = GIMP_DRAWABLE(layer)->gimage;
|
||||
gdouble img_scale_w = (gdouble)new_width/(gdouble)gimage->width;
|
||||
gdouble img_scale_h = (gdouble)new_height/(gdouble)gimage->height;
|
||||
gint new_layer_width = (gint)(0.5 + img_scale_w * (gdouble)GIMP_DRAWABLE(layer)->width);
|
||||
gint new_layer_height = (gint)(0.5 + img_scale_h * (gdouble)GIMP_DRAWABLE(layer)->height);
|
||||
|
||||
return (new_layer_width != 0 && new_layer_height != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* layer_scale_by_factors:
|
||||
* @layer: Layer to be transformed by explicit width and height factors.
|
||||
* @w_factor: scale factor to apply to width and horizontal offset
|
||||
* @h_factor: scale factor to apply to height and vertical offset
|
||||
*
|
||||
* Scales layer dimensions and offsets by uniform width and
|
||||
* height factors.
|
||||
*
|
||||
* Use layer_scale_by_factors() in circumstances when the
|
||||
* same width and height scaling factors are to be uniformly
|
||||
* applied to a set of layers. In this context, the layer's
|
||||
* dimensions and offsets from the sides of the containing
|
||||
* image all change by these predetermined factors. By fiat,
|
||||
* the fixed point of the transform is the upper left hand
|
||||
* corner of the image. Returns gboolean FALSE if a requested
|
||||
* scale factor is zero or if a scaling zero's out a layer
|
||||
* dimension; returns TRUE otherwise.
|
||||
*
|
||||
* Use layer_scale() in circumstances where new layer width
|
||||
* and height dimensions are predetermined instead.
|
||||
*
|
||||
* #Returns: TRUE, if the scaled layer has positive dimensions
|
||||
* FALSE if the scaled layer has at least one zero dimension
|
||||
*
|
||||
* #Side effects: undo set created for layer.
|
||||
* Old layer imagery scaled
|
||||
* & painted to new layer tiles
|
||||
*/
|
||||
|
||||
gboolean
|
||||
layer_scale_by_factors(Layer *layer,
|
||||
gdouble w_factor,
|
||||
gdouble h_factor)
|
||||
{
|
||||
gint new_width, new_height, new_offset_x, new_offset_y;
|
||||
|
||||
if (w_factor == 0.0 || h_factor == 0.0)
|
||||
{
|
||||
g_message(_("layer_scale_by_factors: Error. Requested width or height scale equals zero."));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
new_offset_x = (gint)(0.5 + w_factor * (gdouble)GIMP_DRAWABLE(layer)->offset_x);
|
||||
new_offset_y = (gint)(0.5 + h_factor * (gdouble)GIMP_DRAWABLE(layer)->offset_y);
|
||||
new_width = (gint)(0.5 + w_factor * (gdouble)GIMP_DRAWABLE(layer)->width);
|
||||
new_height = (gint)(0.5 + h_factor * (gdouble)GIMP_DRAWABLE(layer)->height);
|
||||
|
||||
if(new_width != 0 && new_height != 0)
|
||||
{
|
||||
layer_scale_lowlevel(layer, new_width, new_height, new_offset_x, new_offset_y);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* layer_scale:
|
||||
* @layer: The layer to be transformed by width & height scale factors
|
||||
* @new_width: The width that layer will acquire
|
||||
* @new_height: The height that the layer will acquire
|
||||
* @local_origin: sets fixed point of the scaling transform. See below.
|
||||
*
|
||||
* Sets layer dimensions to new_width and
|
||||
* new_height. Derives vertical and horizontal scaling
|
||||
* transforms from new width and height. If local_origin is
|
||||
* TRUE, the fixed point of the scaling transform coincides
|
||||
* with the layer's center point. Otherwise, the fixed
|
||||
* point is taken to be [-GIMP_DRAWABLE(layer)->offset_x,
|
||||
* -GIMP_DRAWABLE(layer)->offset_y].
|
||||
*
|
||||
* Since this function derives scale factors from new and
|
||||
* current layer dimensions, these factors will vary from
|
||||
* layer to layer because of aliasing artifacts; factor
|
||||
* variations among layers can be quite large where layer
|
||||
* dimensions approach pixel dimensions. Use
|
||||
* layer_scale_by_factors where constant scales are to
|
||||
* be uniformly applied to a number of layers.
|
||||
*
|
||||
* Side effects: undo set created for layer.
|
||||
* Old layer imagery scaled
|
||||
* & painted to new layer tiles
|
||||
*/
|
||||
|
||||
void
|
||||
layer_scale (Layer *layer,
|
||||
gint new_width,
|
||||
gint new_height,
|
||||
gboolean local_origin)
|
||||
{
|
||||
gint new_offset_x, new_offset_y;
|
||||
|
||||
if (new_width == 0 || new_height == 0)
|
||||
{
|
||||
g_message(_("layer_scale: Error. Requested width or height equals zero."));
|
||||
return;
|
||||
}
|
||||
if (local_origin)
|
||||
{
|
||||
new_offset_x = GIMP_DRAWABLE(layer)->offset_x + ((GIMP_DRAWABLE(layer)->width - new_width)/2.0);
|
||||
new_offset_y = GIMP_DRAWABLE(layer)->offset_y + ((GIMP_DRAWABLE(layer)->height - new_height)/2.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
new_offset_x = (gint)(((gdouble) new_width * GIMP_DRAWABLE(layer)->offset_x/(gdouble) GIMP_DRAWABLE(layer)->width));
|
||||
new_offset_y = (gint)(((gdouble) new_height * GIMP_DRAWABLE(layer)->offset_y/(gdouble) GIMP_DRAWABLE(layer)->height));
|
||||
}
|
||||
layer_scale_lowlevel(layer, new_width, new_height, new_offset_x, new_offset_y);
|
||||
}
|
||||
|
||||
void
|
||||
layer_resize (Layer *layer,
|
||||
gint new_width,
|
||||
|
|
|
@ -82,6 +82,7 @@ void layer_unref (Layer *);
|
|||
Layer * layer_new_from_tiles (GimpImage *, GimpImageType, TileManager *,
|
||||
gchar *, gint, LayerModeEffects);
|
||||
LayerMask * layer_add_mask (Layer *, LayerMask *);
|
||||
gboolean layer_check_scaling (Layer *, gint, gint);
|
||||
LayerMask * layer_create_mask (Layer *, AddMaskType);
|
||||
Layer * layer_get_ID (gint);
|
||||
void layer_delete (Layer *);
|
||||
|
@ -90,7 +91,8 @@ void layer_apply_mask (Layer *, MaskApplyMode);
|
|||
void layer_temporarily_translate (Layer *, gint, gint);
|
||||
void layer_translate (Layer *, gint, gint);
|
||||
void layer_add_alpha (Layer *);
|
||||
void layer_scale (Layer *, gint, gint, gint);
|
||||
gboolean layer_scale_by_factors (Layer *, gdouble, gdouble);
|
||||
void layer_scale (Layer *, gint, gint, gboolean);
|
||||
void layer_resize (Layer *, gint, gint, gint, gint);
|
||||
void layer_resize_to_image (Layer *);
|
||||
BoundSeg * layer_boundary (Layer *, gint *);
|
||||
|
|
|
@ -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 = (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.*/
|
||||
|
||||
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);
|
||||
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 */
|
||||
|
|
|
@ -65,19 +65,19 @@ struct _ResizePrivate
|
|||
gint orig_x, orig_y;
|
||||
};
|
||||
|
||||
static void resize_draw (Resize *);
|
||||
static void unit_update (GtkWidget *, gpointer);
|
||||
static gint resize_bound_off_x (Resize *, gint);
|
||||
static gint resize_bound_off_y (Resize *, gint);
|
||||
static void orig_labels_update (GtkWidget *, gpointer);
|
||||
static void size_callback (GtkWidget *, gpointer);
|
||||
static void ratio_callback (GtkWidget *, gpointer);
|
||||
static void size_update (Resize *, gdouble, gdouble, gdouble, gdouble);
|
||||
static void offset_update (GtkWidget *, gpointer);
|
||||
static gint resize_events (GtkWidget *, GdkEvent *);
|
||||
static void printsize_update (GtkWidget *, gpointer);
|
||||
static void resolution_update (GtkWidget *, gpointer);
|
||||
|
||||
static void resize_draw (Resize *);
|
||||
static void unit_update (GtkWidget *, gpointer);
|
||||
static gint resize_bound_off_x (Resize *, gint);
|
||||
static gint resize_bound_off_y (Resize *, gint);
|
||||
static void orig_labels_update (GtkWidget *, gpointer);
|
||||
static void size_callback (GtkWidget *, gpointer);
|
||||
static void ratio_callback (GtkWidget *, gpointer);
|
||||
static void size_update (Resize *, gdouble, gdouble, gdouble, gdouble);
|
||||
static void offset_update (GtkWidget *, gpointer);
|
||||
static gint resize_events (GtkWidget *, GdkEvent *);
|
||||
static void printsize_update (GtkWidget *, gpointer);
|
||||
static void resolution_update (GtkWidget *, gpointer);
|
||||
static void resize_scale_warn_callback (GtkWidget *, gboolean, gpointer);
|
||||
|
||||
Resize *
|
||||
resize_widget_new (ResizeType type,
|
||||
|
@ -1191,3 +1191,164 @@ resize_events (GtkWidget *widget,
|
|||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*** Resize sanity checks ***/
|
||||
|
||||
void resize_scale_implement (ImageResize *image_scale)
|
||||
{
|
||||
GImage *gimage = NULL;
|
||||
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 */
|
||||
g_assert(image_scale != NULL);
|
||||
gimage = image_scale->gimage;
|
||||
g_assert(gimage != NULL);
|
||||
|
||||
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 ();
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void resize_scale_warn_callback (GtkWidget *widget,
|
||||
gboolean do_scale,
|
||||
gpointer client_data)
|
||||
{
|
||||
ImageResize *image_scale = NULL;
|
||||
GImage *gimage = NULL;
|
||||
|
||||
g_assert(client_data != NULL);
|
||||
image_scale = (ImageResize *) client_data;
|
||||
gimage = image_scale->gimage;
|
||||
g_assert(gimage != NULL);
|
||||
|
||||
if(do_scale == TRUE) /* User doesn't mind losing layers... */
|
||||
{
|
||||
resize_scale_implement(image_scale);
|
||||
resize_widget_free (image_scale->resize);
|
||||
g_free (image_scale);
|
||||
}
|
||||
else
|
||||
gtk_widget_set_sensitive (image_scale->resize->resize_shell, TRUE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
resize_check_layer_scaling (ImageResize *image_scale)
|
||||
{
|
||||
/* Inventory the layer list in gimage and return TRUE if, after
|
||||
* scaling, they all retain positive x and y pixel dimensions.
|
||||
* Otherwise, put up a modal boolean dialog box and ask the user if
|
||||
* she wishes to proceed. Return FALSE in the dialog case; the dialog box
|
||||
* callback will complete the job if the user really wants to
|
||||
* proceed. <02/22/2000 gosgood@idt.net>
|
||||
*/
|
||||
|
||||
gboolean success = FALSE;
|
||||
GImage *gimage = NULL;
|
||||
GSList *list = NULL;
|
||||
Layer *layer = NULL;
|
||||
GtkWidget *dialog = NULL;
|
||||
gchar *str = NULL;
|
||||
|
||||
g_assert(image_scale != NULL);
|
||||
|
||||
if(NULL != (gimage = image_scale->gimage))
|
||||
{
|
||||
/* Step through layers; test scaled dimensions. */
|
||||
|
||||
success = TRUE;
|
||||
list = gimage->layers;
|
||||
while(list && success == TRUE)
|
||||
{
|
||||
layer = (Layer *)list->data;
|
||||
success = layer_check_scaling (layer,
|
||||
image_scale->resize->width,
|
||||
image_scale->resize->height);
|
||||
list = g_slist_next (list);
|
||||
|
||||
}
|
||||
/* Warn user on failure */
|
||||
if(success == FALSE)
|
||||
{
|
||||
gtk_widget_set_sensitive (image_scale->resize->resize_shell, FALSE);
|
||||
|
||||
str = g_strdup (_("The chosen image size will shrink\n"
|
||||
"some layers completely away.\nIs this what you want?"));
|
||||
|
||||
dialog =
|
||||
gimp_query_boolean_box (_("Layer Too Small"),
|
||||
gimp_standard_help_func,
|
||||
"dialogs/scale_layer_warn.html",
|
||||
FALSE,
|
||||
str,
|
||||
_("OK"), _("Cancel"),
|
||||
NULL, NULL,
|
||||
resize_scale_warn_callback,
|
||||
image_scale);
|
||||
|
||||
g_free (str);
|
||||
gtk_widget_show (dialog);
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#define __RESIZE_H__
|
||||
|
||||
#include "libgimp/gimpunit.h"
|
||||
#include "gimage.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
@ -59,9 +60,16 @@ struct _Resize
|
|||
void * private_part;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Resize *resize;
|
||||
GimpImage *gimage;
|
||||
} ImageResize;
|
||||
|
||||
/* If resolution_x is zero, then don't show resolution modification
|
||||
* parts of the dialog. If object is non-NULL, then attach the cancel
|
||||
* callback to its destroy signal. */
|
||||
|
||||
Resize * resize_widget_new (ResizeType type,
|
||||
ResizeTarget target,
|
||||
GtkObject * object,
|
||||
|
@ -76,4 +84,9 @@ Resize * resize_widget_new (ResizeType type,
|
|||
gpointer user_data);
|
||||
void resize_widget_free (Resize * resize);
|
||||
|
||||
/* Layer scaling sanity check and warning dialogs */
|
||||
|
||||
gboolean resize_check_layer_scaling (ImageResize *);
|
||||
void resize_scale_implement (ImageResize *);
|
||||
|
||||
#endif /* __RESIZE_H__ */
|
||||
|
|
|
@ -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 = (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.*/
|
||||
|
||||
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);
|
||||
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 */
|
||||
|
|
180
app/gimplayer.c
180
app/gimplayer.c
|
@ -346,7 +346,7 @@ layer_copy (Layer *layer,
|
|||
new_type, layer_name, layer->opacity, layer->mode);
|
||||
if (!new_layer)
|
||||
{
|
||||
g_message ("layer_copy: could not allocate new layer");
|
||||
g_message (_("layer_copy: could not allocate new layer"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
@ -421,7 +421,7 @@ layer_new_from_tiles (GimpImage *gimage,
|
|||
|
||||
if (!new_layer)
|
||||
{
|
||||
g_message ("layer_new_from_tiles: could not allocate new layer");
|
||||
g_message (_("layer_new_from_tiles: could not allocate new layer"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -723,18 +723,16 @@ layer_add_alpha (Layer *layer)
|
|||
"restructure");
|
||||
}
|
||||
|
||||
void
|
||||
layer_scale (Layer *layer,
|
||||
gint new_width,
|
||||
gint new_height,
|
||||
gint local_origin)
|
||||
static void
|
||||
layer_scale_lowlevel(Layer *layer,
|
||||
gint new_width,
|
||||
gint new_height,
|
||||
gint new_offset_x,
|
||||
gint new_offset_y)
|
||||
{
|
||||
PixelRegion srcPR, destPR;
|
||||
TileManager *new_tiles;
|
||||
|
||||
if (new_width == 0 || new_height == 0)
|
||||
return;
|
||||
|
||||
/* Update the old layer position */
|
||||
drawable_update (GIMP_DRAWABLE(layer),
|
||||
0, 0,
|
||||
|
@ -761,29 +759,12 @@ layer_scale (Layer *layer,
|
|||
undo_push_layer_mod (GIMP_DRAWABLE(layer)->gimage, layer);
|
||||
|
||||
/* Configure the new layer */
|
||||
if (local_origin)
|
||||
{
|
||||
int cx, cy;
|
||||
|
||||
cx = GIMP_DRAWABLE(layer)->offset_x + GIMP_DRAWABLE(layer)->width / 2;
|
||||
cy = GIMP_DRAWABLE(layer)->offset_y + GIMP_DRAWABLE(layer)->height / 2;
|
||||
|
||||
GIMP_DRAWABLE(layer)->offset_x = cx - (new_width / 2);
|
||||
GIMP_DRAWABLE(layer)->offset_y = cy - (new_height / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
double xrat, yrat;
|
||||
|
||||
xrat = (double) new_width / (double) GIMP_DRAWABLE(layer)->width;
|
||||
yrat = (double) new_height / (double) GIMP_DRAWABLE(layer)->height;
|
||||
|
||||
GIMP_DRAWABLE(layer)->offset_x = (int) (xrat * GIMP_DRAWABLE(layer)->offset_x);
|
||||
GIMP_DRAWABLE(layer)->offset_y = (int) (yrat * GIMP_DRAWABLE(layer)->offset_y);
|
||||
}
|
||||
GIMP_DRAWABLE(layer)->tiles = new_tiles;
|
||||
GIMP_DRAWABLE(layer)->width = new_width;
|
||||
GIMP_DRAWABLE(layer)->height = new_height;
|
||||
GIMP_DRAWABLE(layer)->offset_x = new_offset_x;
|
||||
GIMP_DRAWABLE(layer)->offset_y = new_offset_y;
|
||||
GIMP_DRAWABLE(layer)->tiles = new_tiles;
|
||||
GIMP_DRAWABLE(layer)->width = new_width;
|
||||
GIMP_DRAWABLE(layer)->height = new_height;
|
||||
|
||||
/* If there is a layer mask, make sure it gets scaled also */
|
||||
if (layer->mask)
|
||||
|
@ -794,11 +775,146 @@ layer_scale (Layer *layer,
|
|||
}
|
||||
|
||||
/* Update the new layer position */
|
||||
|
||||
drawable_update (GIMP_DRAWABLE(layer),
|
||||
0, 0,
|
||||
GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height);
|
||||
}
|
||||
|
||||
/**
|
||||
* layer_check_scaling:
|
||||
* @layer: Layer to check
|
||||
* @new_width: proposed width of layer, in pixels
|
||||
* @new_height: proposed height of layer, in pixels
|
||||
* Scales layer dimensions, then snaps them to pixel centers
|
||||
* Returns FALSE if any dimension reduces to zero as a result
|
||||
* of this; otherwise, returns TRUE.
|
||||
*/
|
||||
|
||||
gboolean layer_check_scaling (Layer *layer,
|
||||
gint new_width,
|
||||
gint new_height)
|
||||
{
|
||||
GImage *gimage = GIMP_DRAWABLE(layer)->gimage;
|
||||
gdouble img_scale_w = (gdouble)new_width/(gdouble)gimage->width;
|
||||
gdouble img_scale_h = (gdouble)new_height/(gdouble)gimage->height;
|
||||
gint new_layer_width = (gint)(0.5 + img_scale_w * (gdouble)GIMP_DRAWABLE(layer)->width);
|
||||
gint new_layer_height = (gint)(0.5 + img_scale_h * (gdouble)GIMP_DRAWABLE(layer)->height);
|
||||
|
||||
return (new_layer_width != 0 && new_layer_height != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* layer_scale_by_factors:
|
||||
* @layer: Layer to be transformed by explicit width and height factors.
|
||||
* @w_factor: scale factor to apply to width and horizontal offset
|
||||
* @h_factor: scale factor to apply to height and vertical offset
|
||||
*
|
||||
* Scales layer dimensions and offsets by uniform width and
|
||||
* height factors.
|
||||
*
|
||||
* Use layer_scale_by_factors() in circumstances when the
|
||||
* same width and height scaling factors are to be uniformly
|
||||
* applied to a set of layers. In this context, the layer's
|
||||
* dimensions and offsets from the sides of the containing
|
||||
* image all change by these predetermined factors. By fiat,
|
||||
* the fixed point of the transform is the upper left hand
|
||||
* corner of the image. Returns gboolean FALSE if a requested
|
||||
* scale factor is zero or if a scaling zero's out a layer
|
||||
* dimension; returns TRUE otherwise.
|
||||
*
|
||||
* Use layer_scale() in circumstances where new layer width
|
||||
* and height dimensions are predetermined instead.
|
||||
*
|
||||
* #Returns: TRUE, if the scaled layer has positive dimensions
|
||||
* FALSE if the scaled layer has at least one zero dimension
|
||||
*
|
||||
* #Side effects: undo set created for layer.
|
||||
* Old layer imagery scaled
|
||||
* & painted to new layer tiles
|
||||
*/
|
||||
|
||||
gboolean
|
||||
layer_scale_by_factors(Layer *layer,
|
||||
gdouble w_factor,
|
||||
gdouble h_factor)
|
||||
{
|
||||
gint new_width, new_height, new_offset_x, new_offset_y;
|
||||
|
||||
if (w_factor == 0.0 || h_factor == 0.0)
|
||||
{
|
||||
g_message(_("layer_scale_by_factors: Error. Requested width or height scale equals zero."));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
new_offset_x = (gint)(0.5 + w_factor * (gdouble)GIMP_DRAWABLE(layer)->offset_x);
|
||||
new_offset_y = (gint)(0.5 + h_factor * (gdouble)GIMP_DRAWABLE(layer)->offset_y);
|
||||
new_width = (gint)(0.5 + w_factor * (gdouble)GIMP_DRAWABLE(layer)->width);
|
||||
new_height = (gint)(0.5 + h_factor * (gdouble)GIMP_DRAWABLE(layer)->height);
|
||||
|
||||
if(new_width != 0 && new_height != 0)
|
||||
{
|
||||
layer_scale_lowlevel(layer, new_width, new_height, new_offset_x, new_offset_y);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* layer_scale:
|
||||
* @layer: The layer to be transformed by width & height scale factors
|
||||
* @new_width: The width that layer will acquire
|
||||
* @new_height: The height that the layer will acquire
|
||||
* @local_origin: sets fixed point of the scaling transform. See below.
|
||||
*
|
||||
* Sets layer dimensions to new_width and
|
||||
* new_height. Derives vertical and horizontal scaling
|
||||
* transforms from new width and height. If local_origin is
|
||||
* TRUE, the fixed point of the scaling transform coincides
|
||||
* with the layer's center point. Otherwise, the fixed
|
||||
* point is taken to be [-GIMP_DRAWABLE(layer)->offset_x,
|
||||
* -GIMP_DRAWABLE(layer)->offset_y].
|
||||
*
|
||||
* Since this function derives scale factors from new and
|
||||
* current layer dimensions, these factors will vary from
|
||||
* layer to layer because of aliasing artifacts; factor
|
||||
* variations among layers can be quite large where layer
|
||||
* dimensions approach pixel dimensions. Use
|
||||
* layer_scale_by_factors where constant scales are to
|
||||
* be uniformly applied to a number of layers.
|
||||
*
|
||||
* Side effects: undo set created for layer.
|
||||
* Old layer imagery scaled
|
||||
* & painted to new layer tiles
|
||||
*/
|
||||
|
||||
void
|
||||
layer_scale (Layer *layer,
|
||||
gint new_width,
|
||||
gint new_height,
|
||||
gboolean local_origin)
|
||||
{
|
||||
gint new_offset_x, new_offset_y;
|
||||
|
||||
if (new_width == 0 || new_height == 0)
|
||||
{
|
||||
g_message(_("layer_scale: Error. Requested width or height equals zero."));
|
||||
return;
|
||||
}
|
||||
if (local_origin)
|
||||
{
|
||||
new_offset_x = GIMP_DRAWABLE(layer)->offset_x + ((GIMP_DRAWABLE(layer)->width - new_width)/2.0);
|
||||
new_offset_y = GIMP_DRAWABLE(layer)->offset_y + ((GIMP_DRAWABLE(layer)->height - new_height)/2.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
new_offset_x = (gint)(((gdouble) new_width * GIMP_DRAWABLE(layer)->offset_x/(gdouble) GIMP_DRAWABLE(layer)->width));
|
||||
new_offset_y = (gint)(((gdouble) new_height * GIMP_DRAWABLE(layer)->offset_y/(gdouble) GIMP_DRAWABLE(layer)->height));
|
||||
}
|
||||
layer_scale_lowlevel(layer, new_width, new_height, new_offset_x, new_offset_y);
|
||||
}
|
||||
|
||||
void
|
||||
layer_resize (Layer *layer,
|
||||
gint new_width,
|
||||
|
|
|
@ -82,6 +82,7 @@ void layer_unref (Layer *);
|
|||
Layer * layer_new_from_tiles (GimpImage *, GimpImageType, TileManager *,
|
||||
gchar *, gint, LayerModeEffects);
|
||||
LayerMask * layer_add_mask (Layer *, LayerMask *);
|
||||
gboolean layer_check_scaling (Layer *, gint, gint);
|
||||
LayerMask * layer_create_mask (Layer *, AddMaskType);
|
||||
Layer * layer_get_ID (gint);
|
||||
void layer_delete (Layer *);
|
||||
|
@ -90,7 +91,8 @@ void layer_apply_mask (Layer *, MaskApplyMode);
|
|||
void layer_temporarily_translate (Layer *, gint, gint);
|
||||
void layer_translate (Layer *, gint, gint);
|
||||
void layer_add_alpha (Layer *);
|
||||
void layer_scale (Layer *, gint, gint, gint);
|
||||
gboolean layer_scale_by_factors (Layer *, gdouble, gdouble);
|
||||
void layer_scale (Layer *, gint, gint, gboolean);
|
||||
void layer_resize (Layer *, gint, gint, gint, gint);
|
||||
void layer_resize_to_image (Layer *);
|
||||
BoundSeg * layer_boundary (Layer *, gint *);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -65,19 +65,19 @@ struct _ResizePrivate
|
|||
gint orig_x, orig_y;
|
||||
};
|
||||
|
||||
static void resize_draw (Resize *);
|
||||
static void unit_update (GtkWidget *, gpointer);
|
||||
static gint resize_bound_off_x (Resize *, gint);
|
||||
static gint resize_bound_off_y (Resize *, gint);
|
||||
static void orig_labels_update (GtkWidget *, gpointer);
|
||||
static void size_callback (GtkWidget *, gpointer);
|
||||
static void ratio_callback (GtkWidget *, gpointer);
|
||||
static void size_update (Resize *, gdouble, gdouble, gdouble, gdouble);
|
||||
static void offset_update (GtkWidget *, gpointer);
|
||||
static gint resize_events (GtkWidget *, GdkEvent *);
|
||||
static void printsize_update (GtkWidget *, gpointer);
|
||||
static void resolution_update (GtkWidget *, gpointer);
|
||||
|
||||
static void resize_draw (Resize *);
|
||||
static void unit_update (GtkWidget *, gpointer);
|
||||
static gint resize_bound_off_x (Resize *, gint);
|
||||
static gint resize_bound_off_y (Resize *, gint);
|
||||
static void orig_labels_update (GtkWidget *, gpointer);
|
||||
static void size_callback (GtkWidget *, gpointer);
|
||||
static void ratio_callback (GtkWidget *, gpointer);
|
||||
static void size_update (Resize *, gdouble, gdouble, gdouble, gdouble);
|
||||
static void offset_update (GtkWidget *, gpointer);
|
||||
static gint resize_events (GtkWidget *, GdkEvent *);
|
||||
static void printsize_update (GtkWidget *, gpointer);
|
||||
static void resolution_update (GtkWidget *, gpointer);
|
||||
static void resize_scale_warn_callback (GtkWidget *, gboolean, gpointer);
|
||||
|
||||
Resize *
|
||||
resize_widget_new (ResizeType type,
|
||||
|
@ -1191,3 +1191,164 @@ resize_events (GtkWidget *widget,
|
|||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*** Resize sanity checks ***/
|
||||
|
||||
void resize_scale_implement (ImageResize *image_scale)
|
||||
{
|
||||
GImage *gimage = NULL;
|
||||
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 */
|
||||
g_assert(image_scale != NULL);
|
||||
gimage = image_scale->gimage;
|
||||
g_assert(gimage != NULL);
|
||||
|
||||
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 ();
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void resize_scale_warn_callback (GtkWidget *widget,
|
||||
gboolean do_scale,
|
||||
gpointer client_data)
|
||||
{
|
||||
ImageResize *image_scale = NULL;
|
||||
GImage *gimage = NULL;
|
||||
|
||||
g_assert(client_data != NULL);
|
||||
image_scale = (ImageResize *) client_data;
|
||||
gimage = image_scale->gimage;
|
||||
g_assert(gimage != NULL);
|
||||
|
||||
if(do_scale == TRUE) /* User doesn't mind losing layers... */
|
||||
{
|
||||
resize_scale_implement(image_scale);
|
||||
resize_widget_free (image_scale->resize);
|
||||
g_free (image_scale);
|
||||
}
|
||||
else
|
||||
gtk_widget_set_sensitive (image_scale->resize->resize_shell, TRUE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
resize_check_layer_scaling (ImageResize *image_scale)
|
||||
{
|
||||
/* Inventory the layer list in gimage and return TRUE if, after
|
||||
* scaling, they all retain positive x and y pixel dimensions.
|
||||
* Otherwise, put up a modal boolean dialog box and ask the user if
|
||||
* she wishes to proceed. Return FALSE in the dialog case; the dialog box
|
||||
* callback will complete the job if the user really wants to
|
||||
* proceed. <02/22/2000 gosgood@idt.net>
|
||||
*/
|
||||
|
||||
gboolean success = FALSE;
|
||||
GImage *gimage = NULL;
|
||||
GSList *list = NULL;
|
||||
Layer *layer = NULL;
|
||||
GtkWidget *dialog = NULL;
|
||||
gchar *str = NULL;
|
||||
|
||||
g_assert(image_scale != NULL);
|
||||
|
||||
if(NULL != (gimage = image_scale->gimage))
|
||||
{
|
||||
/* Step through layers; test scaled dimensions. */
|
||||
|
||||
success = TRUE;
|
||||
list = gimage->layers;
|
||||
while(list && success == TRUE)
|
||||
{
|
||||
layer = (Layer *)list->data;
|
||||
success = layer_check_scaling (layer,
|
||||
image_scale->resize->width,
|
||||
image_scale->resize->height);
|
||||
list = g_slist_next (list);
|
||||
|
||||
}
|
||||
/* Warn user on failure */
|
||||
if(success == FALSE)
|
||||
{
|
||||
gtk_widget_set_sensitive (image_scale->resize->resize_shell, FALSE);
|
||||
|
||||
str = g_strdup (_("The chosen image size will shrink\n"
|
||||
"some layers completely away.\nIs this what you want?"));
|
||||
|
||||
dialog =
|
||||
gimp_query_boolean_box (_("Layer Too Small"),
|
||||
gimp_standard_help_func,
|
||||
"dialogs/scale_layer_warn.html",
|
||||
FALSE,
|
||||
str,
|
||||
_("OK"), _("Cancel"),
|
||||
NULL, NULL,
|
||||
resize_scale_warn_callback,
|
||||
image_scale);
|
||||
|
||||
g_free (str);
|
||||
gtk_widget_show (dialog);
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#define __RESIZE_H__
|
||||
|
||||
#include "libgimp/gimpunit.h"
|
||||
#include "gimage.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
@ -59,9 +60,16 @@ struct _Resize
|
|||
void * private_part;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Resize *resize;
|
||||
GimpImage *gimage;
|
||||
} ImageResize;
|
||||
|
||||
/* If resolution_x is zero, then don't show resolution modification
|
||||
* parts of the dialog. If object is non-NULL, then attach the cancel
|
||||
* callback to its destroy signal. */
|
||||
|
||||
Resize * resize_widget_new (ResizeType type,
|
||||
ResizeTarget target,
|
||||
GtkObject * object,
|
||||
|
@ -76,4 +84,9 @@ Resize * resize_widget_new (ResizeType type,
|
|||
gpointer user_data);
|
||||
void resize_widget_free (Resize * resize);
|
||||
|
||||
/* Layer scaling sanity check and warning dialogs */
|
||||
|
||||
gboolean resize_check_layer_scaling (ImageResize *);
|
||||
void resize_scale_implement (ImageResize *);
|
||||
|
||||
#endif /* __RESIZE_H__ */
|
||||
|
|
180
app/layer.c
180
app/layer.c
|
@ -346,7 +346,7 @@ layer_copy (Layer *layer,
|
|||
new_type, layer_name, layer->opacity, layer->mode);
|
||||
if (!new_layer)
|
||||
{
|
||||
g_message ("layer_copy: could not allocate new layer");
|
||||
g_message (_("layer_copy: could not allocate new layer"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
@ -421,7 +421,7 @@ layer_new_from_tiles (GimpImage *gimage,
|
|||
|
||||
if (!new_layer)
|
||||
{
|
||||
g_message ("layer_new_from_tiles: could not allocate new layer");
|
||||
g_message (_("layer_new_from_tiles: could not allocate new layer"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -723,18 +723,16 @@ layer_add_alpha (Layer *layer)
|
|||
"restructure");
|
||||
}
|
||||
|
||||
void
|
||||
layer_scale (Layer *layer,
|
||||
gint new_width,
|
||||
gint new_height,
|
||||
gint local_origin)
|
||||
static void
|
||||
layer_scale_lowlevel(Layer *layer,
|
||||
gint new_width,
|
||||
gint new_height,
|
||||
gint new_offset_x,
|
||||
gint new_offset_y)
|
||||
{
|
||||
PixelRegion srcPR, destPR;
|
||||
TileManager *new_tiles;
|
||||
|
||||
if (new_width == 0 || new_height == 0)
|
||||
return;
|
||||
|
||||
/* Update the old layer position */
|
||||
drawable_update (GIMP_DRAWABLE(layer),
|
||||
0, 0,
|
||||
|
@ -761,29 +759,12 @@ layer_scale (Layer *layer,
|
|||
undo_push_layer_mod (GIMP_DRAWABLE(layer)->gimage, layer);
|
||||
|
||||
/* Configure the new layer */
|
||||
if (local_origin)
|
||||
{
|
||||
int cx, cy;
|
||||
|
||||
cx = GIMP_DRAWABLE(layer)->offset_x + GIMP_DRAWABLE(layer)->width / 2;
|
||||
cy = GIMP_DRAWABLE(layer)->offset_y + GIMP_DRAWABLE(layer)->height / 2;
|
||||
|
||||
GIMP_DRAWABLE(layer)->offset_x = cx - (new_width / 2);
|
||||
GIMP_DRAWABLE(layer)->offset_y = cy - (new_height / 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
double xrat, yrat;
|
||||
|
||||
xrat = (double) new_width / (double) GIMP_DRAWABLE(layer)->width;
|
||||
yrat = (double) new_height / (double) GIMP_DRAWABLE(layer)->height;
|
||||
|
||||
GIMP_DRAWABLE(layer)->offset_x = (int) (xrat * GIMP_DRAWABLE(layer)->offset_x);
|
||||
GIMP_DRAWABLE(layer)->offset_y = (int) (yrat * GIMP_DRAWABLE(layer)->offset_y);
|
||||
}
|
||||
GIMP_DRAWABLE(layer)->tiles = new_tiles;
|
||||
GIMP_DRAWABLE(layer)->width = new_width;
|
||||
GIMP_DRAWABLE(layer)->height = new_height;
|
||||
GIMP_DRAWABLE(layer)->offset_x = new_offset_x;
|
||||
GIMP_DRAWABLE(layer)->offset_y = new_offset_y;
|
||||
GIMP_DRAWABLE(layer)->tiles = new_tiles;
|
||||
GIMP_DRAWABLE(layer)->width = new_width;
|
||||
GIMP_DRAWABLE(layer)->height = new_height;
|
||||
|
||||
/* If there is a layer mask, make sure it gets scaled also */
|
||||
if (layer->mask)
|
||||
|
@ -794,11 +775,146 @@ layer_scale (Layer *layer,
|
|||
}
|
||||
|
||||
/* Update the new layer position */
|
||||
|
||||
drawable_update (GIMP_DRAWABLE(layer),
|
||||
0, 0,
|
||||
GIMP_DRAWABLE(layer)->width, GIMP_DRAWABLE(layer)->height);
|
||||
}
|
||||
|
||||
/**
|
||||
* layer_check_scaling:
|
||||
* @layer: Layer to check
|
||||
* @new_width: proposed width of layer, in pixels
|
||||
* @new_height: proposed height of layer, in pixels
|
||||
* Scales layer dimensions, then snaps them to pixel centers
|
||||
* Returns FALSE if any dimension reduces to zero as a result
|
||||
* of this; otherwise, returns TRUE.
|
||||
*/
|
||||
|
||||
gboolean layer_check_scaling (Layer *layer,
|
||||
gint new_width,
|
||||
gint new_height)
|
||||
{
|
||||
GImage *gimage = GIMP_DRAWABLE(layer)->gimage;
|
||||
gdouble img_scale_w = (gdouble)new_width/(gdouble)gimage->width;
|
||||
gdouble img_scale_h = (gdouble)new_height/(gdouble)gimage->height;
|
||||
gint new_layer_width = (gint)(0.5 + img_scale_w * (gdouble)GIMP_DRAWABLE(layer)->width);
|
||||
gint new_layer_height = (gint)(0.5 + img_scale_h * (gdouble)GIMP_DRAWABLE(layer)->height);
|
||||
|
||||
return (new_layer_width != 0 && new_layer_height != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* layer_scale_by_factors:
|
||||
* @layer: Layer to be transformed by explicit width and height factors.
|
||||
* @w_factor: scale factor to apply to width and horizontal offset
|
||||
* @h_factor: scale factor to apply to height and vertical offset
|
||||
*
|
||||
* Scales layer dimensions and offsets by uniform width and
|
||||
* height factors.
|
||||
*
|
||||
* Use layer_scale_by_factors() in circumstances when the
|
||||
* same width and height scaling factors are to be uniformly
|
||||
* applied to a set of layers. In this context, the layer's
|
||||
* dimensions and offsets from the sides of the containing
|
||||
* image all change by these predetermined factors. By fiat,
|
||||
* the fixed point of the transform is the upper left hand
|
||||
* corner of the image. Returns gboolean FALSE if a requested
|
||||
* scale factor is zero or if a scaling zero's out a layer
|
||||
* dimension; returns TRUE otherwise.
|
||||
*
|
||||
* Use layer_scale() in circumstances where new layer width
|
||||
* and height dimensions are predetermined instead.
|
||||
*
|
||||
* #Returns: TRUE, if the scaled layer has positive dimensions
|
||||
* FALSE if the scaled layer has at least one zero dimension
|
||||
*
|
||||
* #Side effects: undo set created for layer.
|
||||
* Old layer imagery scaled
|
||||
* & painted to new layer tiles
|
||||
*/
|
||||
|
||||
gboolean
|
||||
layer_scale_by_factors(Layer *layer,
|
||||
gdouble w_factor,
|
||||
gdouble h_factor)
|
||||
{
|
||||
gint new_width, new_height, new_offset_x, new_offset_y;
|
||||
|
||||
if (w_factor == 0.0 || h_factor == 0.0)
|
||||
{
|
||||
g_message(_("layer_scale_by_factors: Error. Requested width or height scale equals zero."));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
new_offset_x = (gint)(0.5 + w_factor * (gdouble)GIMP_DRAWABLE(layer)->offset_x);
|
||||
new_offset_y = (gint)(0.5 + h_factor * (gdouble)GIMP_DRAWABLE(layer)->offset_y);
|
||||
new_width = (gint)(0.5 + w_factor * (gdouble)GIMP_DRAWABLE(layer)->width);
|
||||
new_height = (gint)(0.5 + h_factor * (gdouble)GIMP_DRAWABLE(layer)->height);
|
||||
|
||||
if(new_width != 0 && new_height != 0)
|
||||
{
|
||||
layer_scale_lowlevel(layer, new_width, new_height, new_offset_x, new_offset_y);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* layer_scale:
|
||||
* @layer: The layer to be transformed by width & height scale factors
|
||||
* @new_width: The width that layer will acquire
|
||||
* @new_height: The height that the layer will acquire
|
||||
* @local_origin: sets fixed point of the scaling transform. See below.
|
||||
*
|
||||
* Sets layer dimensions to new_width and
|
||||
* new_height. Derives vertical and horizontal scaling
|
||||
* transforms from new width and height. If local_origin is
|
||||
* TRUE, the fixed point of the scaling transform coincides
|
||||
* with the layer's center point. Otherwise, the fixed
|
||||
* point is taken to be [-GIMP_DRAWABLE(layer)->offset_x,
|
||||
* -GIMP_DRAWABLE(layer)->offset_y].
|
||||
*
|
||||
* Since this function derives scale factors from new and
|
||||
* current layer dimensions, these factors will vary from
|
||||
* layer to layer because of aliasing artifacts; factor
|
||||
* variations among layers can be quite large where layer
|
||||
* dimensions approach pixel dimensions. Use
|
||||
* layer_scale_by_factors where constant scales are to
|
||||
* be uniformly applied to a number of layers.
|
||||
*
|
||||
* Side effects: undo set created for layer.
|
||||
* Old layer imagery scaled
|
||||
* & painted to new layer tiles
|
||||
*/
|
||||
|
||||
void
|
||||
layer_scale (Layer *layer,
|
||||
gint new_width,
|
||||
gint new_height,
|
||||
gboolean local_origin)
|
||||
{
|
||||
gint new_offset_x, new_offset_y;
|
||||
|
||||
if (new_width == 0 || new_height == 0)
|
||||
{
|
||||
g_message(_("layer_scale: Error. Requested width or height equals zero."));
|
||||
return;
|
||||
}
|
||||
if (local_origin)
|
||||
{
|
||||
new_offset_x = GIMP_DRAWABLE(layer)->offset_x + ((GIMP_DRAWABLE(layer)->width - new_width)/2.0);
|
||||
new_offset_y = GIMP_DRAWABLE(layer)->offset_y + ((GIMP_DRAWABLE(layer)->height - new_height)/2.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
new_offset_x = (gint)(((gdouble) new_width * GIMP_DRAWABLE(layer)->offset_x/(gdouble) GIMP_DRAWABLE(layer)->width));
|
||||
new_offset_y = (gint)(((gdouble) new_height * GIMP_DRAWABLE(layer)->offset_y/(gdouble) GIMP_DRAWABLE(layer)->height));
|
||||
}
|
||||
layer_scale_lowlevel(layer, new_width, new_height, new_offset_x, new_offset_y);
|
||||
}
|
||||
|
||||
void
|
||||
layer_resize (Layer *layer,
|
||||
gint new_width,
|
||||
|
|
|
@ -82,6 +82,7 @@ void layer_unref (Layer *);
|
|||
Layer * layer_new_from_tiles (GimpImage *, GimpImageType, TileManager *,
|
||||
gchar *, gint, LayerModeEffects);
|
||||
LayerMask * layer_add_mask (Layer *, LayerMask *);
|
||||
gboolean layer_check_scaling (Layer *, gint, gint);
|
||||
LayerMask * layer_create_mask (Layer *, AddMaskType);
|
||||
Layer * layer_get_ID (gint);
|
||||
void layer_delete (Layer *);
|
||||
|
@ -90,7 +91,8 @@ void layer_apply_mask (Layer *, MaskApplyMode);
|
|||
void layer_temporarily_translate (Layer *, gint, gint);
|
||||
void layer_translate (Layer *, gint, gint);
|
||||
void layer_add_alpha (Layer *);
|
||||
void layer_scale (Layer *, gint, gint, gint);
|
||||
gboolean layer_scale_by_factors (Layer *, gdouble, gdouble);
|
||||
void layer_scale (Layer *, gint, gint, gboolean);
|
||||
void layer_resize (Layer *, gint, gint, gint, gint);
|
||||
void layer_resize_to_image (Layer *);
|
||||
BoundSeg * layer_boundary (Layer *, gint *);
|
||||
|
|
187
app/resize.c
187
app/resize.c
|
@ -65,19 +65,19 @@ struct _ResizePrivate
|
|||
gint orig_x, orig_y;
|
||||
};
|
||||
|
||||
static void resize_draw (Resize *);
|
||||
static void unit_update (GtkWidget *, gpointer);
|
||||
static gint resize_bound_off_x (Resize *, gint);
|
||||
static gint resize_bound_off_y (Resize *, gint);
|
||||
static void orig_labels_update (GtkWidget *, gpointer);
|
||||
static void size_callback (GtkWidget *, gpointer);
|
||||
static void ratio_callback (GtkWidget *, gpointer);
|
||||
static void size_update (Resize *, gdouble, gdouble, gdouble, gdouble);
|
||||
static void offset_update (GtkWidget *, gpointer);
|
||||
static gint resize_events (GtkWidget *, GdkEvent *);
|
||||
static void printsize_update (GtkWidget *, gpointer);
|
||||
static void resolution_update (GtkWidget *, gpointer);
|
||||
|
||||
static void resize_draw (Resize *);
|
||||
static void unit_update (GtkWidget *, gpointer);
|
||||
static gint resize_bound_off_x (Resize *, gint);
|
||||
static gint resize_bound_off_y (Resize *, gint);
|
||||
static void orig_labels_update (GtkWidget *, gpointer);
|
||||
static void size_callback (GtkWidget *, gpointer);
|
||||
static void ratio_callback (GtkWidget *, gpointer);
|
||||
static void size_update (Resize *, gdouble, gdouble, gdouble, gdouble);
|
||||
static void offset_update (GtkWidget *, gpointer);
|
||||
static gint resize_events (GtkWidget *, GdkEvent *);
|
||||
static void printsize_update (GtkWidget *, gpointer);
|
||||
static void resolution_update (GtkWidget *, gpointer);
|
||||
static void resize_scale_warn_callback (GtkWidget *, gboolean, gpointer);
|
||||
|
||||
Resize *
|
||||
resize_widget_new (ResizeType type,
|
||||
|
@ -1191,3 +1191,164 @@ resize_events (GtkWidget *widget,
|
|||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*** Resize sanity checks ***/
|
||||
|
||||
void resize_scale_implement (ImageResize *image_scale)
|
||||
{
|
||||
GImage *gimage = NULL;
|
||||
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 */
|
||||
g_assert(image_scale != NULL);
|
||||
gimage = image_scale->gimage;
|
||||
g_assert(gimage != NULL);
|
||||
|
||||
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 ();
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void resize_scale_warn_callback (GtkWidget *widget,
|
||||
gboolean do_scale,
|
||||
gpointer client_data)
|
||||
{
|
||||
ImageResize *image_scale = NULL;
|
||||
GImage *gimage = NULL;
|
||||
|
||||
g_assert(client_data != NULL);
|
||||
image_scale = (ImageResize *) client_data;
|
||||
gimage = image_scale->gimage;
|
||||
g_assert(gimage != NULL);
|
||||
|
||||
if(do_scale == TRUE) /* User doesn't mind losing layers... */
|
||||
{
|
||||
resize_scale_implement(image_scale);
|
||||
resize_widget_free (image_scale->resize);
|
||||
g_free (image_scale);
|
||||
}
|
||||
else
|
||||
gtk_widget_set_sensitive (image_scale->resize->resize_shell, TRUE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
resize_check_layer_scaling (ImageResize *image_scale)
|
||||
{
|
||||
/* Inventory the layer list in gimage and return TRUE if, after
|
||||
* scaling, they all retain positive x and y pixel dimensions.
|
||||
* Otherwise, put up a modal boolean dialog box and ask the user if
|
||||
* she wishes to proceed. Return FALSE in the dialog case; the dialog box
|
||||
* callback will complete the job if the user really wants to
|
||||
* proceed. <02/22/2000 gosgood@idt.net>
|
||||
*/
|
||||
|
||||
gboolean success = FALSE;
|
||||
GImage *gimage = NULL;
|
||||
GSList *list = NULL;
|
||||
Layer *layer = NULL;
|
||||
GtkWidget *dialog = NULL;
|
||||
gchar *str = NULL;
|
||||
|
||||
g_assert(image_scale != NULL);
|
||||
|
||||
if(NULL != (gimage = image_scale->gimage))
|
||||
{
|
||||
/* Step through layers; test scaled dimensions. */
|
||||
|
||||
success = TRUE;
|
||||
list = gimage->layers;
|
||||
while(list && success == TRUE)
|
||||
{
|
||||
layer = (Layer *)list->data;
|
||||
success = layer_check_scaling (layer,
|
||||
image_scale->resize->width,
|
||||
image_scale->resize->height);
|
||||
list = g_slist_next (list);
|
||||
|
||||
}
|
||||
/* Warn user on failure */
|
||||
if(success == FALSE)
|
||||
{
|
||||
gtk_widget_set_sensitive (image_scale->resize->resize_shell, FALSE);
|
||||
|
||||
str = g_strdup (_("The chosen image size will shrink\n"
|
||||
"some layers completely away.\nIs this what you want?"));
|
||||
|
||||
dialog =
|
||||
gimp_query_boolean_box (_("Layer Too Small"),
|
||||
gimp_standard_help_func,
|
||||
"dialogs/scale_layer_warn.html",
|
||||
FALSE,
|
||||
str,
|
||||
_("OK"), _("Cancel"),
|
||||
NULL, NULL,
|
||||
resize_scale_warn_callback,
|
||||
image_scale);
|
||||
|
||||
g_free (str);
|
||||
gtk_widget_show (dialog);
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
|
13
app/resize.h
13
app/resize.h
|
@ -19,6 +19,7 @@
|
|||
#define __RESIZE_H__
|
||||
|
||||
#include "libgimp/gimpunit.h"
|
||||
#include "gimage.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
|
@ -59,9 +60,16 @@ struct _Resize
|
|||
void * private_part;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Resize *resize;
|
||||
GimpImage *gimage;
|
||||
} ImageResize;
|
||||
|
||||
/* If resolution_x is zero, then don't show resolution modification
|
||||
* parts of the dialog. If object is non-NULL, then attach the cancel
|
||||
* callback to its destroy signal. */
|
||||
|
||||
Resize * resize_widget_new (ResizeType type,
|
||||
ResizeTarget target,
|
||||
GtkObject * object,
|
||||
|
@ -76,4 +84,9 @@ Resize * resize_widget_new (ResizeType type,
|
|||
gpointer user_data);
|
||||
void resize_widget_free (Resize * resize);
|
||||
|
||||
/* Layer scaling sanity check and warning dialogs */
|
||||
|
||||
gboolean resize_check_layer_scaling (ImageResize *);
|
||||
void resize_scale_implement (ImageResize *);
|
||||
|
||||
#endif /* __RESIZE_H__ */
|
||||
|
|
|
@ -37,6 +37,7 @@ helpdata_DATA = \
|
|||
really_close.html \
|
||||
really_quit.html \
|
||||
scale_image.html \
|
||||
scale_layer_warn.html \
|
||||
set_canvas_size.html \
|
||||
shrink_selection.html \
|
||||
tip_of_the_day.html \
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
|
||||
<TITLE>Scale Image</TITLE>
|
||||
</HEAD>
|
||||
<BODY text="#000000" bgcolor="#FFFFFF" link="#0000FF" vlink="#FF0000" alink="#000088">
|
||||
<TABLE width="100%" cellspacing="1" cellpadding="1">
|
||||
<TR bgcolor="black">
|
||||
<TD width="100%" align="center"><FONT size="+2" color="white">Layer Too Small</FONT></TD>
|
||||
</TR>
|
||||
<TR bgcolor="white" >
|
||||
<TD width="100%" align="left">
|
||||
<P>
|
||||
[Placeholder: Documentation to come]
|
||||
</P>
|
||||
<H3>
|
||||
Additional Information
|
||||
</H3>
|
||||
<P>
|
||||
For further information see The Gimp User's Manual page XXXX and the Gimp
|
||||
User's Tutorial page YYYY
|
||||
<P>
|
||||
Shortcut Key
|
||||
<P>
|
||||
Modifier
|
||||
<P>
|
||||
Drag and Drop
|
||||
<P>
|
||||
Xinput
|
||||
<P>
|
||||
----DEV----
|
||||
<P>
|
||||
<A href="index.html">Index</A>
|
||||
<P>
|
||||
(/dialogs/scale_layer_warn.html)
|
||||
<P>
|
||||
Sorry but the help file for scale_layer_warn is not yet done.
|
||||
<P>
|
||||
/Karin & Olof
|
||||
<P>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</BODY></HTML>
|
Loading…
Reference in New Issue