[gimp] app: split legacy out of grain extract and merge



commit ec1f7a94e373e38522ac64676cda872db72c6c0c
Author: Øyvind Kolås <pippin gimp org>
Date:   Wed Jan 11 04:36:31 2017 +0100

    app: split legacy out of grain extract and merge

 app/core/core-enums.c                              |   16 ++-
 app/core/core-enums.h                              |    6 +-
 app/gegl/gimp-gegl-nodes.c                         |   14 ++-
 app/operations/Makefile.am                         |    4 -
 app/operations/gimp-operations.c                   |   12 +-
 app/operations/gimplayermodefunctions.c            |   20 ++-
 app/operations/gimpoperationgrainextractmode.h     |   61 -------
 app/operations/gimpoperationgrainmergemode.h       |   61 -------
 app/operations/layer-modes-legacy/Makefile.am      |    6 +-
 .../gimpoperationgrainextractlegacy.c}             |   50 +++---
 .../gimpoperationgrainmergelegacy.c}               |   44 +++---
 .../gimpoperationhardlightlegacy.c}                |   42 +++--
 .../gimpoperationsoftlightlegacy.c                 |  169 ++++++++++++++++++++
 app/operations/layer-modes/Makefile.am             |    6 +-
 .../gimpoperationgrainextract.c}                   |   60 ++++----
 .../layer-modes/gimpoperationgrainmerge.c          |  136 ++++++++++++++++
 .../layer-modes/gimpoperationhardlight.c           |  148 +++++++++++++++++
 .../layer-modes/gimpoperationsoftlight.c           |  166 +++++++++++++++++++
 app/widgets/gimpwidgets-constructors.c             |    4 +-
 libgimp/gimpenums.h                                |    6 +-
 tools/pdbgen/enums.pl                              |   11 +-
 21 files changed, 799 insertions(+), 243 deletions(-)
---
diff --git a/app/core/core-enums.c b/app/core/core-enums.c
index 392468a..45a962b 100644
--- a/app/core/core-enums.c
+++ b/app/core/core-enums.c
@@ -333,6 +333,10 @@ gimp_layer_mode_get_type (void)
     { GIMP_LAYER_MODE_HSV_VALUE, "GIMP_LAYER_MODE_HSV_VALUE", "hsv-value" },
     { GIMP_LAYER_MODE_DIVIDE, "GIMP_LAYER_MODE_DIVIDE", "divide" },
     { GIMP_LAYER_MODE_BURN, "GIMP_LAYER_MODE_BURN", "burn" },
+    { GIMP_LAYER_MODE_HARDLIGHT, "GIMP_LAYER_MODE_HARDLIGHT", "hardlight" },
+    { GIMP_LAYER_MODE_SOFTLIGHT, "GIMP_LAYER_MODE_SOFTLIGHT", "softlight" },
+    { GIMP_LAYER_MODE_GRAIN_EXTRACT, "GIMP_LAYER_MODE_GRAIN_EXTRACT", "grain-extract" },
+    { GIMP_LAYER_MODE_GRAIN_MERGE, "GIMP_LAYER_MODE_GRAIN_MERGE", "grain-merge" },
     { GIMP_LAYER_MODE_ERASE, "GIMP_LAYER_MODE_ERASE", "erase" },
     { GIMP_LAYER_MODE_REPLACE, "GIMP_LAYER_MODE_REPLACE", "replace" },
     { GIMP_LAYER_MODE_ANTI_ERASE, "GIMP_LAYER_MODE_ANTI_ERASE", "anti-erase" },
@@ -359,10 +363,10 @@ gimp_layer_mode_get_type (void)
     { GIMP_LAYER_MODE_DIVIDE_LEGACY, NC_("layer-mode", "Divide (legacy)"), NULL },
     { GIMP_LAYER_MODE_DODGE_LEGACY, NC_("layer-mode", "Dodge (legacy)"), NULL },
     { GIMP_LAYER_MODE_BURN_LEGACY, NC_("layer-mode", "Burn (legacy)"), NULL },
-    { GIMP_LAYER_MODE_HARDLIGHT_LEGACY, NC_("layer-mode", "Hard light"), NULL },
-    { GIMP_LAYER_MODE_SOFTLIGHT_LEGACY, NC_("layer-mode", "Soft light"), NULL },
-    { GIMP_LAYER_MODE_GRAIN_EXTRACT_LEGACY, NC_("layer-mode", "Grain extract"), NULL },
-    { GIMP_LAYER_MODE_GRAIN_MERGE_LEGACY, NC_("layer-mode", "Grain merge"), NULL },
+    { GIMP_LAYER_MODE_HARDLIGHT_LEGACY, NC_("layer-mode", "Hard light (legacy)"), NULL },
+    { GIMP_LAYER_MODE_SOFTLIGHT_LEGACY, NC_("layer-mode", "Soft light (legacy)"), NULL },
+    { GIMP_LAYER_MODE_GRAIN_EXTRACT_LEGACY, NC_("layer-mode", "Grain extract (legacy)"), NULL },
+    { GIMP_LAYER_MODE_GRAIN_MERGE_LEGACY, NC_("layer-mode", "Grain merge (legacy)"), NULL },
     { GIMP_LAYER_MODE_COLOR_ERASE, NC_("layer-mode", "Color erase"), NULL },
     { GIMP_LAYER_MODE_OVERLAY, NC_("layer-mode", "Overlay"), NULL },
     { GIMP_LAYER_MODE_LCH_HUE, NC_("layer-mode", "Hue (LCH)"), NULL },
@@ -385,6 +389,10 @@ gimp_layer_mode_get_type (void)
     { GIMP_LAYER_MODE_HSV_VALUE, NC_("layer-mode", "Value (HSV)"), NULL },
     { GIMP_LAYER_MODE_DIVIDE, NC_("layer-mode", "Divide"), NULL },
     { GIMP_LAYER_MODE_BURN, NC_("layer-mode", "Burn"), NULL },
+    { GIMP_LAYER_MODE_HARDLIGHT, NC_("layer-mode", "Hard light"), NULL },
+    { GIMP_LAYER_MODE_SOFTLIGHT, NC_("layer-mode", "Soft light"), NULL },
+    { GIMP_LAYER_MODE_GRAIN_EXTRACT, NC_("layer-mode", "Grain extract"), NULL },
+    { GIMP_LAYER_MODE_GRAIN_MERGE, NC_("layer-mode", "Grain merge"), NULL },
     { GIMP_LAYER_MODE_ERASE, NC_("layer-mode", "Erase"), NULL },
     { GIMP_LAYER_MODE_REPLACE, NC_("layer-mode", "Replace"), NULL },
     { GIMP_LAYER_MODE_ANTI_ERASE, NC_("layer-mode", "Anti erase"), NULL },
diff --git a/app/core/core-enums.h b/app/core/core-enums.h
index 66be49a..99eeb74 100644
--- a/app/core/core-enums.h
+++ b/app/core/core-enums.h
@@ -174,8 +174,8 @@ typedef enum
   GIMP_LAYER_MODE_BURN_LEGACY,            /*< desc="Burn (legacy)"        >*/
   GIMP_LAYER_MODE_HARDLIGHT_LEGACY,       /*< desc="Hard light (legacy)"  >*/
   GIMP_LAYER_MODE_SOFTLIGHT_LEGACY,       /*< desc="Soft light (legacy)"  >*/
