[gimp] app: make gimp_gegl_apply_cached_operation() cancelable via GimpProgress



commit 16381c9bf9ecfcd7d99b08672a38c1559a42eb52
Author: Michael Natterer <mitch gimp org>
Date:   Mon Jun 30 00:10:25 2014 +0200

    app: make gimp_gegl_apply_cached_operation() cancelable via GimpProgress
    
    In gimp_drawable_merge_filter(), use that feature to make filter
    applying cancelable. Stop projection rendering first, because we have
    to run the event loop manually in order to receive input for
    canceling, but we don't want the projection to be constructed from
    that manual loop running.

 app/core/gimpdrawable-filter.c       |   75 +++++++++++++++++++++++----------
 app/gegl/gimp-gegl-apply-operation.c |   63 ++++++++++++++++++++++------
 app/gegl/gimp-gegl-apply-operation.h |   33 ++++++++-------
 3 files changed, 118 insertions(+), 53 deletions(-)
---
diff --git a/app/core/gimpdrawable-filter.c b/app/core/gimpdrawable-filter.c
index 82a091e..4e1a0a6 100644
--- a/app/core/gimpdrawable-filter.c
+++ b/app/core/gimpdrawable-filter.c
@@ -33,8 +33,10 @@
 #include "gimpdrawableundo.h"
 #include "gimpfilter.h"
 #include "gimpfilterstack.h"
+#include "gimpimage.h"
 #include "gimpimage-undo.h"
 #include "gimpprogress.h"
+#include "gimpprojection.h"
 
 
 GimpContainer *
@@ -96,33 +98,27 @@ gimp_drawable_merge_filter (GimpDrawable *drawable,
                                 &rect.x, &rect.y,
                                 &rect.width, &rect.height))
     {
+      GimpImage      *image   = gimp_item_get_image (GIMP_ITEM (drawable));
+      GeglBuffer     *undo_buffer;
       GimpApplicator *applicator;
       GeglBuffer     *cache   = NULL;
       GeglRectangle  *rects   = NULL;
       gint            n_rects = 0;
 
-      gimp_drawable_push_undo (drawable, undo_desc, NULL,
-                               rect.x, rect.y,
-                               rect.width, rect.height);
+      undo_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0,
+                                                     rect.width, rect.height),
+                                     gimp_drawable_get_format (drawable));
+
+      gegl_buffer_copy (gimp_drawable_get_buffer (drawable),
+                        GEGL_RECTANGLE (rect.x, rect.y,
+                                        rect.width, rect.height),
+                        undo_buffer,
+                        GEGL_RECTANGLE (0, 0, 0, 0));
 
       applicator = gimp_filter_get_applicator (filter);
 
       if (applicator)
         {
-          GimpImage        *image = gimp_item_get_image (GIMP_ITEM (drawable));
-          GimpDrawableUndo *undo;
-
-          undo = GIMP_DRAWABLE_UNDO (gimp_image_undo_get_fadeable (image));
-
-          if (undo)
-            {
-              undo->paint_mode = applicator->paint_mode;
-              undo->opacity    = applicator->opacity;
-
-              undo->applied_buffer =
-                gimp_applicator_dup_apply_buffer (applicator, &rect);
-            }
-
           cache = gimp_applicator_get_cache_buffer (applicator,
                                                     &rects, &n_rects);
 
@@ -137,12 +133,45 @@ gimp_drawable_merge_filter (GimpDrawable *drawable,
             }
         }
 
