Index: app/paint-funcs/paint-funcs.c
===================================================================
--- app/paint-funcs/paint-funcs.c	(revision 26351)
+++ app/paint-funcs/paint-funcs.c	(working copy)
@@ -1387,6 +1387,33 @@
 }
 
 
+#define alphify(src2_alpha,new_alpha) \
+        if (src2_alpha != 0 && new_alpha != 0) \
+          { \
+            b = bytes1 - has_alpha1; \
+            if (src2_alpha == new_alpha) \
+              { \
+                do \
+                  { \
+                    b--; \
+                    dest [b] = affect [b] ? src2 [b] : src1 [b]; \
+                  } \
+                while (b); \
+              } \
+            else \
+              { \
+                ratio = (float) src2_alpha / new_alpha; \
+                compl_ratio = 1.0 - ratio; \
+                do \
+                  { \
+                    b--; \
+                    dest[b] = affect[b] ? \
+                      (guchar) (src2[b] * ratio + src1[b] * compl_ratio + EPSILON) : src1[b]; \
+                  } \
+                while (b); \
+              } \
+          }
+
 /*  replace the contents of one pixel row with the other
  *  The operation is still bounded by mask/opacity constraints
  */
@@ -1404,7 +1431,10 @@
 {
   const guint has_alpha1 = HAS_ALPHA (bytes1);
   const guint has_alpha2 = HAS_ALPHA (bytes2);
-  const guint bytes      = MIN (bytes1, bytes2);
+  const guint alpha1 = bytes1 - 1;
+  const guint alpha2 = bytes2 - 1;
+  gfloat     ratio;
+  gfloat     compl_ratio;
   guint b;
   gint  tmp;
 
@@ -1415,14 +1445,15 @@
       while (length --)
         {
           guchar mask_alpha = INT_MULT (*m, opacity, tmp);
+          guchar src1_alpha = has_alpha1 ? src1[alpha1] : 255;
+          guchar src2_alpha = has_alpha2 ? src2[alpha2] : 255;
+          guchar new_alpha  = INT_BLEND (src2_alpha, src1_alpha, mask_alpha, tmp);
+          guchar alpha2 = INT_MULT (src2_alpha, mask_alpha, tmp);
 
-          for (b = 0; b < bytes; b++)
-            dest[b] = (affect[b] ?
-                       INT_BLEND (src2[b], src1[b], mask_alpha, tmp) :
-                       src1[b]);
+          alphify (alpha2, new_alpha);
 
-          if (has_alpha1 && !has_alpha2)
-            dest[b] = src1[b];
+          if (has_alpha1)
+            dest[alpha1] = affect[alpha1] ? new_alpha : src1[alpha1];
 
           m++;
 
@@ -1433,24 +1464,25 @@
     }
   else
     {
-      const guchar mask_alpha = opacity;
-
       while (length --)
         {
-          for (b = 0; b < bytes; b++)
-            dest[b] = (affect[b] ?
-                       INT_BLEND (src2[b], src1[b], mask_alpha, tmp) :
-                       src1[b]);
+          guchar src1_alpha = has_alpha1 ? src1[alpha1] : 255;
+          guchar src2_alpha = has_alpha2 ? src2[alpha2] : 255;
+          guchar new_alpha  = INT_BLEND (src2_alpha, src1_alpha, opacity, tmp);
+          guchar alpha2 = INT_MULT (src2_alpha, opacity, tmp);
 
-          if (has_alpha1 && !has_alpha2)
-            dest[b] = src1[b];
+          alphify (alpha2, new_alpha);
 
+          if (has_alpha1)
+            dest[alpha1] = affect[alpha1] ? new_alpha : src1[alpha1];
+
           src1 += bytes1;
           src2 += bytes2;
           dest += bytes1;
         }
     }
 }
+#undef alphify
 
 /*  replace the contents of one pixel row with the other
  *  The operation is still bounded by mask/opacity constraints
