diff --git a/app/core/gimpdrawable-private.h b/app/core/gimpdrawable-private.h index bfe9d3829e..b7b8754b8c 100644 --- a/app/core/gimpdrawable-private.h +++ b/app/core/gimpdrawable-private.h @@ -32,6 +32,8 @@ struct _GimpDrawablePrivate GeglNode *fs_mode_node; GeglNode *mode_node; + + gboolean is_last_node; }; #endif /* __GIMP_DRAWABLE_PRIVATE_H__ */ diff --git a/app/core/gimpdrawable.c b/app/core/gimpdrawable.c index 28b4fc1822..b34852e332 100644 --- a/app/core/gimpdrawable.c +++ b/app/core/gimpdrawable.c @@ -61,6 +61,12 @@ enum LAST_SIGNAL }; +enum +{ + PROP_0, + PROP_IS_LAST_NODE +}; + /* local function prototypes */ @@ -68,6 +74,14 @@ static void gimp_drawable_pickable_iface_init (GimpPickableInterface *iface); static void gimp_drawable_dispose (GObject *object); static void gimp_drawable_finalize (GObject *object); +static void gimp_drawable_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_drawable_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); static gint64 gimp_drawable_get_memsize (GimpObject *object, gint64 *gui_size); @@ -212,6 +226,8 @@ gimp_drawable_class_init (GimpDrawableClass *klass) object_class->dispose = gimp_drawable_dispose; object_class->finalize = gimp_drawable_finalize; + object_class->set_property = gimp_drawable_set_property; + object_class->get_property = gimp_drawable_get_property; gimp_object_class->get_memsize = gimp_drawable_get_memsize; @@ -242,6 +258,12 @@ gimp_drawable_class_init (GimpDrawableClass *klass) klass->push_undo = gimp_drawable_real_push_undo; klass->swap_pixels = gimp_drawable_real_swap_pixels; + g_object_class_install_property (object_class, PROP_IS_LAST_NODE, + g_param_spec_boolean ("is-last-node", + NULL, NULL, + FALSE, + GIMP_PARAM_READWRITE)); + g_type_class_add_private (klass, sizeof (GimpDrawablePrivate)); } @@ -298,6 +320,46 @@ gimp_drawable_finalize (GObject *object) G_OBJECT_CLASS (parent_class)->finalize (object); } +static void +gimp_drawable_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GimpDrawable *drawable = GIMP_DRAWABLE (object); + + switch (property_id) + { + case PROP_IS_LAST_NODE: + drawable->private->is_last_node = g_value_get_boolean (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gimp_drawable_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GimpDrawable *drawable = GIMP_DRAWABLE (object); + + switch (property_id) + { + case PROP_IS_LAST_NODE: + g_value_set_boolean (value, drawable->private->is_last_node); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + static gint64 gimp_drawable_get_memsize (GimpObject *object, gint64 *gui_size) @@ -1318,6 +1380,28 @@ gimp_drawable_get_mode_node (GimpDrawable *drawable) return drawable->private->mode_node; } +void +gimp_drawable_set_is_last_node (GimpDrawable *drawable, + gboolean last_node) +{ + g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); + + if (last_node != drawable->private->is_last_node) + { + g_object_set (drawable, + "is-last-node", last_node ? TRUE : FALSE, + NULL); + } +} + +gboolean +gimp_drawable_get_is_last_node (GimpDrawable *drawable) +{ + g_return_val_if_fail (GIMP_IS_DRAWABLE (drawable), FALSE); + + return drawable->private->is_last_node; +} + void gimp_drawable_swap_pixels (GimpDrawable *drawable, GeglBuffer *buffer, diff --git a/app/core/gimpdrawable.h b/app/core/gimpdrawable.h index 06485cb958..339a6b8b89 100644 --- a/app/core/gimpdrawable.h +++ b/app/core/gimpdrawable.h @@ -180,6 +180,10 @@ void gimp_drawable_set_buffer_full (GimpDrawable *drawable, GeglNode * gimp_drawable_get_source_node (GimpDrawable *drawable); GeglNode * gimp_drawable_get_mode_node (GimpDrawable *drawable); +void gimp_drawable_set_is_last_node (GimpDrawable *drawable, + gboolean last_node); +gboolean gimp_drawable_get_is_last_node (GimpDrawable *drawable); + void gimp_drawable_swap_pixels (GimpDrawable *drawable, GeglBuffer *buffer, gint x, diff --git a/app/core/gimpdrawablestack.c b/app/core/gimpdrawablestack.c index 0d12a1fbca..33b86a49f7 100644 --- a/app/core/gimpdrawablestack.c +++ b/app/core/gimpdrawablestack.c @@ -235,6 +235,9 @@ gimp_drawable_stack_get_graph (GimpDrawableStack *stack) GimpDrawable *drawable = list->data; reverse_list = g_list_prepend (reverse_list, drawable); + + if (! g_list_next (list)) + gimp_drawable_set_is_last_node (drawable, TRUE); } stack->graph = gegl_node_new (); @@ -271,6 +274,7 @@ static void gimp_drawable_stack_add_node (GimpDrawableStack *stack, GimpDrawable *drawable) { + GimpDrawable *drawable_above = NULL; GimpDrawable *drawable_below; GeglNode *node_above; GeglNode *node; @@ -287,8 +291,6 @@ gimp_drawable_stack_add_node (GimpDrawableStack *stack, } else { - GimpDrawable *drawable_above; - drawable_above = (GimpDrawable *) gimp_container_get_child_by_index (GIMP_CONTAINER (stack), index - 1); @@ -308,12 +310,20 @@ gimp_drawable_stack_add_node (GimpDrawableStack *stack, gegl_node_connect_to (node_below, "output", node, "input"); } + else + { + if (drawable_above) + gimp_drawable_set_is_last_node (drawable_above, FALSE); + + gimp_drawable_set_is_last_node (drawable, TRUE); + } } static void gimp_drawable_stack_remove_node (GimpDrawableStack *stack, GimpDrawable *drawable) { + GimpDrawable *drawable_above = NULL; GimpDrawable *drawable_below; GeglNode *node_above; GeglNode *node; @@ -330,8 +340,6 @@ gimp_drawable_stack_remove_node (GimpDrawableStack *stack, } else { - GimpDrawable *drawable_above; - drawable_above = (GimpDrawable *) gimp_container_get_child_by_index (GIMP_CONTAINER (stack), index - 1); @@ -352,6 +360,11 @@ gimp_drawable_stack_remove_node (GimpDrawableStack *stack, else { gegl_node_disconnect (node_above, "input"); + + gimp_drawable_set_is_last_node (drawable, FALSE); + + if (drawable_above) + gimp_drawable_set_is_last_node (drawable_above, TRUE); } } diff --git a/app/core/gimplayer.c b/app/core/gimplayer.c index 2525d20dfb..1329577969 100644 --- a/app/core/gimplayer.c +++ b/app/core/gimplayer.c @@ -85,6 +85,8 @@ static void gimp_layer_get_property (GObject *object, GParamSpec *pspec); static void gimp_layer_dispose (GObject *object); static void gimp_layer_finalize (GObject *object); +static void gimp_layer_notify (GObject *object, + GParamSpec *pspec); static void gimp_layer_name_changed (GimpObject *object); static gint64 gimp_layer_get_memsize (GimpObject *object, @@ -264,6 +266,7 @@ gimp_layer_class_init (GimpLayerClass *klass) object_class->get_property = gimp_layer_get_property; object_class->dispose = gimp_layer_dispose; object_class->finalize = gimp_layer_finalize; + object_class->notify = gimp_layer_notify; gimp_object_class->name_changed = gimp_layer_name_changed; gimp_object_class->get_memsize = gimp_layer_get_memsize; @@ -466,6 +469,39 @@ gimp_layer_finalize (GObject *object) G_OBJECT_CLASS (parent_class)->finalize (object); } +static GimpLayerModeEffects +gimp_layer_get_visible_mode (GimpLayer *layer) +{ + if (layer->mode != GIMP_DISSOLVE_MODE && + gimp_drawable_get_is_last_node (GIMP_DRAWABLE (layer))) + return GIMP_NORMAL_MODE; + + return layer->mode; +} + +static void +gimp_layer_notify (GObject *object, + GParamSpec *pspec) +{ + if (! strcmp (pspec->name, "is-last-node") && + gimp_item_peek_node (GIMP_ITEM (object))) + { + GimpLayer *layer = GIMP_LAYER (object); + GeglNode *mode_node; + + mode_node = gimp_drawable_get_mode_node (GIMP_DRAWABLE (layer)); + + gimp_gegl_mode_node_set (mode_node, + gimp_layer_get_visible_mode (layer), + layer->opacity, FALSE); + + gimp_drawable_update (GIMP_DRAWABLE (layer), + 0, 0, + gimp_item_get_width (GIMP_ITEM (layer)), + gimp_item_get_height (GIMP_ITEM (layer))); + } +} + static void gimp_layer_name_changed (GimpObject *object) { @@ -880,7 +916,9 @@ gimp_layer_get_node (GimpItem *item) */ mode_node = gimp_drawable_get_mode_node (drawable); - gimp_gegl_mode_node_set (mode_node, layer->mode, layer->opacity, FALSE); + gimp_gegl_mode_node_set (mode_node, + gimp_layer_get_visible_mode (layer), + layer->opacity, FALSE); /* the layer's offset node */ layer->layer_offset_node = gegl_node_new_child (node, @@ -1944,7 +1982,8 @@ gimp_layer_set_opacity (GimpLayer *layer, mode_node = gimp_drawable_get_mode_node (GIMP_DRAWABLE (layer)); gimp_gegl_mode_node_set (mode_node, - layer->mode, layer->opacity, FALSE); + gimp_layer_get_visible_mode (layer), + layer->opacity, FALSE); } gimp_drawable_update (GIMP_DRAWABLE (layer), @@ -1990,7 +2029,8 @@ gimp_layer_set_mode (GimpLayer *layer, mode_node = gimp_drawable_get_mode_node (GIMP_DRAWABLE (layer)); gimp_gegl_mode_node_set (mode_node, - layer->mode, layer->opacity, FALSE); + gimp_layer_get_visible_mode (layer), + layer->opacity, FALSE); } gimp_drawable_update (GIMP_DRAWABLE (layer),