[gimp/soc-2011-seamless-clone2] app: add new class GimpFilter as parent class of GimpItem



commit b09deab53fe6c1071c951a52b4d29c64e51a5082
Author: Michael Natterer <mitch gimp org>
Date:   Thu Apr 11 02:54:42 2013 +0200

    app: add new class GimpFilter as parent class of GimpItem
    
    and move the item's GeglNode API there. The purpose of this is to
    factor out "gimp object that manages a node".

 app/core/Makefile.am         |    2 +
 app/core/core-types.h        |    1 +
 app/core/gimpchannel.c       |  133 +++++++++++++++--------------
 app/core/gimpdrawable.c      |   89 ++++++++++----------
 app/core/gimpdrawablestack.c |   18 ++--
 app/core/gimpfilter.c        |  136 ++++++++++++++++++++++++++++++
 app/core/gimpfilter.h        |   56 ++++++++++++
 app/core/gimpitem.c          |   71 +++-------------
 app/core/gimpitem.h          |   11 +--
 app/core/gimplayer.c         |  189 +++++++++++++++++++++---------------------
 10 files changed, 431 insertions(+), 275 deletions(-)
---
diff --git a/app/core/Makefile.am b/app/core/Makefile.am
index 510cc96..069c5a2 100644
--- a/app/core/Makefile.am
+++ b/app/core/Makefile.am
@@ -163,6 +163,8 @@ libappcore_a_sources = \
        gimperror.h                             \
        gimpfilloptions.c                       \
        gimpfilloptions.h                       \
+       gimpfilter.c                            \
+       gimpfilter.h                            \
        gimpfilteredcontainer.c                 \
        gimpfilteredcontainer.h                 \
        gimpfloatingselundo.c                   \
diff --git a/app/core/core-types.h b/app/core/core-types.h
index 7f9df47..0926318 100644
--- a/app/core/core-types.h
+++ b/app/core/core-types.h
@@ -77,6 +77,7 @@
 
 typedef struct _GimpObject          GimpObject;
 typedef struct _GimpViewable        GimpViewable;
+typedef struct _GimpFilter          GimpFilter;
 typedef struct _GimpItem            GimpItem;
 
 typedef struct _Gimp                Gimp;
