gimp r27204 - in trunk: . app/core app/gegl



Author: mitch
Date: Thu Oct  9 20:44:23 2008
New Revision: 27204
URL: http://svn.gnome.org/viewvc/gimp?rev=27204&view=rev

Log:
2008-10-09  Michael Natterer  <mitch gimp org>

	Address Bug 554983 â Layers Projection using GEGL

	* app/gegl/gimp-gegl-utils.[ch]: add (imcomplete) function
	gimp_layer_mode_to_gegl_operation() from bug #554983.

	* app/core/gimpdrawable.[ch]: add gimp_drawable_get_source_node()
	which returns a GimpOperationTileSource for the drawable's
	tiles.

	(gimp_drawable_real_set_tiles)
	(gimp_drawable_configure): set the node's "tiles" property.

	* app/core/gimplayer.[ch]: add gimp_layer_get_node() which returns
	a GeglNode with proxy "input" and "output" pads to be plugged
	into the projection graph. The node has children for opacity,
	mask, layer mode and layer offset.

	(gimp_layer_translate)
	(gimp_layer_add_mask)
	(gimp_layer_apply_mask)
	(gimp_layer_set_opacity)
	(gimp_layer_set_mode): reconfigure the respective nodes.

	* app/core/gimpimage.[ch]: keep a "graph" node around and destroy
	it in finalize(). Not even a stub, just a silly GEGL dependency.



Modified:
   trunk/ChangeLog
   trunk/app/core/gimpdrawable.c
   trunk/app/core/gimpdrawable.h
   trunk/app/core/gimpimage.c
   trunk/app/core/gimpimage.h
   trunk/app/core/gimplayer.c
   trunk/app/core/gimplayer.h
   trunk/app/gegl/gimp-gegl-utils.c
   trunk/app/gegl/gimp-gegl-utils.h

Modified: trunk/app/core/gimpdrawable.c
==============================================================================
--- trunk/app/core/gimpdrawable.c	(original)
+++ trunk/app/core/gimpdrawable.c	Thu Oct  9 20:44:23 2008
@@ -261,6 +261,12 @@
 
   gimp_drawable_free_shadow_tiles (drawable);
 
+  if (drawable->source_node)
+    {
+      g_object_unref (drawable->source_node);
+      drawable->source_node = NULL;
+    }
+
   if (drawable->preview_cache)
     gimp_preview_cache_invalidate (&drawable->preview_cache);
 
@@ -702,6 +708,11 @@
 
   if (old_has_alpha != gimp_drawable_has_alpha (drawable))
     gimp_drawable_alpha_changed (drawable);
+
+  if (drawable->source_node)
+    gegl_node_set (drawable->source_node,
+                   "tile-manager", drawable->tiles,
+                   NULL);
 }
 
 static void
@@ -839,6 +850,11 @@
   /*  preview variables  */
   drawable->preview_cache = NULL;
   drawable->preview_valid = FALSE;
+
+  if (drawable->source_node)
+    gegl_node_set (drawable->source_node,
+                   "tile-manager", drawable->tiles,
+                   NULL);
 }
 
 void
@@ -1012,6 +1028,25 @@
                         gimp_item_height (item));
 }
 
+GeglNode *
+gimp_drawable_get_source_node (GimpDrawable *drawable)
+{
+  g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), NULL);
+
+  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);
+
+  return drawable->source_node;
+}
+
 void
 gimp_drawable_swap_pixels (GimpDrawable *drawable,
                            TileManager  *tiles,

Modified: trunk/app/core/gimpdrawable.h
==============================================================================
--- trunk/app/core/gimpdrawable.h	(original)
+++ trunk/app/core/gimpdrawable.h	Thu Oct  9 20:44:23 2008
@@ -40,6 +40,8 @@
   TileManager   *tiles;              /* tiles for drawable data        */
   TileManager   *shadow;             /* shadow buffer tiles            */
 
+  GeglNode      *source_node;
+
   gint           bytes;              /* bytes per pixel                */
   GimpImageType  type;               /* type of drawable               */
   gboolean       has_alpha;          /* drawable has alpha             */
@@ -169,6 +171,8 @@
                                                   gint                offset_x,
                                                   gint                offset_y);
 
