[gimp] app: add internal and PDB API and UI to control a layer's composite mode



commit 2a96d598c38d78e1a5d2f74ce919d1a46c0162ca
Author: Michael Natterer <mitch gimp org>
Date:   Thu Feb 2 00:38:25 2017 +0100

    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              |   62 +++++++------
 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, 904 insertions(+), 317 deletions(-)
---
diff --git a/app/actions/layers-actions.c b/app/actions/layers-actions.c
index 116bd94..fb56b4e 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 d8d5323..da4cd23 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,
@@ -1134,6 +1139,34 @@ layers_mode_cmd_callback (GtkAction *action,
 }
 
 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 32db839..27d3e72 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 d63ada2..3ccbf12 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 e84fb44..554acf5 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 55cfcdc..78ea299 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 036b4a5..02c2cf8 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 b622a8f..dc43e05 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 2ec9db5..86cbef4 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 50e39a2..094affb 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 568c9c6..c196beb 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 635a778..a285313 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 9b73208..09a29ad 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 75566c2..59937ea 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 0ceff8b..e3acecd 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 cb6f01f..52493fb 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 79217fc..7c5d80c 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 09a33d7..db23c81 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 62a4a31..9639f63 100644
--- a/app/core/gimpdrawablefilter.c
+++ b/app/core/gimpdrawablefilter.c
@@ -57,29 +57,30 @@ enum
 
 struct _GimpDrawableFilter
 {
-  GimpFilter         parent_instance;
-
-  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;
-
-  GeglRectangle      filter_area;
-
-  GeglNode          *translate;
-  GeglNode          *crop;
-  GeglNode          *cast_before;
-  GeglNode          *transform_before;
-  GeglNode          *transform_after;
-  GeglNode          *cast_after;
-  GimpApplicator    *applicator;
+  GimpFilter              parent_instance;
+
+  GimpDrawable           *drawable;
+  GeglNode               *operation;
+
+  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;
+
+  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 9e3a11d..3e364c0 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 ff07b41..d355a5a 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 5a8b24e..02cc17b 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 b716ba3..bc64f09 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);
 
@@ -2072,6 +2117,42 @@ gimp_layer_get_mode (GimpLayer *layer)
 }
 
 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,
                            gboolean   push_undo)
diff --git a/app/core/gimplayer.h b/app/core/gimplayer.h
index b19199f..078054f 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 e097c87..35597b5 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 e660669..f3d61ba 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 424c2cd..fd4f13f 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 1dbaab5..ad18b90 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 54b034b..548ed80 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 e1233c9..6d63288 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 9d8dd16..b4ee0e4 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 18b5497..6d4ee5b 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 7b4519d..de7adcf 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 78227ca..be1eb4e 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 72b116d..72bc503 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 5379699..ff75522 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 4126217..fde14a7 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 f219fb9..4bdeaa8 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 c0523c6..1f95b70 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 cc21d48..99e4853 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 c43726d..de445c6 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 2d7213b..f7eecdb 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 ee44b28..d81f076 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 65fb76a..b21de2b 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 dce0dcf..c06c219 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 d5a8fef..d88b21d 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 27d8674..03d28e4 100644
--- a/menus/layers-menu.xml
+++ b/menus/layers-menu.xml
@@ -5,6 +5,13 @@
   <popup action="layers-popup">
     <menuitem action="layers-text-tool" />
     <menuitem action="layers-edit-attributes" />
+    <menu action="layers-composite-menu" name="Composite">
+     <menuitem action="layers-composite-auto" />
+     <menuitem action="layers-composite-src-over" />
+     <menuitem action="layers-composite-src-atop" />
+     <menuitem action="layers-composite-src-in" />
+     <menuitem action="layers-composite-dst-atop" />
+    </menu>
     <menu action="layers-color-tag-menu" name="Color Tags">
      <menuitem action="layers-color-tag-none" />
      <menuitem action="layers-color-tag-blue" />
diff --git a/po/POTFILES.in b/po/POTFILES.in
index be9cad4..75b57f9 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 b396303..8940408 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 35a480b..46a3d20 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 a4d19c0..e259605 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(<cairo.h>
               "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 c73bb67..e4e3cb7 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', '', @_);
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]