diff --git a/app/core/gimpgrouplayer.c b/app/core/gimpgrouplayer.c index b78ecee9b0..e81ba8eb9c 100644 --- a/app/core/gimpgrouplayer.c +++ b/app/core/gimpgrouplayer.c @@ -810,42 +810,30 @@ gimp_group_layer_scale (GimpLayer *layer, while (list) { GimpItem *child = list->data; - gint child_width; - gint child_height; - gint child_offset_x; - gint child_offset_y; list = g_list_next (list); if (queue) gimp_object_queue_pop (queue); - child_width = ROUND (width_factor * gimp_item_get_width (child)); - child_height = ROUND (height_factor * gimp_item_get_height (child)); - child_offset_x = ROUND (width_factor * (gimp_item_get_offset_x (child) - - old_offset_x)); - child_offset_y = ROUND (height_factor * (gimp_item_get_offset_y (child) - - old_offset_y)); - - child_offset_x += new_offset_x; - child_offset_y += new_offset_y; - - if (child_width > 0 && child_height > 0) + if (! gimp_item_scale_by_factors_with_origin (child, + width_factor, height_factor, + old_offset_x, old_offset_y, + new_offset_x, new_offset_y, + interpolation_type, + progress)) { - gimp_item_scale (child, - child_width, child_height, - child_offset_x, child_offset_y, - interpolation_type, progress); - } - else if (gimp_item_is_attached (item)) - { - gimp_image_remove_layer (gimp_item_get_image (item), - GIMP_LAYER (child), - TRUE, NULL); - } - else - { - gimp_container_remove (private->children, GIMP_OBJECT (child)); + /* new width or height are 0; remove item */ + if (gimp_item_is_attached (item)) + { + gimp_image_remove_layer (gimp_item_get_image (item), + GIMP_LAYER (child), + TRUE, NULL); + } + else + { + gimp_container_remove (private->children, GIMP_OBJECT (child)); + } } } diff --git a/app/core/gimpitem.c b/app/core/gimpitem.c index 1fbf375937..29dfbccc04 100644 --- a/app/core/gimpitem.c +++ b/app/core/gimpitem.c @@ -1261,22 +1261,32 @@ gimp_item_check_scaling (GimpItem *item, gint new_width, gint new_height) { - GimpImage *image; - gdouble img_scale_w; - gdouble img_scale_h; - gint new_item_width; - gint new_item_height; + GimpItemPrivate *private; + GimpImage *image; + gdouble img_scale_w; + gdouble img_scale_h; + gint new_item_offset_x; + gint new_item_offset_y; + gint new_item_width; + gint new_item_height; g_return_val_if_fail (GIMP_IS_ITEM (item), FALSE); - image = gimp_item_get_image (item); + private = GET_PRIVATE (item); + image = gimp_item_get_image (item); - img_scale_w = ((gdouble) new_width / - (gdouble) gimp_image_get_width (image)); - img_scale_h = ((gdouble) new_height / - (gdouble) gimp_image_get_height (image)); - new_item_width = ROUND (img_scale_w * (gdouble) gimp_item_get_width (item)); - new_item_height = ROUND (img_scale_h * (gdouble) gimp_item_get_height (item)); + img_scale_w = ((gdouble) new_width / + (gdouble) gimp_image_get_width (image)); + img_scale_h = ((gdouble) new_height / + (gdouble) gimp_image_get_height (image)); + new_item_offset_x = SIGNED_ROUND (img_scale_w * private->offset_x); + new_item_offset_y = SIGNED_ROUND (img_scale_h * private->offset_y); + new_item_width = SIGNED_ROUND (img_scale_w * (private->offset_x + + gimp_item_get_width (item))) - + new_item_offset_x; + new_item_height = SIGNED_ROUND (img_scale_h * (private->offset_y + + gimp_item_get_height (item))) - + new_item_offset_y; return (new_item_width > 0 && new_item_height > 0); } @@ -1359,6 +1369,41 @@ gimp_item_scale_by_factors (GimpItem *item, gdouble h_factor, GimpInterpolationType interpolation, GimpProgress *progress) +{ + return gimp_item_scale_by_factors_with_origin (item, + w_factor, h_factor, + 0, 0, 0, 0, + interpolation, progress); +} + +/** + * gimp_item_scale_by_factors: + * @item: Item 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 + * @origin_x: x-coordinate of the transformation input origin + * @origin_y: y-coordinate of the transformation input origin + * @new_origin_x: x-coordinate of the transformation output origin + * @new_origin_y: y-coordinate of the transformation output origin + * @interpolation: + * @progress: + * + * Same as gimp_item_scale_by_factors(), but with the option to specify + * custom input and output points of origin for the transformation. + * + * Returns: #TRUE, if the scaled item has positive dimensions + * #FALSE if the scaled item has at least one zero dimension + **/ +gboolean +gimp_item_scale_by_factors_with_origin (GimpItem *item, + gdouble w_factor, + gdouble h_factor, + gint origin_x, + gint origin_y, + gint new_origin_x, + gint new_origin_y, + GimpInterpolationType interpolation, + GimpProgress *progress) { GimpItemPrivate *private; gint new_width, new_height; @@ -1369,18 +1414,26 @@ gimp_item_scale_by_factors (GimpItem *item, private = GET_PRIVATE (item); - if (w_factor == 0.0 || h_factor == 0.0) + if (w_factor <= 0.0 || h_factor <= 0.0) { - g_warning ("%s: requested width or height scale equals zero", G_STRFUNC); + g_warning ("%s: requested width or height scale is non-positive", + G_STRFUNC); return FALSE; } - new_offset_x = SIGNED_ROUND (w_factor * (gdouble) private->offset_x); - new_offset_y = SIGNED_ROUND (h_factor * (gdouble) private->offset_y); - new_width = ROUND (w_factor * (gdouble) gimp_item_get_width (item)); - new_height = ROUND (h_factor * (gdouble) gimp_item_get_height (item)); + new_offset_x = SIGNED_ROUND (w_factor * (private->offset_x - origin_x)); + new_offset_y = SIGNED_ROUND (h_factor * (private->offset_y - origin_y)); + new_width = SIGNED_ROUND (w_factor * (private->offset_x - origin_x + + gimp_item_get_width (item))) - + new_offset_x; + new_height = SIGNED_ROUND (h_factor * (private->offset_y - origin_y + + gimp_item_get_height (item))) - + new_offset_y; - if (new_width != 0 && new_height != 0) + new_offset_x += new_origin_x; + new_offset_y += new_origin_y; + + if (new_width > 0 && new_height > 0) { gimp_item_scale (item, new_width, new_height, diff --git a/app/core/gimpitem.h b/app/core/gimpitem.h index b9023cfe57..783d07a727 100644 --- a/app/core/gimpitem.h +++ b/app/core/gimpitem.h @@ -236,6 +236,16 @@ gboolean gimp_item_scale_by_factors (GimpItem *item, gdouble h_factor, GimpInterpolationType interpolation, GimpProgress *progress); +gboolean + gimp_item_scale_by_factors_with_origin (GimpItem *item, + gdouble w_factor, + gdouble h_factor, + gint origin_x, + gint origin_y, + gint new_origin_x, + gint new_origin_y, + GimpInterpolationType interpolation, + GimpProgress *progress); void gimp_item_scale_by_origin (GimpItem *item, gint new_width, gint new_height,