[gimp] app: add a GimpFilterStack to each GimpDrawable



commit f3308e6ba3c6379075d7ea5938578c07a22db739
Author: Michael Natterer <mitch gimp org>
Date:   Thu Apr 11 19:06:23 2013 +0200

    app: add a GimpFilterStack to each GimpDrawable
    
    which is part of the drawable's source_node, so we can generically
    filter a drawable's pixels. Reading from the source_node will
    transparently give the filtered results.
    
    Turn floating selection compositing into a GimpFilter and add it to
    the filter stack while we have a floating selection on the drawable.

 app/core/gimpdrawable-private.h |    2 +
 app/core/gimpdrawable.c         |  157 ++++++++++++++++++++++++---------------
 2 files changed, 100 insertions(+), 59 deletions(-)
---
diff --git a/app/core/gimpdrawable-private.h b/app/core/gimpdrawable-private.h
index bfe9d38..db1c5ab 100644
--- a/app/core/gimpdrawable-private.h
+++ b/app/core/gimpdrawable-private.h
@@ -25,8 +25,10 @@ struct _GimpDrawablePrivate
 
   GeglNode      *source_node;
   GeglNode      *buffer_source_node;
+  GimpContainer *filter_stack;
 
   GimpLayer     *floating_selection;
+  GimpFilter    *fs_filter;
   GeglNode      *fs_crop_node;
   GeglNode      *fs_offset_node;
   GeglNode      *fs_mode_node;
diff --git a/app/core/gimpdrawable.c b/app/core/gimpdrawable.c
index 3e12212..8862f5a 100644
--- a/app/core/gimpdrawable.c
+++ b/app/core/gimpdrawable.c
@@ -40,6 +40,7 @@
 #include "gimpdrawable-private.h"
 #include "gimpdrawable-shadow.h"
 #include "gimpdrawable-transform.h"
+#include "gimpfilterstack.h"
 #include "gimpimage.h"
 #include "gimpimage-colormap.h"
 #include "gimpimage-undo-push.h"
@@ -172,7 +173,7 @@ static void       gimp_drawable_real_swap_pixels   (GimpDrawable      *drawable,
                                                     gint               x,
                                                     gint               y);
 
-static void       gimp_drawable_sync_source_node   (GimpDrawable      *drawable,
+static void       gimp_drawable_sync_fs_filter     (GimpDrawable      *drawable,
                                                     gboolean           detach_fs);
 static void       gimp_drawable_fs_notify          (GimpLayer         *fs,
                                                     const GParamSpec  *pspec,
@@ -269,6 +270,8 @@ gimp_drawable_init (GimpDrawable *drawable)
   drawable->private = G_TYPE_INSTANCE_GET_PRIVATE (drawable,
                                                    GIMP_TYPE_DRAWABLE,
                                                    GimpDrawablePrivate);
+
+  drawable->private->filter_stack = gimp_filter_stack_new (GIMP_TYPE_FILTER);
 }
 
 /* sorry for the evil casts */
@@ -313,6 +316,12 @@ gimp_drawable_finalize (GObject *object)
       drawable->private->source_node = NULL;
     }
 
+  if (drawable->private->filter_stack)
+    {
+      g_object_unref (drawable->private->filter_stack);
+      drawable->private->filter_stack = NULL;
+    }
+
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -887,24 +896,71 @@ gimp_drawable_real_swap_pixels (GimpDrawable *drawable,
   gimp_drawable_update (drawable, x, y, width, height);
 }
 
