Index: app/paint-funcs/paint-funcs.c
===================================================================
RCS file: /cvs/gnome/gimp/app/paint-funcs/paint-funcs.c,v
retrieving revision 1.137
diff -c -r1.137 paint-funcs.c
*** app/paint-funcs/paint-funcs.c	18 Jul 2003 10:29:56 -0000	1.137
--- app/paint-funcs/paint-funcs.c	26 Jul 2003 05:40:28 -0000
***************
*** 91,97 ****
    { TRUE,  FALSE, TRUE,  },  /*  GIMP_COLOR_ERASE_MODE   */
    { TRUE,  FALSE, TRUE,  },  /*  GIMP_ERASE_MODE         */
    { TRUE,  TRUE,  TRUE,  },  /*  GIMP_REPLACE_MODE       */
!   { TRUE,  TRUE,  FALSE, }   /*  GIMP_ANTI_ERASE_MODE    */
  };
  
  typedef void (* LayerModeFunc) (struct apply_layer_mode_struct *);
--- 91,98 ----
    { TRUE,  FALSE, TRUE,  },  /*  GIMP_COLOR_ERASE_MODE   */
    { TRUE,  FALSE, TRUE,  },  /*  GIMP_ERASE_MODE         */
    { TRUE,  TRUE,  TRUE,  },  /*  GIMP_REPLACE_MODE       */
!   { TRUE,  TRUE,  FALSE, },  /*  GIMP_ANTI_ERASE_MODE    */
!   { TRUE,  TRUE,  TRUE,  }   /*  GIMP_CUSTOM_MODE        */
  };
  
  typedef void (* LayerModeFunc) (struct apply_layer_mode_struct *);
***************
*** 122,128 ****
    layer_color_erase_mode,
    layer_erase_mode,
    layer_replace_mode,
!   layer_anti_erase_mode
  };
  
  
--- 123,130 ----
    layer_color_erase_mode,
    layer_erase_mode,
    layer_replace_mode,
!   layer_anti_erase_mode,
!   layer_custom_mode
  };
  
  
Index: app/paint-funcs/paint-funcs-generic.h
===================================================================
RCS file: /cvs/gnome/gimp/app/paint-funcs/paint-funcs-generic.h,v
retrieving revision 1.14
diff -c -r1.14 paint-funcs-generic.h
*** app/paint-funcs/paint-funcs-generic.h	13 Jun 2003 11:12:04 -0000	1.14
--- app/paint-funcs/paint-funcs-generic.h	26 Jul 2003 05:40:33 -0000
***************
*** 48,58 ****
   * masking is always cheaper than passing parameters over the stack.      */
  /* FIXME: Move to a global place */
  #define HAS_ALPHA(bytes) (~bytes & 1)
!   
  /* FIXME: Move to a more global place */
  struct apply_layer_mode_struct
  {
!   guchar             bytes1 : 3; 
    guchar             bytes2 : 3;
    guchar            *src1;
    guchar            *src2;
--- 48,58 ----
   * masking is always cheaper than passing parameters over the stack.      */
  /* FIXME: Move to a global place */
  #define HAS_ALPHA(bytes) (~bytes & 1)
! 
  /* FIXME: Move to a more global place */
  struct apply_layer_mode_struct
  {
!   guchar             bytes1 : 3;
    guchar             bytes2 : 3;
    guchar            *src1;
    guchar            *src2;
***************
*** 64,69 ****
--- 64,112 ----
    guint              length;
    CombinationMode    combine;
  };
+ /* FIXME: keep this one together with ALMS above */
+ struct 


+ {
+  guint               number_of_operators;
+  guint               number_of_operands;
+  guint               *operators;
+  guint               *operands;
+ };
+ #define CUSTOM_LAYER_OPERATORS_ENUM enum  { \
+    ADD,               \
+    SUBTRACT,          \
+    MULTIPLY,          \
+    DIVIDE,            \
+    XOR,               \
+    AND,               \
+    OR,                \
+    NEGATE,            \
+    NEGATIVE,          \
+    EQUALS,            \
+    LT,                \
+    GT,                \
+    LE,                \
+    GE,                \
+    SATURATE,          \
+    IF,                \
+    GOTO,              \
+    EXCH,              \
+    OTHER_LAYER_MODE,  \
+    COMMIT             \
+  }
+ /* >> 8 IF and GOTO operator values to know how many operators to skip
+         before the ELSE part of the expression */
+ #define CUSTOM_LAYER_OPERANDS_ENUM enum   {  \
+     NUMBER,                        \
+     R1, G1,  B1,  K1,  A1,  E1,    \
+     R2, G2,  B2,  K2,  A2,  E2,    \
+     RD, GD,  BD,  KD,  AD,  ED,    \
+     H1, S1,  V1,                   \
+     H2, V2,  S2,                   \
+     HD, SD,  VD                    \
+    }
+ /* NUMBER encoded in the upper 24 bits */
+ 
  
  static const guchar	no_mask = OPAQUE_OPACITY;
  static guchar		add_lut[511];
