mirror of https://github.com/GNOME/gimp.git
The GEGL projection does floating selections now:
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... svn path=/trunk/; revision=27961
This commit is contained in:
parent
abe3230755
commit
785eef1af9
27
ChangeLog
27
ChangeLog
|
@ -1,3 +1,30 @@
|
||||||
|
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...
|
||||||
|
|
||||||
2009-01-26 Michael Natterer <mitch@gimp.org>
|
2009-01-26 Michael Natterer <mitch@gimp.org>
|
||||||
|
|
||||||
* app/core/gimpdrawable.c (gimp_drawable_visibility_changed):
|
* app/core/gimpdrawable.c (gimp_drawable_visibility_changed):
|
||||||
|
|
|
@ -150,6 +150,12 @@ static void gimp_drawable_real_swap_pixels (GimpDrawable *drawable,
|
||||||
gint width,
|
gint width,
|
||||||
gint height);
|
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_DEFINE_TYPE_WITH_CODE (GimpDrawable, gimp_drawable, GIMP_TYPE_ITEM,
|
||||||
G_IMPLEMENT_INTERFACE (GIMP_TYPE_PICKABLE,
|
G_IMPLEMENT_INTERFACE (GIMP_TYPE_PICKABLE,
|
||||||
|
@ -250,6 +256,9 @@ gimp_drawable_finalize (GObject *object)
|
||||||
{
|
{
|
||||||
GimpDrawable *drawable = GIMP_DRAWABLE (object);
|
GimpDrawable *drawable = GIMP_DRAWABLE (object);
|
||||||
|
|
||||||
|
if (drawable->fs_opacity_node)
|
||||||
|
gimp_drawable_sync_source_node (drawable, TRUE);
|
||||||
|
|
||||||
if (drawable->tiles)
|
if (drawable->tiles)
|
||||||
{
|
{
|
||||||
tile_manager_unref (drawable->tiles);
|
tile_manager_unref (drawable->tiles);
|
||||||
|
@ -672,12 +681,12 @@ gimp_drawable_real_update (GimpDrawable *drawable,
|
||||||
gint width,
|
gint width,
|
||||||
gint height)
|
gint height)
|
||||||
{
|
{
|
||||||
if (drawable->source_node)
|
if (drawable->tile_source_node)
|
||||||
{
|
{
|
||||||
GObject *operation;
|
GObject *operation;
|
||||||
GeglRectangle rect;
|
GeglRectangle rect;
|
||||||
|
|
||||||
g_object_get (drawable->source_node,
|
g_object_get (drawable->tile_source_node,
|
||||||
"gegl-operation", &operation,
|
"gegl-operation", &operation,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
@ -757,8 +766,8 @@ gimp_drawable_real_set_tiles (GimpDrawable *drawable,
|
||||||
if (old_has_alpha != gimp_drawable_has_alpha (drawable))
|
if (old_has_alpha != gimp_drawable_has_alpha (drawable))
|
||||||
gimp_drawable_alpha_changed (drawable);
|
gimp_drawable_alpha_changed (drawable);
|
||||||
|
|
||||||
if (drawable->source_node)
|
if (drawable->tile_source_node)
|
||||||
gegl_node_set (drawable->source_node,
|
gegl_node_set (drawable->tile_source_node,
|
||||||
"tile-manager", drawable->tiles,
|
"tile-manager", drawable->tiles,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
@ -888,6 +897,133 @@ gimp_drawable_real_swap_pixels (GimpDrawable *drawable,
|
||||||
gimp_drawable_update (drawable, x, y, width, height);
|
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 */
|
/* public functions */
|
||||||
|
|
||||||
|
@ -932,8 +1068,8 @@ gimp_drawable_configure (GimpDrawable *drawable,
|
||||||
drawable->preview_cache = NULL;
|
drawable->preview_cache = NULL;
|
||||||
drawable->preview_valid = FALSE;
|
drawable->preview_valid = FALSE;
|
||||||
|
|
||||||
if (drawable->source_node)
|
if (drawable->tile_source_node)
|
||||||
gegl_node_set (drawable->source_node,
|
gegl_node_set (drawable->tile_source_node,
|
||||||
"tile-manager", drawable->tiles,
|
"tile-manager", drawable->tiles,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
@ -1239,13 +1375,16 @@ gimp_drawable_get_source_node (GimpDrawable *drawable)
|
||||||
if (drawable->source_node)
|
if (drawable->source_node)
|
||||||
return drawable->source_node;
|
return drawable->source_node;
|
||||||
|
|
||||||
drawable->source_node = g_object_new (GEGL_TYPE_NODE,
|
drawable->source_node = gegl_node_new ();
|
||||||
"operation", "gimp:tilemanager-source",
|
|
||||||
NULL);
|
drawable->tile_source_node =
|
||||||
gegl_node_set (drawable->source_node,
|
gegl_node_new_child (drawable->source_node,
|
||||||
"tile-manager", drawable->tiles,
|
"operation", "gimp:tilemanager-source",
|
||||||
"linear", TRUE,
|
"tile-manager", drawable->tiles,
|
||||||
NULL);
|
"linear", TRUE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
gimp_drawable_sync_source_node (drawable, FALSE);
|
||||||
|
|
||||||
return drawable->source_node;
|
return drawable->source_node;
|
||||||
}
|
}
|
||||||
|
@ -1654,3 +1793,44 @@ gimp_drawable_get_colormap (const GimpDrawable *drawable)
|
||||||
|
|
||||||
return image ? gimp_image_get_colormap (image) : NULL;
|
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));
|
||||||
|
}
|
||||||
|
|
|
@ -40,6 +40,10 @@ struct _GimpDrawable
|
||||||
TileManager *shadow; /* shadow buffer tiles */
|
TileManager *shadow; /* shadow buffer tiles */
|
||||||
|
|
||||||
GeglNode *source_node;
|
GeglNode *source_node;
|
||||||
|
GeglNode *tile_source_node;
|
||||||
|
GeglNode *fs_opacity_node;
|
||||||
|
GeglNode *fs_offset_node;
|
||||||
|
GeglNode *fs_mode_node;
|
||||||
|
|
||||||
GeglNode *mode_node;
|
GeglNode *mode_node;
|
||||||
|
|
||||||
|
@ -248,5 +252,10 @@ gboolean gimp_drawable_has_floating_sel (const GimpDrawable *drawable);
|
||||||
|
|
||||||
const guchar * gimp_drawable_get_colormap (const GimpDrawable *drawable);
|
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__ */
|
#endif /* __GIMP_DRAWABLE_H__ */
|
||||||
|
|
|
@ -114,11 +114,14 @@ gimp_floating_sel_undo_pop (GimpUndo *undo,
|
||||||
|
|
||||||
/* clear the selection */
|
/* clear the selection */
|
||||||
gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (floating_layer));
|
gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (floating_layer));
|
||||||
|
|
||||||
|
gimp_drawable_attach_floating_sel (floating_layer->fs.drawable,
|
||||||
|
floating_layer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Update the preview for the underlying drawable */
|
gimp_drawable_detach_floating_sel (floating_layer->fs.drawable,
|
||||||
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (floating_layer));
|
floating_layer);
|
||||||
|
|
||||||
/* clear the selection */
|
/* clear the selection */
|
||||||
gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (floating_layer));
|
gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (floating_layer));
|
||||||
|
|
|
@ -2969,7 +2969,11 @@ gimp_image_add_layer (GimpImage *image,
|
||||||
|
|
||||||
/* If the layer is a floating selection, set the fs pointer */
|
/* If the layer is a floating selection, set the fs pointer */
|
||||||
if (gimp_layer_is_floating_sel (layer))
|
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))
|
if (old_has_alpha != gimp_image_has_alpha (image))
|
||||||
image->flush_accum.alpha_changed = TRUE;
|
image->flush_accum.alpha_changed = TRUE;
|
||||||
|
@ -3019,16 +3023,11 @@ gimp_image_remove_layer (GimpImage *image,
|
||||||
|
|
||||||
old_has_alpha = gimp_image_has_alpha (image);
|
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");
|
undo_desc = _("Remove Floating Selection");
|
||||||
|
|
||||||
/* Invalidate the preview of the obscured drawable. We do this here
|
gimp_drawable_detach_floating_sel (layer->fs.drawable, layer);
|
||||||
* 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));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -139,8 +139,7 @@ floating_sel_to_layer (GimpLayer *layer,
|
||||||
|
|
||||||
gimp_image_undo_push_fs_to_layer (image, NULL, layer);
|
gimp_image_undo_push_fs_to_layer (image, NULL, layer);
|
||||||
|
|
||||||
/* clear the selection */
|
gimp_drawable_detach_floating_sel (layer->fs.drawable, layer);
|
||||||
gimp_drawable_invalidate_boundary (GIMP_DRAWABLE (layer));
|
|
||||||
|
|
||||||
/* Set pointers */
|
/* Set pointers */
|
||||||
gimp_layer_set_floating_sel_drawable (layer, NULL);
|
gimp_layer_set_floating_sel_drawable (layer, NULL);
|
||||||
|
|
Loading…
Reference in New Issue