diff --git a/app/core/gimpimage-flip.c b/app/core/gimpimage-flip.c index e999c3392e..5db05fe935 100644 --- a/app/core/gimpimage-flip.c +++ b/app/core/gimpimage-flip.c @@ -20,9 +20,12 @@ #include #include +#include "libgimpmath/gimpmath.h" + #include "core-types.h" #include "gimp.h" +#include "gimpchannel.h" #include "gimpcontainer.h" #include "gimpcontext.h" #include "gimpguide.h" @@ -38,38 +41,185 @@ #include "gimpsamplepoint.h" +/* local function prototypes */ + +static void gimp_image_flip_guides (GimpImage *image, + GimpOrientationType flip_type, + gdouble axis); +static void gimp_image_flip_sample_points (GimpImage *image, + GimpOrientationType flip_type, + gdouble axis); + + +/* private functions */ + +static void +gimp_image_flip_guides (GimpImage *image, + GimpOrientationType flip_type, + gdouble axis) +{ + gint width = gimp_image_get_width (image); + gint height = gimp_image_get_height (image); + GList *iter; + + for (iter = gimp_image_get_guides (image); iter;) + { + GimpGuide *guide = iter->data; + gint position = gimp_guide_get_position (guide); + + iter = g_list_next (iter); + + position = SIGNED_ROUND (2.0 * axis - position); + + switch (gimp_guide_get_orientation (guide)) + { + case GIMP_ORIENTATION_HORIZONTAL: + if (flip_type == GIMP_ORIENTATION_VERTICAL) + { + if (position >= 0 && position <= height) + gimp_image_move_guide (image, guide, position, TRUE); + else + gimp_image_remove_guide (image, guide, TRUE); + } + break; + + case GIMP_ORIENTATION_VERTICAL: + if (flip_type == GIMP_ORIENTATION_HORIZONTAL) + { + if (position >= 0 && position <= width) + gimp_image_move_guide (image, guide, position, TRUE); + else + gimp_image_remove_guide (image, guide, TRUE); + } + break; + + case GIMP_ORIENTATION_UNKNOWN: + g_return_if_reached (); + } + } +} + +static void +gimp_image_flip_sample_points (GimpImage *image, + GimpOrientationType flip_type, + gdouble axis) +{ + gint width = gimp_image_get_width (image); + gint height = gimp_image_get_height (image); + GList *iter; + + for (iter = gimp_image_get_sample_points (image); iter;) + { + GimpSamplePoint *sample_point = iter->data; + gint x; + gint y; + + iter = g_list_next (iter); + + gimp_sample_point_get_position (sample_point, &x, &y); + + switch (flip_type) + { + case GIMP_ORIENTATION_HORIZONTAL: + x = SIGNED_ROUND (2.0 * axis - x); + break; + + case GIMP_ORIENTATION_VERTICAL: + y = SIGNED_ROUND (2.0 * axis - y); + break; + + case GIMP_ORIENTATION_UNKNOWN: + g_return_if_reached (); + } + + if (x >= 0 && x < width && + y >= 0 && y < height) + { + gimp_image_move_sample_point (image, sample_point, x, y, TRUE); + } + else + { + gimp_image_remove_sample_point (image, sample_point, TRUE); + } + } +} + + +/* public functions */ + void gimp_image_flip (GimpImage *image, GimpContext *context, GimpOrientationType flip_type, GimpProgress *progress) { - GimpObjectQueue *queue; - GimpItem *item; - GList *list; - gdouble axis; + gdouble axis = 0.0; g_return_if_fail (GIMP_IS_IMAGE (image)); g_return_if_fail (GIMP_IS_CONTEXT (context)); g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress)); - gimp_set_busy (image->gimp); - switch (flip_type) { case GIMP_ORIENTATION_HORIZONTAL: - axis = (gdouble) gimp_image_get_width (image) / 2.0; + axis = gimp_image_get_width (image) / 2.0; break; case GIMP_ORIENTATION_VERTICAL: - axis = (gdouble) gimp_image_get_height (image) / 2.0; + axis = gimp_image_get_height (image) / 2.0; break; - default: - g_warning ("%s: unknown flip_type", G_STRFUNC); - return; + case GIMP_ORIENTATION_UNKNOWN: + g_return_if_reached (); } + gimp_image_flip_full (image, context, flip_type, axis, + GIMP_TRANSFORM_RESIZE_CLIP, progress); +} + +void +gimp_image_flip_full (GimpImage *image, + GimpContext *context, + GimpOrientationType flip_type, + gdouble axis, + gboolean clip_result, + GimpProgress *progress) +{ + GimpObjectQueue *queue; + GimpItem *item; + gint width; + gint height; + gint offset_x = 0; + gint offset_y = 0; + + g_return_if_fail (GIMP_IS_IMAGE (image)); + g_return_if_fail (GIMP_IS_CONTEXT (context)); + g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress)); + + width = gimp_image_get_width (image); + height = gimp_image_get_height (image); + + if (! clip_result) + { + switch (flip_type) + { + case GIMP_ORIENTATION_HORIZONTAL: + offset_x = SIGNED_ROUND (2.0 * axis - width); + axis = width / 2.0; + break; + + case GIMP_ORIENTATION_VERTICAL: + offset_y = SIGNED_ROUND (2.0 * axis - height); + axis = height / 2.0; + break; + + case GIMP_ORIENTATION_UNKNOWN: + g_return_if_reached (); + } + } + + gimp_set_busy (image->gimp); + queue = gimp_object_queue_new (progress); progress = GIMP_PROGRESS (queue); @@ -83,67 +233,44 @@ gimp_image_flip (GimpImage *image, /* Flip all layers, channels (including selection mask), and vectors */ while ((item = gimp_object_queue_pop (queue))) { - gimp_item_flip (item, context, flip_type, axis, FALSE); + gboolean clip = FALSE; + + if (GIMP_IS_CHANNEL (item)) + clip = clip_result; + + gimp_item_flip (item, context, flip_type, axis, clip); gimp_progress_set_value (progress, 1.0); } /* Flip all Guides */ - for (list = gimp_image_get_guides (image); - list; - list = g_list_next (list)) - { - GimpGuide *guide = list->data; - gint position = gimp_guide_get_position (guide); - - switch (gimp_guide_get_orientation (guide)) - { - case GIMP_ORIENTATION_HORIZONTAL: - if (flip_type == GIMP_ORIENTATION_VERTICAL) - gimp_image_move_guide (image, guide, - gimp_image_get_height (image) - position, - TRUE); - break; - - case GIMP_ORIENTATION_VERTICAL: - if (flip_type == GIMP_ORIENTATION_HORIZONTAL) - gimp_image_move_guide (image, guide, - gimp_image_get_width (image) - position, - TRUE); - break; - - default: - break; - } - } + gimp_image_flip_guides (image, flip_type, axis); /* Flip all sample points */ - for (list = gimp_image_get_sample_points (image); - list; - list = g_list_next (list)) + gimp_image_flip_sample_points (image, flip_type, axis); + + if (offset_x || offset_y) { - GimpSamplePoint *sample_point = list->data; - gint x; - gint y; - - gimp_sample_point_get_position (sample_point, &x, &y); - - if (flip_type == GIMP_ORIENTATION_VERTICAL) - gimp_image_move_sample_point (image, sample_point, - x, - gimp_image_get_height (image) - y, - TRUE); - - if (flip_type == GIMP_ORIENTATION_HORIZONTAL) - gimp_image_move_sample_point (image, sample_point, - gimp_image_get_width (image) - x, - y, - TRUE); + gimp_image_undo_push_image_size (image, + NULL, + offset_x, + offset_y, + width, + height); } gimp_image_undo_group_end (image); g_object_unref (queue); + if (offset_x || offset_y) + { + gimp_image_size_changed_detailed (image, + -offset_x, + -offset_y, + width, + height); + } + gimp_unset_busy (image->gimp); } diff --git a/app/core/gimpimage-flip.h b/app/core/gimpimage-flip.h index 0ab220f3d2..5fa6ce6046 100644 --- a/app/core/gimpimage-flip.h +++ b/app/core/gimpimage-flip.h @@ -19,10 +19,16 @@ #define __GIMP_IMAGE_FLIP_H__ -void gimp_image_flip (GimpImage *image, - GimpContext *context, - GimpOrientationType flip_type, - GimpProgress *progress); +void gimp_image_flip (GimpImage *image, + GimpContext *context, + GimpOrientationType flip_type, + GimpProgress *progress); +void gimp_image_flip_full (GimpImage *image, + GimpContext *context, + GimpOrientationType flip_type, + gdouble axis, + gboolean clip_result, + GimpProgress *progress); #endif /* __GIMP_IMAGE_FLIP_H__ */