+GeglNode      * gimp_drawable_get_source_node    (GimpDrawable       *drawable);
+
 void            gimp_drawable_swap_pixels        (GimpDrawable       *drawable,
                                                   TileManager        *tiles,
                                                   gboolean            sparse,

Modified: trunk/app/core/gimpimage.c
==============================================================================
--- trunk/app/core/gimpimage.c	(original)
+++ trunk/app/core/gimpimage.c	Thu Oct  9 20:44:23 2008
@@ -891,6 +891,12 @@
       image->projection = NULL;
     }
 
+  if (image->graph)
+    {
+      g_object_unref (image->graph);
+      image->graph = NULL;
+    }
+
   if (image->colormap)
     {
       g_free (image->colormap);

Modified: trunk/app/core/gimpimage.h
==============================================================================
--- trunk/app/core/gimpimage.h	(original)
+++ trunk/app/core/gimpimage.h	Thu Oct  9 20:44:23 2008
@@ -126,6 +126,7 @@
   GimpTattoo         tattoo_state;          /*  the last used tattoo         */
 
   GimpProjection    *projection;            /*  projection layers & channels */
+  GeglNode          *graph;                 /*  GEGL projection graph        */
 
   GList             *guides;                /*  guides                       */
   GimpGrid          *grid;                  /*  grid                         */

Modified: trunk/app/core/gimplayer.c
==============================================================================
--- trunk/app/core/gimplayer.c	(original)
+++ trunk/app/core/gimplayer.c	Thu Oct  9 20:44:23 2008
@@ -35,6 +35,8 @@
 
 #include "paint-funcs/paint-funcs.h"
 
+#include "gegl/gimp-gegl-utils.h"
+
 #include "gimpcontext.h"
 #include "gimpcontainer.h"
 #include "gimpdrawable-convert.h"
@@ -69,6 +71,19 @@
 };
 
 
+#ifdef __GNUC__
+#warning FIXME: gegl_node_add_child() needs to be public
+#endif
+GeglNode * gegl_node_add_child (GeglNode *self,
+                                GeglNode *child);
+
+#ifdef __GNUC__
+#warning FIXME: gegl_node_remove_child() needs to be public
+#endif
+GeglNode * gegl_node_remove_child (GeglNode *self,
+                                   GeglNode *child);
+
+
 static void   gimp_layer_pickable_iface_init (GimpPickableInterface *iface);
 
 static void       gimp_layer_set_property       (GObject            *object,
@@ -376,6 +391,12 @@
       layer->mask = NULL;
     }
 