***************
*** 782,788 ****
  {
    const guint has_alpha1 = HAS_ALPHA (bytes1);
    const guint has_alpha2 = HAS_ALPHA (bytes2);
!   const guint alpha = (has_alpha1 || has_alpha2) ? MAX (bytes1, bytes2) - 1 : bytes1; 
    guint b, tmpS, tmpM, tmp1, tmp2, tmp3;
  
    while (length --)
--- 825,831 ----
  {
    const guint has_alpha1 = HAS_ALPHA (bytes1);
    const guint has_alpha2 = HAS_ALPHA (bytes2);
!   const guint alpha = (has_alpha1 || has_alpha2) ? MAX (bytes1, bytes2) - 1 : bytes1;
    guint b, tmpS, tmpM, tmp1, tmp2, tmp3;
  
    while (length --)
***************
*** 953,959 ****
  {
    const guint has_alpha1 = HAS_ALPHA (bytes1);
    const guint has_alpha2 = HAS_ALPHA (bytes2);
!   const guint alpha = (has_alpha1 || has_alpha2) ? MAX (bytes1, bytes2) - 1 : bytes1; 
    guint b;
    gint diff;
  
--- 996,1002 ----
  {
    const guint has_alpha1 = HAS_ALPHA (bytes1);
    const guint has_alpha2 = HAS_ALPHA (bytes2);
!   const guint alpha = (has_alpha1 || has_alpha2) ? MAX (bytes1, bytes2) - 1 : bytes1;
    guint b;
    gint diff;
  
***************
*** 1009,1029 ****
  	dest[b] = src[b];
  
        /*  dissolve if random value is > opacity  */
!       rand_val = g_rand_int_range (gr, 0, 256);       
  
        if (mask)
          {
            if (has_alpha)
!             combined_opacity = opacity * src[alpha] * *mask / (255 * 255);
            else
!             combined_opacity = opacity * *mask / 255;       
  
            mask++;
          }
        else
          {
            if (has_alpha)
!             combined_opacity = opacity * src[alpha] / 255;       
            else
              combined_opacity = opacity;
          }
--- 1052,1073 ----
  	dest[b] = src[b];
  
        /*  dissolve if random value is > opacity  */
!       rand_val = g_rand_int_range (gr, 0, 256);
  
        if (mask)
          {
            if (has_alpha)
!             combined_opacity = opacity * src[alpha] * *mask / (65025);
!             /* 65025 == 255 * 255 */
            else
!             combined_opacity = opacity * *mask / 255;
  
            mask++;
          }
        else
          {
            if (has_alpha)
!             combined_opacity = opacity * src[alpha] / 255;
            else
              combined_opacity = opacity;
          }
***************
*** 1038,1043 ****
--- 1082,1418 ----
  
  }
  
+ 
+ /*Custom Layer Mode
+ by Joao S. O. Bueno
+ 
+ */
+ static inline void
+ custom_pixels (struct apply_layer_mode_struct *alms,
+                struct custom_layer_operation_struct *clos
+               )
+ {
+ 
+   guint has_alpha1, has_alpha2;
+   const guchar  *src1, *src2;
+   guchar *dest;
+   guint bytes1, bytes2, length;
+   gint b,  alpha1, alpha2, alphaflag;
+   gint h1,s1,v1, h2, s2, v2, hd, sd, vd, hsvflag1, hsvflag2, hsvflagd;
+   gint tmp;
+   gint  *operators, *operands, numeric_operands[100];
+   guint operator_top, operand_top, operator_size, operand_size;
+   CUSTOM_LAYER_OPERATORS_ENUM;
+   CUSTOM_LAYER_OPERANDS_ENUM;
+ 
+   src1=alms->src1;
+   src2= alms->src2;
+   dest= *(alms->dest);
+   length= alms->length;
+   bytes1=alms->bytes1;
+   bytes2= alms->bytes2;
+ 
+ 
+ 
+   operators= clos->operators;
+   operands=clos->operands;
+   operator_size=clos->number_of_operators;
+   operand_size=clos->number_of_operands;
+ 
+   has_alpha1 = HAS_ALPHA (bytes1);
+   has_alpha2 = HAS_ALPHA (bytes2);
+ 
+ 
+   /*translate the operands into numeric values */
+   alpha1=bytes1 - 1;
+   alpha2=bytes2 - 1;
+ 
+   while (length--)
+     {
+       operator_top=operator_size;
+       operand_top=operand_size;
+       hsvflag1=hsvflag2=hsvflagd=alphaflag=0;
+ 
+       /*translate the operands into numeric values */
+       for (b=0;b<operand_top;b++)
+         {
+           switch (operands[b]& 0xff)
+             {
+               case NUMBER:
+                 numeric_operands[b]=operands[b]>>8;
+               case R1:
+                 numeric_operands[b]=src1[0];
+                 break;
+               case G1:
+                 numeric_operands[b]=src1[1];
+                 break;
+               case B1:
+                 numeric_operands[b]=src1[2];
+                 break;
+               case K1:
+                 numeric_operands[b]=src1[3];
+               case A1:
+                 numeric_operands[b]=src1[alpha1];
+                 break;
+               case E1:
+                 numeric_operands[b]=0; /*not supported */
+               case R2:
+                 numeric_operands[b]=src2[0];
+                 break;
+               case G2:
+                 numeric_operands[b]=src2[1];
+                 break;
+               case B2:
+                 numeric_operands[b]=src2[2];
+                 break;
+               case K2:
+                 numeric_operands[b]=src2[3];
+               case A2:
+                 numeric_operands[b]=src2[alpha2];
+                 break;
+               case E2:
+                 numeric_operands[b]=0; /*not supported */
+                 break;
+               case H1:
+                 if (hsvflag1)
+                   numeric_operands[b]=h1;
+                 else
+                   {
+                     h1=src1[0]; s1=src1[1]; v1=src1[2];
+                     gimp_rgb_to_hsv_int (&h1, &s1, &v1);
+                     numeric_operands[b]=h1;
+                     hsvflag1=1;
+                   }
+                 break;
+               case S1:
+                 if (hsvflag1)
+                   numeric_operands[b]=s1;
+                 else
+                   {
+                     h1=src1[0]; s1=src1[1]; v1=src1[2];
+                     gimp_rgb_to_hsv_int (&h1, &s1, &v1);
+                     numeric_operands[b]=s1;
+                     hsvflag1=1;
+                   }
+                 break;
+               case V1:
+                 if (hsvflag1)
+                   numeric_operands[b]=v1;
+                 else
+                   {
+                     h1=src1[0]; s1=src1[1]; v1=src1[2];
+                     gimp_rgb_to_hsv_int (&h1, &s1, &v1);
+                     numeric_operands[b]=v1;
+                     hsvflag1=1;
+                   }
+                 break;
+               case H2:
+                 if (hsvflag2)
+                   numeric_operands[b]=h2;
+                 else
+                   {
+                     h2=src2[0]; s2=src2[1]; v2=src2[2];
+                     gimp_rgb_to_hsv_int (&h2, &s2, &v2);
+                     numeric_operands[b]=h2;
+                     hsvflag2=1;
+                   }
+                 break;
+               case S2:
+                 if (hsvflag2)
+                   numeric_operands[b]=s2;
+                 else
+                   {
+                     h2=src2[0]; s2=src2[1]; v2=src2[2];
+                     gimp_rgb_to_hsv_int (&h2, &s2, &v2);
+                     numeric_operands[b]=s2;
+                     hsvflag2=1;
+                   }
+                 break;
+               case V2:
+                 if (hsvflag1)
+                   numeric_operands[b]=v2;
+                 else
+                   {
+                     h2=src1[0]; s2=src1[1]; v2=src1[2];
+                     gimp_rgb_to_hsv_int (&h2, &s2, &v2);
+                     numeric_operands[b]=v2;
+                     hsvflag2=1;
+                   }
+                 break;
+               default:
+                 numeric_operands[b]=0xffffffff;
+                 /*when this is found, reach for operand on operands stack.
+                 if its not a destination operand, use this value.
+                 */
+                 break;
+             }
+         }
+       operand_top--;
+       while (operator_top)
+         { operator_top--;
+           switch (operators[operator_top] & 0xff)
+             {
+               case ADD:
+                 numeric_operands [operand_top-1]+=numeric_operands[operand_top];
+                 operand_top--;
+                 break;
+               case SUBTRACT:
+                 numeric_operands [operand_top-1]-=numeric_operands[operand_top];
+                 operand_top--;
+                 break;
+               case MULTIPLY:
+                 numeric_operands [operand_top-1]*=numeric_operands[operand_top];
+                 operand_top--;
+                 break;
+               case DIVIDE:
+                 if (numeric_operands[operand_top])
+                   numeric_operands [operand_top-1]/=numeric_operands[operand_top];
+                 else /*saturate on division by zero */
+                   numeric_operands [operand_top-1]=  (numeric_operands[operand_top-1] & 0x80000000)?-255:255;
+                 operand_top--;
+                 break;
+               case AND:
+                 numeric_operands [operand_top-1]&=numeric_operands[operand_top];
+                 operand_top--;
+                 break;
+               case OR:
+                 numeric_operands [operand_top-1]|=numeric_operands[operand_top];
+                 operand_top--;
+                 break;
+               case XOR:
+                 numeric_operands [operand_top-1]^=numeric_operands[operand_top];
+                 operand_top--;
+                 break;
+               case NEGATE:
+                 numeric_operands [operand_top]=~numeric_operands[operand_top];
+                 break;
+               case NEGATIVE:
+                 numeric_operands [operand_top]=-numeric_operands[operand_top];
+                 break;
+               case EQUALS:
+                 numeric_operands[operand_top-1]= numeric_operands[operand_top]==numeric_operands[operand_top-1];
+                 operand_top--;
+                 break;
+               case GT:
+                 numeric_operands[operand_top-1]= numeric_operands[operand_top-1]>numeric_operands[operand_top];
+                 operand_top--;
+                 break;
+               case LT:
+                 numeric_operands[operand_top-1]= numeric_operands[operand_top-1]<numeric_operands[operand_top];
+                 operand_top--;
+                 break;
+               case GE:
+                 numeric_operands[operand_top-1]= numeric_operands[operand_top-1]>=numeric_operands[operand_top];
+                 operand_top--;
+                 break;
+               case LE:
+                 numeric_operands[operand_top-1]= numeric_operands[operand_top-1]<=numeric_operands[operand_top];
+                 operand_top--;
+                 break;
+               case SATURATE:
+                 numeric_operands[operand_top]=CLAMP0255( numeric_operands[operand_top]);
+                 break;
+               case IF:
+                 if (numeric_operands[operand_top])
+                   /*if condition true, just pop the top two elements */
+                   operand_top-=2;
+                 else
+                   {
+                     /*discards a number from operands from the stack,  which would be used
+                     within the IF block. The number of operands to discard is given as
+                     an argument to IF */
+                     operand_top-=numeric_operands[operand_top-1]-2;
+                     /* dito for operators. Number of operators to discard comes in
+                     upper 24 bits of the operator itself */
+                     operator_top-=operators[operator_top]>>8;
+                   }
+                 break;
+               case GOTO:
+                 /*inserted by the expression compiler at the end of an IF block to skip the
+                 ELSE code */
+                 operand_top-=numeric_operands[operand_top-1]-1;
+                 operator_top-=operators[operator_top]>>8;
+                 break;
+               case OTHER_LAYER_MODE:
+                 /*I will work on this one later.
+                 I think the better thing to do is to
+                 make another ALMS structure, make a call akim to the grandparent of
+                 this in paint-funcs.c, and cache the results to use the other color
+                 components later */
+ 
+                 break;
+               case EXCH:
+                 tmp=operands[operand_top];
+                 numeric_operands[operand_top]=numeric_operands[operand_top-1];
+                 numeric_operands[operand_top-1]=tmp;
+               case COMMIT:
+                 switch (operands[operand_top-1])
+                   {
+                     case RD:
+                       dest[0]=(guchar)numeric_operands[operand_top];
+                       operand_top-=2;
+                       break;
+                     case GD:
+                       dest[1]=(guchar)numeric_operands[operand_top];
+                       operand_top-=2;
+                       break;
+                     case BD:
+                       dest[2]=(guchar)numeric_operands[operand_top];
+                       operand_top-=2;
+                       break;
+                     case KD:
+                       dest[3]=(guchar)numeric_operands[operand_top];
+                       operand_top-=2;
+                       break;
+                     case AD:
+                       dest[alpha2]=(guchar)numeric_operands[operand_top];
+                       operand_top-=2;
+                       alphaflag=1;
+                       break;
+                     case HD:
+                       hd=(guchar)numeric_operands[operand_top];
+                       hsvflagd=1;
+                       operand_top=-2;
+                       break;
+                     case SD:
+                       sd=(guchar)numeric_operands[operand_top];
+                       hsvflagd=1;
+                       operand_top=-2;
+                       break;
+                     case VD:
+                       vd=(guchar)numeric_operands[operand_top];
+                       hsvflagd=1;
+                       operand_top=-2;
+                       break;
+                     /* for debugging.
+                     default:
+                       dest[0]=0;
+                       dest[1]=src1[1];*/
+                   }
+             }
+         } /*while */
+       if (hsvflagd)
+         {
+           gimp_hsv_to_rgb_int (&hd, &sd, &vd);
+           dest[0]=hd; dest[1]=sd; dest[2]=vd;
+ 
+         }
+       if (! alphaflag)
+         {
+           if (has_alpha1 && has_alpha2)
+             dest[3] = MIN (src1[3], src2[3]);
+           else if (has_alpha2)
+             dest[3] = src2[3];
+         }
+ 
+ 
+     src1 += bytes1;
+     src2 += bytes2;
+     dest += bytes2;
+   } /*while length */
+ 
+ }
+ 
  static inline void
  replace_pixels (guchar   *src1,
  		guchar   *src2,
***************
*** 1849,1853 ****
--- 2224,2248 ----
    grain_merge_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
                        alms->bytes1, alms->bytes2);
  }
+ 
+ static void
+ layer_custom_mode (struct apply_layer_mode_struct *alms)
+ {CUSTOM_LAYER_OPERATORS_ENUM;
+  CUSTOM_LAYER_OPERANDS_ENUM;
+  struct custom_layer_operation_struct clos;
+  guint operators[]={COMMIT, COMMIT, COMMIT, DIVIDE, EXCH, ADD };
+  guint operands[]={GD, G1, RD, R2, BD, 2, B1, B2};
+ 
+  clos.number_of_operators=3;
+  clos.number_of_operands=6;
+  clos.operators=operators;
+  clos.operands=operands;
+   /*custm_pixels needs alms, as it may need to call other layer_modes */
+   custom_pixels (alms, &clos);
+ 
+ 
+ }
+ 
+ 
  
  #endif  /*  __PAINT_FUNCS_GENERIC_H__  */
Index: app/base/base-enums.h
===================================================================
RCS file: /cvs/gnome/gimp/app/base/base-enums.h,v
retrieving revision 1.12
diff -c -r1.12 base-enums.h
*** app/base/base-enums.h	1 Jul 2003 10:53:36 -0000	1.12
--- app/base/base-enums.h	26 Jul 2003 05:40:33 -0000
***************
*** 21,27 ****
  
  #if 0
     This file is parsed by two scripts, enumgen.pl in tools/pdbgen,
!    and gimp-mkenums. All enums that are not marked with 
     /*< pdb-skip >*/ are exported to libgimp and the PDB. Enums that are
     not marked with /*< skip >*/ are registered with the GType system. 
     If you want the enum to be skipped by both scripts, you have to use 
--- 21,27 ----
  
  #if 0
     This file is parsed by two scripts, enumgen.pl in tools/pdbgen,
!    and gimp-mkenums. All enums that are not marked with
     /*< pdb-skip >*/ are exported to libgimp and the PDB. Enums that are
     not marked with /*< skip >*/ are registered with the GType system. 
     If you want the enum to be skipped by both scripts, you have to use 
***************
*** 131,139 ****
    GIMP_COLOR_ERASE_MODE,
    GIMP_ERASE_MODE,           /*< skip >*/
    GIMP_REPLACE_MODE,         /*< skip >*/
!   GIMP_ANTI_ERASE_MODE       /*< skip >*/
  } GimpLayerModeEffects;
! 
  
  #define GIMP_TYPE_TRANSFER_MODE (gimp_transfer_mode_get_type ())
  
--- 131,141 ----
    GIMP_COLOR_ERASE_MODE,
    GIMP_ERASE_MODE,           /*< skip >*/
    GIMP_REPLACE_MODE,         /*< skip >*/
!   GIMP_ANTI_ERASE_MODE,       /*< skip >*/
!   GIMP_CUSTOM_LAYER_MODE
  } GimpLayerModeEffects;