-      gimp_gegl_apply_cached_operation (gimp_drawable_get_buffer (drawable),
-                                        progress, undo_desc,
-                                        gimp_filter_get_node (filter),
-                                        gimp_drawable_get_buffer (drawable),
-                                        &rect,
-                                        cache, rects, n_rects);
+      gimp_projection_stop_rendering (gimp_image_get_projection (image));
+
+      if (gimp_gegl_apply_cached_operation (gimp_drawable_get_buffer (drawable),
+                                            progress, undo_desc,
+                                            gimp_filter_get_node (filter),
+                                            gimp_drawable_get_buffer (drawable),
+                                            &rect,
+                                            cache, rects, n_rects,
+                                            TRUE))
+        {
+          gimp_drawable_push_undo (drawable, undo_desc, undo_buffer,
+                                   rect.x, rect.y,
+                                   rect.width, rect.height);
+
+          if (applicator)
+            {
+              GimpDrawableUndo *undo;
+
+              undo = GIMP_DRAWABLE_UNDO (gimp_image_undo_get_fadeable (image));
+
+              if (undo)
+                {
+                  undo->paint_mode = applicator->paint_mode;
+                  undo->opacity    = applicator->opacity;
+
+                  undo->applied_buffer =
+                    gimp_applicator_dup_apply_buffer (applicator, &rect);
+                }
+            }
+        }
+      else
+        {
+          gegl_buffer_copy (undo_buffer,
+                            GEGL_RECTANGLE (0, 0, rect.width, rect.height),
+                            gimp_drawable_get_buffer (drawable),
+                            GEGL_RECTANGLE (rect.x, rect.y, 0, 0));
+        }
+
+      g_object_unref (undo_buffer);
 
       if (cache)
         {
diff --git a/app/gegl/gimp-gegl-apply-operation.c b/app/gegl/gimp-gegl-apply-operation.c
index b31326a..310f464 100644
--- a/app/gegl/gimp-gegl-apply-operation.c
+++ b/app/gegl/gimp-gegl-apply-operation.c
@@ -48,10 +48,18 @@ gimp_gegl_apply_operation (GeglBuffer          *src_buffer,
                                     operation,
                                     dest_buffer,
                                     dest_rect,
-                                    NULL, NULL, 0);
+                                    NULL, NULL, 0,
+                                    FALSE);
 }
 
