From 2a96d598c38d78e1a5d2f74ce919d1a46c0162ca Mon Sep 17 00:00:00 2001 From: Michael Natterer Date: Thu, 2 Feb 2017 00:38:25 +0100 Subject: [PATCH] app: add internal and PDB API and UI to control a layer's composite mode Largely based on a patch by Ell, with the enum type renamed and various small changes. Adds another axis of configurability to the existing layer mode madness, and is WIP too. --- app/actions/layers-actions.c | 65 +++++++++- app/actions/layers-commands.c | 129 +++++++++++++------- app/actions/layers-commands.h | 3 + app/config/gimpcoreconfig.h | 1 + app/config/gimpdialogconfig.c | 15 +++ app/config/gimpdialogconfig.h | 1 + app/config/gimprc-blurbs.h | 3 + app/core/gimp-edit.c | 2 + app/core/gimpchannel.c | 24 ++-- app/core/gimpdrawable-blend.c | 2 +- app/core/gimpdrawable-bucket-fill.c | 1 + app/core/gimpdrawable-combine.c | 28 +++-- app/core/gimpdrawable-combine.h | 41 +++---- app/core/gimpdrawable-fill.c | 1 + app/core/gimpdrawable-floating-selection.c | 3 +- app/core/gimpdrawable-shadow.c | 1 + app/core/gimpdrawable.c | 23 ++-- app/core/gimpdrawable.h | 2 + app/core/gimpdrawablefilter.c | 54 +++++---- app/core/gimpdrawablefilter.h | 3 +- app/core/gimpdrawableundo.h | 15 +-- app/core/gimpimage-merge.c | 20 ++-- app/core/gimplayer.c | 97 +++++++++++++-- app/core/gimplayer.h | 28 +++-- app/core/gimplayerpropundo.c | 15 ++- app/core/gimplayerpropundo.h | 9 +- app/dialogs/layer-options-dialog.c | 13 ++ app/dialogs/layer-options-dialog.h | 42 +++---- app/gegl/gimp-gegl-nodes.c | 10 +- app/gegl/gimp-gegl-nodes.h | 5 +- app/gegl/gimpapplicator.c | 24 ++-- app/gegl/gimpapplicator.h | 64 +++++----- app/operations/operations-enums.c | 12 +- app/operations/operations-enums.h | 11 +- app/paint/gimppaintcore.c | 3 +- app/pdb/internal-procs.c | 2 +- app/pdb/layer-cmds.c | 113 +++++++++++++++++ app/tools/gimpblendtool.c | 6 +- app/xcf/xcf-load.c | 11 ++ app/xcf/xcf-private.h | 1 + app/xcf/xcf-save.c | 15 +++ libgimp/gimp.def | 3 + libgimp/gimpenums.c.tail | 2 + libgimp/gimpenums.h | 14 +++ libgimp/gimplayer_pdb.c | 66 ++++++++++ libgimp/gimplayer_pdb.h | 133 +++++++++++---------- menus/layers-menu.xml | 7 ++ po/POTFILES.in | 1 + tools/pdbgen/Makefile.am | 1 + tools/pdbgen/enums.pl | 14 +++ tools/pdbgen/pdb/layer.pdb | 50 +++++++- tools/pdbgen/stddefs.pdb | 4 + 52 files changed, 900 insertions(+), 313 deletions(-) diff --git a/app/actions/layers-actions.c b/app/actions/layers-actions.c index 116bd9406f..fb56b4e9ca 100644 --- a/app/actions/layers-actions.c +++ b/app/actions/layers-actions.c @@ -50,6 +50,10 @@ static const GimpActionEntry layers_actions[] = NC_("layers-action", "Layers Menu"), NULL, NULL, NULL, GIMP_HELP_LAYER_DIALOG }, + { "layers-composite-menu", NULL, + NC_("layers-action", "Composite"), NULL, NULL, NULL, + NULL }, + { "layers-color-tag-menu", GIMP_STOCK_CLOSE /* abused */, NC_("layers-action", "Color Tag"), NULL, NULL, NULL, GIMP_HELP_LAYER_COLOR_TAG }, @@ -315,6 +319,34 @@ static const GimpToggleActionEntry layers_toggle_actions[] = GIMP_HELP_LAYER_LOCK_ALPHA }, }; +static const GimpRadioActionEntry layers_composite_actions[] = +{ + { "layers-composite-auto", NULL, + NC_("layers-action", "Auto"), NULL, NULL, + GIMP_LAYER_COMPOSITE_AUTO, + NULL }, + + { "layers-composite-src-over", NULL, + NC_("layers-action", "Source over"), NULL, NULL, + GIMP_LAYER_COMPOSITE_SRC_OVER, + NULL }, + + { "layers-composite-src-atop", NULL, + NC_("layers-action", "Source atop"), NULL, NULL, + GIMP_LAYER_COMPOSITE_SRC_ATOP, + NULL }, + + { "layers-composite-src-in", NULL, + NC_("layers-action", "Source in"), NULL, NULL, + GIMP_LAYER_COMPOSITE_SRC_IN, + NULL }, + + { "layers-composite-dst-atop", NULL, + NC_("layers-action", "Destination atop"), NULL, NULL, + GIMP_LAYER_COMPOSITE_DST_ATOP, + NULL } +}; + static const GimpEnumActionEntry layers_color_tag_actions[] = { { "layers-color-tag-none", GIMP_STOCK_CLOSE /* abused */, @@ -582,6 +614,12 @@ layers_actions_setup (GimpActionGroup *group) layers_toggle_actions, G_N_ELEMENTS (layers_toggle_actions)); + gimp_action_group_add_radio_actions (group, "layers-action", + layers_composite_actions, + G_N_ELEMENTS (layers_composite_actions), + NULL, 0, + G_CALLBACK (layers_composite_cmd_callback)); + gimp_action_group_add_enum_actions (group, "layers-action", layers_color_tag_actions, G_N_ELEMENTS (layers_color_tag_actions), @@ -662,8 +700,25 @@ layers_actions_update (GimpActionGroup *group, if (layer) { - GList *layer_list; - GList *list; + const gchar *action = NULL; + GList *layer_list; + GList *list; + + switch (gimp_layer_get_composite (layer)) + { + case GIMP_LAYER_COMPOSITE_AUTO: + action = "layers-composite-auto"; break; + case GIMP_LAYER_COMPOSITE_SRC_OVER: + action = "layers-composite-src-over"; break; + case GIMP_LAYER_COMPOSITE_SRC_ATOP: + action = "layers-composite-src-atop"; break; + case GIMP_LAYER_COMPOSITE_SRC_IN: + action = "layers-composite-src-in"; break; + case GIMP_LAYER_COMPOSITE_DST_ATOP: + action = "layers-composite-dst-atop"; break; + } + + gimp_action_group_set_action_active (group, action, TRUE); mask = gimp_layer_get_mask (layer); lock_alpha = gimp_layer_get_lock_alpha (layer); @@ -770,6 +825,12 @@ layers_actions_update (GimpActionGroup *group, SET_SENSITIVE ("layers-lock-alpha", can_lock_alpha); SET_ACTIVE ("layers-lock-alpha", lock_alpha); + SET_SENSITIVE ("layers-composite-auto", layer); + SET_SENSITIVE ("layers-composite-src-over", layer); + SET_SENSITIVE ("layers-composite-src-atop", layer); + SET_SENSITIVE ("layers-composite-src-in", layer); + SET_SENSITIVE ("layers-composite-dst-atop", layer); + SET_SENSITIVE ("layers-mask-add", layer && !fs && !ac && !mask && !children); SET_SENSITIVE ("layers-mask-add-button", layer && !fs && !ac && !children); SET_SENSITIVE ("layers-mask-add-last-values", layer && !fs && !ac && !mask && !children); diff --git a/app/actions/layers-commands.c b/app/actions/layers-commands.c index d8d532332e..da4cd23132 100644 --- a/app/actions/layers-commands.c +++ b/app/actions/layers-commands.c @@ -42,6 +42,7 @@ #include "core/gimpimage-undo.h" #include "core/gimpimage-undo-push.h" #include "core/gimpitemundo.h" +#include "core/gimplayerpropundo.h" #include "core/gimplayer-floating-selection.h" #include "core/gimplayer-new.h" #include "core/gimppickable.h" @@ -119,6 +120,7 @@ static void layers_new_callback (GtkWidget *dialog, GimpContext *context, const gchar *layer_name, GimpLayerMode layer_mode, + GimpLayerCompositeMode layer_composite, gdouble layer_opacity, GimpFillType layer_fill_type, gint layer_width, @@ -139,6 +141,7 @@ static void layers_edit_attributes_callback (GtkWidget *dialog, GimpContext *context, const gchar *layer_name, GimpLayerMode layer_mode, + GimpLayerCompositeMode layer_composite, gdouble layer_opacity, GimpFillType layer_fill_type, gint layer_width, @@ -259,6 +262,7 @@ layers_edit_attributes_cmd_callback (GtkAction *action, GIMP_HELP_LAYER_EDIT, gimp_object_get_name (layer), gimp_layer_get_mode (layer), + gimp_layer_get_composite (layer), gimp_layer_get_opacity (layer), 0 /* unused */, gimp_item_get_visible (item), @@ -325,6 +329,7 @@ layers_new_cmd_callback (GtkAction *action, GIMP_HELP_LAYER_NEW, config->layer_new_name, config->layer_new_mode, + config->layer_new_composite_mode, config->layer_new_opacity, config->layer_new_fill_type, TRUE, @@ -1133,6 +1138,34 @@ layers_mode_cmd_callback (GtkAction *action, gimp_image_flush (image); } +void +layers_composite_cmd_callback (GtkAction *action, + GtkAction *current, + gpointer data) +{ + GimpImage *image; + GimpLayer *layer; + GimpLayerCompositeMode composite; + return_if_no_layer (image, layer, data); + + composite = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + + if (composite != gimp_layer_get_composite (layer)) + { + GimpUndo *undo; + gboolean push_undo = TRUE; + + undo = gimp_image_undo_can_compress (image, GIMP_TYPE_LAYER_PROP_UNDO, + GIMP_UNDO_LAYER_MODE); + + if (undo && GIMP_ITEM_UNDO (undo)->item == GIMP_ITEM (layer)) + push_undo = FALSE; + + gimp_layer_set_composite (layer, composite, push_undo); + gimp_image_flush (image); + } +} + void layers_visible_cmd_callback (GtkAction *action, gpointer data) @@ -1221,34 +1254,36 @@ layers_color_tag_cmd_callback (GtkAction *action, /* private functions */ static void -layers_new_callback (GtkWidget *dialog, - GimpImage *image, - GimpLayer *layer, - GimpContext *context, - const gchar *layer_name, - GimpLayerMode layer_mode, - gdouble layer_opacity, - GimpFillType layer_fill_type, - gint layer_width, - gint layer_height, - gint layer_offset_x, - gint layer_offset_y, - gboolean layer_visible, - gboolean layer_linked, - GimpColorTag layer_color_tag, - gboolean layer_lock_pixels, - gboolean layer_lock_position, - gboolean layer_lock_alpha, - gboolean rename_text_layer, /* unused */ - gpointer user_data) +layers_new_callback (GtkWidget *dialog, + GimpImage *image, + GimpLayer *layer, + GimpContext *context, + const gchar *layer_name, + GimpLayerMode layer_mode, + GimpLayerCompositeMode layer_composite, + gdouble layer_opacity, + GimpFillType layer_fill_type, + gint layer_width, + gint layer_height, + gint layer_offset_x, + gint layer_offset_y, + gboolean layer_visible, + gboolean layer_linked, + GimpColorTag layer_color_tag, + gboolean layer_lock_pixels, + gboolean layer_lock_position, + gboolean layer_lock_alpha, + gboolean rename_text_layer, /* unused */ + gpointer user_data) { GimpDialogConfig *config = GIMP_DIALOG_CONFIG (image->gimp->config); g_object_set (config, - "layer-new-name", layer_name, - "layer-new-mode", layer_mode, - "layer-new-opacity", layer_opacity, - "layer-new-fill-type", layer_fill_type, + "layer-new-name", layer_name, + "layer-new-mode", layer_mode, + "layer-new-composite-mode", layer_composite, + "layer-new-opacity", layer_opacity, + "layer-new-fill-type", layer_fill_type, NULL); layer = gimp_layer_new (image, layer_width, layer_height, @@ -1270,6 +1305,7 @@ layers_new_callback (GtkWidget *dialog, gimp_item_set_lock_position (GIMP_ITEM (layer), layer_lock_position, FALSE); gimp_layer_set_lock_alpha (layer, layer_lock_alpha, FALSE); + gimp_layer_set_composite (layer, layer_composite, FALSE); gimp_image_add_layer (image, layer, GIMP_IMAGE_ACTIVE_PARENT, -1, TRUE); @@ -1284,31 +1320,33 @@ layers_new_callback (GtkWidget *dialog, } static void -layers_edit_attributes_callback (GtkWidget *dialog, - GimpImage *image, - GimpLayer *layer, - GimpContext *context, - const gchar *layer_name, - GimpLayerMode layer_mode, - gdouble layer_opacity, - GimpFillType unused1, - gint unused2, - gint unused3, - gint layer_offset_x, - gint layer_offset_y, - gboolean layer_visible, - gboolean layer_linked, - GimpColorTag layer_color_tag, - gboolean layer_lock_pixels, - gboolean layer_lock_position, - gboolean layer_lock_alpha, - gboolean rename_text_layer, - gpointer user_data) +layers_edit_attributes_callback (GtkWidget *dialog, + GimpImage *image, + GimpLayer *layer, + GimpContext *context, + const gchar *layer_name, + GimpLayerMode layer_mode, + GimpLayerCompositeMode layer_composite, + gdouble layer_opacity, + GimpFillType unused1, + gint unused2, + gint unused3, + gint layer_offset_x, + gint layer_offset_y, + gboolean layer_visible, + gboolean layer_linked, + GimpColorTag layer_color_tag, + gboolean layer_lock_pixels, + gboolean layer_lock_position, + gboolean layer_lock_alpha, + gboolean rename_text_layer, + gpointer user_data) { GimpItem *item = GIMP_ITEM (layer); if (strcmp (layer_name, gimp_object_get_name (layer)) || layer_mode != gimp_layer_get_mode (layer) || + layer_composite != gimp_layer_get_composite (layer) || layer_opacity != gimp_layer_get_opacity (layer) || layer_offset_x != gimp_item_get_offset_x (item) || layer_offset_y != gimp_item_get_offset_y (item) || @@ -1339,6 +1377,9 @@ layers_edit_attributes_callback (GtkWidget *dialog, if (layer_mode != gimp_layer_get_mode (layer)) gimp_layer_set_mode (layer, layer_mode, TRUE); + if (layer_composite != gimp_layer_get_composite (layer)) + gimp_layer_set_composite (layer, layer_composite, TRUE); + if (layer_opacity != gimp_layer_get_opacity (layer)) gimp_layer_set_opacity (layer, layer_opacity, TRUE); diff --git a/app/actions/layers-commands.h b/app/actions/layers-commands.h index 32db8395e5..27d3e72c0b 100644 --- a/app/actions/layers-commands.h +++ b/app/actions/layers-commands.h @@ -106,6 +106,9 @@ void layers_opacity_cmd_callback (GtkAction *action, void layers_mode_cmd_callback (GtkAction *action, gint value, gpointer data); +void layers_composite_cmd_callback (GtkAction *action, + GtkAction *current, + gpointer data); void layers_visible_cmd_callback (GtkAction *action, gpointer data); diff --git a/app/config/gimpcoreconfig.h b/app/config/gimpcoreconfig.h index d63ada2b8e..3ccbf1280d 100644 --- a/app/config/gimpcoreconfig.h +++ b/app/config/gimpcoreconfig.h @@ -21,6 +21,7 @@ #ifndef __GIMP_CORE_CONFIG_H__ #define __GIMP_CORE_CONFIG_H__ +#include "operations/operations-enums.h" #include "core/core-enums.h" #include "config/gimpgeglconfig.h" diff --git a/app/config/gimpdialogconfig.c b/app/config/gimpdialogconfig.c index e84fb44fbb..554acf5286 100644 --- a/app/config/gimpdialogconfig.c +++ b/app/config/gimpdialogconfig.c @@ -68,6 +68,7 @@ enum PROP_LAYER_NEW_NAME, PROP_LAYER_NEW_MODE, + PROP_LAYER_NEW_COMPOSITE_MODE, PROP_LAYER_NEW_OPACITY, PROP_LAYER_NEW_FILL_TYPE, @@ -302,6 +303,14 @@ gimp_dialog_config_class_init (GimpDialogConfigClass *klass) GIMP_LAYER_MODE_NORMAL, GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_PROP_ENUM (object_class, PROP_LAYER_NEW_COMPOSITE_MODE, + "layer-new-composite-mode", + "Default new layer composite mode", + LAYER_NEW_COMPOSITE_MODE_BLURB, + GIMP_TYPE_LAYER_COMPOSITE_MODE, + GIMP_LAYER_COMPOSITE_AUTO, + GIMP_PARAM_STATIC_STRINGS); + GIMP_CONFIG_PROP_DOUBLE (object_class, PROP_LAYER_NEW_OPACITY, "layer-new-opacity", "Default new layer opacity", @@ -640,6 +649,9 @@ gimp_dialog_config_set_property (GObject *object, case PROP_LAYER_NEW_MODE: config->layer_new_mode = g_value_get_enum (value); break; + case PROP_LAYER_NEW_COMPOSITE_MODE: + config->layer_new_composite_mode = g_value_get_enum (value); + break; case PROP_LAYER_NEW_OPACITY: config->layer_new_opacity = g_value_get_double (value); break; @@ -820,6 +832,9 @@ gimp_dialog_config_get_property (GObject *object, case PROP_LAYER_NEW_MODE: g_value_set_enum (value, config->layer_new_mode); break; + case PROP_LAYER_NEW_COMPOSITE_MODE: + g_value_set_enum (value, config->layer_new_composite_mode); + break; case PROP_LAYER_NEW_OPACITY: g_value_set_double (value, config->layer_new_opacity); break; diff --git a/app/config/gimpdialogconfig.h b/app/config/gimpdialogconfig.h index 55cfcdc2f7..78ea299268 100644 --- a/app/config/gimpdialogconfig.h +++ b/app/config/gimpdialogconfig.h @@ -66,6 +66,7 @@ struct _GimpDialogConfig gchar *layer_new_name; GimpLayerMode layer_new_mode; + GimpLayerCompositeMode layer_new_composite_mode; gdouble layer_new_opacity; GimpFillType layer_new_fill_type; diff --git a/app/config/gimprc-blurbs.h b/app/config/gimprc-blurbs.h index 036b4a55cf..02c2cf874b 100644 --- a/app/config/gimprc-blurbs.h +++ b/app/config/gimprc-blurbs.h @@ -482,6 +482,9 @@ _("Sets the default layer name for the 'New Layer' dialog.") #define LAYER_NEW_MODE_BLURB \ _("Sets the default mode for the 'New Layer' dialog.") +#define LAYER_NEW_COMPOSITE_MODE_BLURB \ +_("Sets the default composite mode for the 'New Layer' dialog.") + #define LAYER_NEW_OPACITY_BLURB \ _("Sets the default opacity for the 'New Layer' dialog.") diff --git a/app/core/gimp-edit.c b/app/core/gimp-edit.c index b622a8f9e4..dc43e05a5e 100644 --- a/app/core/gimp-edit.c +++ b/app/core/gimp-edit.c @@ -623,6 +623,7 @@ gimp_edit_fill (GimpImage *image, TRUE, undo_desc, gimp_context_get_opacity (GIMP_CONTEXT (options)), gimp_context_get_paint_mode (GIMP_CONTEXT (options)), + GIMP_LAYER_COMPOSITE_AUTO, NULL, x, y); g_object_unref (buffer); @@ -661,6 +662,7 @@ gimp_edit_fade (GimpImage *image, gimp_object_get_name (undo), gimp_context_get_opacity (context), gimp_context_get_paint_mode (context), + GIMP_LAYER_COMPOSITE_AUTO, NULL, undo->x, undo->y); g_object_unref (buffer); diff --git a/app/core/gimpchannel.c b/app/core/gimpchannel.c index 2ec9db5033..86cbef4907 100644 --- a/app/core/gimpchannel.c +++ b/app/core/gimpchannel.c @@ -164,6 +164,7 @@ static void gimp_channel_apply_buffer (GimpDrawable *drawable, const gchar *undo_desc, gdouble opacity, GimpLayerMode mode, + GimpLayerCompositeMode composite, GeglBuffer *base_buffer, gint base_x, gint base_y); @@ -1007,23 +1008,24 @@ gimp_channel_get_active_mask (GimpDrawable *drawable) } static void -gimp_channel_apply_buffer (GimpDrawable *drawable, - GeglBuffer *buffer, - const GeglRectangle *buffer_region, - gboolean push_undo, - const gchar *undo_desc, - gdouble opacity, - GimpLayerMode mode, - GeglBuffer *base_buffer, - gint base_x, - gint base_y) +gimp_channel_apply_buffer (GimpDrawable *drawable, + GeglBuffer *buffer, + const GeglRectangle *buffer_region, + gboolean push_undo, + const gchar *undo_desc, + gdouble opacity, + GimpLayerMode mode, + GimpLayerCompositeMode composite, + GeglBuffer *base_buffer, + gint base_x, + gint base_y) { gimp_drawable_invalidate_boundary (drawable); GIMP_DRAWABLE_CLASS (parent_class)->apply_buffer (drawable, buffer, buffer_region, push_undo, undo_desc, - opacity, mode, + opacity, mode, composite, base_buffer, base_x, base_y); diff --git a/app/core/gimpdrawable-blend.c b/app/core/gimpdrawable-blend.c index 50e39a23d3..094affb73a 100644 --- a/app/core/gimpdrawable-blend.c +++ b/app/core/gimpdrawable-blend.c @@ -148,7 +148,7 @@ gimp_drawable_blend (GimpDrawable *drawable, gimp_drawable_apply_buffer (drawable, buffer, GEGL_RECTANGLE (x, y, width, height), TRUE, C_("undo-type", "Blend"), - opacity, paint_mode, + opacity, paint_mode, GIMP_LAYER_COMPOSITE_AUTO, NULL, x, y); gimp_drawable_update (drawable, x, y, width, height); diff --git a/app/core/gimpdrawable-bucket-fill.c b/app/core/gimpdrawable-bucket-fill.c index 568c9c68e0..c196beb0b9 100644 --- a/app/core/gimpdrawable-bucket-fill.c +++ b/app/core/gimpdrawable-bucket-fill.c @@ -180,6 +180,7 @@ gimp_drawable_bucket_fill (GimpDrawable *drawable, TRUE, C_("undo-type", "Bucket Fill"), gimp_context_get_opacity (GIMP_CONTEXT (options)), gimp_context_get_paint_mode (GIMP_CONTEXT (options)), + GIMP_LAYER_COMPOSITE_AUTO, NULL, x, y); g_object_unref (buffer); diff --git a/app/core/gimpdrawable-combine.c b/app/core/gimpdrawable-combine.c index 635a77868a..a285313c0d 100644 --- a/app/core/gimpdrawable-combine.c +++ b/app/core/gimpdrawable-combine.c @@ -40,16 +40,17 @@ void -gimp_drawable_real_apply_buffer (GimpDrawable *drawable, - GeglBuffer *buffer, - const GeglRectangle *buffer_region, - gboolean push_undo, - const gchar *undo_desc, - gdouble opacity, - GimpLayerMode mode, - GeglBuffer *base_buffer, - gint base_x, - gint base_y) +gimp_drawable_real_apply_buffer (GimpDrawable *drawable, + GeglBuffer *buffer, + const GeglRectangle *buffer_region, + gboolean push_undo, + const gchar *undo_desc, + gdouble opacity, + GimpLayerMode mode, + GimpLayerCompositeMode composite, + GeglBuffer *base_buffer, + gint base_x, + gint base_y) { GimpItem *item = GIMP_ITEM (drawable); GimpImage *image = gimp_item_get_image (item); @@ -102,8 +103,9 @@ gimp_drawable_real_apply_buffer (GimpDrawable *drawable, if (undo) { - undo->paint_mode = mode; - undo->opacity = opacity; + undo->paint_mode = mode; + undo->composite_mode = composite; + undo->opacity = opacity; undo->applied_buffer = gegl_buffer_new (GEGL_RECTANGLE (0, 0, width, height), @@ -141,7 +143,7 @@ gimp_drawable_real_apply_buffer (GimpDrawable *drawable, base_y - buffer_region->y); gimp_applicator_set_opacity (applicator, opacity); - gimp_applicator_set_mode (applicator, mode); + gimp_applicator_set_mode (applicator, mode, composite); gimp_applicator_set_affect (applicator, gimp_drawable_get_active_mask (drawable)); diff --git a/app/core/gimpdrawable-combine.h b/app/core/gimpdrawable-combine.h index 9b73208875..09a29adec1 100644 --- a/app/core/gimpdrawable-combine.h +++ b/app/core/gimpdrawable-combine.h @@ -21,26 +21,27 @@ /* virtual functions of GimpDrawable, don't call directly */ -void gimp_drawable_real_apply_buffer (GimpDrawable *drawable, - GeglBuffer *buffer, - const GeglRectangle *buffer_region, - gboolean push_undo, - const gchar *undo_desc, - gdouble opacity, - GimpLayerMode mode, - GeglBuffer *base_buffer, - gint base_x, - gint base_y); -void gimp_drawable_real_replace_buffer (GimpDrawable *drawable, - GeglBuffer *buffer, - const GeglRectangle *buffer_region, - gboolean push_undo, - const gchar *undo_desc, - gdouble opacity, - GeglBuffer *mask, - const GeglRectangle *mask_region, - gint x, - gint y); +void gimp_drawable_real_apply_buffer (GimpDrawable *drawable, + GeglBuffer *buffer, + const GeglRectangle *buffer_region, + gboolean push_undo, + const gchar *undo_desc, + gdouble opacity, + GimpLayerMode mode, + GimpLayerCompositeMode composite, + GeglBuffer *base_buffer, + gint base_x, + gint base_y); +void gimp_drawable_real_replace_buffer (GimpDrawable *drawable, + GeglBuffer *buffer, + const GeglRectangle *buffer_region, + gboolean push_undo, + const gchar *undo_desc, + gdouble opacity, + GeglBuffer *mask, + const GeglRectangle *mask_region, + gint x, + gint y); #endif /* __GIMP_DRAWABLE_COMBINE_H__ */ diff --git a/app/core/gimpdrawable-fill.c b/app/core/gimpdrawable-fill.c index 75566c2261..59937eac12 100644 --- a/app/core/gimpdrawable-fill.c +++ b/app/core/gimpdrawable-fill.c @@ -256,6 +256,7 @@ gimp_drawable_fill_scan_convert (GimpDrawable *drawable, push_undo, C_("undo-type", "Render Stroke"), gimp_context_get_opacity (context), gimp_context_get_paint_mode (context), + GIMP_LAYER_COMPOSITE_AUTO, NULL, x, y); g_object_unref (buffer); diff --git a/app/core/gimpdrawable-floating-selection.c b/app/core/gimpdrawable-floating-selection.c index 0ceff8beb7..e3acecdc01 100644 --- a/app/core/gimpdrawable-floating-selection.c +++ b/app/core/gimpdrawable-floating-selection.c @@ -304,7 +304,8 @@ gimp_drawable_sync_fs_filter (GimpDrawable *drawable) gimp_applicator_set_opacity (private->fs_applicator, gimp_layer_get_opacity (fs)); gimp_applicator_set_mode (private->fs_applicator, - gimp_layer_get_mode (fs)); + gimp_layer_get_mode (fs), + gimp_layer_get_composite (fs)); gimp_applicator_set_affect (private->fs_applicator, gimp_drawable_get_active_mask (drawable)); } diff --git a/app/core/gimpdrawable-shadow.c b/app/core/gimpdrawable-shadow.c index cb6f01fc46..52493fb4da 100644 --- a/app/core/gimpdrawable-shadow.c +++ b/app/core/gimpdrawable-shadow.c @@ -103,6 +103,7 @@ gimp_drawable_merge_shadow_buffer (GimpDrawable *drawable, push_undo, undo_desc, GIMP_OPACITY_OPAQUE, GIMP_LAYER_MODE_REPLACE, + GIMP_LAYER_COMPOSITE_AUTO, NULL, x, y); g_object_unref (buffer); diff --git a/app/core/gimpdrawable.c b/app/core/gimpdrawable.c index 79217fcce5..7c5d80c89a 100644 --- a/app/core/gimpdrawable.c +++ b/app/core/gimpdrawable.c @@ -1097,16 +1097,17 @@ gimp_drawable_convert_type (GimpDrawable *drawable, } void -gimp_drawable_apply_buffer (GimpDrawable *drawable, - GeglBuffer *buffer, - const GeglRectangle *buffer_region, - gboolean push_undo, - const gchar *undo_desc, - gdouble opacity, - GimpLayerMode mode, - GeglBuffer *base_buffer, - gint base_x, - gint base_y) +gimp_drawable_apply_buffer (GimpDrawable *drawable, + GeglBuffer *buffer, + const GeglRectangle *buffer_region, + gboolean push_undo, + const gchar *undo_desc, + gdouble opacity, + GimpLayerMode mode, + GimpLayerCompositeMode composite, + GeglBuffer *base_buffer, + gint base_x, + gint base_y) { g_return_if_fail (GIMP_IS_DRAWABLE (drawable)); g_return_if_fail (gimp_item_is_attached (GIMP_ITEM (drawable))); @@ -1117,7 +1118,7 @@ gimp_drawable_apply_buffer (GimpDrawable *drawable, GIMP_DRAWABLE_GET_CLASS (drawable)->apply_buffer (drawable, buffer, buffer_region, push_undo, undo_desc, - opacity, mode, + opacity, mode, composite, base_buffer, base_x, base_y); } diff --git a/app/core/gimpdrawable.h b/app/core/gimpdrawable.h index 09a33d7954..db23c8145b 100644 --- a/app/core/gimpdrawable.h +++ b/app/core/gimpdrawable.h @@ -76,6 +76,7 @@ struct _GimpDrawableClass const gchar *undo_desc, gdouble opacity, GimpLayerMode mode, + GimpLayerCompositeMode composite, GeglBuffer *base_buffer, gint base_x, gint base_y); @@ -156,6 +157,7 @@ void gimp_drawable_apply_buffer (GimpDrawable *drawable, const gchar *undo_desc, gdouble opacity, GimpLayerMode mode, + GimpLayerCompositeMode composite, GeglBuffer *base_buffer, gint base_x, gint base_y); diff --git a/app/core/gimpdrawablefilter.c b/app/core/gimpdrawablefilter.c index 62a4a31977..9639f63470 100644 --- a/app/core/gimpdrawablefilter.c +++ b/app/core/gimpdrawablefilter.c @@ -57,29 +57,30 @@ enum struct _GimpDrawableFilter { - GimpFilter parent_instance; + GimpFilter parent_instance; - GimpDrawable *drawable; - GeglNode *operation; + GimpDrawable *drawable; + GeglNode *operation; - GimpFilterRegion region; - gboolean preview_enabled; - GimpAlignmentType preview_alignment; - gdouble preview_position; - gdouble opacity; - GimpLayerMode paint_mode; - gboolean color_managed; - gboolean gamma_hack; + GimpFilterRegion region; + gboolean preview_enabled; + GimpAlignmentType preview_alignment; + gdouble preview_position; + gdouble opacity; + GimpLayerMode paint_mode; + GimpLayerCompositeMode composite_mode; + gboolean color_managed; + gboolean gamma_hack; - GeglRectangle filter_area; + GeglRectangle filter_area; - GeglNode *translate; - GeglNode *crop; - GeglNode *cast_before; - GeglNode *transform_before; - GeglNode *transform_after; - GeglNode *cast_after; - GimpApplicator *applicator; + GeglNode *translate; + GeglNode *crop; + GeglNode *cast_before; + GeglNode *transform_before; + GeglNode *transform_after; + GeglNode *cast_after; + GimpApplicator *applicator; }; @@ -149,6 +150,7 @@ gimp_drawable_filter_init (GimpDrawableFilter *drawable_filter) drawable_filter->preview_position = 1.0; drawable_filter->opacity = GIMP_OPACITY_OPAQUE; drawable_filter->paint_mode = GIMP_LAYER_MODE_REPLACE; + drawable_filter->composite_mode = GIMP_LAYER_COMPOSITE_AUTO; } static void @@ -329,14 +331,17 @@ gimp_drawable_filter_set_opacity (GimpDrawableFilter *filter, } void -gimp_drawable_filter_set_mode (GimpDrawableFilter *filter, - GimpLayerMode paint_mode) +gimp_drawable_filter_set_mode (GimpDrawableFilter *filter, + GimpLayerMode paint_mode, + GimpLayerCompositeMode composite_mode) { g_return_if_fail (GIMP_IS_DRAWABLE_FILTER (filter)); - if (paint_mode != filter->paint_mode) + if (paint_mode != filter->paint_mode || + composite_mode != filter->composite_mode) { - filter->paint_mode = paint_mode; + filter->paint_mode = paint_mode; + filter->composite_mode = composite_mode; gimp_drawable_filter_sync_mode (filter); @@ -583,7 +588,8 @@ static void gimp_drawable_filter_sync_mode (GimpDrawableFilter *filter) { gimp_applicator_set_mode (filter->applicator, - filter->paint_mode); + filter->paint_mode, + filter->composite_mode); } static void diff --git a/app/core/gimpdrawablefilter.h b/app/core/gimpdrawablefilter.h index 9e3a11dd4c..3e364c07b9 100644 --- a/app/core/gimpdrawablefilter.h +++ b/app/core/gimpdrawablefilter.h @@ -64,7 +64,8 @@ void gimp_drawable_filter_set_preview (GimpDrawableFilter *filter, void gimp_drawable_filter_set_opacity (GimpDrawableFilter *filter, gdouble opacity); void gimp_drawable_filter_set_mode (GimpDrawableFilter *filter, - GimpLayerMode paint_mode); + GimpLayerMode paint_mode, + GimpLayerCompositeMode composite_mode); void gimp_drawable_filter_set_color_managed (GimpDrawableFilter *filter, diff --git a/app/core/gimpdrawableundo.h b/app/core/gimpdrawableundo.h index ff07b418ec..d355a5a515 100644 --- a/app/core/gimpdrawableundo.h +++ b/app/core/gimpdrawableundo.h @@ -35,16 +35,17 @@ typedef struct _GimpDrawableUndoClass GimpDrawableUndoClass; struct _GimpDrawableUndo { - GimpItemUndo parent_instance; + GimpItemUndo parent_instance; - GeglBuffer *buffer; - gint x; - gint y; + GeglBuffer *buffer; + gint x; + gint y; /* stuff for "Fade" */ - GeglBuffer *applied_buffer; - GimpLayerMode paint_mode; - gdouble opacity; + GeglBuffer *applied_buffer; + GimpLayerMode paint_mode; + GimpLayerCompositeMode composite_mode; + gdouble opacity; }; struct _GimpDrawableUndoClass diff --git a/app/core/gimpimage-merge.c b/app/core/gimpimage-merge.c index 5a8b24e63a..02cc17b743 100644 --- a/app/core/gimpimage-merge.c +++ b/app/core/gimpimage-merge.c @@ -598,10 +598,11 @@ gimp_image_merge_layers (GimpImage *image, for (layers = reverse_list; layers; layers = g_slist_next (layers)) { - GeglBuffer *merge_buffer; - GeglBuffer *layer_buffer; - GimpApplicator *applicator; - GimpLayerMode mode; + GeglBuffer *merge_buffer; + GeglBuffer *layer_buffer; + GimpApplicator *applicator; + GimpLayerMode mode; + GimpLayerCompositeMode composite; layer = layers->data; @@ -611,9 +612,14 @@ gimp_image_merge_layers (GimpImage *image, * work on the projection with the lower layer, but only locally on * the layers alpha channel. */ - mode = gimp_layer_get_mode (layer); + mode = gimp_layer_get_mode (layer); + composite = gimp_layer_get_composite (layer); + if (layer == bottom_layer && mode != GIMP_LAYER_MODE_DISSOLVE) - mode = GIMP_LAYER_MODE_NORMAL; + { + mode = GIMP_LAYER_MODE_NORMAL; + composite = GIMP_LAYER_COMPOSITE_AUTO; + } merge_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (merge_layer)); layer_buffer = gimp_drawable_get_buffer (GIMP_DRAWABLE (layer)); @@ -642,7 +648,7 @@ gimp_image_merge_layers (GimpImage *image, - (y1 - off_y)); gimp_applicator_set_opacity (applicator, gimp_layer_get_opacity (layer)); - gimp_applicator_set_mode (applicator, mode); + gimp_applicator_set_mode (applicator, mode, composite); gimp_applicator_blit (applicator, GEGL_RECTANGLE (0, 0, diff --git a/app/core/gimplayer.c b/app/core/gimplayer.c index b716ba3f2b..bc64f09dad 100644 --- a/app/core/gimplayer.c +++ b/app/core/gimplayer.c @@ -59,6 +59,7 @@ enum { OPACITY_CHANGED, MODE_CHANGED, + COMPOSITE_CHANGED, LOCK_ALPHA_CHANGED, MASK_CHANGED, APPLY_MASK_CHANGED, @@ -72,6 +73,7 @@ enum PROP_0, PROP_OPACITY, PROP_MODE, + PROP_COMPOSITE, PROP_LOCK_ALPHA, PROP_MASK, PROP_FLOATING_SELECTION @@ -247,6 +249,15 @@ gimp_layer_class_init (GimpLayerClass *klass) gimp_marshal_VOID__VOID, G_TYPE_NONE, 0); + layer_signals[COMPOSITE_CHANGED] = + g_signal_new ("composite-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GimpLayerClass, composite_changed), + NULL, NULL, + gimp_marshal_VOID__VOID, + G_TYPE_NONE, 0); + layer_signals[LOCK_ALPHA_CHANGED] = g_signal_new ("lock-alpha-changed", G_TYPE_FROM_CLASS (klass), @@ -348,6 +359,7 @@ gimp_layer_class_init (GimpLayerClass *klass) klass->opacity_changed = NULL; klass->mode_changed = NULL; + klass->composite_changed = NULL; klass->lock_alpha_changed = NULL; klass->mask_changed = NULL; klass->apply_mask_changed = NULL; @@ -367,6 +379,12 @@ gimp_layer_class_init (GimpLayerClass *klass) GIMP_LAYER_MODE_NORMAL, GIMP_PARAM_READABLE)); + g_object_class_install_property (object_class, PROP_COMPOSITE, + g_param_spec_enum ("composite", NULL, NULL, + GIMP_TYPE_LAYER_COMPOSITE_MODE, + GIMP_LAYER_COMPOSITE_AUTO, + GIMP_PARAM_READABLE)); + g_object_class_install_property (object_class, PROP_LOCK_ALPHA, g_param_spec_boolean ("lock-alpha", NULL, NULL, @@ -391,6 +409,7 @@ gimp_layer_init (GimpLayer *layer) { layer->opacity = GIMP_OPACITY_OPAQUE; layer->mode = GIMP_LAYER_MODE_NORMAL; + layer->composite = GIMP_LAYER_COMPOSITE_AUTO; layer->lock_alpha = FALSE; layer->mask = NULL; @@ -449,6 +468,9 @@ gimp_layer_get_property (GObject *object, case PROP_MODE: g_value_set_enum (value, gimp_layer_get_mode (layer)); break; + case PROP_COMPOSITE: + g_value_set_enum (value, gimp_layer_get_composite (layer)); + break; case PROP_LOCK_ALPHA: g_value_set_boolean (value, gimp_layer_get_lock_alpha (layer)); break; @@ -508,29 +530,33 @@ gimp_layer_finalize (GObject *object) static void gimp_layer_update_mode_node (GimpLayer *layer) { - GeglNode *mode_node; - GimpLayerMode visible_mode; + GeglNode *mode_node; + GimpLayerMode visible_mode; + GimpLayerCompositeMode visible_composite; mode_node = gimp_drawable_get_mode_node (GIMP_DRAWABLE (layer)); if (layer->mask && layer->show_mask) { - visible_mode = GIMP_LAYER_MODE_NORMAL; + visible_mode = GIMP_LAYER_MODE_NORMAL; + visible_composite = GIMP_LAYER_COMPOSITE_AUTO; } else { if (layer->mode != GIMP_LAYER_MODE_DISSOLVE && gimp_filter_get_is_last_node (GIMP_FILTER (layer))) { - visible_mode = GIMP_LAYER_MODE_NORMAL; + visible_mode = GIMP_LAYER_MODE_NORMAL; + visible_composite = GIMP_LAYER_COMPOSITE_AUTO; } else { - visible_mode = layer->mode; + visible_mode = layer->mode; + visible_composite = layer->composite; } } - gimp_gegl_mode_node_set_mode (mode_node, visible_mode); + gimp_gegl_mode_node_set_mode (mode_node, visible_mode, visible_composite); gimp_gegl_mode_node_set_opacity (mode_node, layer->opacity); } @@ -747,8 +773,12 @@ gimp_layer_duplicate (GimpItem *item, GimpLayer *layer = GIMP_LAYER (item); GimpLayer *new_layer = GIMP_LAYER (new_item); - gimp_layer_set_mode (new_layer, gimp_layer_get_mode (layer), FALSE); - gimp_layer_set_opacity (new_layer, gimp_layer_get_opacity (layer), FALSE); + gimp_layer_set_mode (new_layer, + gimp_layer_get_mode (layer), FALSE); + gimp_layer_set_composite (new_layer, + gimp_layer_get_composite (layer), FALSE); + gimp_layer_set_opacity (new_layer, + gimp_layer_get_opacity (layer), FALSE); if (gimp_layer_can_lock_alpha (new_layer)) gimp_layer_set_lock_alpha (new_layer, @@ -2051,11 +2081,26 @@ gimp_layer_set_mode (GimpLayer *layer, gimp_image_undo_push_layer_mode (image, NULL, layer); } + g_object_freeze_notify (G_OBJECT (layer)); + layer->mode = mode; g_signal_emit (layer, layer_signals[MODE_CHANGED], 0); g_object_notify (G_OBJECT (layer), "mode"); + /* when changing modes, we always switch to AUTO composite in + * order to avoid confusion + */ + if (layer->composite != GIMP_LAYER_COMPOSITE_AUTO) + { + layer->composite = GIMP_LAYER_COMPOSITE_AUTO; + + g_signal_emit (layer, layer_signals[COMPOSITE_CHANGED], 0); + g_object_notify (G_OBJECT (layer), "composite"); + } + + g_object_thaw_notify (G_OBJECT (layer)); + if (gimp_filter_peek_node (GIMP_FILTER (layer))) gimp_layer_update_mode_node (layer); @@ -2071,6 +2116,42 @@ gimp_layer_get_mode (GimpLayer *layer) return layer->mode; } +void +gimp_layer_set_composite (GimpLayer *layer, + GimpLayerCompositeMode composite, + gboolean push_undo) +{ + g_return_if_fail (GIMP_IS_LAYER (layer)); + + if (layer->composite != composite) + { + if (push_undo && gimp_item_is_attached (GIMP_ITEM (layer))) + { + GimpImage *image = gimp_item_get_image (GIMP_ITEM (layer)); + + gimp_image_undo_push_layer_mode (image, NULL, layer); + } + + layer->composite = composite; + + g_signal_emit (layer, layer_signals[COMPOSITE_CHANGED], 0); + g_object_notify (G_OBJECT (layer), "composite"); + + if (gimp_filter_peek_node (GIMP_FILTER (layer))) + gimp_layer_update_mode_node (layer); + + gimp_drawable_update (GIMP_DRAWABLE (layer), 0, 0, -1, -1); + } +} + +GimpLayerCompositeMode +gimp_layer_get_composite (GimpLayer *layer) +{ + g_return_val_if_fail (GIMP_IS_LAYER (layer), FALSE); + + return layer->composite; +} + void gimp_layer_set_lock_alpha (GimpLayer *layer, gboolean lock_alpha, diff --git a/app/core/gimplayer.h b/app/core/gimplayer.h index b19199f9fb..078054fc97 100644 --- a/app/core/gimplayer.h +++ b/app/core/gimplayer.h @@ -34,19 +34,20 @@ typedef struct _GimpLayerClass GimpLayerClass; struct _GimpLayer { - GimpDrawable parent_instance; + GimpDrawable parent_instance; - gdouble opacity; /* layer opacity */ - GimpLayerMode mode; /* layer combination mode */ - gboolean lock_alpha; /* lock the alpha channel */ + gdouble opacity; /* layer opacity */ + GimpLayerMode mode; /* layer combination mode */ + GimpLayerCompositeMode composite; /* layer composite mode */ + gboolean lock_alpha; /* lock the alpha channel */ - GimpLayerMask *mask; /* possible layer mask */ - gboolean apply_mask; /* controls mask application */ - gboolean edit_mask; /* edit mask or layer? */ - gboolean show_mask; /* show mask or layer? */ + GimpLayerMask *mask; /* possible layer mask */ + gboolean apply_mask; /* controls mask application */ + gboolean edit_mask; /* edit mask or layer? */ + gboolean show_mask; /* show mask or layer? */ - GeglNode *layer_offset_node; - GeglNode *mask_offset_node; + GeglNode *layer_offset_node; + GeglNode *mask_offset_node; /* Floating selections */ struct @@ -64,6 +65,7 @@ struct _GimpLayerClass void (* opacity_changed) (GimpLayer *layer); void (* mode_changed) (GimpLayer *layer); + void (* composite_changed) (GimpLayer *layer); void (* lock_alpha_changed) (GimpLayer *layer); void (* mask_changed) (GimpLayer *layer); void (* apply_mask_changed) (GimpLayer *layer); @@ -127,6 +129,12 @@ void gimp_layer_set_mode (GimpLayer *layer, gboolean push_undo); GimpLayerMode gimp_layer_get_mode (GimpLayer *layer); +void gimp_layer_set_composite (GimpLayer *layer, + GimpLayerCompositeMode composite, + gboolean push_undo); +GimpLayerCompositeMode + gimp_layer_get_composite (GimpLayer *layer); + void gimp_layer_set_lock_alpha (GimpLayer *layer, gboolean lock_alpha, gboolean push_undo); diff --git a/app/core/gimplayerpropundo.c b/app/core/gimplayerpropundo.c index e097c87dfb..35597b54b4 100644 --- a/app/core/gimplayerpropundo.c +++ b/app/core/gimplayerpropundo.c @@ -72,7 +72,8 @@ gimp_layer_prop_undo_constructed (GObject *object) switch (GIMP_UNDO (object)->undo_type) { case GIMP_UNDO_LAYER_MODE: - layer_prop_undo->mode = gimp_layer_get_mode (layer); + layer_prop_undo->mode = gimp_layer_get_mode (layer); + layer_prop_undo->composite = gimp_layer_get_composite (layer); break; case GIMP_UNDO_LAYER_OPACITY: @@ -102,11 +103,17 @@ gimp_layer_prop_undo_pop (GimpUndo *undo, { case GIMP_UNDO_LAYER_MODE: { - GimpLayerMode mode; + GimpLayerMode mode; + GimpLayerCompositeMode composite; + + mode = gimp_layer_get_mode (layer); + composite = gimp_layer_get_composite (layer); - mode = gimp_layer_get_mode (layer); gimp_layer_set_mode (layer, layer_prop_undo->mode, FALSE); - layer_prop_undo->mode = mode; + gimp_layer_set_composite (layer, layer_prop_undo->composite, FALSE); + + layer_prop_undo->mode = mode; + layer_prop_undo->composite = composite; } break; diff --git a/app/core/gimplayerpropundo.h b/app/core/gimplayerpropundo.h index e660669c61..f3d61bacca 100644 --- a/app/core/gimplayerpropundo.h +++ b/app/core/gimplayerpropundo.h @@ -35,11 +35,12 @@ typedef struct _GimpLayerPropUndoClass GimpLayerPropUndoClass; struct _GimpLayerPropUndo { - GimpItemUndo parent_instance; + GimpItemUndo parent_instance; - GimpLayerMode mode; - gdouble opacity; - gboolean lock_alpha; + GimpLayerMode mode; + GimpLayerCompositeMode composite; + gdouble opacity; + gboolean lock_alpha; }; struct _GimpLayerPropUndoClass diff --git a/app/dialogs/layer-options-dialog.c b/app/dialogs/layer-options-dialog.c index 424c2cd84d..fd4f13f6c4 100644 --- a/app/dialogs/layer-options-dialog.c +++ b/app/dialogs/layer-options-dialog.c @@ -51,6 +51,7 @@ struct _LayerOptionsDialog { GimpLayer *layer; GimpLayerMode mode; + GimpLayerCompositeMode composite; gdouble opacity; GimpFillType fill_type; gboolean lock_alpha; @@ -96,6 +97,7 @@ layer_options_dialog_new (GimpImage *image, const gchar *help_id, const gchar *layer_name, GimpLayerMode layer_mode, + GimpLayerCompositeMode layer_composite, gdouble layer_opacity, GimpFillType layer_fill_type, gboolean layer_visible, @@ -129,6 +131,7 @@ layer_options_dialog_new (GimpImage *image, private->layer = layer; private->mode = layer_mode; + private->composite = layer_composite; private->opacity = layer_opacity * 100.0; private->fill_type = layer_fill_type; private->lock_alpha = layer_lock_alpha; @@ -163,6 +166,15 @@ layer_options_dialog_new (GimpImage *image, gimp_layer_mode_box_set_mode (GIMP_LAYER_MODE_BOX (private->mode_box), private->mode); + combo = gimp_enum_combo_box_new (GIMP_TYPE_LAYER_COMPOSITE_MODE); + item_options_dialog_add_widget (dialog, _("Composite:"), combo); + gimp_enum_combo_box_set_icon_prefix (GIMP_ENUM_COMBO_BOX (combo), + "gimp-layer-composite"); + gimp_int_combo_box_connect (GIMP_INT_COMBO_BOX (combo), + private->composite, + G_CALLBACK (gimp_int_combo_box_get_active), + &private->composite); + adjustment = GTK_ADJUSTMENT (gtk_adjustment_new (private->opacity, 0.0, 100.0, 1.0, 10.0, 0.0)); scale = gimp_spin_scale_new (adjustment, NULL, 1); @@ -446,6 +458,7 @@ layer_options_dialog_callback (GtkWidget *dialog, context, item_name, private->mode, + private->composite, private->opacity / 100.0, private->fill_type, width, diff --git a/app/dialogs/layer-options-dialog.h b/app/dialogs/layer-options-dialog.h index 1dbaab502d..ad18b90e05 100644 --- a/app/dialogs/layer-options-dialog.h +++ b/app/dialogs/layer-options-dialog.h @@ -19,26 +19,27 @@ #define __LAYER_OPTIONS_DIALOG_H__ -typedef void (* GimpLayerOptionsCallback) (GtkWidget *dialog, - GimpImage *image, - GimpLayer *layer, - GimpContext *context, - const gchar *layer_name, - GimpLayerMode layer_mode, - gdouble layer_opacity, - GimpFillType layer_fill_type, - gint layer_width, - gint layer_height, - gint layer_offset_x, - gint layer_offset_y, - gboolean layer_visible, - gboolean layer_linked, - GimpColorTag layer_color_tag, - gboolean layer_lock_content, - gboolean layer_lock_position, - gboolean layer_lock_alpha, - gboolean rename_text_layer, - gpointer user_data); +typedef void (* GimpLayerOptionsCallback) (GtkWidget *dialog, + GimpImage *image, + GimpLayer *layer, + GimpContext *context, + const gchar *layer_name, + GimpLayerMode layer_mode, + GimpLayerCompositeMode layer_composite, + gdouble layer_opacity, + GimpFillType layer_fill_type, + gint layer_width, + gint layer_height, + gint layer_offset_x, + gint layer_offset_y, + gboolean layer_visible, + gboolean layer_linked, + GimpColorTag layer_color_tag, + gboolean layer_lock_content, + gboolean layer_lock_position, + gboolean layer_lock_alpha, + gboolean rename_text_layer, + gpointer user_data); GtkWidget * layer_options_dialog_new (GimpImage *image, @@ -52,6 +53,7 @@ GtkWidget * layer_options_dialog_new (GimpImage *image, const gchar *help_id, const gchar *layer_name, GimpLayerMode layer_mode, + GimpLayerCompositeMode layer_composite, gdouble layer_opacity, GimpFillType layer_fill_type, gboolean layer_visible, diff --git a/app/gegl/gimp-gegl-nodes.c b/app/gegl/gimp-gegl-nodes.c index 54b034b91d..548ed80743 100644 --- a/app/gegl/gimp-gegl-nodes.c +++ b/app/gegl/gimp-gegl-nodes.c @@ -141,13 +141,17 @@ gimp_gegl_add_buffer_source (GeglNode *parent, } void -gimp_gegl_mode_node_set_mode (GeglNode *node, - GimpLayerMode mode) +gimp_gegl_mode_node_set_mode (GeglNode *node, + GimpLayerMode mode, + GimpLayerCompositeMode composite) { gdouble opacity; g_return_if_fail (GEGL_IS_NODE (node)); + if (composite == GIMP_LAYER_COMPOSITE_AUTO) + composite = gimp_layer_mode_get_composite_mode (mode); + gegl_node_get (node, "opacity", &opacity, NULL); @@ -158,11 +162,11 @@ gimp_gegl_mode_node_set_mode (GeglNode *node, gegl_node_set (node, "operation", gimp_layer_mode_get_operation (mode), "layer-mode", mode, + "composite-mode", composite, "opacity", opacity, "linear", gimp_layer_mode_wants_linear_data (mode), "blend-space", gimp_layer_mode_get_blend_space (mode), "composite-space", gimp_layer_mode_get_composite_space (mode), - "composite-mode", gimp_layer_mode_get_composite_mode (mode), NULL); } diff --git a/app/gegl/gimp-gegl-nodes.h b/app/gegl/gimp-gegl-nodes.h index e1233c99e1..6d632889b4 100644 --- a/app/gegl/gimp-gegl-nodes.h +++ b/app/gegl/gimp-gegl-nodes.h @@ -32,8 +32,9 @@ GeglNode * gimp_gegl_add_buffer_source (GeglNode *parent, gint offset_x, gint offset_y); -void gimp_gegl_mode_node_set_mode (GeglNode *node, - GimpLayerMode mode); +void gimp_gegl_mode_node_set_mode (GeglNode *node, + GimpLayerMode mode, + GimpLayerCompositeMode composite); void gimp_gegl_mode_node_set_opacity (GeglNode *node, gdouble opacity); diff --git a/app/gegl/gimpapplicator.c b/app/gegl/gimpapplicator.c index 9d8dd16e0c..b4ee0e4cda 100644 --- a/app/gegl/gimpapplicator.c +++ b/app/gegl/gimpapplicator.c @@ -57,9 +57,10 @@ gimp_applicator_class_init (GimpApplicatorClass *klass) static void gimp_applicator_init (GimpApplicator *applicator) { - applicator->opacity = 1.0; - applicator->paint_mode = GIMP_LAYER_MODE_NORMAL; - applicator->affect = GIMP_COMPONENT_MASK_ALL; + applicator->opacity = 1.0; + applicator->paint_mode = GIMP_LAYER_MODE_NORMAL; + applicator->composite_mode = GIMP_LAYER_COMPOSITE_AUTO; + applicator->affect = GIMP_COMPONENT_MASK_ALL; } static void @@ -134,7 +135,8 @@ gimp_applicator_new (GeglNode *parent, NULL); gimp_gegl_mode_node_set_mode (applicator->mode_node, - applicator->paint_mode); + applicator->paint_mode, + applicator->composite_mode); gimp_gegl_mode_node_set_opacity (applicator->mode_node, applicator->opacity); @@ -445,16 +447,20 @@ gimp_applicator_set_opacity (GimpApplicator *applicator, } void -gimp_applicator_set_mode (GimpApplicator *applicator, - GimpLayerMode paint_mode) +gimp_applicator_set_mode (GimpApplicator *applicator, + GimpLayerMode paint_mode, + GimpLayerCompositeMode composite_mode) { g_return_if_fail (GIMP_IS_APPLICATOR (applicator)); - if (applicator->paint_mode != paint_mode) + if (applicator->paint_mode != paint_mode || + applicator->composite_mode != composite_mode) { - applicator->paint_mode = paint_mode; + applicator->paint_mode = paint_mode; + applicator->composite_mode = composite_mode; - gimp_gegl_mode_node_set_mode (applicator->mode_node, paint_mode); + gimp_gegl_mode_node_set_mode (applicator->mode_node, + paint_mode, composite_mode); } } diff --git a/app/gegl/gimpapplicator.h b/app/gegl/gimpapplicator.h index 18b54977f1..6d4ee5ba1f 100644 --- a/app/gegl/gimpapplicator.h +++ b/app/gegl/gimpapplicator.h @@ -34,48 +34,49 @@ typedef struct _GimpApplicatorClass GimpApplicatorClass; struct _GimpApplicator { - GObject parent_instance; + GObject parent_instance; - GeglNode *node; - GeglNode *input_node; - GeglNode *aux_node; - GeglNode *output_node; + GeglNode *node; + GeglNode *input_node; + GeglNode *aux_node; + GeglNode *output_node; - GeglBuffer *apply_buffer; - GeglNode *apply_src_node; + GeglBuffer *apply_buffer; + GeglNode *apply_src_node; - gint apply_offset_x; - gint apply_offset_y; - GeglNode *apply_offset_node; + gint apply_offset_x; + gint apply_offset_y; + GeglNode *apply_offset_node; - GeglNode *dup_apply_buffer_node; + GeglNode *dup_apply_buffer_node; - gboolean preview_enabled; - GeglRectangle preview_rect; - GeglNode *preview_cache_node; - GeglNode *preview_crop_node; + gboolean preview_enabled; + GeglRectangle preview_rect; + GeglNode *preview_cache_node; + GeglNode *preview_crop_node; - gdouble opacity; - GimpLayerMode paint_mode; - GeglNode *mode_node; + gdouble opacity; + GimpLayerMode paint_mode; + GimpLayerCompositeMode composite_mode; + GeglNode *mode_node; - GimpComponentMask affect; - GeglNode *affect_node; + GimpComponentMask affect; + GeglNode *affect_node; - GeglNode *output_cache_node; + GeglNode *output_cache_node; - GeglBuffer *src_buffer; - GeglNode *src_node; + GeglBuffer *src_buffer; + GeglNode *src_node; - GeglBuffer *dest_buffer; - GeglNode *dest_node; + GeglBuffer *dest_buffer; + GeglNode *dest_node; - GeglBuffer *mask_buffer; - GeglNode *mask_node; + GeglBuffer *mask_buffer; + GeglNode *mask_node; - gint mask_offset_x; - gint mask_offset_y; - GeglNode *mask_offset_node; + gint mask_offset_x; + gint mask_offset_y; + GeglNode *mask_offset_node; }; struct _GimpApplicatorClass @@ -110,7 +111,8 @@ void gimp_applicator_set_apply_offset (GimpApplicator *applicator, void gimp_applicator_set_opacity (GimpApplicator *applicator, gdouble opacity); void gimp_applicator_set_mode (GimpApplicator *applicator, - GimpLayerMode paint_mode); + GimpLayerMode paint_mode, + GimpLayerCompositeMode composite_mode); void gimp_applicator_set_affect (GimpApplicator *applicator, GimpComponentMask affect); diff --git a/app/operations/operations-enums.c b/app/operations/operations-enums.c index 7b4519d4f2..de7adcf1c1 100644 --- a/app/operations/operations-enums.c +++ b/app/operations/operations-enums.c @@ -44,8 +44,9 @@ gimp_layer_composite_mode_get_type (void) { static const GEnumValue values[] = { - { GIMP_LAYER_COMPOSITE_SRC_ATOP, "GIMP_LAYER_COMPOSITE_SRC_ATOP", "src-atop" }, + { GIMP_LAYER_COMPOSITE_AUTO, "GIMP_LAYER_COMPOSITE_AUTO", "auto" }, { GIMP_LAYER_COMPOSITE_SRC_OVER, "GIMP_LAYER_COMPOSITE_SRC_OVER", "src-over" }, + { GIMP_LAYER_COMPOSITE_SRC_ATOP, "GIMP_LAYER_COMPOSITE_SRC_ATOP", "src-atop" }, { GIMP_LAYER_COMPOSITE_SRC_IN, "GIMP_LAYER_COMPOSITE_SRC_IN", "src-in" }, { GIMP_LAYER_COMPOSITE_DST_ATOP, "GIMP_LAYER_COMPOSITE_DST_ATOP", "dst-atop" }, { 0, NULL, NULL } @@ -53,10 +54,11 @@ gimp_layer_composite_mode_get_type (void) static const GimpEnumDesc descs[] = { - { GIMP_LAYER_COMPOSITE_SRC_ATOP, "GIMP_LAYER_COMPOSITE_SRC_ATOP", NULL }, - { GIMP_LAYER_COMPOSITE_SRC_OVER, "GIMP_LAYER_COMPOSITE_SRC_OVER", NULL }, - { GIMP_LAYER_COMPOSITE_SRC_IN, "GIMP_LAYER_COMPOSITE_SRC_IN", NULL }, - { GIMP_LAYER_COMPOSITE_DST_ATOP, "GIMP_LAYER_COMPOSITE_DST_ATOP", NULL }, + { GIMP_LAYER_COMPOSITE_AUTO, NC_("layer-composite-mode", "Auto"), NULL }, + { GIMP_LAYER_COMPOSITE_SRC_OVER, NC_("layer-composite-mode", "Source over"), NULL }, + { GIMP_LAYER_COMPOSITE_SRC_ATOP, NC_("layer-composite-mode", "Source atop"), NULL }, + { GIMP_LAYER_COMPOSITE_SRC_IN, NC_("layer-composite-mode", "Source in"), NULL }, + { GIMP_LAYER_COMPOSITE_DST_ATOP, NC_("layer-composite-mode", "Destination atop"), NULL }, { 0, NULL, NULL } }; diff --git a/app/operations/operations-enums.h b/app/operations/operations-enums.h index 78227caf03..be1eb4e73b 100644 --- a/app/operations/operations-enums.h +++ b/app/operations/operations-enums.h @@ -25,7 +25,7 @@ GType gimp_layer_color_space_get_type (void) G_GNUC_CONST; -typedef enum +typedef enum /*< pdb-skip >*/ { GIMP_LAYER_COLOR_SPACE_RGB_LINEAR, GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL, @@ -39,10 +39,11 @@ GType gimp_layer_composite_mode_get_type (void) G_GNUC_CONST; typedef enum { - GIMP_LAYER_COMPOSITE_SRC_ATOP, - GIMP_LAYER_COMPOSITE_SRC_OVER, - GIMP_LAYER_COMPOSITE_SRC_IN, - GIMP_LAYER_COMPOSITE_DST_ATOP + GIMP_LAYER_COMPOSITE_AUTO, /*< desc="Auto" >*/ + GIMP_LAYER_COMPOSITE_SRC_OVER, /*< desc="Source over" >*/ + GIMP_LAYER_COMPOSITE_SRC_ATOP, /*< desc="Source atop" >*/ + GIMP_LAYER_COMPOSITE_SRC_IN, /*< desc="Source in" >*/ + GIMP_LAYER_COMPOSITE_DST_ATOP /*< desc="Destination atop" >*/ } GimpLayerCompositeMode; diff --git a/app/paint/gimppaintcore.c b/app/paint/gimppaintcore.c index 72b116dfe2..72bc503148 100644 --- a/app/paint/gimppaintcore.c +++ b/app/paint/gimppaintcore.c @@ -901,7 +901,8 @@ gimp_paint_core_paste (GimpPaintCore *core, core->paint_buffer_y); gimp_applicator_set_opacity (core->applicator, image_opacity); - gimp_applicator_set_mode (core->applicator, paint_mode); + gimp_applicator_set_mode (core->applicator, paint_mode, + GIMP_LAYER_COMPOSITE_AUTO); /* apply the paint area to the image */ gimp_applicator_blit (core->applicator, diff --git a/app/pdb/internal-procs.c b/app/pdb/internal-procs.c index 5379699f06..ff7552245e 100644 --- a/app/pdb/internal-procs.c +++ b/app/pdb/internal-procs.c @@ -28,7 +28,7 @@ #include "internal-procs.h" -/* 802 procedures registered total */ +/* 804 procedures registered total */ void internal_procs_init (GimpPDB *pdb) diff --git a/app/pdb/layer-cmds.c b/app/pdb/layer-cmds.c index 4126217a91..fde14a7373 100644 --- a/app/pdb/layer-cmds.c +++ b/app/pdb/layer-cmds.c @@ -1150,6 +1150,59 @@ layer_set_mode_invoker (GimpProcedure *procedure, error ? *error : NULL); } +static GimpValueArray * +layer_get_composite_mode_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error) +{ + gboolean success = TRUE; + GimpValueArray *return_vals; + GimpLayer *layer; + gint32 composite_mode = 0; + + layer = gimp_value_get_layer (gimp_value_array_index (args, 0), gimp); + + if (success) + { + composite_mode = gimp_layer_get_composite (layer); + } + + return_vals = gimp_procedure_get_return_values (procedure, success, + error ? *error : NULL); + + if (success) + g_value_set_enum (gimp_value_array_index (return_vals, 1), composite_mode); + + return return_vals; +} + +static GimpValueArray * +layer_set_composite_mode_invoker (GimpProcedure *procedure, + Gimp *gimp, + GimpContext *context, + GimpProgress *progress, + const GimpValueArray *args, + GError **error) +{ + gboolean success = TRUE; + GimpLayer *layer; + gint32 composite_mode; + + layer = gimp_value_get_layer (gimp_value_array_index (args, 0), gimp); + composite_mode = g_value_get_enum (gimp_value_array_index (args, 1)); + + if (success) + { + gimp_layer_set_composite (layer, composite_mode, TRUE); + } + + return gimp_procedure_get_return_values (procedure, success, + error ? *error : NULL); +} + void register_layer_procs (GimpPDB *pdb) { @@ -2182,4 +2235,64 @@ register_layer_procs (GimpPDB *pdb) GIMP_PARAM_READWRITE)); gimp_pdb_register_procedure (pdb, procedure); g_object_unref (procedure); + + /* + * gimp-layer-get-composite-mode + */ + procedure = gimp_procedure_new (layer_get_composite_mode_invoker); + gimp_object_set_static_name (GIMP_OBJECT (procedure), + "gimp-layer-get-composite-mode"); + gimp_procedure_set_static_strings (procedure, + "gimp-layer-get-composite-mode", + "Get the composite mode of the specified layer.", + "This procedure returns the specified layer's composite mode.", + "Ell", + "Ell", + "2017", + NULL); + gimp_procedure_add_argument (procedure, + gimp_param_spec_layer_id ("layer", + "layer", + "The layer", + pdb->gimp, FALSE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_return_value (procedure, + g_param_spec_enum ("composite-mode", + "composite mode", + "The layer composite mode", + GIMP_TYPE_LAYER_COMPOSITE_MODE, + GIMP_LAYER_COMPOSITE_AUTO, + GIMP_PARAM_READWRITE)); + gimp_pdb_register_procedure (pdb, procedure); + g_object_unref (procedure); + + /* + * gimp-layer-set-composite-mode + */ + procedure = gimp_procedure_new (layer_set_composite_mode_invoker); + gimp_object_set_static_name (GIMP_OBJECT (procedure), + "gimp-layer-set-composite-mode"); + gimp_procedure_set_static_strings (procedure, + "gimp-layer-set-composite-mode", + "Set the composite mode of the specified layer.", + "This procedure sets the specified layer's composite mode.", + "Ell", + "Ell", + "2017", + NULL); + gimp_procedure_add_argument (procedure, + gimp_param_spec_layer_id ("layer", + "layer", + "The layer", + pdb->gimp, FALSE, + GIMP_PARAM_READWRITE)); + gimp_procedure_add_argument (procedure, + g_param_spec_enum ("composite-mode", + "composite mode", + "The new layer composite mode", + GIMP_TYPE_LAYER_COMPOSITE_MODE, + GIMP_LAYER_COMPOSITE_AUTO, + GIMP_PARAM_READWRITE)); + gimp_pdb_register_procedure (pdb, procedure); + g_object_unref (procedure); } diff --git a/app/tools/gimpblendtool.c b/app/tools/gimpblendtool.c index f219fb9e28..4bdeaa843b 100644 --- a/app/tools/gimpblendtool.c +++ b/app/tools/gimpblendtool.c @@ -642,7 +642,8 @@ gimp_blend_tool_options_notify (GimpTool *tool, ! strcmp (pspec->name, "paint-mode")) { gimp_drawable_filter_set_mode (blend_tool->filter, - gimp_context_get_paint_mode (context)); + gimp_context_get_paint_mode (context), + GIMP_LAYER_COMPOSITE_AUTO); } } @@ -1203,7 +1204,8 @@ gimp_blend_tool_create_filter (GimpBlendTool *blend_tool, gimp_drawable_filter_set_opacity (blend_tool->filter, gimp_context_get_opacity (context)); gimp_drawable_filter_set_mode (blend_tool->filter, - gimp_context_get_paint_mode (context)); + gimp_context_get_paint_mode (context), + GIMP_LAYER_COMPOSITE_AUTO); g_signal_connect (blend_tool->filter, "flush", G_CALLBACK (gimp_blend_tool_filter_flush), diff --git a/app/xcf/xcf-load.c b/app/xcf/xcf-load.c index c0523c6c96..1f95b70735 100644 --- a/app/xcf/xcf-load.c +++ b/app/xcf/xcf-load.c @@ -1100,6 +1100,17 @@ xcf_load_layer_props (XcfInfo *info, } break; + case PROP_COMPOSITE: + { + guint32 composite; + + info->cp += xcf_read_int32 (info->input, &composite, 1); + + gimp_layer_set_composite (*layer, + (GimpLayerCompositeMode) composite, FALSE); + } + break; + case PROP_TATTOO: { GimpTattoo tattoo; diff --git a/app/xcf/xcf-private.h b/app/xcf/xcf-private.h index cc21d489b2..99e4853254 100644 --- a/app/xcf/xcf-private.h +++ b/app/xcf/xcf-private.h @@ -59,6 +59,7 @@ typedef enum PROP_LOCK_POSITION = 32, PROP_FLOAT_OPACITY = 33, PROP_COLOR_TAG = 34, + PROP_COMPOSITE = 35, } PropType; typedef enum diff --git a/app/xcf/xcf-save.c b/app/xcf/xcf-save.c index c43726dfa2..de445c63e1 100644 --- a/app/xcf/xcf-save.c +++ b/app/xcf/xcf-save.c @@ -534,6 +534,8 @@ xcf_save_layer_props (XcfInfo *info, offset_x, offset_y)); xcf_check_error (xcf_save_prop (info, image, PROP_MODE, error, gimp_layer_get_mode (layer))); + xcf_check_error (xcf_save_prop (info, image, PROP_COMPOSITE, error, + gimp_layer_get_composite (layer))); xcf_check_error (xcf_save_prop (info, image, PROP_TATTOO, error, gimp_item_get_tattoo (GIMP_ITEM (layer)))); @@ -735,6 +737,19 @@ xcf_save_prop (XcfInfo *info, } break; + case PROP_COMPOSITE: + { + gint32 composite; + + composite = va_arg (args, gint32); + size = 4; + + xcf_write_prop_type_check_error (info, prop_type); + xcf_write_int32_check_error (info, &size, 1); + xcf_write_int32_check_error (info, (guint32 *) &composite, 1); + } + break; + case PROP_VISIBLE: { guint32 visible; diff --git a/libgimp/gimp.def b/libgimp/gimp.def index 2d7213ba58..f7eecdbc03 100644 --- a/libgimp/gimp.def +++ b/libgimp/gimp.def @@ -590,11 +590,13 @@ EXPORTS gimp_item_transform_shear gimp_layer_add_alpha gimp_layer_add_mask + gimp_layer_composite_mode_get_type gimp_layer_copy gimp_layer_create_mask gimp_layer_flatten gimp_layer_from_mask gimp_layer_get_apply_mask + gimp_layer_get_composite_mode gimp_layer_get_edit_mask gimp_layer_get_lock_alpha gimp_layer_get_mask @@ -616,6 +618,7 @@ EXPORTS gimp_layer_scale gimp_layer_scale_full gimp_layer_set_apply_mask + gimp_layer_set_composite_mode gimp_layer_set_edit_mask gimp_layer_set_lock_alpha gimp_layer_set_mode diff --git a/libgimp/gimpenums.c.tail b/libgimp/gimpenums.c.tail index ee44b28954..d81f076f5d 100644 --- a/libgimp/gimpenums.c.tail +++ b/libgimp/gimpenums.c.tail @@ -35,6 +35,7 @@ static const GimpGetTypeFunc get_type_funcs[] = gimp_ink_blob_type_get_type, gimp_interpolation_type_get_type, gimp_join_style_get_type, + gimp_layer_composite_mode_get_type, gimp_layer_mode_get_type, gimp_mask_apply_mode_get_type, gimp_merge_type_get_type, @@ -99,6 +100,7 @@ static const gchar * const type_names[] = "GimpInkBlobType", "GimpInterpolationType", "GimpJoinStyle", + "GimpLayerCompositeMode", "GimpLayerMode", "GimpMaskApplyMode", "GimpMergeType", diff --git a/libgimp/gimpenums.h b/libgimp/gimpenums.h index 65fb76ae27..b21de2bcb7 100644 --- a/libgimp/gimpenums.h +++ b/libgimp/gimpenums.h @@ -63,6 +63,20 @@ typedef enum } GimpHistogramChannel; +#define GIMP_TYPE_LAYER_COMPOSITE_MODE (gimp_layer_composite_mode_get_type ()) + +GType gimp_layer_composite_mode_get_type (void) G_GNUC_CONST; + +typedef enum +{ + GIMP_LAYER_COMPOSITE_AUTO, + GIMP_LAYER_COMPOSITE_SRC_OVER, + GIMP_LAYER_COMPOSITE_SRC_ATOP, + GIMP_LAYER_COMPOSITE_SRC_IN, + GIMP_LAYER_COMPOSITE_DST_ATOP +} GimpLayerCompositeMode; + + #define GIMP_TYPE_LAYER_MODE (gimp_layer_mode_get_type ()) GType gimp_layer_mode_get_type (void) G_GNUC_CONST; diff --git a/libgimp/gimplayer_pdb.c b/libgimp/gimplayer_pdb.c index dce0dcfee6..c06c219a4c 100644 --- a/libgimp/gimplayer_pdb.c +++ b/libgimp/gimplayer_pdb.c @@ -1152,3 +1152,69 @@ gimp_layer_set_mode (gint32 layer_ID, return success; } + +/** + * gimp_layer_get_composite_mode: + * @layer_ID: The layer. + * + * Get the composite mode of the specified layer. + * + * This procedure returns the specified layer's composite mode. + * + * Returns: The layer composite mode. + * + * Since: 2.10 + **/ +GimpLayerCompositeMode +gimp_layer_get_composite_mode (gint32 layer_ID) +{ + GimpParam *return_vals; + gint nreturn_vals; + GimpLayerCompositeMode composite_mode = 0; + + return_vals = gimp_run_procedure ("gimp-layer-get-composite-mode", + &nreturn_vals, + GIMP_PDB_LAYER, layer_ID, + GIMP_PDB_END); + + if (return_vals[0].data.d_status == GIMP_PDB_SUCCESS) + composite_mode = return_vals[1].data.d_int32; + + gimp_destroy_params (return_vals, nreturn_vals); + + return composite_mode; +} + +/** + * gimp_layer_set_composite_mode: + * @layer_ID: The layer. + * @composite_mode: The new layer composite mode. + * + * Set the composite mode of the specified layer. + * + * This procedure sets the specified layer's composite mode. + * + * Returns: TRUE on success. + * + * Since: 2.10 + **/ +gboolean +gimp_layer_set_composite_mode (gint32 layer_ID, + GimpLayerCompositeMode composite_mode) +{ + GimpParam *return_vals; + gint nreturn_vals; + gboolean success = TRUE; + + return_vals = gimp_run_procedure ("gimp-layer-set-composite-mode", + &nreturn_vals, + GIMP_PDB_LAYER, layer_ID, + GIMP_PDB_INT32, composite_mode, + GIMP_PDB_END); + + success = return_vals[0].data.d_status == GIMP_PDB_SUCCESS; + + gimp_destroy_params (return_vals, nreturn_vals); + + return success; +} diff --git a/libgimp/gimplayer_pdb.h b/libgimp/gimplayer_pdb.h index d5a8fef1b5..d88b21da3c 100644 --- a/libgimp/gimplayer_pdb.h +++ b/libgimp/gimplayer_pdb.h @@ -32,72 +32,75 @@ G_BEGIN_DECLS /* For information look into the C source or the html documentation */ -G_GNUC_INTERNAL gint32 _gimp_layer_new (gint32 image_ID, - gint width, - gint height, - GimpImageType type, - const gchar *name, - gdouble opacity, - GimpLayerMode mode); -gint32 gimp_layer_new_from_visible (gint32 image_ID, - gint32 dest_image_ID, - const gchar *name); -gint32 gimp_layer_new_from_drawable (gint32 drawable_ID, - gint32 dest_image_ID); -gint32 gimp_layer_group_new (gint32 image_ID); -G_GNUC_INTERNAL gint32 _gimp_layer_copy (gint32 layer_ID, - gboolean add_alpha); -gboolean gimp_layer_add_alpha (gint32 layer_ID); -gboolean gimp_layer_flatten (gint32 layer_ID); -gboolean gimp_layer_scale (gint32 layer_ID, - gint new_width, - gint new_height, - gboolean local_origin); +G_GNUC_INTERNAL gint32 _gimp_layer_new (gint32 image_ID, + gint width, + gint height, + GimpImageType type, + const gchar *name, + gdouble opacity, + GimpLayerMode mode); +gint32 gimp_layer_new_from_visible (gint32 image_ID, + gint32 dest_image_ID, + const gchar *name); +gint32 gimp_layer_new_from_drawable (gint32 drawable_ID, + gint32 dest_image_ID); +gint32 gimp_layer_group_new (gint32 image_ID); +G_GNUC_INTERNAL gint32 _gimp_layer_copy (gint32 layer_ID, + gboolean add_alpha); +gboolean gimp_layer_add_alpha (gint32 layer_ID); +gboolean gimp_layer_flatten (gint32 layer_ID); +gboolean gimp_layer_scale (gint32 layer_ID, + gint new_width, + gint new_height, + gboolean local_origin); GIMP_DEPRECATED_FOR(gimp_layer_scale) -gboolean gimp_layer_scale_full (gint32 layer_ID, - gint new_width, - gint new_height, - gboolean local_origin, - GimpInterpolationType interpolation); -gboolean gimp_layer_resize (gint32 layer_ID, - gint new_width, - gint new_height, - gint offx, - gint offy); -gboolean gimp_layer_resize_to_image_size (gint32 layer_ID); -gboolean gimp_layer_translate (gint32 layer_ID, - gint offx, - gint offy); -gboolean gimp_layer_set_offsets (gint32 layer_ID, - gint offx, - gint offy); -gint32 gimp_layer_create_mask (gint32 layer_ID, - GimpAddMaskType mask_type); -gint32 gimp_layer_get_mask (gint32 layer_ID); -gint32 gimp_layer_from_mask (gint32 mask_ID); -gboolean gimp_layer_add_mask (gint32 layer_ID, - gint32 mask_ID); -gboolean gimp_layer_remove_mask (gint32 layer_ID, - GimpMaskApplyMode mode); -gboolean gimp_layer_is_floating_sel (gint32 layer_ID); -gboolean gimp_layer_get_lock_alpha (gint32 layer_ID); -gboolean gimp_layer_set_lock_alpha (gint32 layer_ID, - gboolean lock_alpha); -gboolean gimp_layer_get_apply_mask (gint32 layer_ID); -gboolean gimp_layer_set_apply_mask (gint32 layer_ID, - gboolean apply_mask); -gboolean gimp_layer_get_show_mask (gint32 layer_ID); -gboolean gimp_layer_set_show_mask (gint32 layer_ID, - gboolean show_mask); -gboolean gimp_layer_get_edit_mask (gint32 layer_ID); -gboolean gimp_layer_set_edit_mask (gint32 layer_ID, - gboolean edit_mask); -gdouble gimp_layer_get_opacity (gint32 layer_ID); -gboolean gimp_layer_set_opacity (gint32 layer_ID, - gdouble opacity); -GimpLayerMode gimp_layer_get_mode (gint32 layer_ID); -gboolean gimp_layer_set_mode (gint32 layer_ID, - GimpLayerMode mode); +gboolean gimp_layer_scale_full (gint32 layer_ID, + gint new_width, + gint new_height, + gboolean local_origin, + GimpInterpolationType interpolation); +gboolean gimp_layer_resize (gint32 layer_ID, + gint new_width, + gint new_height, + gint offx, + gint offy); +gboolean gimp_layer_resize_to_image_size (gint32 layer_ID); +gboolean gimp_layer_translate (gint32 layer_ID, + gint offx, + gint offy); +gboolean gimp_layer_set_offsets (gint32 layer_ID, + gint offx, + gint offy); +gint32 gimp_layer_create_mask (gint32 layer_ID, + GimpAddMaskType mask_type); +gint32 gimp_layer_get_mask (gint32 layer_ID); +gint32 gimp_layer_from_mask (gint32 mask_ID); +gboolean gimp_layer_add_mask (gint32 layer_ID, + gint32 mask_ID); +gboolean gimp_layer_remove_mask (gint32 layer_ID, + GimpMaskApplyMode mode); +gboolean gimp_layer_is_floating_sel (gint32 layer_ID); +gboolean gimp_layer_get_lock_alpha (gint32 layer_ID); +gboolean gimp_layer_set_lock_alpha (gint32 layer_ID, + gboolean lock_alpha); +gboolean gimp_layer_get_apply_mask (gint32 layer_ID); +gboolean gimp_layer_set_apply_mask (gint32 layer_ID, + gboolean apply_mask); +gboolean gimp_layer_get_show_mask (gint32 layer_ID); +gboolean gimp_layer_set_show_mask (gint32 layer_ID, + gboolean show_mask); +gboolean gimp_layer_get_edit_mask (gint32 layer_ID); +gboolean gimp_layer_set_edit_mask (gint32 layer_ID, + gboolean edit_mask); +gdouble gimp_layer_get_opacity (gint32 layer_ID); +gboolean gimp_layer_set_opacity (gint32 layer_ID, + gdouble opacity); +GimpLayerMode gimp_layer_get_mode (gint32 layer_ID); +gboolean gimp_layer_set_mode (gint32 layer_ID, + GimpLayerMode mode); +GimpLayerCompositeMode gimp_layer_get_composite_mode (gint32 layer_ID); +gboolean gimp_layer_set_composite_mode (gint32 layer_ID, + GimpLayerCompositeMode composite_mode); G_END_DECLS diff --git a/menus/layers-menu.xml b/menus/layers-menu.xml index 27d8674f64..03d28e4b37 100644 --- a/menus/layers-menu.xml +++ b/menus/layers-menu.xml @@ -5,6 +5,13 @@ + + + + + + + diff --git a/po/POTFILES.in b/po/POTFILES.in index be9cad432d..75b57f9039 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -261,6 +261,7 @@ app/file/file-utils.c app/gegl/gimp-babl.c app/gegl/gimp-gegl-enums.c +app/operations/operations-enums.c app/operations/gimpbrightnesscontrastconfig.c app/operations/gimpcolorbalanceconfig.c app/operations/gimpcolorizeconfig.c diff --git a/tools/pdbgen/Makefile.am b/tools/pdbgen/Makefile.am index b396303c06..8940408a31 100644 --- a/tools/pdbgen/Makefile.am +++ b/tools/pdbgen/Makefile.am @@ -76,6 +76,7 @@ EXTRA_DIST = \ enum_headers = \ ../../libgimpbase/gimpbaseenums.h \ ../../libgimpconfig/gimpconfigenums.h \ + ../../app/operations/operations-enums.h \ ../../app/core/core-enums.h \ ../../app/paint/paint-enums.h diff --git a/tools/pdbgen/enums.pl b/tools/pdbgen/enums.pl index 35a480b214..46a3d20cc7 100644 --- a/tools/pdbgen/enums.pl +++ b/tools/pdbgen/enums.pl @@ -669,6 +669,20 @@ package Gimp::CodeGen::enums; GIMP_COLOR_RENDERING_INTENT_SATURATION => '2', GIMP_COLOR_RENDERING_INTENT_ABSOLUTE_COLORIMETRIC => '3' } }, + GimpLayerCompositeMode => + { contig => 1, + header => 'operations/operations-enums.h', + symbols => [ qw(GIMP_LAYER_COMPOSITE_AUTO + GIMP_LAYER_COMPOSITE_SRC_OVER + GIMP_LAYER_COMPOSITE_SRC_ATOP + GIMP_LAYER_COMPOSITE_SRC_IN + GIMP_LAYER_COMPOSITE_DST_ATOP) ], + mapping => { GIMP_LAYER_COMPOSITE_AUTO => '0', + GIMP_LAYER_COMPOSITE_SRC_OVER => '1', + GIMP_LAYER_COMPOSITE_SRC_ATOP => '2', + GIMP_LAYER_COMPOSITE_SRC_IN => '3', + GIMP_LAYER_COMPOSITE_DST_ATOP => '4' } + }, GimpConvertDitherType => { contig => 1, header => 'core/core-enums.h', diff --git a/tools/pdbgen/pdb/layer.pdb b/tools/pdbgen/pdb/layer.pdb index a4d19c00b2..e259605cd1 100644 --- a/tools/pdbgen/pdb/layer.pdb +++ b/tools/pdbgen/pdb/layer.pdb @@ -1198,6 +1198,53 @@ CODE ); } +sub layer_get_composite_mode { + $blurb = 'Get the composite mode of the specified layer.'; + $help = "This procedure returns the specified layer's composite mode."; + + &ell_pdb_misc('2017', '2.10'); + + @inargs = ( + { name => 'layer', type => 'layer', + desc => 'The layer' } + ); + + @outargs = ( + { name => 'composite_mode', type => 'enum GimpLayerCompositeMode', + desc => 'The layer composite mode' } + ); + + %invoke = ( + code => <<'CODE' +{ + composite_mode = gimp_layer_get_composite (layer); +} +CODE + ); +} + +sub layer_set_composite_mode { + $blurb = 'Set the composite mode of the specified layer.'; + $help = "This procedure sets the specified layer's composite mode."; + + &ell_pdb_misc('2017', '2.10'); + + @inargs = ( + { name => 'layer', type => 'layer', + desc => 'The layer' }, + { name => 'composite_mode', type => 'enum GimpLayerCompositeMode', + desc => 'The new layer composite mode' } + ); + + %invoke = ( + code => <<'CODE' +{ + gimp_layer_set_composite (layer, composite_mode, TRUE); +} +CODE + ); +} + @headers = qw( "libgimpbase/gimpbase.h" "libgimpcolor/gimpcolor.h" @@ -1234,7 +1281,8 @@ CODE layer_get_show_mask layer_set_show_mask layer_get_edit_mask layer_set_edit_mask layer_get_opacity layer_set_opacity - layer_get_mode layer_set_mode); + layer_get_mode layer_set_mode + layer_get_composite_mode layer_set_composite_mode); %exports = (app => [@procs], lib => [@procs]); diff --git a/tools/pdbgen/stddefs.pdb b/tools/pdbgen/stddefs.pdb index c73bb67047..e4e3cb7187 100644 --- a/tools/pdbgen/stddefs.pdb +++ b/tools/pdbgen/stddefs.pdb @@ -77,6 +77,10 @@ sub ejs_pdb_misc { contrib_pdb_misc('Ed Swartz', '', @_); } +sub ell_pdb_misc { + contrib_pdb_misc('Ell', '', @_); +} + sub federico_pdb_misc { contrib_pdb_misc('Federico Mena Quintero', '', @_); }