[gimp] app: add gimp_image_flip_full()



commit ae080f06f9934d83a4acb1ef83d126d805b4baad
Author: Ell <ell_se yahoo com>
Date:   Sat Aug 10 22:48:49 2019 +0300

    app: add gimp_image_flip_full()
    
    ... which takes the symmetry axis as a parameter, instead of hard-
    coding the axis to the middle of the image, and which additionally
    takes the clipping mode as a parameter, controlling whether to clip
    or resize the canvas.  Note that the actual canvas size never
    changes, but it may be offset when flipped around an off-center
    axis, without clipping.
    
    Implement gimp_image_flip() in terms of gimp_image_flip_full().

 app/core/gimpimage-flip.c | 245 +++++++++++++++++++++++++++++++++++-----------
 app/core/gimpimage-flip.h |  14 ++-
 2 files changed, 196 insertions(+), 63 deletions(-)
---
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 <gdk-pixbuf/gdk-pixbuf.h>
 #include <gegl.h>
 
+#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))
-    {
-      GimpSamplePoint *sample_point = list->data;
-      gint             x;
-      gint             y;
+  gimp_image_flip_sample_points (image, flip_type, axis);
 
-      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);
+  if (offset_x || offset_y)
+    {
+      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__ */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]