+static GimpFilter *
+gimp_drawable_create_fs_filter (GimpDrawable *drawable,
+                                GimpDrawable *fs)
+{
+  GimpFilter *filter;
+  GeglNode   *node;
+  GeglNode   *input;
+  GeglNode   *output;
+  GeglNode   *fs_source;
+
+  filter = gimp_filter_new ("Floating Selection");
+
+  node = gimp_filter_get_node (filter);
+
+  input  = gegl_node_get_input_proxy  (node, "input");
+  output = gegl_node_get_output_proxy (node, "output");
+
+  fs_source = gimp_drawable_get_source_node (fs);
+
+  drawable->private->fs_crop_node =
+    gegl_node_new_child (node,
+                         "operation", "gegl:crop",
+                         NULL);
+
+  gegl_node_connect_to (fs_source,                       "output",
+                        drawable->private->fs_crop_node, "input");
+
+  drawable->private->fs_offset_node =
+    gegl_node_new_child (node,
+                         "operation", "gegl:translate",
+                         NULL);
+
+  gegl_node_connect_to (drawable->private->fs_crop_node,   "output",
+                        drawable->private->fs_offset_node, "input");
+
+  drawable->private->fs_mode_node =
+    gegl_node_new_child (node,
+                         "operation", "gimp:normal-mode",
+                         NULL);
+
+  gegl_node_connect_to (input,                             "output",
+                        drawable->private->fs_mode_node,   "input");
+  gegl_node_connect_to (drawable->private->fs_offset_node, "output",
+                        drawable->private->fs_mode_node,   "aux");
+  gegl_node_connect_to (drawable->private->fs_mode_node,   "output",
+                        output,                            "input");
+
+  return filter;
+}
+
 static void