-void
+static void
+gimp_gegl_apply_operation_cancel (GimpProgress *progress,
+                                  gboolean     *cancel)
+{
+  *cancel = TRUE;
+}
+
+gboolean
 gimp_gegl_apply_cached_operation (GeglBuffer          *src_buffer,
                                   GimpProgress        *progress,
                                   const gchar         *undo_desc,
@@ -60,14 +68,16 @@ gimp_gegl_apply_cached_operation (GeglBuffer          *src_buffer,
                                   const GeglRectangle *dest_rect,
                                   GeglBuffer          *cache,
                                   const GeglRectangle *valid_rects,
-                                  gint                 n_valid_rects)
+                                  gint                 n_valid_rects,
+                                  gboolean             cancelable)
 {
   GeglNode      *gegl;
   GeglNode      *dest_node;
   GeglRectangle  rect = { 0, };
-  GeglProcessor *processor       = NULL;
-  gboolean       progress_active = FALSE;
+  GeglProcessor *processor        = NULL;
+  gboolean       progress_started = FALSE;
   gdouble        value;
+  gboolean       cancel           = FALSE;
 
   g_return_if_fail (src_buffer == NULL || GEGL_IS_BUFFER (src_buffer));
   g_return_if_fail (progress == NULL || GIMP_IS_PROGRESS (progress));
@@ -127,16 +137,24 @@ gimp_gegl_apply_cached_operation (GeglBuffer          *src_buffer,
     {
       processor = gegl_node_new_processor (dest_node, &rect);
 
-      progress_active = gimp_progress_is_active (progress);
-
-      if (progress_active)
+      if (gimp_progress_is_active (progress))
         {
           if (undo_desc)
             gimp_progress_set_text (progress, undo_desc);
+
+          progress_started = FALSE;
+          cancelable       = FALSE;
         }
       else
         {
-          gimp_progress_start (progress, undo_desc, FALSE);
+          gimp_progress_start (progress, undo_desc, cancelable);
+
+          if (cancelable)
+            g_signal_connect (progress, "cancel",
+                              G_CALLBACK (gimp_gegl_apply_operation_cancel),
+                              &cancel);
+
+          progress_started = TRUE;
         }
     }
 
@@ -171,7 +189,7 @@ gimp_gegl_apply_cached_operation (GeglBuffer          *src_buffer,
 
       n_rects = cairo_region_num_rectangles (region);
 
-      for (i = 0; i < n_rects; i++)
+      for (i = 0; ! cancel && (i < n_rects); i++)
         {
           cairo_rectangle_int_t render_rect;
 
@@ -190,12 +208,16 @@ gimp_gegl_apply_cached_operation (GeglBuffer          *src_buffer,
                                                    (GeglRectangle *) &render_rect);
 #endif
 
-              while (gegl_processor_work (processor, &value))
+              while (! cancel && gegl_processor_work (processor, &value))
                 {
                   gimp_progress_set_value (progress,
                                            ((gdouble) done_pixels +
                                             value * rect_pixels) /
                                            (gdouble) all_pixels);
+
+                  if (cancelable)
+                    while (! cancel && g_main_context_pending (NULL))
+                      g_main_context_iteration (NULL, FALSE);
                 }
 
               done_pixels += rect_pixels;
@@ -213,9 +235,13 @@ gimp_gegl_apply_cached_operation (GeglBuffer          *src_buffer,
     {
       if (progress)
         {
-          while (gegl_processor_work (processor, &value))
+          while (! cancel && gegl_processor_work (processor, &value))
             {
               gimp_progress_set_value (progress, value);
+
+              if (cancelable)
+                while (! cancel && g_main_context_pending (NULL))
+                  g_main_context_iteration (NULL, FALSE);
             }
         }
       else
@@ -230,8 +256,17 @@ gimp_gegl_apply_cached_operation (GeglBuffer          *src_buffer,
 
   g_object_unref (gegl);
 
-  if (progress && ! progress_active)
-    gimp_progress_end (progress);
+  if (progress_started)
+    {
+      gimp_progress_end (progress);
+
+      if (cancelable)
+        g_signal_handlers_disconnect_by_func (progress,
+                                              gimp_gegl_apply_operation_cancel,
+                                              &cancel);
+    }
+
+  return ! cancel;
 }
 
 void
diff --git a/app/gegl/gimp-gegl-apply-operation.h b/app/gegl/gimp-gegl-apply-operation.h
index b67e9c6..fa29068 100644
--- a/app/gegl/gimp-gegl-apply-operation.h
+++ b/app/gegl/gimp-gegl-apply-operation.h
@@ -26,22 +26,23 @@
 
 /*  generic functions, also used by the specific ones below  */
 
-void   gimp_gegl_apply_operation        (GeglBuffer           *src_buffer,
-                                         GimpProgress         *progress,
-                                         const gchar          *undo_desc,
-                                         GeglNode             *operation,
-                                         GeglBuffer           *dest_buffer,
-                                         const GeglRectangle  *dest_rect);
-
-void   gimp_gegl_apply_cached_operation (GeglBuffer           *src_buffer,
-                                         GimpProgress         *progress,
-                                         const gchar          *undo_desc,
-                                         GeglNode             *operation,
-                                         GeglBuffer           *dest_buffer,
-                                         const GeglRectangle  *dest_rect,
-                                         GeglBuffer           *cache,
-                                         const GeglRectangle  *valid_rects,
-                                         gint                  n_valid_rects);
+void       gimp_gegl_apply_operation        (GeglBuffer          *src_buffer,
+                                             GimpProgress        *progress,
+                                             const gchar         *undo_desc,
+                                             GeglNode            *operation,
+                                             GeglBuffer          *dest_buffer,
+                                             const GeglRectangle *dest_rect);
+
+gboolean   gimp_gegl_apply_cached_operation (GeglBuffer          *src_buffer,
+                                             GimpProgress        *progress,
+                                             const gchar         *undo_desc,
+                                             GeglNode            *operation,
+                                             GeglBuffer          *dest_buffer,
+                                             const GeglRectangle *dest_rect,
+                                             GeglBuffer          *cache,
+                                             const GeglRectangle *valid_rects,
+                                             gint                 n_valid_rects,
+                                             gboolean             cancelable);
 
 
 /*  apply specific operations  */


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