-  GIMP_LAYER_MODE_GRAIN_EXTRACT_LEGACY,   /*< desc="Grain extract"        >*/
-  GIMP_LAYER_MODE_GRAIN_MERGE_LEGACY,     /*< desc="Grain merge"          >*/
+  GIMP_LAYER_MODE_GRAIN_EXTRACT_LEGACY,   /*< desc="Grain extract (legacy)">*/
+  GIMP_LAYER_MODE_GRAIN_MERGE_LEGACY,     /*< desc="Grain merge (legacy)" >*/
   GIMP_LAYER_MODE_COLOR_ERASE,            /*< desc="Color erase"          >*/
   GIMP_LAYER_MODE_OVERLAY,                /*< desc="Overlay"              >*/
   GIMP_LAYER_MODE_LCH_HUE,                /*< desc="Hue (LCH)"            >*/
@@ -200,6 +200,8 @@ typedef enum
   GIMP_LAYER_MODE_BURN,                   /*< desc="Burn"                 >*/
   GIMP_LAYER_MODE_HARDLIGHT,              /*< desc="Hard light"           >*/
   GIMP_LAYER_MODE_SOFTLIGHT,              /*< desc="Soft light"           >*/
+  GIMP_LAYER_MODE_GRAIN_EXTRACT,          /*< desc="Grain extract"        >*/
+  GIMP_LAYER_MODE_GRAIN_MERGE,            /*< desc="Grain merge"          >*/
 
   /* internal modes, not available to the PDB */
   GIMP_LAYER_MODE_ERASE      = 1000, /*< pdb-skip, desc="Erase"      >*/