+  if (layer->node)
+    {
+      g_object_unref (layer->node);
+      layer->node = NULL;
+    }
+
   if (layer->fs.backing_store)
     {
       tile_manager_unref (layer->fs.backing_store);
@@ -692,6 +713,12 @@
   if (gimp_layer_is_floating_sel (layer))
     floating_sel_rigor (layer, FALSE);
 
+  if (layer->shift_node)
+    gegl_node_set (layer->shift_node,
+                   "x", item->offset_x,
+                   "y", item->offset_y,
+                   NULL);
+
   /*  update the new region  */
   gimp_drawable_update (GIMP_DRAWABLE (layer),
                         0, 0,
@@ -1286,6 +1313,27 @@
 
   gimp_layer_mask_set_layer (mask, layer);
 
+  if (layer->node)
+    {
+      GeglNode *source;
+      GeglNode *mask;
+
+      layer->mask_node = gegl_node_new_child (layer->node,
+                                              "operation", "opacity",
+                                              NULL);
+
+      source = gimp_drawable_get_source_node (GIMP_DRAWABLE (layer));
+      gegl_node_connect_to (source,           "output",
+                            layer->mask_node, "input");
+
+      mask = gimp_drawable_get_source_node (GIMP_DRAWABLE (layer->mask));
+      gegl_node_connect_to (mask,             "output",
+                            layer->mask_node, "aux");
+
+      gegl_node_connect_to (layer->mask_node,  "output",
+                            layer->shift_node, "input");
+    }
+
   if (gimp_layer_mask_get_apply (mask) ||
       gimp_layer_mask_get_show (mask))
     {
@@ -1610,6 +1658,18 @@
   if (push_undo)
     gimp_image_undo_group_end (image);
 
+  if (layer->node)
+    {
+      GeglNode *source;
+
+      gegl_node_remove_child (layer->node, layer->mask_node);
+      layer->mask_node = NULL;
+
+      source = gimp_drawable_get_source_node (GIMP_DRAWABLE (layer));
+      gegl_node_connect_to (source,            "output",
+                            layer->shift_node, "input");
+    }
+
   /*  If applying actually changed the view  */
   if (view_changed)
     {
@@ -1836,6 +1896,77 @@
   return (layer->fs.drawable != NULL);
 }
 
+GeglNode *
+gimp_layer_get_node (GimpLayer *layer)
+{
+  GeglNode *source;
+  gint      off_x, off_y;
+  GeglNode *input;
+  GeglNode *output;
+
+  g_return_val_if_fail (GIMP_IS_LAYER (layer), NULL);
+
+  if (layer->node)
+    return layer->node;
+
+  layer->node = gegl_node_new ();
+
+  source = gimp_drawable_get_source_node (GIMP_DRAWABLE (layer));
+  gegl_node_add_child (layer->node, source);
+
+  if (layer->mask)
+    {
+      GeglNode *mask;
+
+      mask = gimp_drawable_get_source_node (GIMP_DRAWABLE (layer->mask));
+
+      layer->mask_node = gegl_node_new_child (layer->node,
+                                              "operation", "opacity",
+                                              NULL);
+      gegl_node_connect_to (mask,             "output",
+                            layer->mask_node, "aux");
+      gegl_node_connect_to (source,           "output",
+                            layer->mask_node, "input");
+    }
+
+  gimp_item_offsets (GIMP_ITEM (layer), &off_x, &off_y);
+  layer->shift_node = gegl_node_new_child (layer->node,
+                                           "operation", "shift",
+                                           "x",         off_x,
+                                           "y",         off_y,
+                                           NULL);
+
+  if (layer->mask_node)
+    gegl_node_connect_to (layer->mask_node,  "output",
+                          layer->shift_node, "input");
+  else
+    gegl_node_connect_to (source,            "output",
+                          layer->shift_node, "input");
+
+  layer->opacity_node = gegl_node_new_child (layer->node,
+                                             "operation", "opacity",
+                                             "value",     layer->opacity,
+                                             NULL);
+  gegl_node_connect_to (layer->shift_node,   "output",
+                        layer->opacity_node, "input");
+
+  layer->mode_node = gegl_node_new_child (layer->node,
+                                          "operation", gimp_layer_mode_to_gegl_operation (layer->mode),
+                                          NULL);
+  gegl_node_connect_to (layer->opacity_node, "output",
+                        layer->mode_node,    "aux");
+
+  input = gegl_node_get_input_proxy (layer->node, "input");
+  gegl_node_connect_to (input,            "output",
+                        layer->mode_node, "input");
+
+  output = gegl_node_get_output_proxy (layer->node, "output");
+  gegl_node_connect_to (layer->mode_node, "output",
+                        output,           "input");
+
+  return layer->node;
+}
+
 void
 gimp_layer_set_opacity (GimpLayer *layer,
                         gdouble    opacity,
@@ -1859,6 +1990,11 @@
       g_signal_emit (layer, layer_signals[OPACITY_CHANGED], 0);
       g_object_notify (G_OBJECT (layer), "opacity");
 
+      if (layer->opacity_node)
+        gegl_node_set (layer->opacity_node,
+                       "opacity", layer->opacity,
+                       NULL);
+
       gimp_drawable_update (GIMP_DRAWABLE (layer),
                             0, 0,
                             gimp_item_width  (GIMP_ITEM (layer)),
@@ -1895,6 +2031,11 @@
       g_signal_emit (layer, layer_signals[MODE_CHANGED], 0);
       g_object_notify (G_OBJECT (layer), "mode");
 
+      if (layer->mode_node)
+        gegl_node_set (layer->mode_node,
+                       "operation", gimp_layer_mode_to_gegl_operation (layer->mode),
+                       NULL);
+
       gimp_drawable_update (GIMP_DRAWABLE (layer),
                             0, 0,
                             gimp_item_width  (GIMP_ITEM (layer)),

Modified: trunk/app/core/gimplayer.h
==============================================================================
--- trunk/app/core/gimplayer.h	(original)
+++ trunk/app/core/gimplayer.h	Thu Oct  9 20:44:23 2008
@@ -43,6 +43,12 @@
 
   GimpLayerMask        *mask;             /*  possible layer mask        */
 
+  GeglNode             *node;
+  GeglNode             *mask_node;
+  GeglNode             *shift_node;
+  GeglNode             *opacity_node;
+  GeglNode             *mode_node;
+
   /*  Floating selections  */
   struct
   {
@@ -121,6 +127,8 @@
 
 gboolean        gimp_layer_is_floating_sel     (const GimpLayer      *layer);
 
+GeglNode      * gimp_layer_get_node            (GimpLayer            *layer);
+
 void            gimp_layer_set_opacity         (GimpLayer            *layer,
                                                 gdouble               opacity,
                                                 gboolean              push_undo);

Modified: trunk/app/gegl/gimp-gegl-utils.c
==============================================================================
--- trunk/app/gegl/gimp-gegl-utils.c	(original)
+++ trunk/app/gegl/gimp-gegl-utils.c	Thu Oct  9 20:44:23 2008
@@ -85,3 +85,42 @@
 
   return NULL;
 }
+
+const gchar *
+gimp_layer_mode_to_gegl_operation (GimpLayerModeEffects mode)
+{
+#ifdef __GNUC__
+#warning FIXME: add all layer modes as GEGL operations
+#endif
+
+  switch (mode)
+    {
+    case GIMP_NORMAL_MODE:        return "normal";
+    case GIMP_DISSOLVE_MODE:      return "normal";
+    case GIMP_BEHIND_MODE:        return "normal";
+    case GIMP_MULTIPLY_MODE:      return "gimp-multiply-mode";
+    case GIMP_SCREEN_MODE:        return "gimp-screen_mode";
+    case GIMP_OVERLAY_MODE:       return "gimp-overlay-mode";
+    case GIMP_DIFFERENCE_MODE:    return "gimp-difference-mode";
+    case GIMP_ADDITION_MODE:      return "gimp-addition-mode";
+    case GIMP_SUBTRACT_MODE:      return "gimp-subtract-mode";
+    case GIMP_DARKEN_ONLY_MODE:   return "gimp-darken-mode";
+    case GIMP_LIGHTEN_ONLY_MODE:  return "gimp-lighten-mode";
+    case GIMP_HUE_MODE:           return "normal";
+    case GIMP_SATURATION_MODE:    return "normal";
+    case GIMP_COLOR_MODE:         return "normal";
+    case GIMP_VALUE_MODE:         return "normal";
+    case GIMP_DIVIDE_MODE:        return "gimp-divide-mode";
+    case GIMP_DODGE_MODE:         return "gimp-dodge-mode";
+    case GIMP_BURN_MODE:          return "gimp-burn-mode";
+    case GIMP_HARDLIGHT_MODE:     return "gimp-hardlight-mode";
+    case GIMP_SOFTLIGHT_MODE:     return "gimp-softlight-mode";
+    case GIMP_GRAIN_EXTRACT_MODE: return "gimp-grain-extract-mode";
+    case GIMP_GRAIN_MERGE_MODE:   return "gimp-grain-merge-mode";
+    case GIMP_COLOR_ERASE_MODE:   return "normal";
+    default:
+      break;
+    }
+
+  return "normal";
+}

Modified: trunk/app/gegl/gimp-gegl-utils.h
==============================================================================
--- trunk/app/gegl/gimp-gegl-utils.h	(original)
+++ trunk/app/gegl/gimp-gegl-utils.h	Thu Oct  9 20:44:23 2008
@@ -23,9 +23,10 @@
 #define __GIMP_GEGL_UTILS_H__
 
 
-const Babl * gimp_bpp_to_babl_format        (guint bpp) G_GNUC_CONST;
-const Babl * gimp_bpp_to_babl_format_linear (guint bpp) G_GNUC_CONST;
+const Babl  * gimp_bpp_to_babl_format           (guint                bpp) G_GNUC_CONST;
+const Babl  * gimp_bpp_to_babl_format_linear    (guint                bpp) G_GNUC_CONST;
 
+const gchar * gimp_layer_mode_to_gegl_operation (GimpLayerModeEffects mode) G_GNUC_CONST;
 
 
 #endif /* __GIMP_GEGL_UTILS_H__ */



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