From 8bf314f47ab6f97c94a949da304cc66dfd031009 Mon Sep 17 00:00:00 2001 From: Jehan Date: Tue, 11 Mar 2025 23:10:41 +0100 Subject: [PATCH] app: use the mode node output on a pass-through group with no filter. The call to gimp_drawable_merge_filters() on a group set a buffer to the group layer (a bit like when we rasterize text layer) which was why it worked fine. But when the group had no filter, we didn't have this side effect. So let's make sure we use the mode node output as our merged layer's buffer in such case. Also when the bottom layer (to merge) is a pass-through group, we don't want to disconnect its input. --- app/core/gimpimage-merge.c | 45 +++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/app/core/gimpimage-merge.c b/app/core/gimpimage-merge.c index 9ebc6a6f08..704110bac8 100644 --- a/app/core/gimpimage-merge.c +++ b/app/core/gimpimage-merge.c @@ -432,7 +432,9 @@ gimp_image_merge_group_layer (GimpImage *image, is_pass_through = (gimp_layer_get_mode (GIMP_LAYER (group)) == GIMP_LAYER_MODE_PASS_THROUGH && gimp_item_get_visible (GIMP_ITEM (group))); - if (is_pass_through && gimp_layer_get_opacity (GIMP_LAYER (group)) < 1.0) + if (is_pass_through && + (gimp_layer_get_opacity (GIMP_LAYER (group)) < 1.0 || + ! gimp_drawable_has_visible_filters (GIMP_DRAWABLE (group)))) { GimpDrawable *drawable = GIMP_DRAWABLE (group); GeglNode *mode_node = gimp_drawable_get_mode_node (drawable); @@ -456,12 +458,15 @@ gimp_image_merge_group_layer (GimpImage *image, gimp_image_add_layer (image, layer, parent, index, TRUE); /* Pass-through groups are a very special case. The duplicate works - * out if the original was at full opacity. But with lower opacity, - * what we want is in fact the output of the "gimp:pass-through" mode - * (similar to "gimp:replace") because we can't reproduce the same - * render otherwise. - * This works well, since anyway the merged layer is ensured to be the - * bottomest one on its own level. + * only if both these points are true: + * - The group is at full opacity: with lower opacity, what we want is + * in fact the output of the "gimp:pass-through" mode (similar to + * "gimp:replace") because we can't reproduce the same render + * otherwise. This works well, since anyway the merged layer is + * ensured to be the bottomest one on its own level. + * - The group has filters: gimp_drawable_merge_filters() will + * actually set the end-rendering to the drawable (kinda rasterizing + * the group layer). */ if (pass_through_buffer) { @@ -661,12 +666,13 @@ gimp_image_merge_layers (GimpImage *image, GimpLayer *bottom_layer; GimpLayer *merge_layer; gint position; + gint n_bottom_removed = 0; GeglNode *node; GeglNode *source_node; GeglNode *flatten_node; GeglNode *offset_node; GeglNode *last_node; - GeglNode *last_node_source; + GeglNode *last_node_source = NULL; GimpParasiteList *parasites; GSList *trimmed_list; @@ -857,11 +863,16 @@ gimp_image_merge_layers (GimpImage *image, gegl_node_link_many (source_node, offset_node, NULL); } - /* Disconnect the bottom-layer node's input */ - last_node = gimp_filter_get_node (GIMP_FILTER (bottom_layer)); - last_node_source = gegl_node_get_producer (last_node, "input", NULL); + /* Disconnect the bottom-layer node's input, unless it's a + * pass-through group. + */ + if (gimp_layer_get_mode (bottom_layer) != GIMP_LAYER_MODE_PASS_THROUGH) + { + last_node = gimp_filter_get_node (GIMP_FILTER (bottom_layer)); + last_node_source = gegl_node_get_producer (last_node, "input", NULL); - gegl_node_disconnect (last_node, "input"); + gegl_node_disconnect (last_node, "input"); + } /* Render the graph into the merge layer */ gimp_gegl_apply_operation (NULL, progress, undo_desc, offset_node, @@ -910,9 +921,13 @@ gimp_image_merge_layers (GimpImage *image, { if (iter->data == layers->data) remove = TRUE; - else if (remove) + else if (remove && gimp_item_get_visible (GIMP_ITEM (iter->data))) to_remove = g_list_prepend (to_remove, iter->data); } + + if (layers->data == bottom_layer) + n_bottom_removed = g_list_length (to_remove); + for (iter = to_remove; iter; iter = iter->next) gimp_image_remove_layer (image, iter->data, TRUE, NULL); @@ -945,8 +960,8 @@ gimp_image_merge_layers (GimpImage *image, { /* Add the layer to the image */ gimp_image_add_layer (image, merge_layer, parent, - gimp_container_get_n_children (container) - - position + 1, + gimp_container_get_n_children (container) + + n_bottom_removed - position + 1, TRUE); }