diff --git a/app/gegl/gimp-gegl-nodes.c b/app/gegl/gimp-gegl-nodes.c
index af7c049..2ce3dba 100644
--- a/app/gegl/gimp-gegl-nodes.c
+++ b/app/gegl/gimp-gegl-nodes.c
@@ -295,12 +295,20 @@ gimp_gegl_mode_node_set_mode (GeglNode      *node,
       operation = "gimp:softlight-legacy";
       break;
 
+    case GIMP_LAYER_MODE_GRAIN_EXTRACT:
+      operation = "gimp:grain-extract";
+      break;
+
     case GIMP_LAYER_MODE_GRAIN_EXTRACT_LEGACY:
-      operation = "gimp:grain-extract-mode";
+      operation = "gimp:grain-extract-legacy";
+      break;
+
+    case GIMP_LAYER_MODE_GRAIN_MERGE:
+      operation = "gimp:grain-merge";
       break;
 
     case GIMP_LAYER_MODE_GRAIN_MERGE_LEGACY:
-      operation = "gimp:grain-merge-mode";
+      operation = "gimp:grain-merge-legacy";
       break;
 
     case GIMP_LAYER_MODE_COLOR_ERASE:
@@ -398,7 +406,9 @@ gimp_gegl_mode_node_set_mode (GeglNode      *node,
     case GIMP_LAYER_MODE_BURN_LEGACY:
     case GIMP_LAYER_MODE_HARDLIGHT_LEGACY:
     case GIMP_LAYER_MODE_SOFTLIGHT_LEGACY:
+    case GIMP_LAYER_MODE_GRAIN_EXTRACT:
     case GIMP_LAYER_MODE_GRAIN_EXTRACT_LEGACY:
+    case GIMP_LAYER_MODE_GRAIN_MERGE:
     case GIMP_LAYER_MODE_GRAIN_MERGE_LEGACY:
     case GIMP_LAYER_MODE_COLOR_ERASE:
     case GIMP_LAYER_MODE_OVERLAY:
diff --git a/app/operations/Makefile.am b/app/operations/Makefile.am
index 1c2b21e..977ebd7 100644
--- a/app/operations/Makefile.am
+++ b/app/operations/Makefile.am
@@ -99,10 +99,6 @@ libappoperations_a_SOURCES = \
        gimpoperationpointlayermode.h           \
        gimpoperationbehindmode.c               \
        gimpoperationbehindmode.h               \
-       gimpoperationgrainextractmode.c         \
-       gimpoperationgrainextractmode.h         \
-       gimpoperationgrainmergemode.c           \
-       gimpoperationgrainmergemode.h           \
        gimpoperationcolorerasemode.c           \
        gimpoperationcolorerasemode.h           \
        gimpoperationreplacemode.c              \
diff --git a/app/operations/gimp-operations.c b/app/operations/gimp-operations.c
index 77ea621..444712c 100644
--- a/app/operations/gimp-operations.c
+++ b/app/operations/gimp-operations.c
@@ -102,8 +102,10 @@
 #include "layer-modes-legacy/gimpoperationhardlightlegacy.h"
 #include "layer-modes/gimpoperationsoftlight.h"
 #include "layer-modes-legacy/gimpoperationsoftlightlegacy.h"
-#include "gimpoperationgrainextractmode.h"
-#include "gimpoperationgrainmergemode.h"
+#include "layer-modes/gimpoperationgrainextract.h"
+#include "layer-modes-legacy/gimpoperationgrainextractlegacy.h"
+#include "layer-modes/gimpoperationgrainmerge.h"
+#include "layer-modes-legacy/gimpoperationgrainmergelegacy.h"
 #include "gimpoperationcolorerasemode.h"
 #include "layer-modes/gimpoperationlchhue.h"
 #include "layer-modes/gimpoperationlchchroma.h"
@@ -182,8 +184,10 @@ gimp_operations_init (void)
   g_type_class_ref (GIMP_TYPE_OPERATION_HARDLIGHT_LEGACY);
   g_type_class_ref (GIMP_TYPE_OPERATION_SOFTLIGHT);
   g_type_class_ref (GIMP_TYPE_OPERATION_SOFTLIGHT_LEGACY);
-  g_type_class_ref (GIMP_TYPE_OPERATION_GRAIN_EXTRACT_MODE);
-  g_type_class_ref (GIMP_TYPE_OPERATION_GRAIN_MERGE_MODE);
+  g_type_class_ref (GIMP_TYPE_OPERATION_GRAIN_EXTRACT);
+  g_type_class_ref (GIMP_TYPE_OPERATION_GRAIN_EXTRACT_LEGACY);
+  g_type_class_ref (GIMP_TYPE_OPERATION_GRAIN_MERGE);
+  g_type_class_ref (GIMP_TYPE_OPERATION_GRAIN_MERGE_LEGACY);
   g_type_class_ref (GIMP_TYPE_OPERATION_COLOR_ERASE_MODE);
   g_type_class_ref (GIMP_TYPE_OPERATION_LCH_HUE);
   g_type_class_ref (GIMP_TYPE_OPERATION_LCH_CHROMA);
diff --git a/app/operations/gimplayermodefunctions.c b/app/operations/gimplayermodefunctions.c
index 5642b1a..7f07bd1 100644
--- a/app/operations/gimplayermodefunctions.c
+++ b/app/operations/gimplayermodefunctions.c
@@ -62,8 +62,10 @@
 #include "layer-modes-legacy/gimpoperationhardlightlegacy.h"
 #include "layer-modes/gimpoperationsoftlight.h"
 #include "layer-modes-legacy/gimpoperationsoftlightlegacy.h"
-#include "gimpoperationgrainextractmode.h"
-#include "gimpoperationgrainmergemode.h"
+#include "layer-modes/gimpoperationgrainextract.h"
+#include "layer-modes-legacy/gimpoperationgrainextractlegacy.h"
+#include "layer-modes/gimpoperationgrainmerge.h"
+#include "layer-modes-legacy/gimpoperationgrainmergelegacy.h"
 #include "gimpoperationcolorerasemode.h"
 #include "layer-modes/gimpoperationlchhue.h"
 #include "layer-modes/gimpoperationlchchroma.h"
@@ -111,7 +113,7 @@ get_layer_mode_function (GimpLayerMode  paint_mode,
       break;
 
     case GIMP_LAYER_MODE_OVERLAY_LEGACY:
-      func = gimp_operation_softlight_mode_process_pixels;
+      func = gimp_operation_softlight_legacy_process_pixels;
       break;
 
     case GIMP_LAYER_MODE_DIFFERENCE_LEGACY:
@@ -226,12 +228,20 @@ get_layer_mode_function (GimpLayerMode  paint_mode,
       func = gimp_operation_softlight_legacy_process_pixels;
       break;
 
+    case GIMP_LAYER_MODE_GRAIN_EXTRACT:
+      func = gimp_operation_grain_extract_process_pixels;
+      break;
+
     case GIMP_LAYER_MODE_GRAIN_EXTRACT_LEGACY:
-      func = gimp_operation_grain_extract_mode_process_pixels;
+      func = gimp_operation_grain_extract_legacy_process_pixels;
+      break;
+
+    case GIMP_LAYER_MODE_GRAIN_MERGE:
+      func = gimp_operation_grain_merge_process_pixels;
       break;
 
     case GIMP_LAYER_MODE_GRAIN_MERGE_LEGACY:
-      func = gimp_operation_grain_merge_mode_process_pixels;
+      func = gimp_operation_grain_merge_legacy_process_pixels;
       break;
 
     case GIMP_LAYER_MODE_COLOR_ERASE:
diff --git a/app/operations/layer-modes-legacy/Makefile.am b/app/operations/layer-modes-legacy/Makefile.am
index 88c6424..37675ed 100644
--- a/app/operations/layer-modes-legacy/Makefile.am
+++ b/app/operations/layer-modes-legacy/Makefile.am
@@ -46,5 +46,9 @@ libapplayermodeslegacy_a_SOURCES = \
        gimpoperationhardlightlegacy.c  \
        gimpoperationhardlightlegacy.h  \
        gimpoperationsoftlightlegacy.c  \
-       gimpoperationsoftlightlegacy.h
+       gimpoperationsoftlightlegacy.h  \
+       gimpoperationgrainextractlegacy.c       \
+       gimpoperationgrainextractlegacy.h       \
+       gimpoperationgrainmergelegacy.c         \
+       gimpoperationgrainmergelegacy.h
 
diff --git a/app/operations/gimpoperationgrainextractmode.c 
b/app/operations/layer-modes-legacy/gimpoperationgrainextractlegacy.c
similarity index 62%
copy from app/operations/gimpoperationgrainextractmode.c
copy to app/operations/layer-modes-legacy/gimpoperationgrainextractlegacy.c
index 9c4041d..1ee14de 100644
--- a/app/operations/gimpoperationgrainextractmode.c
+++ b/app/operations/layer-modes-legacy/gimpoperationgrainextractlegacy.c
@@ -23,12 +23,12 @@
 
 #include <gegl-plugin.h>
 
-#include "operations-types.h"
+#include "../operations-types.h"
 
-#include "gimpoperationgrainextractmode.h"
+#include "gimpoperationgrainextractlegacy.h"
 
 
-static gboolean gimp_operation_grain_extract_mode_process (GeglOperation       *operation,
+static gboolean gimp_operation_grain_extract_legacy_process (GeglOperation       *operation,
                                                            void                *in_buf,
                                                            void                *aux_buf,
                                                            void                *aux2_buf,
@@ -38,12 +38,12 @@ static gboolean gimp_operation_grain_extract_mode_process (GeglOperation       *
                                                            gint                 level);
 
 
-G_DEFINE_TYPE (GimpOperationGrainExtractMode, gimp_operation_grain_extract_mode,
+G_DEFINE_TYPE (GimpOperationGrainExtractLegacy, gimp_operation_grain_extract_legacy,
                GIMP_TYPE_OPERATION_POINT_LAYER_MODE)
 
 
 static void
-gimp_operation_grain_extract_mode_class_init (GimpOperationGrainExtractModeClass *klass)
+gimp_operation_grain_extract_legacy_class_init (GimpOperationGrainExtractLegacyClass *klass)
 {
   GeglOperationClass               *operation_class;
   GeglOperationPointComposer3Class *point_class;
@@ -52,42 +52,42 @@ gimp_operation_grain_extract_mode_class_init (GimpOperationGrainExtractModeClass
   point_class     = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass);
 
   gegl_operation_class_set_keys (operation_class,
-                                 "name",        "gimp:grain-extract-mode",
+                                 "name",        "gimp:grain-extract-legacy",
                                  "description", "GIMP grain extract mode operation",
                                  NULL);
 
-  point_class->process = gimp_operation_grain_extract_mode_process;
+  point_class->process = gimp_operation_grain_extract_legacy_process;
 }
 
 static void
-gimp_operation_grain_extract_mode_init (GimpOperationGrainExtractMode *self)
+gimp_operation_grain_extract_legacy_init (GimpOperationGrainExtractLegacy *self)
 {
 }
 
 static gboolean
-gimp_operation_grain_extract_mode_process (GeglOperation       *operation,
-                                           void                *in_buf,
-                                           void                *aux_buf,
-                                           void                *aux2_buf,
-                                           void                *out_buf,
-                                           glong                samples,
-                                           const GeglRectangle *roi,
-                                           gint                 level)
+gimp_operation_grain_extract_legacy_process (GeglOperation       *operation,
+                                             void                *in_buf,
+                                             void                *aux_buf,
+                                             void                *aux2_buf,
+                                             void                *out_buf,
+                                             glong                samples,
+                                             const GeglRectangle *roi,
+                                             gint                 level)
 {
   gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
 
-  return gimp_operation_grain_extract_mode_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, 
samples, roi, level);
+  return gimp_operation_grain_extract_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, 
samples, roi, level);
 }
 
 gboolean
-gimp_operation_grain_extract_mode_process_pixels (gfloat              *in,
-                                                  gfloat              *layer,
-                                                  gfloat              *mask,
-                                                  gfloat              *out,
-                                                  gfloat               opacity,
-                                                  glong                samples,
-                                                  const GeglRectangle *roi,
-                                                  gint                 level)
+gimp_operation_grain_extract_legacy_process_pixels (gfloat              *in,
+                                                    gfloat              *layer,
+                                                    gfloat              *mask,
+                                                    gfloat              *out,
+                                                    gfloat               opacity,
+                                                    glong                samples,
+                                                    const GeglRectangle *roi,
+                                                    gint                 level)
 {
   const gboolean has_mask = mask != NULL;
 
diff --git a/app/operations/gimpoperationgrainextractmode.c 
b/app/operations/layer-modes-legacy/gimpoperationgrainmergelegacy.c
similarity index 69%
copy from app/operations/gimpoperationgrainextractmode.c
copy to app/operations/layer-modes-legacy/gimpoperationgrainmergelegacy.c
index 9c4041d..9ee1690 100644
--- a/app/operations/gimpoperationgrainextractmode.c
+++ b/app/operations/layer-modes-legacy/gimpoperationgrainmergelegacy.c
@@ -1,7 +1,7 @@
 /* GIMP - The GNU Image Manipulation Program
  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  *
- * gimpoperationgrainextractmode.c
+ * gimpoperationgrainmergemode.c
  * Copyright (C) 2008 Michael Natterer <mitch gimp org>
  *               2012 Ville Sokk <ville sokk gmail com>
  *
@@ -23,27 +23,27 @@
 
 #include <gegl-plugin.h>
 
-#include "operations-types.h"
+#include "../operations-types.h"
 
-#include "gimpoperationgrainextractmode.h"
+#include "gimpoperationgrainmergelegacy.h"
 
 
-static gboolean gimp_operation_grain_extract_mode_process (GeglOperation       *operation,
-                                                           void                *in_buf,
-                                                           void                *aux_buf,
-                                                           void                *aux2_buf,
-                                                           void                *out_buf,
-                                                           glong                samples,
-                                                           const GeglRectangle *roi,
-                                                           gint                 level);
+static gboolean gimp_operation_grain_merge_legacy_process (GeglOperation       *operation,
+                                                         void                *in_buf,
+                                                         void                *aux_buf,
+                                                         void                *aux2_buf,
+                                                         void                *out_buf,
+                                                         glong                samples,
+                                                         const GeglRectangle *roi,
+                                                         gint                 level);
 
 
-G_DEFINE_TYPE (GimpOperationGrainExtractMode, gimp_operation_grain_extract_mode,
+G_DEFINE_TYPE (GimpOperationGrainMergeLegacy, gimp_operation_grain_merge_legacy,
                GIMP_TYPE_OPERATION_POINT_LAYER_MODE)
 
 
 static void
-gimp_operation_grain_extract_mode_class_init (GimpOperationGrainExtractModeClass *klass)
+gimp_operation_grain_merge_legacy_class_init (GimpOperationGrainMergeLegacyClass *klass)
 {
   GeglOperationClass               *operation_class;
   GeglOperationPointComposer3Class *point_class;
@@ -52,20 +52,20 @@ gimp_operation_grain_extract_mode_class_init (GimpOperationGrainExtractModeClass
   point_class     = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass);
 
   gegl_operation_class_set_keys (operation_class,
-                                 "name",        "gimp:grain-extract-mode",
-                                 "description", "GIMP grain extract mode operation",
+                                 "name",        "gimp:grain-merge-legacy",
+                                 "description", "GIMP grain merge mode operation",
                                  NULL);
 
-  point_class->process = gimp_operation_grain_extract_mode_process;
+  point_class->process = gimp_operation_grain_merge_legacy_process;
 }
 
 static void
-gimp_operation_grain_extract_mode_init (GimpOperationGrainExtractMode *self)
+gimp_operation_grain_merge_legacy_init (GimpOperationGrainMergeLegacy *self)
 {
 }
 
 static gboolean
-gimp_operation_grain_extract_mode_process (GeglOperation       *operation,
+gimp_operation_grain_merge_legacy_process (GeglOperation       *operation,
                                            void                *in_buf,
                                            void                *aux_buf,
                                            void                *aux2_buf,
@@ -76,11 +76,11 @@ gimp_operation_grain_extract_mode_process (GeglOperation       *operation,
 {
   gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
 
-  return gimp_operation_grain_extract_mode_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, 
samples, roi, level);
+  return gimp_operation_grain_merge_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, 
samples, roi, level);
 }
 
 gboolean
-gimp_operation_grain_extract_mode_process_pixels (gfloat              *in,
+gimp_operation_grain_merge_legacy_process_pixels (gfloat              *in,
                                                   gfloat              *layer,
                                                   gfloat              *mask,
                                                   gfloat              *out,
@@ -108,7 +108,7 @@ gimp_operation_grain_extract_mode_process_pixels (gfloat              *in,
 
           for (b = RED; b < ALPHA; b++)
             {
-              gfloat comp = in[b] - layer[b] + 0.5;
+              gfloat comp = in[b] + layer[b] - 0.5;
 
               out[b] = comp * ratio + in[b] * (1.0 - ratio);
               out[b] = CLAMP (out[b], 0.0, 1.0);
@@ -131,7 +131,7 @@ gimp_operation_grain_extract_mode_process_pixels (gfloat              *in,
       out   += 4;
 
       if (has_mask)
-        mask++;
+        mask ++;
     }
 
   return TRUE;
diff --git a/app/operations/gimpoperationgrainmergemode.c 
b/app/operations/layer-modes-legacy/gimpoperationhardlightlegacy.c
similarity index 77%
rename from app/operations/gimpoperationgrainmergemode.c
rename to app/operations/layer-modes-legacy/gimpoperationhardlightlegacy.c
index e3feade..826bca6 100644
--- a/app/operations/gimpoperationgrainmergemode.c
+++ b/app/operations/layer-modes-legacy/gimpoperationhardlightlegacy.c
@@ -1,7 +1,7 @@
 /* GIMP - The GNU Image Manipulation Program
  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  *
- * gimpoperationgrainmergemode.c
+ * gimpoperationhardlightmode.c
  * Copyright (C) 2008 Michael Natterer <mitch gimp org>
  *               2012 Ville Sokk <ville sokk gmail com>
  *
@@ -23,12 +23,12 @@
 
 #include <gegl-plugin.h>
 
-#include "operations-types.h"
+#include "../operations-types.h"
 
-#include "gimpoperationgrainmergemode.h"
+#include "gimpoperationhardlightlegacy.h"
 
 
-static gboolean gimp_operation_grain_merge_mode_process (GeglOperation       *operation,
+static gboolean gimp_operation_hardlight_legacy_process (GeglOperation       *operation,
                                                          void                *in_buf,
                                                          void                *aux_buf,
                                                          void                *aux2_buf,
@@ -36,14 +36,14 @@ static gboolean gimp_operation_grain_merge_mode_process (GeglOperation       *op
                                                          glong                samples,
                                                          const GeglRectangle *roi,
                                                          gint                 level);
+ 
 
-
-G_DEFINE_TYPE (GimpOperationGrainMergeMode, gimp_operation_grain_merge_mode,
+G_DEFINE_TYPE (GimpOperationHardlightLegacy, gimp_operation_hardlight_legacy,
                GIMP_TYPE_OPERATION_POINT_LAYER_MODE)
 
 
 static void
-gimp_operation_grain_merge_mode_class_init (GimpOperationGrainMergeModeClass *klass)
+gimp_operation_hardlight_legacy_class_init (GimpOperationHardlightLegacyClass *klass)
 {
   GeglOperationClass               *operation_class;
   GeglOperationPointComposer3Class *point_class;
@@ -52,20 +52,20 @@ gimp_operation_grain_merge_mode_class_init (GimpOperationGrainMergeModeClass *kl
   point_class     = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass);
 
   gegl_operation_class_set_keys (operation_class,
-                                 "name",        "gimp:grain-merge-mode",
-                                 "description", "GIMP grain merge mode operation",
+                                 "name",        "gimp:hardlight-legacy",
+                                 "description", "GIMP hardlight mode operation",
                                  NULL);
 
-  point_class->process = gimp_operation_grain_merge_mode_process;
+  point_class->process = gimp_operation_hardlight_legacy_process;
 }
 
 static void
-gimp_operation_grain_merge_mode_init (GimpOperationGrainMergeMode *self)
+gimp_operation_hardlight_legacy_init (GimpOperationHardlightLegacy *self)
 {
 }
 
 static gboolean
-gimp_operation_grain_merge_mode_process (GeglOperation       *operation,
+gimp_operation_hardlight_legacy_process (GeglOperation       *operation,
                                          void                *in_buf,
                                          void                *aux_buf,
                                          void                *aux2_buf,
@@ -76,11 +76,11 @@ gimp_operation_grain_merge_mode_process (GeglOperation       *operation,
 {
   gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
 
-  return gimp_operation_grain_merge_mode_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, 
samples, roi, level);
+  return gimp_operation_hardlight_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, 
samples, roi, level);
 }
 
 gboolean
-gimp_operation_grain_merge_mode_process_pixels (gfloat              *in,
+gimp_operation_hardlight_legacy_process_pixels (gfloat              *in,
                                                 gfloat              *layer,
                                                 gfloat              *mask,
                                                 gfloat              *out,
@@ -108,10 +108,20 @@ gimp_operation_grain_merge_mode_process_pixels (gfloat              *in,
 
           for (b = RED; b < ALPHA; b++)
             {
-              gfloat comp = in[b] + layer[b] - 0.5;
+              gfloat comp;
+
+              if (layer[b] > 0.5)
+                {
+                  comp = (1.0 - in[b]) * (1.0 - (layer[b] - 0.5) * 2.0);
+                  comp = MIN (1 - comp, 1);
+                }
+              else
+                {
+                  comp = in[b] * (layer[b] * 2.0);
+                  comp = MIN (comp, 1.0);
+                }
 
               out[b] = comp * ratio + in[b] * (1.0 - ratio);
-              out[b] = CLAMP (out[b], 0.0, 1.0);
             }
         }
       else
diff --git a/app/operations/layer-modes-legacy/gimpoperationsoftlightlegacy.c 
b/app/operations/layer-modes-legacy/gimpoperationsoftlightlegacy.c
new file mode 100644
index 0000000..ee1e4ed
--- /dev/null
+++ b/app/operations/layer-modes-legacy/gimpoperationsoftlightlegacy.c
@@ -0,0 +1,169 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpoperationsoftlightmode.c
+ * Copyright (C) 2008 Michael Natterer <mitch gimp org>
+ *               2012 Ville Sokk <ville sokk gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl-plugin.h>
+
+#include "../operations-types.h"
+
+#include "gimpoperationsoftlightlegacy.h"
+
+
+static gboolean gimp_operation_softlight_legacy_process (GeglOperation       *operation,
+                                                         void                *in_buf,
+                                                         void                *aux_buf,
+                                                         void                *aux2_buf,
+                                                         void                *out_buf,
+                                                         glong                samples,
+                                                         const GeglRectangle *roi,
+                                                         gint                 level);
+
+
+G_DEFINE_TYPE (GimpOperationSoftlightLegacy, gimp_operation_softlight_legacy,
+               GIMP_TYPE_OPERATION_POINT_LAYER_MODE)
+
+static const gchar* reference_xml = "<?xml version='1.0' encoding='UTF-8'?>"
+"<gegl>"
+"<node operation='gimp:softlight-mode'>"
+"  <node operation='gegl:load'>"
+"    <params>"
+"      <param name='path'>B.png</param>"
+"    </params>"
+"  </node>"
+"</node>"
+"<node operation='gegl:load'>"
+"  <params>"
+"    <param name='path'>A.png</param>"
+"  </params>"
+"</node>"
+"</gegl>";
+
+
+static void
+gimp_operation_softlight_legacy_class_init (GimpOperationSoftlightLegacyClass *klass)
+{
+  GeglOperationClass               *operation_class;
+  GeglOperationPointComposer3Class *point_class;
+
+  operation_class = GEGL_OPERATION_CLASS (klass);
+  point_class     = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass);
+
+  gegl_operation_class_set_keys (operation_class,
+                                 "name",        "gimp:softlight-legacy",
+                                 "description", "GIMP softlight mode operation",
+                                 "reference-image", "soft-light-mode.png",
+                                 "reference-composition", reference_xml,
+                                 NULL);
+
+  point_class->process = gimp_operation_softlight_legacy_process;
+}
+
+static void
+gimp_operation_softlight_legacy_init (GimpOperationSoftlightLegacy *self)
+{
+}
+
+static gboolean
+gimp_operation_softlight_legacy_process (GeglOperation       *operation,
+                                       void                *in_buf,
+                                       void                *aux_buf,
+                                       void                *aux2_buf,
+                                       void                *out_buf,
+                                       glong                samples,
+                                       const GeglRectangle *roi,
+                                       gint                 level)
+{
+  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+
+  return gimp_operation_softlight_legacy_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, 
samples, roi, level);
+}
+
+gboolean
+gimp_operation_softlight_legacy_process_pixels (gfloat              *in,
+                                              gfloat              *layer,
+                                              gfloat              *mask,
+                                              gfloat              *out,
+                                              gfloat               opacity,
+                                              glong                samples,
+                                              const GeglRectangle *roi,
+                                              gint                 level)
+{
+  const gboolean has_mask = mask != NULL;
+
+  while (samples--)
+    {
+      gfloat comp_alpha, new_alpha;
+
+      comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity;
+      if (has_mask)
+        comp_alpha *= *mask;
+
+      new_alpha = in[ALPHA] + (1.0 - in[ALPHA]) * comp_alpha;
+
+      if (comp_alpha && new_alpha)
+        {
+          gfloat ratio = comp_alpha / new_alpha;
+          gint   b;
+
+          for (b = RED; b < ALPHA; b++)
+            {
+#if 0
+              /* softlight is now used for what GIMP formerly called
+               * OVERLAY.  We fixed OVERLAY to use the right math
+               * (under the name NEW_OVERLAY), and redirect uses of
+               * the old OVERLAY blend mode here. This math was
+               * formerly used for OVERLAY and is exactly the same as
+               * the multiply, screen, comp math used below.
+               * See bug #673501.
+               */
+              gfloat comp = in[b] * (in[b] + (2.0 * layer[b]) * (1.0 - in[b]));
+#endif
+
+              gfloat multiply = in[b] * layer[b];
+              gfloat screen   = 1.0 - (1.0 - in[b]) * (1.0 - layer[b]);
+              gfloat comp     = (1.0 - in[b]) * multiply + in[b] * screen;
+
+              out[b] = comp * ratio + in[b] * (1.0 - ratio);
+            }
+        }
+      else
+        {
+          gint b;
+
+          for (b = RED; b < ALPHA; b++)
+            {
+              out[b] = in[b];
+            }
+        }
+
+      out[ALPHA] = in[ALPHA];
+
+      in    += 4;
+      layer += 4;
+      out   += 4;
+
+      if (has_mask)
+        mask ++;
+    }
+
+  return TRUE;
+}
diff --git a/app/operations/layer-modes/Makefile.am b/app/operations/layer-modes/Makefile.am
index 84cee81..9e0d04a 100644
--- a/app/operations/layer-modes/Makefile.am
+++ b/app/operations/layer-modes/Makefile.am
@@ -68,7 +68,11 @@ libapplayermodes_generic_a_sources = \
        gimpoperationhardlight.c        \
        gimpoperationhardlight.h        \
        gimpoperationsoftlight.c        \
-       gimpoperationsoftlight.h
+       gimpoperationsoftlight.h        \
+       gimpoperationgrainextract.c     \
+       gimpoperationgrainextract.h     \
+       gimpoperationgrainmerge.c       \
+       gimpoperationgrainmerge.h
 
 libapplayermodes_sse2_a_sources = \
        gimpoperationnormal-sse2.c
diff --git a/app/operations/gimpoperationgrainextractmode.c 
b/app/operations/layer-modes/gimpoperationgrainextract.c
similarity index 58%
rename from app/operations/gimpoperationgrainextractmode.c
rename to app/operations/layer-modes/gimpoperationgrainextract.c
index 9c4041d..733bb46 100644
--- a/app/operations/gimpoperationgrainextractmode.c
+++ b/app/operations/layer-modes/gimpoperationgrainextract.c
@@ -4,6 +4,7 @@
  * gimpoperationgrainextractmode.c
  * Copyright (C) 2008 Michael Natterer <mitch gimp org>
  *               2012 Ville Sokk <ville sokk gmail com>
+ *               2017 Øyvind Kolås <pippin gimp org>
  *
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -23,12 +24,12 @@
 
 #include <gegl-plugin.h>
 
-#include "operations-types.h"
+#include "../operations-types.h"
 
-#include "gimpoperationgrainextractmode.h"
+#include "gimpoperationgrainextract.h"
 
 
-static gboolean gimp_operation_grain_extract_mode_process (GeglOperation       *operation,
+static gboolean gimp_operation_grain_extract_process (GeglOperation       *operation,
                                                            void                *in_buf,
                                                            void                *aux_buf,
                                                            void                *aux2_buf,
@@ -38,12 +39,12 @@ static gboolean gimp_operation_grain_extract_mode_process (GeglOperation       *
                                                            gint                 level);
 
 
-G_DEFINE_TYPE (GimpOperationGrainExtractMode, gimp_operation_grain_extract_mode,
+G_DEFINE_TYPE (GimpOperationGrainExtract, gimp_operation_grain_extract,
                GIMP_TYPE_OPERATION_POINT_LAYER_MODE)
 
 
 static void
-gimp_operation_grain_extract_mode_class_init (GimpOperationGrainExtractModeClass *klass)
+gimp_operation_grain_extract_class_init (GimpOperationGrainExtractClass *klass)
 {
   GeglOperationClass               *operation_class;
   GeglOperationPointComposer3Class *point_class;
@@ -52,65 +53,62 @@ gimp_operation_grain_extract_mode_class_init (GimpOperationGrainExtractModeClass
   point_class     = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass);
 
   gegl_operation_class_set_keys (operation_class,
-                                 "name",        "gimp:grain-extract-mode",
+                                 "name",        "gimp:grain-extract",
                                  "description", "GIMP grain extract mode operation",
                                  NULL);
 
-  point_class->process = gimp_operation_grain_extract_mode_process;
+  point_class->process = gimp_operation_grain_extract_process;
 }
 
 static void
-gimp_operation_grain_extract_mode_init (GimpOperationGrainExtractMode *self)
+gimp_operation_grain_extract_init (GimpOperationGrainExtract *self)
 {
 }
 
 static gboolean
-gimp_operation_grain_extract_mode_process (GeglOperation       *operation,
-                                           void                *in_buf,
-                                           void                *aux_buf,
-                                           void                *aux2_buf,
-                                           void                *out_buf,
-                                           glong                samples,
-                                           const GeglRectangle *roi,
-                                           gint                 level)
+gimp_operation_grain_extract_process (GeglOperation       *operation,
+                                      void                *in_buf,
+                                      void                *aux_buf,
+                                      void                *aux2_buf,
+                                      void                *out_buf,
+                                      glong                samples,
+                                      const GeglRectangle *roi,
+                                      gint                 level)
 {
   gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
 
-  return gimp_operation_grain_extract_mode_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, 
samples, roi, level);
+  return gimp_operation_grain_extract_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, 
roi, level);
 }
 
 gboolean
-gimp_operation_grain_extract_mode_process_pixels (gfloat              *in,
-                                                  gfloat              *layer,
-                                                  gfloat              *mask,
-                                                  gfloat              *out,
-                                                  gfloat               opacity,
-                                                  glong                samples,
-                                                  const GeglRectangle *roi,
-                                                  gint                 level)
+gimp_operation_grain_extract_process_pixels (gfloat              *in,
+                                             gfloat              *layer,
+                                             gfloat              *mask,
+                                             gfloat              *out,
+                                             gfloat               opacity,
+                                             glong                samples,
+                                             const GeglRectangle *roi,
+                                             gint                 level)
 {
   const gboolean has_mask = mask != NULL;
 
   while (samples--)
     {
-      gfloat comp_alpha, new_alpha;
+      gfloat comp_alpha;
 
       comp_alpha = MIN (in[ALPHA], layer[ALPHA]) * opacity;
       if (has_mask)
         comp_alpha *= *mask;
 
-      new_alpha = in[ALPHA] + (1.0 - in[ALPHA]) * comp_alpha;
-
-      if (comp_alpha && new_alpha)
+      if (comp_alpha != 0.0f)
         {
-          gfloat ratio = comp_alpha / new_alpha;
           gint   b;
 
           for (b = RED; b < ALPHA; b++)
             {
               gfloat comp = in[b] - layer[b] + 0.5;
 
-              out[b] = comp * ratio + in[b] * (1.0 - ratio);
+              out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
               out[b] = CLAMP (out[b], 0.0, 1.0);
             }
         }
diff --git a/app/operations/layer-modes/gimpoperationgrainmerge.c 
b/app/operations/layer-modes/gimpoperationgrainmerge.c
new file mode 100644
index 0000000..cd626fb
--- /dev/null
+++ b/app/operations/layer-modes/gimpoperationgrainmerge.c
@@ -0,0 +1,136 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpoperationgrainmergemode.c
+ * Copyright (C) 2008 Michael Natterer <mitch gimp org>
+ *               2012 Ville Sokk <ville sokk gmail com>
+ *               2017 Øyvind Kolås <pippin gimp org>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl-plugin.h>
+
+#include "../operations-types.h"
+
+#include "gimpoperationgrainmerge.h"
+
+
+static gboolean gimp_operation_grain_merge_process (GeglOperation       *operation,
+                                                    void                *in_buf,
+                                                    void                *aux_buf,
+                                                    void                *aux2_buf,
+                                                    void                *out_buf,
+                                                    glong                samples,
+                                                    const GeglRectangle *roi,
+                                                    gint                 level);
+
+
+G_DEFINE_TYPE (GimpOperationGrainMerge, gimp_operation_grain_merge,
+               GIMP_TYPE_OPERATION_POINT_LAYER_MODE)
+
+
+static void
+gimp_operation_grain_merge_class_init (GimpOperationGrainMergeClass *klass)
+{
+  GeglOperationClass               *operation_class;
+  GeglOperationPointComposer3Class *point_class;
+
+  operation_class = GEGL_OPERATION_CLASS (klass);
+  point_class     = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass);
+
+  gegl_operation_class_set_keys (operation_class,
+                                 "name",        "gimp:grain-merge",
+                                 "description", "GIMP grain merge mode operation",
+                                 NULL);
+
+  point_class->process = gimp_operation_grain_merge_process;
+}
+
+static void
+gimp_operation_grain_merge_init (GimpOperationGrainMerge *self)
+{
+}
+
+static gboolean
+gimp_operation_grain_merge_process (GeglOperation       *operation,
+                                    void                *in_buf,
+                                    void                *aux_buf,
+                                    void                *aux2_buf,
+                                    void                *out_buf,
+                                    glong                samples,
+                                    const GeglRectangle *roi,
+                                    gint                 level)
+{
+  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+
+  return gimp_operation_grain_merge_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, 
roi, level);
+}
+
+gboolean
+gimp_operation_grain_merge_process_pixels (gfloat              *in,
+                                           gfloat              *layer,
+                                           gfloat              *mask,
+                                           gfloat              *out,
+                                           gfloat               opacity,
+                                           glong                samples,
+                                           const GeglRectangle *roi,
+                                           gint                 level)
+{
+  const gboolean has_mask = mask != NULL;
+
+  while (samples--)
+    {
+      gfloat comp_alpha;
+
+      comp_alpha = layer[ALPHA] * opacity;
+      if (has_mask)
+        comp_alpha *= *mask;
+
+      if (comp_alpha != 0.0)
+        {
+          gint   b;
+
+          for (b = RED; b < ALPHA; b++)
+            {
+              gfloat comp = in[b] + layer[b] - 0.5;
+
+              out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
+              out[b] = CLAMP (out[b], 0.0, 1.0);
+            }
+        }
+      else
+        {
+          gint b;
+
+          for (b = RED; b < ALPHA; b++)
+            {
+              out[b] = in[b];
+            }
+        }
+
+      out[ALPHA] = in[ALPHA];
+
+      in    += 4;
+      layer += 4;
+      out   += 4;
+
+      if (has_mask)
+        mask ++;
+    }
+
+  return TRUE;
+}
diff --git a/app/operations/layer-modes/gimpoperationhardlight.c 
b/app/operations/layer-modes/gimpoperationhardlight.c
new file mode 100644
index 0000000..34b8db2
--- /dev/null
+++ b/app/operations/layer-modes/gimpoperationhardlight.c
@@ -0,0 +1,148 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpoperationhardlightmode.c
+ * Copyright (C) 2008 Michael Natterer <mitch gimp org>
+ *               2012 Ville Sokk <ville sokk gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl-plugin.h>
+
+#include "../operations-types.h"
+
+#include "gimpoperationhardlight.h"
+
+
+static gboolean gimp_operation_hardlight_process (GeglOperation       *operation,
+                                                  void                *in_buf,
+                                                  void                *aux_buf,
+                                                  void                *aux2_buf,
+                                                  void                *out_buf,
+                                                  glong                samples,
+                                                  const GeglRectangle *roi,
+                                                  gint                 level);
+
+
+G_DEFINE_TYPE (GimpOperationHardlight, gimp_operation_hardlight,
+               GIMP_TYPE_OPERATION_POINT_LAYER_MODE)
+
+
+static void
+gimp_operation_hardlight_class_init (GimpOperationHardlightClass *klass)
+{
+  GeglOperationClass               *operation_class;
+  GeglOperationPointComposer3Class *point_class;
+
+  operation_class = GEGL_OPERATION_CLASS (klass);
+  point_class     = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass);
+
+  gegl_operation_class_set_keys (operation_class,
+                                 "name",        "gimp:hardlight",
+                                 "description", "GIMP hardlight mode operation",
+                                 NULL);
+
+  point_class->process = gimp_operation_hardlight_process;
+}
+
+static void
+gimp_operation_hardlight_init (GimpOperationHardlight *self)
+{
+}
+
+static gboolean
+gimp_operation_hardlight_process (GeglOperation       *operation,
+                                  void                *in_buf,
+                                  void                *aux_buf,
+                                  void                *aux2_buf,
+                                  void                *out_buf,
+                                  glong                samples,
+                                  const GeglRectangle *roi,
+                                  gint                 level)
+{
+  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+
+  return gimp_operation_hardlight_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, 
level);
+}
+
+gboolean
+gimp_operation_hardlight_process_pixels (gfloat              *in,
+                                         gfloat              *layer,
+                                         gfloat              *mask,
+                                         gfloat              *out,
+                                         gfloat               opacity,
+                                         glong                samples,
+                                         const GeglRectangle *roi,
+                                         gint                 level)
+{
+  const gboolean has_mask = mask != NULL;
+
+  while (samples--)
+    {
+      gfloat comp_alpha, new_alpha;
+
+      comp_alpha = layer[ALPHA] * opacity;
+      if (has_mask)
+        comp_alpha *= *mask;
+
+      new_alpha = in[ALPHA] + (1.0 - in[ALPHA]) * comp_alpha;
+
+      if (comp_alpha && new_alpha)
+        {
+          gfloat ratio = comp_alpha / new_alpha;
+          gint   b;
+
+          for (b = RED; b < ALPHA; b++)
+            {
+              gfloat comp;
+
+              if (layer[b] > 0.5)
+                {
+                  comp = (1.0 - in[b]) * (1.0 - (layer[b] - 0.5) * 2.0);
+                  comp = MIN (1 - comp, 1);
+                }
+              else
+                {
+                  comp = in[b] * (layer[b] * 2.0);
+                  comp = MIN (comp, 1.0);
+                }
+
+              out[b] = comp * ratio + in[b] * (1.0 - ratio);
+            }
+        }
+      else
+        {
+          gint b;
+
+          for (b = RED; b < ALPHA; b++)
+            {
+              out[b] = in[b];
+            }
+        }
+
+      out[ALPHA] = in[ALPHA];
+
+      in    += 4;
+      layer += 4;
+      out   += 4;
+
+      if (has_mask)
+        mask ++;
+    }
+
+  return TRUE;
+}
diff --git a/app/operations/layer-modes/gimpoperationsoftlight.c 
b/app/operations/layer-modes/gimpoperationsoftlight.c
new file mode 100644
index 0000000..74b3ea1
--- /dev/null
+++ b/app/operations/layer-modes/gimpoperationsoftlight.c
@@ -0,0 +1,166 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * gimpoperationsoftlightmode.c
+ * Copyright (C) 2008 Michael Natterer <mitch gimp org>
+ *               2012 Ville Sokk <ville sokk gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl-plugin.h>
+
+#include "../operations-types.h"
+
+#include "gimpoperationsoftlight.h"
+
+
+static gboolean gimp_operation_softlight_process (GeglOperation       *operation,
+                                                       void                *in_buf,
+                                                       void                *aux_buf,
+                                                       void                *aux2_buf,
+                                                       void                *out_buf,
+                                                       glong                samples,
+                                                       const GeglRectangle *roi,
+                                                       gint                 level);
+
+
+G_DEFINE_TYPE (GimpOperationSoftlight, gimp_operation_softlight,
+               GIMP_TYPE_OPERATION_POINT_LAYER_MODE)
+
+static const gchar* reference_xml = "<?xml version='1.0' encoding='UTF-8'?>"
+"<gegl>"
+"<node operation='gimp:softlight-mode'>"
+"  <node operation='gegl:load'>"
+"    <params>"
+"      <param name='path'>B.png</param>"
+"    </params>"
+"  </node>"
+"</node>"
+"<node operation='gegl:load'>"
+"  <params>"
+"    <param name='path'>A.png</param>"
+"  </params>"
+"</node>"
+"</gegl>";
+
+
+static void
+gimp_operation_softlight_class_init (GimpOperationSoftlightClass *klass)
+{
+  GeglOperationClass               *operation_class;
+  GeglOperationPointComposer3Class *point_class;
+
+  operation_class = GEGL_OPERATION_CLASS (klass);
+  point_class     = GEGL_OPERATION_POINT_COMPOSER3_CLASS (klass);
+
+  gegl_operation_class_set_keys (operation_class,
+                                 "name",        "gimp:softlight",
+                                 "description", "GIMP softlight mode operation",
+                                 "reference-image", "soft-light-mode.png",
+                                 "reference-composition", reference_xml,
+                                 NULL);
+
+  point_class->process = gimp_operation_softlight_process;
+}
+
+static void
+gimp_operation_softlight_init (GimpOperationSoftlight *self)
+{
+}
+
+static gboolean
+gimp_operation_softlight_process (GeglOperation       *operation,
+                                  void                *in_buf,
+                                  void                *aux_buf,
+                                  void                *aux2_buf,
+                                  void                *out_buf,
+                                  glong                samples,
+                                  const GeglRectangle *roi,
+                                  gint                 level)
+{
+  gfloat opacity = GIMP_OPERATION_POINT_LAYER_MODE (operation)->opacity;
+
+  return gimp_operation_softlight_process_pixels (in_buf, aux_buf, aux2_buf, out_buf, opacity, samples, roi, 
level);
+}
+
+gboolean
+gimp_operation_softlight_process_pixels (gfloat              *in,
+                                         gfloat              *layer,
+                                         gfloat              *mask,
+                                         gfloat              *out,
+                                         gfloat               opacity,
+                                         glong                samples,
+                                         const GeglRectangle *roi,
+                                         gint                 level)
+{
+  const gboolean has_mask = mask != NULL;
+
+  while (samples--)
+    {
+      gfloat comp_alpha;
+
+      comp_alpha = layer[ALPHA] * opacity;
+      if (has_mask)
+        comp_alpha *= *mask;
+
+      if (comp_alpha != 0.0f)
+        {
+          gint   b;
+
+          for (b = RED; b < ALPHA; b++)
+            {
+#if 0
+              /* softlight is now used for what GIMP formerly called
+               * OVERLAY.  We fixed OVERLAY to use the right math
+               * (under the name NEW_OVERLAY), and redirect uses of
+               * the old OVERLAY blend mode here. This math was
+               * formerly used for OVERLAY and is exactly the same as
+               * the multiply, screen, comp math used below.
+               * See bug #673501.
+               */
+              gfloat comp = in[b] * (in[b] + (2.0 * layer[b]) * (1.0 - in[b]));
+#endif
+
+              gfloat multiply = in[b] * layer[b];
+              gfloat screen   = 1.0 - (1.0 - in[b]) * (1.0 - layer[b]);
+              gfloat comp     = (1.0 - in[b]) * multiply + in[b] * screen;
+
+              out[b] = comp * comp_alpha + in[b] * (1.0 - comp_alpha);
+            }
+        }
+      else
+        {
+          gint b;
+
+          for (b = RED; b < ALPHA; b++)
+            {
+              out[b] = in[b];
+            }
+        }
+
+      out[ALPHA] = in[ALPHA];
+
+      in    += 4;
+      layer += 4;
+      out   += 4;
+
+      if (has_mask)
+        mask ++;
+    }
+
+  return TRUE;
+}
diff --git a/app/widgets/gimpwidgets-constructors.c b/app/widgets/gimpwidgets-constructors.c
index 9b65231..ecf60f8 100644
--- a/app/widgets/gimpwidgets-constructors.c
+++ b/app/widgets/gimpwidgets-constructors.c
@@ -104,7 +104,7 @@ gimp_paint_mode_menu_new (gboolean with_behind_mode,
   GtkWidget    *combo;
 
   store = gimp_enum_store_new_with_values (GIMP_TYPE_LAYER_MODE,
-                                           43,
+                                           45,
                                            GIMP_LAYER_MODE_NORMAL,
                                            GIMP_LAYER_MODE_NORMAL_NON_LINEAR,
                                            GIMP_LAYER_MODE_DISSOLVE,
@@ -132,7 +132,9 @@ gimp_paint_mode_menu_new (gboolean with_behind_mode,
                                            GIMP_LAYER_MODE_DIFFERENCE_LEGACY,
                                            GIMP_LAYER_MODE_SUBTRACT,
                                            GIMP_LAYER_MODE_SUBTRACT_LEGACY,
+                                           GIMP_LAYER_MODE_GRAIN_EXTRACT,
                                            GIMP_LAYER_MODE_GRAIN_EXTRACT_LEGACY,
+                                           GIMP_LAYER_MODE_GRAIN_MERGE,
                                            GIMP_LAYER_MODE_GRAIN_MERGE_LEGACY,
                                            GIMP_LAYER_MODE_DIVIDE,
                                            GIMP_LAYER_MODE_DIVIDE_LEGACY,
diff --git a/libgimp/gimpenums.h b/libgimp/gimpenums.h
index 6190261..b956c47 100644
--- a/libgimp/gimpenums.h
+++ b/libgimp/gimpenums.h
@@ -112,7 +112,11 @@ typedef enum
   GIMP_LAYER_MODE_HSV_COLOR,
   GIMP_LAYER_MODE_HSV_VALUE,
   GIMP_LAYER_MODE_DIVIDE,
-  GIMP_LAYER_MODE_BURN
+  GIMP_LAYER_MODE_BURN,
+  GIMP_LAYER_MODE_HARDLIGHT,
+  GIMP_LAYER_MODE_SOFTLIGHT,
+  GIMP_LAYER_MODE_GRAIN_EXTRACT,
+  GIMP_LAYER_MODE_GRAIN_MERGE
 } GimpLayerMode;
 
 
diff --git a/tools/pdbgen/enums.pl b/tools/pdbgen/enums.pl
index 28ed6a0..3711e5b 100644
--- a/tools/pdbgen/enums.pl
+++ b/tools/pdbgen/enums.pl
@@ -732,7 +732,10 @@ package Gimp::CodeGen::enums;
                          GIMP_LAYER_MODE_HSV_SATURATION
                          GIMP_LAYER_MODE_HSV_COLOR
                          GIMP_LAYER_MODE_HSV_VALUE GIMP_LAYER_MODE_DIVIDE
-                         GIMP_LAYER_MODE_BURN) ],
+                         GIMP_LAYER_MODE_BURN GIMP_LAYER_MODE_HARDLIGHT
+                         GIMP_LAYER_MODE_SOFTLIGHT
+                         GIMP_LAYER_MODE_GRAIN_EXTRACT
+                         GIMP_LAYER_MODE_GRAIN_MERGE) ],
          mapping => { GIMP_LAYER_MODE_NORMAL_NON_LINEAR => '0',
                       GIMP_LAYER_MODE_DISSOLVE => '1',
                       GIMP_LAYER_MODE_BEHIND => '2',
@@ -776,7 +779,11 @@ package Gimp::CodeGen::enums;
                       GIMP_LAYER_MODE_HSV_COLOR => '40',
                       GIMP_LAYER_MODE_HSV_VALUE => '41',
                       GIMP_LAYER_MODE_DIVIDE => '42',
-                      GIMP_LAYER_MODE_BURN => '43' }
+                      GIMP_LAYER_MODE_BURN => '43',
+                      GIMP_LAYER_MODE_HARDLIGHT => '44',
+                      GIMP_LAYER_MODE_SOFTLIGHT => '45',
+                      GIMP_LAYER_MODE_GRAIN_EXTRACT => '46',
+                      GIMP_LAYER_MODE_GRAIN_MERGE => '47' }
        },
     GimpBrushApplicationMode =>
        { contig => 1,


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