diff --git a/app/core/gimpchannel.c b/app/core/gimpchannel.c
index d6011c2..d719fec 100644
--- a/app/core/gimpchannel.c
+++ b/app/core/gimpchannel.c
@@ -72,6 +72,8 @@ static gint64     gimp_channel_get_memsize   (GimpObject        *object,
 static gchar  * gimp_channel_get_description (GimpViewable      *viewable,
                                               gchar            **tooltip);
 
+static GeglNode * gimp_channel_get_node      (GimpFilter        *filter);
+
 static gboolean   gimp_channel_is_attached   (const GimpItem    *item);
 static GimpItemTree * gimp_channel_get_tree  (GimpItem          *item);
 static GimpItem * gimp_channel_duplicate     (GimpItem          *item,
@@ -167,7 +169,6 @@ static void      gimp_channel_set_buffer     (GimpDrawable        *drawable,
                                               GeglBuffer          *buffer,
                                               gint                 offset_x,
                                               gint                 offset_y);
-static GeglNode * gimp_channel_get_node      (GimpItem            *item);
 static void      gimp_channel_swap_pixels    (GimpDrawable        *drawable,
                                               GeglBuffer          *buffer,
                                               gint                 x,
@@ -237,6 +238,7 @@ gimp_channel_class_init (GimpChannelClass *klass)
   GObjectClass      *object_class      = G_OBJECT_CLASS (klass);
   GimpObjectClass   *gimp_object_class = GIMP_OBJECT_CLASS (klass);
   GimpViewableClass *viewable_class    = GIMP_VIEWABLE_CLASS (klass);
+  GimpFilterClass   *filter_class      = GIMP_FILTER_CLASS (klass);
   GimpItemClass     *item_class        = GIMP_ITEM_CLASS (klass);
   GimpDrawableClass *drawable_class    = GIMP_DRAWABLE_CLASS (klass);
 
@@ -256,6 +258,8 @@ gimp_channel_class_init (GimpChannelClass *klass)
   viewable_class->get_description  = gimp_channel_get_description;
   viewable_class->default_stock_id = "gimp-channel";
 
+  filter_class->get_node           = gimp_channel_get_node;
+
   item_class->is_attached          = gimp_channel_is_attached;
   item_class->get_tree             = gimp_channel_get_tree;
   item_class->duplicate            = gimp_channel_duplicate;
@@ -268,7 +272,6 @@ gimp_channel_class_init (GimpChannelClass *klass)
   item_class->transform            = gimp_channel_transform;
   item_class->stroke               = gimp_channel_stroke;
   item_class->to_selection         = gimp_channel_to_selection;
-  item_class->get_node             = gimp_channel_get_node;
   item_class->default_name         = _("Channel");
   item_class->rename_desc          = C_("undo-type", "Rename Channel");
   item_class->translate_desc       = C_("undo-type", "Move Channel");
@@ -391,6 +394,67 @@ gimp_channel_get_description (GimpViewable  *viewable,
                                                               tooltip);
 }
 
+static GeglNode *
+gimp_channel_get_node (GimpFilter *filter)
+{
+  GimpDrawable *drawable = GIMP_DRAWABLE (filter);
+  GimpChannel  *channel  = GIMP_CHANNEL (filter);
+  GeglNode     *node;
+  GeglNode     *source;
+  GeglNode     *mode_node;
+  GeglColor    *color;
+
+  node = GIMP_FILTER_CLASS (parent_class)->get_node (filter);
+
+  source = gimp_drawable_get_source_node (drawable);
+  gegl_node_add_child (node, source);
+
+  color = gimp_gegl_color_new (&channel->color);
+
+  g_warn_if_fail (channel->color_node == NULL);
+
+  channel->color_node = gegl_node_new_child (node,
+                                             "operation", "gegl:color",
+                                             "value",     color,
+                                             NULL);
+
+  g_object_unref (color);
+
+  g_warn_if_fail (channel->mask_node == NULL);
+
+  channel->mask_node = gegl_node_new_child (node,
+                                            "operation", "gegl:opacity",
+                                            NULL);
+  gegl_node_connect_to (channel->color_node, "output",
+                        channel->mask_node,  "input");
+
+  g_warn_if_fail (channel->invert_node == NULL);
+
+  channel->invert_node = gegl_node_new_child (node,
+                                              "operation", "gegl:invert",
+                                              NULL);
+
+  if (channel->show_masked)
+    {
+      gegl_node_connect_to (source,               "output",
+                            channel->invert_node, "input");
+      gegl_node_connect_to (channel->invert_node, "output",
+                            channel->mask_node,   "aux");
+    }
+  else
+    {
+      gegl_node_connect_to (source,             "output",
+                            channel->mask_node, "aux");
+    }
+
+  mode_node = gimp_drawable_get_mode_node (drawable);
+
+  gegl_node_connect_to (channel->mask_node, "output",
+                        mode_node,          "aux");
+
+  return node;
+}
+
 static gboolean
 gimp_channel_is_attached (const GimpItem *item)
 {
@@ -916,67 +980,6 @@ gimp_channel_set_buffer (GimpDrawable *drawable,
   GIMP_CHANNEL (drawable)->bounds_known = FALSE;
 }
 
-static GeglNode *
-gimp_channel_get_node (GimpItem *item)
-{
-  GimpDrawable *drawable = GIMP_DRAWABLE (item);
-  GimpChannel  *channel  = GIMP_CHANNEL (item);
-  GeglNode     *node;
-  GeglNode     *source;
-  GeglNode     *mode_node;
-  GeglColor    *color;
-
-  node = GIMP_ITEM_CLASS (parent_class)->get_node (item);
-
-  source = gimp_drawable_get_source_node (drawable);
-  gegl_node_add_child (node, source);
-
-  color = gimp_gegl_color_new (&channel->color);
-
-  g_warn_if_fail (channel->color_node == NULL);
-
-  channel->color_node = gegl_node_new_child (node,
-                                             "operation", "gegl:color",
-                                             "value",     color,
-                                             NULL);
-
-  g_object_unref (color);
-
-  g_warn_if_fail (channel->mask_node == NULL);
-
-  channel->mask_node = gegl_node_new_child (node,
-                                            "operation", "gegl:opacity",
-                                            NULL);
-  gegl_node_connect_to (channel->color_node, "output",
-                        channel->mask_node,  "input");
-
-  g_warn_if_fail (channel->invert_node == NULL);
-
-  channel->invert_node = gegl_node_new_child (node,
-                                              "operation", "gegl:invert",
-                                              NULL);
-
-  if (channel->show_masked)
-    {
-      gegl_node_connect_to (source,               "output",
-                            channel->invert_node, "input");
-      gegl_node_connect_to (channel->invert_node, "output",
-                            channel->mask_node,   "aux");
-    }
-  else
-    {
-      gegl_node_connect_to (source,             "output",
-                            channel->mask_node, "aux");
-    }
-
-  mode_node = gimp_drawable_get_mode_node (drawable);
-
-  gegl_node_connect_to (channel->mask_node, "output",
-                        mode_node,          "aux");
-
-  return node;
-}
-
 static void
 gimp_channel_swap_pixels (GimpDrawable *drawable,
                           GeglBuffer   *buffer,
@@ -1654,7 +1657,7 @@ gimp_channel_set_color (GimpChannel   *channel,
 
       channel->color = *color;
 
-      if (gimp_item_peek_node (GIMP_ITEM (channel)))
+      if (gimp_filter_peek_node (GIMP_FILTER (channel)))
         {
           GeglColor *gegl_color = gimp_gegl_color_new (&channel->color);
 
@@ -1713,7 +1716,7 @@ gimp_channel_set_opacity (GimpChannel *channel,
 
       channel->color.a = opacity;
 
-      if (gimp_item_peek_node (GIMP_ITEM (channel)))
+      if (gimp_filter_peek_node (GIMP_FILTER (channel)))
         {
           GeglColor *gegl_color = gimp_gegl_color_new (&channel->color);
 
diff --git a/app/core/gimpdrawable.c b/app/core/gimpdrawable.c
index b34852e..88e40ba 100644
--- a/app/core/gimpdrawable.c
+++ b/app/core/gimpdrawable.c
@@ -90,6 +90,8 @@ static gboolean   gimp_drawable_get_size           (GimpViewable      *viewable,
                                                     gint              *width,
                                                     gint              *height);
 
+static GeglNode * gimp_drawable_get_node           (GimpFilter        *filter);
+
 static void       gimp_drawable_removed            (GimpItem          *item);
 static void       gimp_drawable_visibility_changed (GimpItem          *item);
 static GimpItem * gimp_drawable_duplicate          (GimpItem          *item,
@@ -158,7 +160,6 @@ static void       gimp_drawable_real_set_buffer    (GimpDrawable      *drawable,
                                                     GeglBuffer        *buffer,
                                                     gint               offset_x,
                                                     gint               offset_y);
-static GeglNode * gimp_drawable_get_node           (GimpItem          *item);
 
 static void       gimp_drawable_real_push_undo     (GimpDrawable      *drawable,
                                                     const gchar       *undo_desc,
@@ -200,6 +201,7 @@ gimp_drawable_class_init (GimpDrawableClass *klass)
   GObjectClass      *object_class      = G_OBJECT_CLASS (klass);
   GimpObjectClass   *gimp_object_class = GIMP_OBJECT_CLASS (klass);
   GimpViewableClass *viewable_class    = GIMP_VIEWABLE_CLASS (klass);
+  GimpFilterClass   *filter_class      = GIMP_FILTER_CLASS (klass);
   GimpItemClass     *item_class        = GIMP_ITEM_CLASS (klass);
 
   gimp_drawable_signals[UPDATE] =
@@ -234,6 +236,8 @@ gimp_drawable_class_init (GimpDrawableClass *klass)
   viewable_class->get_size           = gimp_drawable_get_size;
   viewable_class->get_new_preview    = gimp_drawable_get_new_preview;
 
+  filter_class->get_node             = gimp_drawable_get_node;
+
   item_class->removed                = gimp_drawable_removed;
   item_class->visibility_changed     = gimp_drawable_visibility_changed;
   item_class->duplicate              = gimp_drawable_duplicate;
@@ -242,7 +246,6 @@ gimp_drawable_class_init (GimpDrawableClass *klass)
   item_class->flip                   = gimp_drawable_flip;
   item_class->rotate                 = gimp_drawable_rotate;
   item_class->transform              = gimp_drawable_transform;
-  item_class->get_node               = gimp_drawable_get_node;
 
   klass->update                      = gimp_drawable_real_update;
   klass->alpha_changed               = NULL;
@@ -387,6 +390,42 @@ gimp_drawable_get_size (GimpViewable *viewable,
   return TRUE;
 }
 
+static GeglNode *
+gimp_drawable_get_node (GimpFilter *filter)
+{
+  GimpDrawable *drawable = GIMP_DRAWABLE (filter);
+  GeglNode     *node;
+  GeglNode     *input;
+  GeglNode     *output;
+
+  node = GIMP_FILTER_CLASS (parent_class)->get_node (filter);
+
+  g_warn_if_fail (drawable->private->mode_node == NULL);
+
+  drawable->private->mode_node =
+    gegl_node_new_child (node,
+                         "operation", "gimp:normal-mode",
+                         NULL);
+
+  input  = gegl_node_get_input_proxy  (node, "input");
+  output = gegl_node_get_output_proxy (node, "output");
+
+  if (gimp_item_get_visible (GIMP_ITEM (drawable)))
+    {
+      gegl_node_connect_to (input,                        "output",
+                            drawable->private->mode_node, "input");
+      gegl_node_connect_to (drawable->private->mode_node, "output",
+                            output,                       "input");
+    }
+  else
+    {
+      gegl_node_connect_to (input,  "output",
+                            output, "input");
+    }
+
+  return node;
+}
+
 static void
 gimp_drawable_removed (GimpItem *item)
 {
@@ -404,10 +443,10 @@ gimp_drawable_visibility_changed (GimpItem *item)
   GimpDrawable *drawable = GIMP_DRAWABLE (item);
   GeglNode     *node;
 
-  /*  don't use gimp_item_get_node() because that would create
+  /*  don't use gimp_filter_get_node() because that would create
    *  the node.
    */
-  node = gimp_item_peek_node (item);
+  node = gimp_filter_peek_node (GIMP_FILTER (item));
 
   if (node)
     {
@@ -810,42 +849,6 @@ gimp_drawable_real_set_buffer (GimpDrawable *drawable,
                    NULL);
 }
 
-static GeglNode *
-gimp_drawable_get_node (GimpItem *item)
-{
-  GimpDrawable *drawable = GIMP_DRAWABLE (item);
-  GeglNode     *node;
-  GeglNode     *input;
-  GeglNode     *output;
-
-  node = GIMP_ITEM_CLASS (parent_class)->get_node (item);
-
-  g_warn_if_fail (drawable->private->mode_node == NULL);
-
-  drawable->private->mode_node =
-    gegl_node_new_child (node,
-                         "operation", "gimp:normal-mode",
-                         NULL);
-
-  input  = gegl_node_get_input_proxy  (node, "input");
-  output = gegl_node_get_output_proxy (node, "output");
-
-  if (gimp_item_get_visible (GIMP_ITEM (drawable)))
-    {
-      gegl_node_connect_to (input,                        "output",
-                            drawable->private->mode_node, "input");
-      gegl_node_connect_to (drawable->private->mode_node, "output",
-                            output,                       "input");
-    }
-  else
-    {
-      gegl_node_connect_to (input,  "output",
-                            output, "input");
-    }
-
-  return node;
-}
-
 static void
 gimp_drawable_real_push_undo (GimpDrawable *drawable,
                               const gchar  *undo_desc,
@@ -930,7 +933,7 @@ gimp_drawable_sync_source_node (GimpDrawable *drawable,
           if (fs->layer_offset_node)
             {
               gegl_node_disconnect (fs->layer_offset_node, "input");
-              gegl_node_remove_child (gimp_item_get_node (GIMP_ITEM (fs)),
+              gegl_node_remove_child (gimp_filter_get_node (GIMP_FILTER (fs)),
                                       fs_source);
             }
 
@@ -1008,7 +1011,7 @@ gimp_drawable_sync_source_node (GimpDrawable *drawable,
           /* plug the fs' source node back into its graph */
           if (fs->layer_offset_node)
             {
-              gegl_node_add_child (gimp_item_get_node (GIMP_ITEM (fs)),
+              gegl_node_add_child (gimp_filter_get_node (GIMP_FILTER (fs)),
                                    fs_source);
               gegl_node_connect_to (fs_source,             "output",
                                     fs->layer_offset_node, "input");
@@ -1375,7 +1378,7 @@ gimp_drawable_get_mode_node (GimpDrawable *drawable)
   g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
 
   if (! drawable->private->mode_node)
-    gimp_item_get_node (GIMP_ITEM (drawable));
+    gimp_filter_get_node (GIMP_FILTER (drawable));
 
   return drawable->private->mode_node;
 }
diff --git a/app/core/gimpdrawablestack.c b/app/core/gimpdrawablestack.c
index 966c50e..1b547f4 100644
--- a/app/core/gimpdrawablestack.c
+++ b/app/core/gimpdrawablestack.c
@@ -151,7 +151,7 @@ gimp_drawable_stack_add (GimpContainer *container,
   if (stack->graph)
     {
       gegl_node_add_child (stack->graph,
-                           gimp_item_get_node (GIMP_ITEM (object)));
+                           gimp_filter_get_node (GIMP_FILTER (object)));
 
       gimp_drawable_stack_add_node (stack, GIMP_DRAWABLE (object));
     }
@@ -171,7 +171,7 @@ gimp_drawable_stack_remove (GimpContainer *container,
       gimp_drawable_stack_remove_node (stack, GIMP_DRAWABLE (object));
 
       gegl_node_remove_child (stack->graph,
-                              gimp_item_get_node (GIMP_ITEM (object)));
+                              gimp_filter_get_node (GIMP_FILTER (object)));
     }
 
   GIMP_CONTAINER_CLASS (parent_class)->remove (container, object);
@@ -244,7 +244,7 @@ gimp_drawable_stack_get_graph (GimpDrawableStack *stack)
   for (list = reverse_list; list; list = g_list_next (list))
     {
       GimpDrawable *drawable = list->data;
-      GeglNode     *node     = gimp_item_get_node (GIMP_ITEM (drawable));
+      GeglNode     *node     = gimp_filter_get_node (GIMP_FILTER (drawable));
 
       gegl_node_add_child (stack->graph, node);
 
@@ -279,7 +279,7 @@ gimp_drawable_stack_add_node (GimpDrawableStack *stack,
   GeglNode     *node;
   gint          index;
 
-  node = gimp_item_get_node (GIMP_ITEM (drawable));
+  node = gimp_filter_get_node (GIMP_FILTER (drawable));
 
   index = gimp_container_get_child_index (GIMP_CONTAINER (stack),
                                           GIMP_OBJECT (drawable));
@@ -293,7 +293,7 @@ gimp_drawable_stack_add_node (GimpDrawableStack *stack,
       drawable_above = (GimpDrawable *)
         gimp_container_get_child_by_index (GIMP_CONTAINER (stack), index - 1);
 
-      node_above = gimp_item_get_node (GIMP_ITEM (drawable_above));
+      node_above = gimp_filter_get_node (GIMP_FILTER (drawable_above));
     }
 
   gegl_node_connect_to (node,       "output",
@@ -304,7 +304,7 @@ gimp_drawable_stack_add_node (GimpDrawableStack *stack,
 
   if (drawable_below)
     {
-      GeglNode *node_below = gimp_item_get_node (GIMP_ITEM (drawable_below));
+      GeglNode *node_below = gimp_filter_get_node (GIMP_FILTER (drawable_below));
 
       gegl_node_connect_to (node_below, "output",
                             node,       "input");
@@ -328,7 +328,7 @@ gimp_drawable_stack_remove_node (GimpDrawableStack *stack,
   GeglNode     *node;
   gint          index;
 
-  node = gimp_item_get_node (GIMP_ITEM (drawable));
+  node = gimp_filter_get_node (GIMP_FILTER (drawable));
 
   index = gimp_container_get_child_index (GIMP_CONTAINER (stack),
                                           GIMP_OBJECT (drawable));
@@ -342,7 +342,7 @@ gimp_drawable_stack_remove_node (GimpDrawableStack *stack,
       drawable_above = (GimpDrawable *)
         gimp_container_get_child_by_index (GIMP_CONTAINER (stack), index - 1);
 
-      node_above = gimp_item_get_node (GIMP_ITEM (drawable_above));
+      node_above = gimp_filter_get_node (GIMP_FILTER (drawable_above));
     }
 
   drawable_below = (GimpDrawable *)
@@ -350,7 +350,7 @@ gimp_drawable_stack_remove_node (GimpDrawableStack *stack,
 
   if (drawable_below)
     {
-      GeglNode *node_below = gimp_item_get_node (GIMP_ITEM (drawable_below));
+      GeglNode *node_below = gimp_filter_get_node (GIMP_FILTER (drawable_below));
 
       gegl_node_disconnect (node,       "input");
       gegl_node_connect_to (node_below, "output",
diff --git a/app/core/gimpfilter.c b/app/core/gimpfilter.c
new file mode 100644
index 0000000..b588d9c
--- /dev/null
+++ b/app/core/gimpfilter.c
@@ -0,0 +1,136 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpfilter.c
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+
+#include "core-types.h"
+
+#include "gimp.h"
+#include "gimpfilter.h"
+
+
+typedef struct _GimpFilterPrivate GimpFilterPrivate;
+
+struct _GimpFilterPrivate
+{
+  GeglNode *node;
+};
+
+#define GET_PRIVATE(filter) G_TYPE_INSTANCE_GET_PRIVATE (filter, \
+                                                         GIMP_TYPE_FILTER, \
+                                                         GimpFilterPrivate)
+
+
+/*  local function prototypes  */
+
+static void       gimp_filter_finalize      (GObject    *object);
+
+static gint64     gimp_filter_get_memsize   (GimpObject *object,
+                                             gint64     *gui_size);
+
+static GeglNode * gimp_filter_real_get_node (GimpFilter *filter);
+
+
+G_DEFINE_TYPE (GimpFilter, gimp_filter, GIMP_TYPE_VIEWABLE)
+
+#define parent_class gimp_filter_parent_class
+
+
+static void
+gimp_filter_class_init (GimpFilterClass *klass)
+{
+  GObjectClass    *object_class      = G_OBJECT_CLASS (klass);
+  GimpObjectClass *gimp_object_class = GIMP_OBJECT_CLASS (klass);
+
+  object_class->finalize         = gimp_filter_finalize;
+
+  gimp_object_class->get_memsize = gimp_filter_get_memsize;
+
+  klass->get_node                = gimp_filter_real_get_node;
+
+  g_type_class_add_private (klass, sizeof (GimpFilterPrivate));
+}
+
+static void
+gimp_filter_init (GimpFilter *filter)
+{
+}
+
+static void
+gimp_filter_finalize (GObject *object)
+{
+  GimpFilterPrivate *private = GET_PRIVATE (object);
+
+  if (private->node)
+    {
+      g_object_unref (private->node);
+      private->node = NULL;
+    }
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gint64
+gimp_filter_get_memsize (GimpObject *object,
+                         gint64     *gui_size)
+{
+  GimpFilterPrivate *private = GET_PRIVATE (object);
+  gint64             memsize = 0;
+
+  memsize += gimp_g_object_get_memsize (G_OBJECT (private->node),
+                                        gui_size);
+
+  return memsize + GIMP_OBJECT_CLASS (parent_class)->get_memsize (object,
+                                                                  gui_size);
+}
+
+static GeglNode *
+gimp_filter_real_get_node (GimpFilter *filter)
+{
+  GimpFilterPrivate *private = GET_PRIVATE (filter);
+
+  private->node = gegl_node_new ();
+
+  return private->node;
+}
+
+GeglNode *
+gimp_filter_get_node (GimpFilter *filter)
+{
+  GimpFilterPrivate *private;
+
+  g_return_val_if_fail (GIMP_IS_FILTER (filter), NULL);
+
+  private = GET_PRIVATE (filter);
+
+  if (private->node)
+    return private->node;
+
+  return GIMP_FILTER_GET_CLASS (filter)->get_node (filter);
+}
+
+GeglNode *
+gimp_filter_peek_node (GimpFilter *filter)
+{
+  g_return_val_if_fail (GIMP_IS_FILTER (filter), NULL);
+
+  return GET_PRIVATE (filter)->node;
+}
diff --git a/app/core/gimpfilter.h b/app/core/gimpfilter.h
new file mode 100644
index 0000000..987da29
--- /dev/null
+++ b/app/core/gimpfilter.h
@@ -0,0 +1,56 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpfilter.h
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __GIMP_FILTER_H__
+#define __GIMP_FILTER_H__
+
+
+#include "gimpviewable.h"
+
+
+#define GIMP_TYPE_FILTER            (gimp_filter_get_type ())
+#define GIMP_FILTER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GIMP_TYPE_FILTER, GimpFilter))
+#define GIMP_FILTER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GIMP_TYPE_FILTER, GimpFilterClass))
+#define GIMP_IS_FILTER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GIMP_TYPE_FILTER))
+#define GIMP_IS_FILTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GIMP_TYPE_FILTER))
+#define GIMP_FILTER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GIMP_TYPE_FILTER, GimpFilterClass))
+
+
+typedef struct _GimpFilterClass GimpFilterClass;
+
+struct _GimpFilter
+{
+  GimpViewable  parent_instance;
+};
+
+struct _GimpFilterClass
+{
+  GimpViewableClass  parent_class;
+
+  GeglNode * (* get_node) (GimpFilter *filter);
+};
+
+
+GType      gimp_filter_get_type  (void) G_GNUC_CONST;
+
+GeglNode * gimp_filter_get_node  (GimpFilter *filter);
+GeglNode * gimp_filter_peek_node (GimpFilter *filter);
+
+
+#endif /* __GIMP_FILTER_H__ */
diff --git a/app/core/gimpitem.c b/app/core/gimpitem.c
index 61cd9d4..c6bf279 100644
--- a/app/core/gimpitem.c
+++ b/app/core/gimpitem.c
@@ -94,8 +94,6 @@ struct _GimpItemPrivate
 
   guint             removed : 1;        /*  removed from the image?  */
 
-  GeglNode         *node;               /*  the GEGL node to plug
-                                            into the graph           */
   GList            *offset_nodes;       /*  offset nodes to manage   */
 };
 
@@ -149,10 +147,9 @@ static void       gimp_item_real_resize             (GimpItem       *item,
                                                      gint            new_height,
                                                      gint            offset_x,
                                                      gint            offset_y);
-static GeglNode * gimp_item_real_get_node           (GimpItem       *item);
 
 
-G_DEFINE_TYPE (GimpItem, gimp_item, GIMP_TYPE_VIEWABLE)
+G_DEFINE_TYPE (GimpItem, gimp_item, GIMP_TYPE_FILTER)
 
 #define parent_class gimp_item_parent_class
 
@@ -243,7 +240,6 @@ gimp_item_class_init (GimpItemClass *klass)
   klass->transform                 = NULL;
   klass->stroke                    = NULL;
   klass->to_selection              = NULL;
-  klass->get_node                  = gimp_item_real_get_node;
 
   klass->default_name              = NULL;
   klass->rename_desc               = NULL;
@@ -349,12 +345,6 @@ gimp_item_finalize (GObject *object)
 {
   GimpItemPrivate *private = GET_PRIVATE (object);
 
-  if (private->node)
-    {
-      g_object_unref (private->node);
-      private->node = NULL;
-    }
-
   if (private->offset_nodes)
     {
       g_list_free_full (private->offset_nodes,
@@ -461,22 +451,22 @@ gimp_item_get_memsize (GimpObject *object,
 static void
 gimp_item_real_visibility_changed (GimpItem *item)
 {
-  GimpItemPrivate *private = GET_PRIVATE (item);
+  GeglNode *node = gimp_filter_peek_node (GIMP_FILTER (item));
 
-  if (! private->node)
-    return;
-
-  if (gimp_item_get_visible (item))
-    {
-      /* Leave this up to subclasses */
-    }
-  else
+  if (node)
     {
-      GeglNode *input  = gegl_node_get_input_proxy  (private->node, "input");
-      GeglNode *output = gegl_node_get_output_proxy (private->node, "output");
+      if (gimp_item_get_visible (item))
+        {
+          /* Leave this up to subclasses */
+        }
+      else
+        {
+          GeglNode *input  = gegl_node_get_input_proxy  (node, "input");
+          GeglNode *output = gegl_node_get_output_proxy (node, "output");
 
-      gegl_node_connect_to (input,  "output",
-                            output, "input");
+          gegl_node_connect_to (input,  "output",
+                                output, "input");
+        }
     }
 }
 
@@ -658,16 +648,6 @@ gimp_item_real_resize (GimpItem    *item,
                         private->offset_y - offset_y);
 }
 
-static GeglNode *
-gimp_item_real_get_node (GimpItem *item)
-{
-  GimpItemPrivate *private = GET_PRIVATE (item);
-
-  private->node = gegl_node_new ();
-
-  return private->node;
-}
-
 
 /*  public functions  */
 
@@ -1576,29 +1556,6 @@ gimp_item_to_selection (GimpItem       *item,
                               feather, feather_radius_x, feather_radius_y);
 }
 
-GeglNode *
-gimp_item_get_node (GimpItem *item)
-{
-  GimpItemPrivate *private;
-
-  g_return_val_if_fail (GIMP_IS_ITEM (item), NULL);
-
-  private = GET_PRIVATE (item);
-
-  if (private->node)
-    return private->node;
-
-  return GIMP_ITEM_GET_CLASS (item)->get_node (item);
-}
-
-GeglNode *
-gimp_item_peek_node (GimpItem *item)
-{
-  g_return_val_if_fail (GIMP_IS_ITEM (item), NULL);
-
-  return GET_PRIVATE (item)->node;
-}
-
 void
 gimp_item_add_offset_node (GimpItem *item,
                            GeglNode *node)
diff --git a/app/core/gimpitem.h b/app/core/gimpitem.h
index ca4f14c..4d700ff 100644
--- a/app/core/gimpitem.h
+++ b/app/core/gimpitem.h
@@ -19,7 +19,7 @@
 #define __GIMP_ITEM_H__
 
 
-#include "gimpviewable.h"
+#include "gimpfilter.h"
 
 
 #define GIMP_TYPE_ITEM            (gimp_item_get_type ())
@@ -34,12 +34,12 @@ typedef struct _GimpItemClass GimpItemClass;
 
 struct _GimpItem
 {
-  GimpViewable  parent_instance;
+  GimpFilter  parent_instance;
 };
 
 struct _GimpItemClass
 {
-  GimpViewableClass  parent_class;
+  GimpFilterClass  parent_class;
 
   /*  signals  */
   void            (* removed)               (GimpItem            *item);
@@ -110,8 +110,6 @@ struct _GimpItemClass
                                           gboolean                feather,
                                           gdouble                 feather_radius_x,
                                           gdouble                 feather_radius_y);
-  GeglNode      * (* get_node)           (GimpItem               *item);
-
 
   const gchar *default_name;
   const gchar *rename_desc;
@@ -254,9 +252,6 @@ void            gimp_item_to_selection       (GimpItem           *item,
                                               gdouble             feather_radius_x,
                                               gdouble             feather_radius_y);
 
-GeglNode      * gimp_item_get_node           (GimpItem           *item);
-GeglNode      * gimp_item_peek_node          (GimpItem           *item);
-
 void            gimp_item_add_offset_node    (GimpItem           *item,
                                               GeglNode           *node);
 void            gimp_item_remove_offset_node (GimpItem           *item,
diff --git a/app/core/gimplayer.c b/app/core/gimplayer.c
index 1329577..3581638 100644
--- a/app/core/gimplayer.c
+++ b/app/core/gimplayer.c
@@ -96,6 +96,8 @@ static void       gimp_layer_invalidate_preview (GimpViewable       *viewable);
 static gchar    * gimp_layer_get_description    (GimpViewable       *viewable,
                                                  gchar             **tooltip);
 
+static GeglNode * gimp_layer_get_node           (GimpFilter         *filter);
+
 static void       gimp_layer_removed            (GimpItem           *item);
 static void       gimp_layer_unset_removed      (GimpItem           *item);
 static gboolean   gimp_layer_is_attached        (const GimpItem     *item);
@@ -150,7 +152,6 @@ static void       gimp_layer_to_selection       (GimpItem           *item,
                                                  gboolean            feather,
                                                  gdouble             feather_radius_x,
                                                  gdouble             feather_radius_y);
-static GeglNode * gimp_layer_get_node           (GimpItem           *item);
 
 static gint64  gimp_layer_estimate_memsize      (const GimpDrawable *drawable,
                                                  gint                width,
@@ -196,6 +197,7 @@ gimp_layer_class_init (GimpLayerClass *klass)
   GObjectClass      *object_class      = G_OBJECT_CLASS (klass);
   GimpObjectClass   *gimp_object_class = GIMP_OBJECT_CLASS (klass);
   GimpViewableClass *viewable_class    = GIMP_VIEWABLE_CLASS (klass);
+  GimpFilterClass   *filter_class      = GIMP_FILTER_CLASS (klass);
   GimpItemClass     *item_class        = GIMP_ITEM_CLASS (klass);
   GimpDrawableClass *drawable_class    = GIMP_DRAWABLE_CLASS (klass);
 
@@ -275,6 +277,8 @@ gimp_layer_class_init (GimpLayerClass *klass)
   viewable_class->invalidate_preview  = gimp_layer_invalidate_preview;
   viewable_class->get_description     = gimp_layer_get_description;
 
+  filter_class->get_node              = gimp_layer_get_node;
+
   item_class->removed                 = gimp_layer_removed;
   item_class->unset_removed           = gimp_layer_unset_removed;
   item_class->is_attached             = gimp_layer_is_attached;
@@ -289,7 +293,6 @@ gimp_layer_class_init (GimpLayerClass *klass)
   item_class->rotate                  = gimp_layer_rotate;
   item_class->transform               = gimp_layer_transform;
   item_class->to_selection            = gimp_layer_to_selection;
-  item_class->get_node                = gimp_layer_get_node;
   item_class->default_name            = _("Layer");
   item_class->rename_desc             = C_("undo-type", "Rename Layer");
   item_class->translate_desc          = C_("undo-type", "Move Layer");
@@ -484,7 +487,7 @@ gimp_layer_notify (GObject    *object,
                    GParamSpec *pspec)
 {
   if (! strcmp (pspec->name, "is-last-node") &&
-      gimp_item_peek_node (GIMP_ITEM (object)))
+      gimp_filter_peek_node (GIMP_FILTER (object)))
     {
       GimpLayer *layer = GIMP_LAYER (object);
       GeglNode  *mode_node;
@@ -559,6 +562,90 @@ gimp_layer_get_description (GimpViewable  *viewable,
                                                               tooltip);
 }
 
+static GeglNode *
+gimp_layer_get_node (GimpFilter *filter)
+{
+  GimpDrawable *drawable = GIMP_DRAWABLE (filter);
+  GimpLayer    *layer    = GIMP_LAYER (filter);
+  GeglNode     *node;
+  GeglNode     *source;
+  GeglNode     *mode_node;
+  gboolean      source_node_hijacked = FALSE;
+
+  node = GIMP_FILTER_CLASS (parent_class)->get_node (filter);
+
+  source = gimp_drawable_get_source_node (drawable);
+
+  /* if the source node already has a parent, we are a floating
+   * selection and the source node has been hijacked by the fs'
+   * drawable
+   */
+  if (gegl_node_get_parent (source))
+    source_node_hijacked = TRUE;
+
+  if (! source_node_hijacked)
+    gegl_node_add_child (node, source);
+
+  g_warn_if_fail (layer->layer_offset_node == NULL);
+  g_warn_if_fail (layer->mask_offset_node == NULL);
+
+  /* the mode node connects it all, and has aux and aux2 inputs for
+   * the layer and its mask
+   */
+  mode_node = gimp_drawable_get_mode_node (drawable);
+
+  gimp_gegl_mode_node_set (mode_node,
+                           gimp_layer_get_visible_mode (layer),
+                           layer->opacity, FALSE);
+
+  /* the layer's offset node */
+  layer->layer_offset_node = gegl_node_new_child (node,
+                                                  "operation", "gegl:translate",
+                                                  NULL);
+  gimp_item_add_offset_node (GIMP_ITEM (layer), layer->layer_offset_node);
+
+  /* the layer mask's offset node */
+  layer->mask_offset_node = gegl_node_new_child (node,
+                                                 "operation", "gegl:translate",
+                                                  NULL);
+  gimp_item_add_offset_node (GIMP_ITEM (layer), layer->mask_offset_node);
+
+  if (! source_node_hijacked)
+    {
+      gegl_node_connect_to (source,                   "output",
+                            layer->layer_offset_node, "input");
+    }
+
+  if (! (layer->mask && gimp_layer_get_show_mask (layer)))
+    {
+      gegl_node_connect_to (layer->layer_offset_node, "output",
+                            mode_node,                "aux");
+    }
+
+  if (layer->mask)
+    {
+      GeglNode *mask;
+
+      mask = gimp_drawable_get_source_node (GIMP_DRAWABLE (layer->mask));
+
+      gegl_node_connect_to (mask,                    "output",
+                            layer->mask_offset_node, "input");
+
+      if (gimp_layer_get_show_mask (layer))
+        {
+          gegl_node_connect_to (layer->mask_offset_node, "output",
+                                mode_node,               "aux");
+        }
+      else if (gimp_layer_get_apply_mask (layer))
+        {
+          gegl_node_connect_to (layer->mask_offset_node, "output",
+                                mode_node,               "aux2");
+        }
+    }
+
+  return node;
+}
+
 static void
 gimp_layer_removed (GimpItem *item)
 {
@@ -884,90 +971,6 @@ gimp_layer_to_selection (GimpItem       *item,
                              feather, feather_radius_x, feather_radius_y);
 }
 
-static GeglNode *
-gimp_layer_get_node (GimpItem *item)
-{
-  GimpDrawable *drawable = GIMP_DRAWABLE (item);
-  GimpLayer    *layer    = GIMP_LAYER (item);
-  GeglNode     *node;
-  GeglNode     *source;
-  GeglNode     *mode_node;
-  gboolean      source_node_hijacked = FALSE;
-
-  node = GIMP_ITEM_CLASS (parent_class)->get_node (item);
-
-  source = gimp_drawable_get_source_node (drawable);
-
-  /* if the source node already has a parent, we are a floating
-   * selection and the source node has been hijacked by the fs'
-   * drawable
-   */
-  if (gegl_node_get_parent (source))
-    source_node_hijacked = TRUE;
-
-  if (! source_node_hijacked)
-    gegl_node_add_child (node, source);
-
-  g_warn_if_fail (layer->layer_offset_node == NULL);
-  g_warn_if_fail (layer->mask_offset_node == NULL);
-
-  /* the mode node connects it all, and has aux and aux2 inputs for
-   * the layer and its mask
-   */
-  mode_node = gimp_drawable_get_mode_node (drawable);
-
-  gimp_gegl_mode_node_set (mode_node,
-                           gimp_layer_get_visible_mode (layer),
-                           layer->opacity, FALSE);
-
-  /* the layer's offset node */
-  layer->layer_offset_node = gegl_node_new_child (node,
-                                                  "operation", "gegl:translate",
-                                                  NULL);
-  gimp_item_add_offset_node (GIMP_ITEM (layer), layer->layer_offset_node);
-
-  /* the layer mask's offset node */
-  layer->mask_offset_node = gegl_node_new_child (node,
-                                                 "operation", "gegl:translate",
-                                                  NULL);
-  gimp_item_add_offset_node (GIMP_ITEM (layer), layer->mask_offset_node);
-
-  if (! source_node_hijacked)
-    {
-      gegl_node_connect_to (source,                   "output",
-                            layer->layer_offset_node, "input");
-    }
-
-  if (! (layer->mask && gimp_layer_get_show_mask (layer)))
-    {
-      gegl_node_connect_to (layer->layer_offset_node, "output",
-                            mode_node,                "aux");
-    }
-
-  if (layer->mask)
-    {
-      GeglNode *mask;
-
-      mask = gimp_drawable_get_source_node (GIMP_DRAWABLE (layer->mask));
-
-      gegl_node_connect_to (mask,                    "output",
-                            layer->mask_offset_node, "input");
-
-      if (gimp_layer_get_show_mask (layer))
-        {
-          gegl_node_connect_to (layer->mask_offset_node, "output",
-                                mode_node,               "aux");
-        }
-      else if (gimp_layer_get_apply_mask (layer))
-        {
-          gegl_node_connect_to (layer->mask_offset_node, "output",
-                                mode_node,               "aux2");
-        }
-    }
-
-  return node;
-}
-
 static gint64
 gimp_layer_estimate_memsize (const GimpDrawable *drawable,
                              gint                width,
@@ -1324,7 +1327,7 @@ gimp_layer_add_mask (GimpLayer      *layer,
 
   gimp_layer_mask_set_layer (mask, layer);
 
-  if (gimp_item_peek_node (GIMP_ITEM (layer)))
+  if (gimp_filter_peek_node (GIMP_FILTER (layer)))
     {
       GeglNode *mode_node;
       GeglNode *mask;
@@ -1643,7 +1646,7 @@ gimp_layer_apply_mask (GimpLayer         *layer,
   if (push_undo)
     gimp_image_undo_group_end (image);
 
-  if (gimp_item_peek_node (item))
+  if (gimp_filter_peek_node (GIMP_FILTER (layer)))
     {
       GeglNode *mode_node;
 
@@ -1699,7 +1702,7 @@ gimp_layer_set_apply_mask (GimpLayer *layer,
 
       layer->apply_mask = apply ? TRUE : FALSE;
 
-      if (gimp_item_peek_node (GIMP_ITEM (layer)) &&
+      if (gimp_filter_peek_node (GIMP_FILTER (layer)) &&
           ! gimp_layer_get_show_mask (layer))
         {
           GeglNode *mode_node;
@@ -1778,7 +1781,7 @@ gimp_layer_set_show_mask (GimpLayer *layer,
 
       layer->show_mask = show ? TRUE : FALSE;
 
-      if (gimp_item_peek_node (GIMP_ITEM (layer)))
+      if (gimp_filter_peek_node (GIMP_FILTER (layer)))
         {
           GeglNode *mode_node;
 
@@ -1975,7 +1978,7 @@ gimp_layer_set_opacity (GimpLayer *layer,
       g_signal_emit (layer, layer_signals[OPACITY_CHANGED], 0);
       g_object_notify (G_OBJECT (layer), "opacity");
 
-      if (gimp_item_peek_node (GIMP_ITEM (layer)))
+      if (gimp_filter_peek_node (GIMP_FILTER (layer)))
         {
           GeglNode *mode_node;
 
@@ -2022,7 +2025,7 @@ gimp_layer_set_mode (GimpLayer            *layer,
       g_signal_emit (layer, layer_signals[MODE_CHANGED], 0);
       g_object_notify (G_OBJECT (layer), "mode");
 
-      if (gimp_item_peek_node (GIMP_ITEM (layer)))
+      if (gimp_filter_peek_node (GIMP_FILTER (layer)))
         {
           GeglNode *mode_node;
 



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