! /* GIMP_CUSTOM_MODE is defined somewere else
!  Therefore I had to use GIMp_CUSTOM_LAYER_MODE */
  
  #define GIMP_TYPE_TRANSFER_MODE (gimp_transfer_mode_get_type ())
  
Index: app/widgets/gimpwidgets-constructors.c
===================================================================
RCS file: /cvs/gnome/gimp/app/widgets/gimpwidgets-constructors.c,v
retrieving revision 1.5
diff -c -r1.5 gimpwidgets-constructors.c
*** app/widgets/gimpwidgets-constructors.c	25 Mar 2003 16:37:18 -0000	1.5
--- app/widgets/gimpwidgets-constructors.c	26 Jul 2003 05:40:33 -0000
***************
*** 69,74 ****
--- 69,76 ----
           _("Saturation"),    (gpointer) GIMP_SATURATION_MODE,    NULL,
           _("Color"),         (gpointer) GIMP_COLOR_MODE,         NULL,
           _("Value"),         (gpointer) GIMP_VALUE_MODE,         NULL,
+ 	 "---",              (gpointer) NULL,                    NULL,
+          _("Custom"),        (gpointer) GIMP_CUSTOM_LAYER_MODE,  NULL,
  
           NULL);
      }
***************
*** 102,108 ****
           _("Saturation"),    (gpointer) GIMP_SATURATION_MODE,    NULL,
           _("Color"),         (gpointer) GIMP_COLOR_MODE,         NULL,
           _("Value"),         (gpointer) GIMP_VALUE_MODE,         NULL,