-gimp_drawable_sync_source_node (GimpDrawable *drawable,
-                                gboolean      detach_fs)
+gimp_drawable_sync_fs_filter (GimpDrawable *drawable,
+                              gboolean      detach_fs)
 {
   GimpLayer *fs = gimp_drawable_get_floating_sel (drawable);
-  GeglNode  *output;
 
   if (! drawable->private->source_node)
     return;
 
-  output = gegl_node_get_output_proxy (drawable->private->source_node, "output");
-
   if (fs && ! detach_fs)
     {
       gint off_x, off_y;
       gint fs_off_x, fs_off_y;
 
-      if (! drawable->private->fs_crop_node)
+      if (! drawable->private->fs_filter)
         {
           GeglNode *fs_source;
 
@@ -920,34 +976,11 @@ gimp_drawable_sync_source_node (GimpDrawable *drawable,
 
           gegl_node_add_child (drawable->private->source_node, fs_source);
 
-          drawable->private->fs_crop_node =
-            gegl_node_new_child (drawable->private->source_node,
-                                 "operation", "gegl:crop",
-                                 NULL);
-
-          gegl_node_connect_to (fs_source,                       "output",
-                                drawable->private->fs_crop_node, "input");
-
-          drawable->private->fs_offset_node =
-            gegl_node_new_child (drawable->private->source_node,
-                                 "operation", "gegl:translate",
-                                 NULL);
-
-          gegl_node_connect_to (drawable->private->fs_crop_node,   "output",
-                                drawable->private->fs_offset_node, "input");
+          drawable->private->fs_filter =
+            gimp_drawable_create_fs_filter (drawable, GIMP_DRAWABLE (fs));
 
-          drawable->private->fs_mode_node =
-            gegl_node_new_child (drawable->private->source_node,
-                                 "operation", "gimp:normal-mode",
-                                 NULL);
-
-          gegl_node_connect_to (drawable->private->buffer_source_node, "output",
-                                drawable->private->fs_mode_node,       "input");
-          gegl_node_connect_to (drawable->private->fs_offset_node,     "output",
-                                drawable->private->fs_mode_node,       "aux");
-
-          gegl_node_connect_to (drawable->private->fs_mode_node, "output",
-                                output,                          "input");
+          gimp_container_add (drawable->private->filter_stack,
+                              GIMP_OBJECT (drawable->private->fs_filter));
 
           g_signal_connect (fs, "notify",
                             G_CALLBACK (gimp_drawable_fs_notify),
@@ -976,16 +1009,19 @@ gimp_drawable_sync_source_node (GimpDrawable *drawable,
     }
   else
     {
-      if (drawable->private->fs_crop_node)
+      if (drawable->private->fs_filter)
         {
           GeglNode *fs_source;
 
-          gegl_node_disconnect (drawable->private->fs_crop_node, "input");
-          gegl_node_disconnect (drawable->private->fs_offset_node, "input");
-          gegl_node_disconnect (drawable->private->fs_mode_node, "input");
-          gegl_node_disconnect (drawable->private->fs_mode_node, "aux");
+          g_signal_handlers_disconnect_by_func (fs,
+                                                gimp_drawable_fs_notify,
+                                                drawable);
+
+          gimp_container_remove (drawable->private->filter_stack,
+                                 GIMP_OBJECT (drawable->private->fs_filter));
 
           fs_source = gimp_drawable_get_source_node (GIMP_DRAWABLE (fs));
+
           gegl_node_remove_child (drawable->private->source_node,
                                   fs_source);
 
@@ -998,25 +1034,13 @@ gimp_drawable_sync_source_node (GimpDrawable *drawable,
                                     fs->layer_offset_node, "input");
             }
 
-          gegl_node_remove_child (drawable->private->source_node,
-                                  drawable->private->fs_crop_node);
-          drawable->private->fs_crop_node = NULL;
+          g_object_unref (drawable->private->fs_filter);
+          drawable->private->fs_filter = NULL;
 
-          gegl_node_remove_child (drawable->private->source_node,
-                                  drawable->private->fs_offset_node);
+          drawable->private->fs_crop_node   = NULL;
           drawable->private->fs_offset_node = NULL;
-
-          gegl_node_remove_child (drawable->private->source_node,
-                                  drawable->private->fs_mode_node);
-          drawable->private->fs_mode_node = NULL;
-
-          g_signal_handlers_disconnect_by_func (fs,
-                                                gimp_drawable_fs_notify,
-                                                drawable);
+          drawable->private->fs_mode_node   = NULL;
         }
-
-      gegl_node_connect_to (drawable->private->buffer_source_node, "output",
-                            output,                                "input");
     }
 }
 
@@ -1031,7 +1055,7 @@ gimp_drawable_fs_notify (GimpLayer        *fs,
       ! strcmp (pspec->name, "mode")     ||
       ! strcmp (pspec->name, "opacity"))
     {
-      gimp_drawable_sync_source_node (drawable, FALSE);
+      gimp_drawable_sync_fs_filter (drawable, FALSE);
     }
 }
 
@@ -1335,6 +1359,9 @@ gimp_drawable_set_buffer_full (GimpDrawable *drawable,
 GeglNode *
 gimp_drawable_get_source_node (GimpDrawable *drawable)
 {
+  GeglNode *filter;
+  GeglNode *output;
+
   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
 
   if (drawable->private->source_node)
@@ -1348,7 +1375,19 @@ gimp_drawable_get_source_node (GimpDrawable *drawable)
                          "buffer",    gimp_drawable_get_buffer (drawable),
                          NULL);
 
-  gimp_drawable_sync_source_node (drawable, FALSE);
+  filter = gimp_filter_stack_get_graph (GIMP_FILTER_STACK (drawable->private->filter_stack));
+
+  gegl_node_add_child (drawable->private->source_node, filter);
+
+  gegl_node_connect_to (drawable->private->buffer_source_node, "output",
+                        filter,                                "input");
+
+  output = gegl_node_get_output_proxy (drawable->private->source_node, "output");
+
+  gegl_node_connect_to (filter, "output",
+                        output, "input");
+
+  gimp_drawable_sync_fs_filter (drawable, FALSE);
 
   return drawable->private->source_node;
 }
@@ -1622,7 +1661,7 @@ gimp_drawable_attach_floating_sel (GimpDrawable *drawable,
   /*  clear the selection  */
   gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (floating_sel));
 
-  gimp_drawable_sync_source_node (drawable, FALSE);
+  gimp_drawable_sync_fs_filter (drawable, FALSE);
 
   g_signal_connect (floating_sel, "update",
                     G_CALLBACK (gimp_drawable_fs_update),
@@ -1649,7 +1688,7 @@ gimp_drawable_detach_floating_sel (GimpDrawable *drawable)
   image        = gimp_item_get_image (GIMP_ITEM (drawable));
   floating_sel = drawable->private->floating_selection;
 
-  gimp_drawable_sync_source_node (drawable, TRUE);
+  gimp_drawable_sync_fs_filter (drawable, TRUE);
 
   g_signal_handlers_disconnect_by_func (floating_sel,
                                         gimp_drawable_fs_update,


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