Address Bug 554983 – Layers Projection using GEGL
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. svn path=/trunk/; revision=27204
This commit is contained in:
parent
511d9c6581
commit
517e58cdeb
9 changed files with 265 additions and 2 deletions
28
ChangeLog
28
ChangeLog
|
|
@ -1,3 +1,31 @@
|
|||
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.
|
||||
|
||||
2008-10-09 Michael Natterer <mitch@gimp.org>
|
||||
|
||||
Add GEGL_CFLAGS and #includes as if gimpdrawable.h and gimpimage.h
|
||||
|
|
|
|||
|
|
@ -261,6 +261,12 @@ gimp_drawable_finalize (GObject *object)
|
|||
|
||||
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 @@ gimp_drawable_real_set_tiles (GimpDrawable *drawable,
|
|||
|
||||
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 @@ gimp_drawable_configure (GimpDrawable *drawable,
|
|||
/* 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_drawable_set_tiles_full (GimpDrawable *drawable,
|
|||
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,
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ struct _GimpDrawable
|
|||
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 @@ void gimp_drawable_set_tiles_full (GimpDrawable *drawable,
|
|||
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,
|
||||
|
|
|
|||
|
|
@ -891,6 +891,12 @@ gimp_image_finalize (GObject *object)
|
|||
image->projection = NULL;
|
||||
}
|
||||
|
||||
if (image->graph)
|
||||
{
|
||||
g_object_unref (image->graph);
|
||||
image->graph = NULL;
|
||||
}
|
||||
|
||||
if (image->colormap)
|
||||
{
|
||||
g_free (image->colormap);
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@ struct _GimpImage
|
|||
GimpTattoo tattoo_state; /* the last used tattoo */
|
||||
|
||||
GimpProjection *projection; /* projection layers & channels */
|
||||
GeglNode *graph; /* GEGL projection graph */
|
||||
|
||||
GList *guides; /* guides */
|
||||
GimpGrid *grid; /* grid */
|
||||
|
|
|
|||
|
|
@ -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 @@ enum
|
|||
};
|
||||
|
||||
|
||||
#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 @@ gimp_layer_finalize (GObject *object)
|
|||
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 @@ gimp_layer_translate (GimpItem *item,
|
|||
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_add_mask (GimpLayer *layer,
|
|||
|
||||
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 @@ gimp_layer_apply_mask (GimpLayer *layer,
|
|||
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 @@ gimp_layer_is_floating_sel (const GimpLayer *layer)
|
|||
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 @@ gimp_layer_set_opacity (GimpLayer *layer,
|
|||
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 @@ gimp_layer_set_mode (GimpLayer *layer,
|
|||
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)),
|
||||
|
|
|
|||
|
|
@ -43,6 +43,12 @@ struct _GimpLayer
|
|||
|
||||
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 @@ GimpLayerMask * gimp_layer_get_mask (const GimpLayer *layer);
|
|||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -85,3 +85,42 @@ gimp_bpp_to_babl_format_linear (guint bpp)
|
|||
|
||||
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";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
Loading…
Reference in a new issue