gimp r27961 - in trunk: . app/core



Author: mitch
Date: Mon Jan 26 22:05:07 2009
New Revision: 27961
URL: http://svn.gnome.org/viewvc/gimp?rev=27961&view=rev

Log:
2009-01-26  Michael Natterer  <mitch gimp org>

	The GEGL projection does floating selections now:

	* app/core/gimpdrawable.[ch] (struct GimpDrawable): add a couple
	of GeglNodes which are used to create a sub-graph for this
	drawable's floating selection.

	(gimp_drawable_detach_floating_sel)
	(gimp_drawable_attach_floating_sel): new functions to call
	whenever a floating selection gets attached or detached.

	Change the role of the drawable's "source_node": it's no longer a
	direct tile source but an arbitrary graph. Add new internal
	function gimp_drawable_sync_source_node() which creates a
	sub-graph for the floating selection within the source node, and
	uses the new "tile_source_node" directly otherwise. Connect to
	"notify" of the floating selection and reconfigure its sub-graph
	when its properties change. This is also one more refactoring in
	the direction of layer trees.

	* app/core/gimpfloatingselundo.c
	* app/core/gimpimage.c
	* app/core/gimplayer-floating-sel.c: call the new attach/detach
	API whenever a floating selection is attached or detached from a
	drawable. This will need more refactoring i guess...



Modified:
   trunk/ChangeLog
   trunk/app/core/gimpdrawable.c
   trunk/app/core/gimpdrawable.h
   trunk/app/core/gimpfloatingselundo.c
   trunk/app/core/gimpimage.c
   trunk/app/core/gimplayer-floating-sel.c

Modified: trunk/app/core/gimpdrawable.c
==============================================================================
--- trunk/app/core/gimpdrawable.c	(original)
+++ trunk/app/core/gimpdrawable.c	Mon Jan 26 22:05:07 2009
@@ -150,6 +150,12 @@
                                                     gint               width,
                                                     gint               height);
 