! 
           NULL);
      }
  
--- 104,111 ----
           _("Saturation"),    (gpointer) GIMP_SATURATION_MODE,    NULL,
           _("Color"),         (gpointer) GIMP_COLOR_MODE,         NULL,
           _("Value"),         (gpointer) GIMP_VALUE_MODE,         NULL,
! 	 "---",              (gpointer) NULL,                    NULL,
!          _("Custom"),        (gpointer) GIMP_CUSTOM_LAYER_MODE,  NULL,
           NULL);
      }
  
Index: tools/pdbgen/enums.pl
===================================================================
RCS file: /cvs/gnome/gimp/tools/pdbgen/enums.pl,v
retrieving revision 1.93
diff -c -r1.93 enums.pl
*** tools/pdbgen/enums.pl	3 Jul 2003 00:47:05 -0000	1.93
--- tools/pdbgen/enums.pl	26 Jul 2003 05:40:35 -0000
***************
*** 120,126 ****
  			  GIMP_VALUE_MODE GIMP_DIVIDE_MODE GIMP_DODGE_MODE
  			  GIMP_BURN_MODE GIMP_HARDLIGHT_MODE
  			  GIMP_SOFTLIGHT_MODE GIMP_GRAIN_EXTRACT_MODE
! 			  GIMP_GRAIN_MERGE_MODE GIMP_COLOR_ERASE_MODE) ],
  	  mapping => { GIMP_NORMAL_MODE => '0',
  		       GIMP_DISSOLVE_MODE => '1',
  		       GIMP_BEHIND_MODE => '2',
--- 120,127 ----
  			  GIMP_VALUE_MODE GIMP_DIVIDE_MODE GIMP_DODGE_MODE
  			  GIMP_BURN_MODE GIMP_HARDLIGHT_MODE
  			  GIMP_SOFTLIGHT_MODE GIMP_GRAIN_EXTRACT_MODE
! 			  GIMP_GRAIN_MERGE_MODE GIMP_COLOR_ERASE_MODE
! 			  GIMP_CUSTOM_LAYER_MODE) ],
  	  mapping => { GIMP_NORMAL_MODE => '0',
  		       GIMP_DISSOLVE_MODE => '1',
  		       GIMP_BEHIND_MODE => '2',
***************
*** 143,149 ****
  		       GIMP_SOFTLIGHT_MODE => '19',
  		       GIMP_GRAIN_EXTRACT_MODE => '20',
  		       GIMP_GRAIN_MERGE_MODE => '21',
! 		       GIMP_COLOR_ERASE_MODE => '22' }
  	},
      GimpTransferMode =>
  	{ contig => 1,
--- 144,151 ----
  		       GIMP_SOFTLIGHT_MODE => '19',
  		       GIMP_GRAIN_EXTRACT_MODE => '20',
  		       GIMP_GRAIN_MERGE_MODE => '21',
! 		       GIMP_COLOR_ERASE_MODE => '22',
! 		       GIMP_CUSTOM_LAYER_MODE => '23' }
  	},
      GimpTransferMode =>
  	{ contig => 1,
