gimp r27207 - in trunk: . app/core
- From: mitch svn gnome org
- To: svn-commits-list gnome org
- Subject: gimp r27207 - in trunk: . app/core
- Date: Fri, 10 Oct 2008 12:24:56 +0000 (UTC)
Author: mitch
Date: Fri Oct 10 12:24:56 2008
New Revision: 27207
URL: http://svn.gnome.org/viewvc/gimp?rev=27207&view=rev
Log:
2008-10-10 Michael Natterer <mitch gimp org>
Bug 554983 â Layers Projection using GEGL
First projection using GEGL, wheeeee. Disabled by default because
it doesn't work with floating selection (and will not, FS
refactoring is in the queue).
* app/core/gimpimage.[ch]: add gimp_image_get_graph() which
returns a GeglNode representing the image's projection.
(gimp_image_add_layer_node)
(gimp_image_remove_layer_node): new utility functions to add and
remove layer nodes to/from the graph.
(gimp_image_add_layer)
(gimp_image_remove_layer)
(gimp_image_position_layer): call them to keep the graph up to date.
* app/core/gimpdrawable.c (gimp_drawable_real_update): invalidate
the source node.
* app/core/gimpprojection.[ch]: keep a projection graph around and
add gimp_projection_get_sink_node() which returns the node that
writes to the projection tiles.
* app/core/gimpprojection-construct.c: add
gimp_projection_construct_gegl() which is a few-liner that uses a
GeglProcessor to run the projection graph.
(gimp_projection_construct): call the new function (disabled by
default).
Modified:
trunk/ChangeLog
trunk/app/core/gimpdrawable.c
trunk/app/core/gimpimage.c
trunk/app/core/gimpimage.h
trunk/app/core/gimpprojection-construct.c
trunk/app/core/gimpprojection.c
trunk/app/core/gimpprojection.h
Modified: trunk/app/core/gimpdrawable.c
==============================================================================
--- trunk/app/core/gimpdrawable.c (original)
+++ trunk/app/core/gimpdrawable.c Fri Oct 10 12:24:56 2008
@@ -642,6 +642,25 @@
gint width,
gint height)
{
+ if (drawable->source_node)
+ {
+ GObject *operation;
+ GeglRectangle rect;
+
+ g_object_get (drawable->source_node,
+ "gegl-operation", &operation,
+ NULL);
+
+ rect.x = x;
+ rect.y = y;
+ rect.width = width;
+ rect.height = height;
+
+ gegl_operation_invalidate (operation, &rect);
+
+ g_object_unref (operation);
+ }
+
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (drawable));
}
Modified: trunk/app/core/gimpimage.c
==============================================================================
--- trunk/app/core/gimpimage.c (original)
+++ trunk/app/core/gimpimage.c Fri Oct 10 12:24:56 2008
@@ -119,6 +119,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);
+
+
/* local function prototypes */
static void gimp_color_managed_iface_init (GimpColorManagedInterface *iface);
@@ -2537,6 +2550,155 @@
return image->projection;
}
+GeglNode *
+gimp_image_get_graph (GimpImage *image)
+{
+ GList *list;
+ GList *reverse_list = NULL;
+ GeglNode *previous = NULL;
+
+ g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
+
+ if (image->graph)
+ return image->graph;
+
+ for (list = GIMP_LIST (image->layers)->list;
+ list;
+ list = g_list_next (list))
+ {
+ GimpLayer *layer = list->data;
+
+ if (! gimp_layer_is_floating_sel (layer))
+ reverse_list = g_list_prepend (reverse_list, layer);
+ }
+
+ image->graph = gegl_node_new ();
+
+ for (list = reverse_list; list; list = g_list_next (list))
+ {
+ GimpLayer *layer = list->data;
+ GeglNode *node = gimp_layer_get_node (layer);
+
+ gegl_node_add_child (image->graph, node);
+
+ if (previous)
+ gegl_node_connect_to (previous, "output",
+ node, "input");
+
+ previous = node;
+ }
+
+ if (previous)
+ {
+ GeglNode *output;
+
+ output = gegl_node_get_output_proxy (image->graph, "output");
+
+ gegl_node_connect_to (previous, "output",
+ output, "input");
+ }
+
+ return image->graph;
+}
+
+/* layer must be part of image->layers !!! */
+static void
+gimp_image_add_layer_node (GimpImage *image,
+ GimpLayer *layer)
+{
+ GimpLayer *layer_below;
+ GeglNode *node;
+ gint index;
+
+ index = gimp_image_get_layer_index (image, layer);
+
+ node = gimp_layer_get_node (layer);
+
+ if (index == 0)
+ {
+ GeglNode *output;
+
+ output = gegl_node_get_output_proxy (image->graph, "output");
+
+ gegl_node_connect_to (node, "output",
+ output, "input");
+ }
+ else
+ {
+ GimpLayer *layer_above;
+ GeglNode *node_above;
+
+ layer_above = gimp_image_get_layer_by_index (image, index - 1);
+
+ node_above = gimp_layer_get_node (layer_above);
+
+ gegl_node_connect_to (node, "output",
+ node_above, "input");
+ }
+
+ layer_below = gimp_image_get_layer_by_index (image, index + 1);
+
+ if (layer_below)
+ {
+ GeglNode *node_below = gimp_layer_get_node (layer_below);
+
+ gegl_node_connect_to (node_below, "output",
+ node, "input");
+ }
+}
+
+/* layer must be part of image->layers !!! */
+static void
+gimp_image_remove_layer_node (GimpImage *image,
+ GimpLayer *layer)
+{
+ GimpLayer *layer_below;
+ GeglNode *node;
+ gint index;
+
+ index = gimp_image_get_layer_index (image, layer);
+
+ node = gimp_layer_get_node (layer);
+
+ layer_below = gimp_image_get_layer_by_index (image, index + 1);
+
+ if (index == 0)
+ {
+ if (layer_below)
+ {
+ GeglNode *node_below = gimp_layer_get_node (layer_below);
+ GeglNode *output;
+
+ output = gegl_node_get_output_proxy (image->graph, "output");
+
+ gegl_node_disconnect (node, "input");
+ gegl_node_connect_to (node_below, "output",
+ output, "input");
+ }
+ }
+ else
+ {
+ GimpLayer *layer_above;
+ GeglNode *node_above;
+
+ layer_above = gimp_image_get_layer_by_index (image, index - 1);
+ node_above = gimp_layer_get_node (layer_above);
+
+ if (layer_below)
+ {
+ GeglNode *node_below = gimp_layer_get_node (layer_below);
+
+ gegl_node_disconnect (node, "input");
+ gegl_node_connect_to (node_below, "output",
+ node_above, "input");
+ }
+ else
+ {
+ gegl_node_disconnect (node_above, "input");
+ }
+ }
+}
+
/* layers / channels / vectors */
@@ -2941,6 +3103,9 @@
gimp_container_insert (image->layers, GIMP_OBJECT (layer), position);
g_object_unref (layer);
+ if (! gimp_layer_is_floating_sel (layer) && image->graph)
+ gimp_image_add_layer_node (image, layer);
+
/* notify the layers dialog of the currently active layer */
gimp_image_set_active_layer (image, layer);
@@ -3003,6 +3168,13 @@
if (layer == active_layer)
gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (layer));
+ if (! gimp_layer_is_floating_sel (layer) && image->graph)
+ {
+ gimp_image_remove_layer_node (image, layer);
+
+ gegl_node_remove_child (image->graph, gimp_layer_get_node (layer));
+ }
+
gimp_container_remove (image->layers, GIMP_OBJECT (layer));
image->layer_stack = g_slist_remove (image->layer_stack, layer);
@@ -3226,8 +3398,14 @@
if (push_undo)
gimp_image_undo_push_layer_reposition (image, undo_desc, layer);
+ if (! gimp_layer_is_floating_sel (layer) && image->graph)
+ gimp_image_remove_layer_node (image, layer);
+
gimp_container_reorder (image->layers, GIMP_OBJECT (layer), new_index);
+ if (! gimp_layer_is_floating_sel (layer) && image->graph)
+ gimp_image_add_layer_node (image, layer);
+
if (gimp_item_get_visible (GIMP_ITEM (layer)))
{
gint off_x, off_y;
Modified: trunk/app/core/gimpimage.h
==============================================================================
--- trunk/app/core/gimpimage.h (original)
+++ trunk/app/core/gimpimage.h Fri Oct 10 12:24:56 2008
@@ -411,6 +411,7 @@
/* projection */
GimpProjection * gimp_image_get_projection (const GimpImage *image);
+GeglNode * gimp_image_get_graph (GimpImage *image);
/* layers / channels / vectors */
Modified: trunk/app/core/gimpprojection-construct.c
==============================================================================
--- trunk/app/core/gimpprojection-construct.c (original)
+++ trunk/app/core/gimpprojection-construct.c Fri Oct 10 12:24:56 2008
@@ -41,6 +41,11 @@
/* local function prototypes */
+static void gimp_projection_construct_gegl (GimpProjection *proj,
+ gint x,
+ gint y,
+ gint w,
+ gint h);
static void gimp_projection_construct_layers (GimpProjection *proj,
gint x,
gint y,
@@ -150,7 +155,11 @@
/* call functions which process the list of layers and
* the list of channels
*/
- gimp_projection_construct_layers (proj, x, y, w, h);
+ if (FALSE)
+ gimp_projection_construct_gegl (proj, x, y, w, h);
+ else
+ gimp_projection_construct_layers (proj, x, y, w, h);
+
gimp_projection_construct_channels (proj, x, y, w, h);
}
@@ -158,6 +167,33 @@
/* private functions */
static void
+gimp_projection_construct_gegl (GimpProjection *proj,
+ gint x,
+ gint y,
+ gint w,
+ gint h)
+{
+ GeglNode *sink;
+ GeglProcessor *processor;
+ GeglRectangle rect;
+
+ sink = gimp_projection_get_sink_node (proj);
+
+ rect.x = x;
+ rect.y = y;
+ rect.width = w;
+ rect.height = h;
+
+ processor = gegl_node_new_processor (sink, &rect);
+
+ while (gegl_processor_work (processor, NULL));
+
+ g_object_unref (processor);
+
+ proj->construct_flag = TRUE;
+}
+
+static void
gimp_projection_construct_layers (GimpProjection *proj,
gint x,
gint y,
Modified: trunk/app/core/gimpprojection.c
==============================================================================
--- trunk/app/core/gimpprojection.c (original)
+++ trunk/app/core/gimpprojection.c Fri Oct 10 12:24:56 2008
@@ -46,6 +46,13 @@
};
+#ifdef __GNUC__
+#warning FIXME: gegl_node_add_child() needs to be public
+#endif
+GeglNode * gegl_node_add_child (GeglNode *self,
+ GeglNode *child);
+
+
/* local function prototypes */
static void gimp_projection_pickable_iface_init (GimpPickableInterface *iface);
@@ -185,6 +192,13 @@
proj->pyramid = NULL;
}
+ if (proj->graph)
+ {
+ g_object_unref (proj->graph);
+ proj->graph = NULL;
+ proj->sink_node = NULL;
+ }
+
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -317,6 +331,38 @@
}
+GeglNode *
+gimp_projection_get_sink_node (GimpProjection *proj)
+{
+ GeglNode *image_graph;
+
+ g_return_val_if_fail (GIMP_IS_PROJECTION (proj), NULL);
+
+ if (proj->sink_node)
+ return proj->sink_node;
+
+ proj->graph = gegl_node_new ();
+
+ g_object_set (proj->graph,
+ "dont-cache", TRUE,
+ NULL);
+
+ image_graph = gimp_image_get_graph (proj->image);
+ gegl_node_add_child (proj->graph, image_graph);
+
+ proj->sink_node =
+ gegl_node_new_child (proj->graph,
+ "operation", "gimp-tilemanager-sink",
+ "tile-manager", gimp_projection_get_tiles (proj),
+ "linear", TRUE,
+ NULL);
+
+ gegl_node_connect_to (image_graph, "output",
+ proj->sink_node, "input");
+
+ return proj->sink_node;
+}
+
TileManager *
gimp_projection_get_tiles_at_level (GimpProjection *proj,
gint level,
@@ -333,6 +379,15 @@
tile_pyramid_set_validate_proc (proj->pyramid,
(TileValidateProc) gimp_projection_validate_tile,
proj);
+
+ if (proj->sink_node)
+ {
+ TileManager *tiles = tile_pyramid_get_tiles (proj->pyramid, 0, NULL);
+
+ gegl_node_set (proj->sink_node,
+ "tile-manager", tiles,
+ NULL);
+ }
}
return tile_pyramid_get_tiles (proj->pyramid, level, is_premult);
Modified: trunk/app/core/gimpprojection.h
==============================================================================
--- trunk/app/core/gimpprojection.h (original)
+++ trunk/app/core/gimpprojection.h Fri Oct 10 12:24:56 2008
@@ -56,6 +56,8 @@
GimpImage *image;
TilePyramid *pyramid;
+ GeglNode *graph;
+ GeglNode *sink_node;
GSList *update_areas;
GimpProjectionIdleRender idle_render;
@@ -82,6 +84,7 @@
GimpProjection * gimp_projection_new (GimpImage *image);
TileManager * gimp_projection_get_tiles (GimpProjection *proj);
+GeglNode * gimp_projection_get_sink_node (GimpProjection *proj);
TileManager * gimp_projection_get_tiles_at_level
(GimpProjection *proj,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]