+static void       gimp_drawable_sync_source_node   (GimpDrawable      *drawable,
+                                                    gboolean           detach_fs);
+static void       gimp_drawable_fs_notify          (GimpLayer         *fs,
+                                                    const GParamSpec  *pspec,
+                                                    GimpDrawable      *drawable);
+
 
 G_DEFINE_TYPE_WITH_CODE (GimpDrawable, gimp_drawable, GIMP_TYPE_ITEM,
                          G_IMPLEMENT_INTERFACE (GIMP_TYPE_PICKABLE,
@@ -250,6 +256,9 @@
 {
   GimpDrawable *drawable = GIMP_DRAWABLE (object);
 
+  if (drawable->fs_opacity_node)
+    gimp_drawable_sync_source_node (drawable, TRUE);
+
   if (drawable->tiles)
     {
       tile_manager_unref (drawable->tiles);
@@ -672,12 +681,12 @@
                            gint          width,
                            gint          height)
 {
-  if (drawable->source_node)
+  if (drawable->tile_source_node)
     {
       GObject       *operation;
       GeglRectangle  rect;
 
-      g_object_get (drawable->source_node,
+      g_object_get (drawable->tile_source_node,
                     "gegl-operation", &operation,
                     NULL);
 
@@ -757,8 +766,8 @@
   if (old_has_alpha != gimp_drawable_has_alpha (drawable))
     gimp_drawable_alpha_changed (drawable);
 
-  if (drawable->source_node)
-    gegl_node_set (drawable->source_node,
+  if (drawable->tile_source_node)
+    gegl_node_set (drawable->tile_source_node,
                    "tile-manager", drawable->tiles,
                    NULL);
 }
@@ -888,6 +897,133 @@
   gimp_drawable_update (drawable, x, y, width, height);
 }
 
+static void
+gimp_drawable_sync_source_node (GimpDrawable *drawable,
+                                gboolean      detach_fs)
+{
+  GimpImage *image = gimp_item_get_image (GIMP_ITEM (drawable));
+  GimpLayer *fs    = gimp_image_get_floating_selection (image);
+  GeglNode  *output;
+
+  if (! drawable->source_node)
+    return;
+
+  output = gegl_node_get_output_proxy (drawable->source_node, "output");
+
+  if (gimp_drawable_has_floating_sel (drawable) && ! detach_fs)
+    {
+      gint off_x, off_y;
+      gint fs_off_x, fs_off_y;
+
+      if (! drawable->fs_opacity_node)
+        {
+          GeglNode *fs_source;
+
+          fs_source = gimp_drawable_get_source_node (GIMP_DRAWABLE (fs));
+          gegl_node_add_child (drawable->source_node, fs_source);
+
+          drawable->fs_opacity_node =
+            gegl_node_new_child (drawable->source_node,
+                                 "operation", "gegl:opacity",
+                                 NULL);
+
+          gegl_node_connect_to (fs_source,                 "output",
+                                drawable->fs_opacity_node, "input");
+
+          drawable->fs_offset_node =
+            gegl_node_new_child (drawable->source_node,
+                                 "operation", "gegl:translate",
+                                 NULL);
+
+          gegl_node_connect_to (drawable->fs_opacity_node, "output",
+                                drawable->fs_offset_node,  "input");
+
+          drawable->fs_mode_node =
+            gegl_node_new_child (drawable->source_node,
+                                 "operation", "gimp:point-layer-mode",
+                                 NULL);
+
+          gegl_node_connect_to (drawable->tile_source_node, "output",
+                                drawable->fs_mode_node,     "input");
+          gegl_node_connect_to (drawable->fs_offset_node,   "output",
+                                drawable->fs_mode_node,     "aux");
+
+          gegl_node_connect_to (drawable->fs_mode_node, "output",
+                                output,                 "input");
+
+          g_signal_connect (fs, "notify",
+                            G_CALLBACK (gimp_drawable_fs_notify),
+                            drawable);
+        }
+
+      gegl_node_set (drawable->fs_opacity_node,
+                     "value", gimp_layer_get_opacity (fs),
+                     NULL);
+
+      gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
+      gimp_item_get_offset (GIMP_ITEM (fs), &fs_off_x, &fs_off_y);
+
+      gegl_node_set (drawable->fs_offset_node,
+                     "x", (gdouble) (fs_off_x - off_x),
+                     "y", (gdouble) (fs_off_y - off_y),
+                     NULL);
+
+      gegl_node_set (drawable->fs_mode_node,
+                     "blend-mode", gimp_layer_get_mode (fs),
+                     NULL);
+    }
+  else
+    {
+      if (drawable->fs_opacity_node)
+        {
+          GeglNode *fs_source;
+
+          gegl_node_disconnect (drawable->fs_opacity_node, "input");
+          gegl_node_disconnect (drawable->fs_offset_node, "input");
+          gegl_node_disconnect (drawable->fs_mode_node, "input");
+          gegl_node_disconnect (drawable->fs_mode_node, "aux");
+
+          fs_source = gimp_drawable_get_source_node (GIMP_DRAWABLE (fs));
+          gegl_node_remove_child (drawable->source_node,
+                                  fs_source);
+
+          gegl_node_remove_child (drawable->source_node,
+                                  drawable->fs_opacity_node);
+          drawable->fs_opacity_node = NULL;
+
+          gegl_node_remove_child (drawable->source_node,
+                                  drawable->fs_offset_node);
+          drawable->fs_offset_node = NULL;
+
+          gegl_node_remove_child (drawable->source_node,
+                                  drawable->fs_mode_node);
+          drawable->fs_mode_node = NULL;
+
+          g_signal_handlers_disconnect_by_func (fs,
+                                                gimp_drawable_fs_notify,
+                                                drawable);
+        }
+
+      gegl_node_connect_to (drawable->tile_source_node, "output",
+                            output,                     "input");
+    }
+}
+
+static void
+gimp_drawable_fs_notify (GimpLayer        *fs,
+                         const GParamSpec *pspec,
+                         GimpDrawable     *drawable)
+{
+  if (! strcmp (pspec->name, "offset-x") ||
+      ! strcmp (pspec->name, "offset-y") ||
+      ! strcmp (pspec->name, "visible")  ||
+      ! strcmp (pspec->name, "mode")     ||
+      ! strcmp (pspec->name, "opacity"))
+    {
+      gimp_drawable_sync_source_node (drawable, FALSE);
+    }
+}
+
 
 /*  public functions  */
 
@@ -932,8 +1068,8 @@
   drawable->preview_cache = NULL;
   drawable->preview_valid = FALSE;
 
-  if (drawable->source_node)
-    gegl_node_set (drawable->source_node,
+  if (drawable->tile_source_node)
+    gegl_node_set (drawable->tile_source_node,
                    "tile-manager", drawable->tiles,
                    NULL);
 }
@@ -1239,13 +1375,16 @@
   if (drawable->source_node)
     return drawable->source_node;
 
-  drawable->source_node = g_object_new (GEGL_TYPE_NODE,
-                                        "operation", "gimp:tilemanager-source",
-                                        NULL);
-  gegl_node_set (drawable->source_node,
-                 "tile-manager", drawable->tiles,
-                 "linear",       TRUE,
-                 NULL);
+  drawable->source_node = gegl_node_new ();
+
+  drawable->tile_source_node =
+    gegl_node_new_child (drawable->source_node,
+                         "operation",    "gimp:tilemanager-source",
+                         "tile-manager", drawable->tiles,
+                         "linear",       TRUE,
+                         NULL);
+
+  gimp_drawable_sync_source_node (drawable, FALSE);
 
   return drawable->source_node;
 }
@@ -1654,3 +1793,44 @@
 
   return image ? gimp_image_get_colormap (image) : NULL;
 }
+
+void
+gimp_drawable_attach_floating_sel (GimpDrawable *drawable,
+                                   GimpLayer    *floating_sel)
+{
+  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
+  g_return_if_fail (GIMP_IS_LAYER (floating_sel));
+
+  g_printerr ("%s\n", G_STRFUNC);
+
+  gimp_drawable_sync_source_node (drawable, FALSE);
+
+#ifdef __GNUC__
+#warning FIXME: remove this hack when the floating sel is no layer any longer
+#endif
+  g_signal_emit_by_name (floating_sel, "visibility-changed");
+}
+
+void
+gimp_drawable_detach_floating_sel (GimpDrawable *drawable,
+                                   GimpLayer    *floating_sel)
+{
+  g_return_if_fail (GIMP_IS_DRAWABLE (drawable));
+  g_return_if_fail (GIMP_IS_LAYER (floating_sel));
+
+  g_printerr ("%s\n", G_STRFUNC);
+
+  gimp_drawable_sync_source_node (drawable, TRUE);
+
+#ifdef __GNUC__
+#warning FIXME: remove this hack when the floating sel is no layer any longer
+#endif
+  g_signal_emit_by_name (floating_sel, "visibility-changed");
+
+  /*  Invalidate the preview of the obscured drawable.  We do this here
+   *  because it will not be done until the floating selection is removed,
+   *  at which point the obscured drawable's preview will not be declared
+   *  invalid.
+   */
+  gimp_viewable_invalidate_preview (GIMP_VIEWABLE (floating_sel));
+}

Modified: trunk/app/core/gimpdrawable.h
==============================================================================
--- trunk/app/core/gimpdrawable.h	(original)
+++ trunk/app/core/gimpdrawable.h	Mon Jan 26 22:05:07 2009
@@ -40,6 +40,10 @@
   TileManager   *shadow;             /* shadow buffer tiles            */
 
   GeglNode      *source_node;
+  GeglNode      *tile_source_node;
+  GeglNode      *fs_opacity_node;
+  GeglNode      *fs_offset_node;
+  GeglNode      *fs_mode_node;
 
   GeglNode      *mode_node;
 
@@ -248,5 +252,10 @@
 
 const guchar  * gimp_drawable_get_colormap       (const GimpDrawable *drawable);
 
+void           gimp_drawable_attach_floating_sel (GimpDrawable       *drawable,
+                                                  GimpLayer          *floating_sel);
+void           gimp_drawable_detach_floating_sel (GimpDrawable       *drawable,
+                                                  GimpLayer          *floating_sel);
+
 
 #endif /* __GIMP_DRAWABLE_H__ */

Modified: trunk/app/core/gimpfloatingselundo.c
==============================================================================
--- trunk/app/core/gimpfloatingselundo.c	(original)
+++ trunk/app/core/gimpfloatingselundo.c	Mon Jan 26 22:05:07 2009
@@ -114,11 +114,14 @@
 
           /*  clear the selection  */
           gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (floating_layer));
+
+          gimp_drawable_attach_floating_sel (floating_layer->fs.drawable,
+                                             floating_layer);
         }
       else
         {
-          /*  Update the preview for the underlying drawable  */
-          gimp_viewable_invalidate_preview (GIMP_VIEWABLE (floating_layer));
+          gimp_drawable_detach_floating_sel (floating_layer->fs.drawable,
+                                             floating_layer);
 
           /*  clear the selection  */
           gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (floating_layer));

Modified: trunk/app/core/gimpimage.c
==============================================================================
--- trunk/app/core/gimpimage.c	(original)
+++ trunk/app/core/gimpimage.c	Mon Jan 26 22:05:07 2009
@@ -2969,7 +2969,11 @@
 
   /*  If the layer is a floating selection, set the fs pointer  */
   if (gimp_layer_is_floating_sel (layer))
-    gimp_image_set_floating_selection (image, layer);
+    {
+      gimp_image_set_floating_selection (image, layer);
+
+      gimp_drawable_attach_floating_sel (layer->fs.drawable, layer);
+    }
 
   if (old_has_alpha != gimp_image_has_alpha (image))
     image->flush_accum.alpha_changed = TRUE;
@@ -3019,16 +3023,11 @@
 
   old_has_alpha = gimp_image_has_alpha (image);
 
-  if (gimp_image_get_floating_selection (image) == layer)
+  if (gimp_layer_is_floating_sel (layer))
     {
       undo_desc = _("Remove Floating Selection");
 
-      /*  Invalidate the preview of the obscured drawable.  We do this here
-       *  because it will not be done until the floating selection is removed,
-       *  at which point the obscured drawable's preview will not be declared
-       *  invalid.
-       */
-      gimp_viewable_invalidate_preview (GIMP_VIEWABLE (layer));
+      gimp_drawable_detach_floating_sel (layer->fs.drawable, layer);
     }
   else
     {

Modified: trunk/app/core/gimplayer-floating-sel.c
==============================================================================
--- trunk/app/core/gimplayer-floating-sel.c	(original)
+++ trunk/app/core/gimplayer-floating-sel.c	Mon Jan 26 22:05:07 2009
@@ -139,8 +139,7 @@
 
   gimp_image_undo_push_fs_to_layer (image, NULL, layer);
 
-  /*  clear the selection  */
-  gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (layer));
+  gimp_drawable_detach_floating_sel (layer->fs.drawable, layer);
 
   /*  Set pointers  */
   gimp_layer_set_floating_sel_drawable (layer, NULL);



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