gimp r27268 - in trunk: . app/paint-funcs



Author: neo
Date: Mon Oct 13 18:51:32 2008
New Revision: 27268
URL: http://svn.gnome.org/viewvc/gimp?rev=27268&view=rev

Log:
2008-10-13  Sven Neumann  <sven gimp org>

	Bug 547967 â Improve app/paint-funcs/ maintainability

	Applied patch from Luidnel Maignan that splits the legacy code 
for
	layer modes into new files.
	
	* app/paint-funcs/Makefile.am
	* app/paint-funcs/layer-modes.[ch]
	* app/paint-funcs/paint-funcs-utils.h: new files with code taken
	from ...

	* app/paint-funcs/paint-funcs-generic.h
	* app/paint-funcs/paint-funcs.c: ... these two files.



Added:
   trunk/app/paint-funcs/layer-modes.c
   trunk/app/paint-funcs/layer-modes.h
   trunk/app/paint-funcs/paint-funcs-utils.h
Modified:
   trunk/ChangeLog
   trunk/app/paint-funcs/Makefile.am
   trunk/app/paint-funcs/paint-funcs-generic.h
   trunk/app/paint-funcs/paint-funcs.c

Modified: trunk/app/paint-funcs/Makefile.am
==============================================================================
--- trunk/app/paint-funcs/Makefile.am	(original)
+++ trunk/app/paint-funcs/Makefile.am	Mon Oct 13 18:51:32 2008
@@ -19,10 +19,13 @@
 noinst_LIBRARIES = libapppaint-funcs.a
 
 libapppaint_funcs_a_SOURCES = \
-	paint-funcs-types.h	\
+	layer-modes.c		\
+	layer-modes.h		\
 	paint-funcs.c		\
 	paint-funcs.h		\
 	paint-funcs-generic.h	\
+	paint-funcs-types.h	\
+	paint-funcs-utils.h	\
 	reduce-region.c		\
 	reduce-region.h		\
 	scale-region.c		\

Added: trunk/app/paint-funcs/layer-modes.c
==============================================================================
--- (empty file)
+++ trunk/app/paint-funcs/layer-modes.c	Mon Oct 13 18:51:32 2008
@@ -0,0 +1,1112 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib-object.h>
+
+#include "libgimpcolor/gimpcolor.h"
+
+#include "paint-funcs-types.h"
+
+#include "layer-modes.h"
+#include "paint-funcs-utils.h"
+
+
+#define RANDOM_SEED   314159265
+#define RANDOM_TABLE_SIZE  4096
+
+static guchar  add_lut[511];
+static gint32  random_table[RANDOM_TABLE_SIZE];
+
+
+/** FIXME: should be static inline **/
+void
+dissolve_pixels (const guchar *src,
+                 const guchar *mask,
+                 guchar       *dest,
+                 gint          x,
+                 gint          y,
+                 gint          opacity,
+                 gint          length,
+                 gint          sb,
+                 gint          db,
+                 gboolean      has_alpha)
+{
+  const gint  alpha = db - 1;
+  gint        b;
+  GRand      *gr;
+
+  gr = g_rand_new_with_seed (random_table[y % RANDOM_TABLE_SIZE]);
+
+  /* Ignore x random values so we get a deterministic result */
+  for (b = 0; b < x; b ++)
+    g_rand_int (gr);
+
+  while (length--)
+    {
+      gint    combined_opacity;
+      gint32  rand_val;
+
+      /*  preserve the intensity values  */
+      for (b = 0; b < alpha; b++)
+        dest[b] = src[b];
+
+      /*  dissolve if random value is >= opacity  */
+      rand_val = g_rand_int_range (gr, 0, 255);
+
+      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;
+        }
+
+      dest[alpha] = (rand_val >= combined_opacity) ? 0 : OPAQUE_OPACITY;
+
+      src  += sb;
+      dest += db;
+    }
+
+  g_rand_free (gr);
+
+}
+
+static inline void
+multiply_pixels (const guchar *src1,
+                 const guchar *src2,
+                 guchar       *dest,
+                 guint         length,
+                 guint         bytes1,
+                 guint         bytes2)
+{
+  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);
+
+  if (has_alpha1 && has_alpha2)
+    {
+      while (length --)
+        {
+          guint b;
+
+          for (b = 0; b < alpha; b++)
+            {
+              guint tmp;
+
+              dest[b] = INT_MULT(src1[b], src2[b], tmp);
+            }
+
+          dest[alpha] = MIN (src1[alpha], src2[alpha]);
+
+          src1 += bytes1;
+          src2 += bytes2;
+          dest += bytes2;
+        }
+    }
+  else if (has_alpha2)
+    {
+      while (length --)
+        {
+          guint b;
+
+          for (b = 0; b < alpha; b++)
+            {
+              guint tmp;
+
+              dest[b] = INT_MULT(src1[b], src2[b], tmp);
+            }
+
+          dest[alpha] = src2[alpha];
+
+          src1 += bytes1;
+          src2 += bytes2;
+          dest += bytes2;
+        }
+    }
+  else
+    {
+      while (length --)
+        {
+          guint b;
+
+          for (b = 0; b < alpha; b++)
+            {
+              guint tmp;
+
+              dest[b] = INT_MULT (src1[b], src2[b], tmp);
+            }
+
+          src1 += bytes1;
+          src2 += bytes2;
+          dest += bytes2;
+        }
+    }
+}
+
+static inline void
+divide_pixels (const guchar *src1,
+               const guchar *src2,
+               guchar       *dest,
+               guint         length,
+               guint         bytes1,
+               guint         bytes2)
+{
+  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);
+  while (length--)
+    {
+      guint b;
+
+      for (b = 0; b < alpha; b++)
+        {
+          guint result = ((src1[b] * 256) / (1 + src2[b]));
+
+          dest[b] = MIN (result, 255);
+        }
+
+      if (has_alpha1 && has_alpha2)
+        dest[alpha] = MIN (src1[alpha], src2[alpha]);
+      else if (has_alpha2)
+        dest[alpha] = src2[alpha];
+
+      src1 += bytes1;
+      src2 += bytes2;
+      dest += bytes2;
+    }
+}
+
+
+static inline void
+screen_pixels (const guchar *src1,
+               const guchar *src2,
+               guchar       *dest,
+               guint         length,
+               guint         bytes1,
+               guint         bytes2)
+{
+  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);
+
+  while (length --)
+    {
+      guint b;
+
+      for (b = 0; b < alpha; b++)
+        {
+          guint tmp;
+
+          dest[b] = 255 - INT_MULT((255 - src1[b]), (255 - src2[b]), tmp);
+        }
+
+      if (has_alpha1 && has_alpha2)
+        dest[alpha] = MIN (src1[alpha], src2[alpha]);
+      else if (has_alpha2)
+        dest[alpha] = src2[alpha];
+
+      src1 += bytes1;
+      src2 += bytes2;
+      dest += bytes2;
+    }
+}
+
+
+static inline void
+overlay_pixels (const guchar *src1,
+                const guchar *src2,
+                guchar       *dest,
+                guint         length,
+                guint         bytes1,
+                guint         bytes2)
+{
+  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);
+
+  while (length --)
+    {
+      guint b;
+
+      for (b = 0; b < alpha; b++)
+        {
+          guint tmp, tmpM;
+
+          dest[b] = INT_MULT(src1[b], src1[b] + INT_MULT (2 * src2[b],
+                                                          255 - src1[b],
+                                                          tmpM), tmp);
+        }
+
+      if (has_alpha1 && has_alpha2)
+        dest[alpha] = MIN (src1[alpha], src2[alpha]);
+      else if (has_alpha2)
+        dest[alpha] = src2[alpha];
+
+      src1 += bytes1;
+      src2 += bytes2;
+      dest += bytes2;
+    }
+}
+
+static inline void
+difference_pixels (const guchar *src1,
+                   const guchar *src2,
+                   guchar       *dest,
+                   guint         length,
+                   guint         bytes1,
+                   guint         bytes2)
+{
+  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);
+
+  while (length --)
+    {
+      guint b;
+
+      for (b = 0; b < alpha; b++)
+        {
+          gint diff = src1[b] - src2[b];
+
+          dest[b] = (diff < 0) ? -diff : diff;
+        }
+
+      if (has_alpha1 && has_alpha2)
+        dest[alpha] = MIN (src1[alpha], src2[alpha]);
+      else if (has_alpha2)
+        dest[alpha] = src2[alpha];
+
+      src1 += bytes1;
+      src2 += bytes2;
+      dest += bytes2;
+    }
+}
+
+static inline void
+add_pixels (const guchar *src1,
+            const guchar *src2,
+            guchar       *dest,
+            guint         length,
+            guint         bytes1,
+            guint         bytes2)
+{
+  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);
+
+  while (length --)
+    {
+      guint b;
+
+      for (b = 0; b < alpha; b++)
+          dest[b] = add_lut[src1[b] + src2[b]];
+
+      if (has_alpha1 && has_alpha2)
+        dest[alpha] = MIN (src1[alpha], src2[alpha]);
+      else if (has_alpha2)
+        dest[alpha] = src2[alpha];
+
+      src1 += bytes1;
+      src2 += bytes2;
+      dest += bytes2;
+    }
+}
+
+
+static inline void
+subtract_pixels (const guchar *src1,
+                 const guchar *src2,
+                 guchar       *dest,
+                 guint         length,
+                 guint         bytes1,
+                 guint         bytes2)
+{
+  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);
+
+  while (length --)
+    {
+      guint b;
+
+      for (b = 0; b < alpha; b++)
+        {
+          gint diff = src1[b] - src2[b];
+
+          dest[b] = (diff < 0) ? 0 : diff;
+        }
+
+      if (has_alpha1 && has_alpha2)
+        dest[alpha] = MIN (src1[alpha], src2[alpha]);
+      else if (has_alpha2)
+        dest[alpha] = src2[alpha];
+
+      src1 += bytes1;
+      src2 += bytes2;
+      dest += bytes2;
+    }
+}
+
+static inline void
+darken_pixels (const guchar *src1,
+               const guchar *src2,
+               guchar       *dest,
+               guint         length,
+               guint         bytes1,
+               guint         bytes2)
+{
+  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);
+
+  while (length--)
+    {
+      guint b;
+
+      for (b = 0; b < alpha; b++)
+        {
+          guchar s1 = src1[b];
+          guchar s2 = src2[b];
+
+          dest[b] = (s1 < s2) ? s1 : s2;
+        }
+
+      if (has_alpha1 && has_alpha2)
+        dest[alpha] = MIN (src1[alpha], src2[alpha]);
+      else if (has_alpha2)
+        dest[alpha] = src2[alpha];
+
+      src1 += bytes1;
+      src2 += bytes2;
+      dest += bytes2;
+    }
+}
+
+
+static inline void
+lighten_pixels (const guchar *src1,
+                const guchar *src2,
+                guchar       *dest,
+                guint         length,
+                guint         bytes1,
+                guint         bytes2)
+{
+  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);
+
+  while (length--)
+    {
+      guint b;
+
+      for (b = 0; b < alpha; b++)
+        {
+          guchar s1 = src1[b];
+          guchar s2 = src2[b];
+
+          dest[b] = (s1 < s2) ? s2 : s1;
+        }
+
+      if (has_alpha1 && has_alpha2)
+        dest[alpha] = MIN (src1[alpha], src2[alpha]);
+      else if (has_alpha2)
+        dest[alpha] = src2[alpha];
+
+      src1 += bytes1;
+      src2 += bytes2;
+      dest += bytes2;
+    }
+}
+
+
+static inline void
+hue_only_pixels (const guchar *src1,
+                 const guchar *src2,
+                 guchar       *dest,
+                 guint         length,
+                 guint         bytes1,
+                 guint         bytes2)
+{
+  const guint has_alpha1 = HAS_ALPHA (bytes1);
+  const guint has_alpha2 = HAS_ALPHA (bytes2);
+
+  /*  assumes inputs are only 4 byte RGBA pixels  */
+  while (length--)
+    {
+      gint r1, g1, b1;
+      gint r2, g2, b2;
+
+      r1 = src1[0]; g1 = src1[1]; b1 = src1[2];
+      r2 = src2[0]; g2 = src2[1]; b2 = src2[2];
+
+      gimp_rgb_to_hsv_int (&r1, &g1, &b1);
+      gimp_rgb_to_hsv_int (&r2, &g2, &b2);
+
+      r1 = r2;
+
+      /*  set the destination  */
+      gimp_hsv_to_rgb_int (&r1, &g1, &b1);
+
+      dest[0] = r1; dest[1] = g1; dest[2] = b1;
+
+      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;
+    }
+}
+
+
+static inline void
+saturation_only_pixels (const guchar *src1,
+                        const guchar *src2,
+                        guchar       *dest,
+                        guint         length,
+                        guint         bytes1,
+                        guint         bytes2)
+{
+  const guint has_alpha1 = HAS_ALPHA (bytes1);
+  const guint has_alpha2 = HAS_ALPHA (bytes2);
+
+  /*  assumes inputs are only 4 byte RGBA pixels  */
+  while (length--)
+    {
+      gint r1, g1, b1;
+      gint r2, g2, b2;
+
+      r1 = src1[0]; g1 = src1[1]; b1 = src1[2];
+      r2 = src2[0]; g2 = src2[1]; b2 = src2[2];
+
+      gimp_rgb_to_hsv_int (&r1, &g1, &b1);
+      gimp_rgb_to_hsv_int (&r2, &g2, &b2);
+
+      g1 = g2;
+
+      /*  set the destination  */
+      gimp_hsv_to_rgb_int (&r1, &g1, &b1);
+
+      dest[0] = r1; dest[1] = g1; dest[2] = b1;
+
+      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;
+    }
+}
+
+
+static inline void
+value_only_pixels (const guchar *src1,
+                   const guchar *src2,
+                   guchar       *dest,
+                   guint         length,
+                   guint         bytes1,
+                   guint         bytes2)
+{
+  const guint has_alpha1 = HAS_ALPHA (bytes1);
+  const guint has_alpha2 = HAS_ALPHA (bytes2);
+
+  /*  assumes inputs are only 4 byte RGBA pixels  */
+  while (length--)
+    {
+      gint r1, g1, b1;
+      gint r2, g2, b2;
+
+      r1 = src1[0]; g1 = src1[1]; b1 = src1[2];
+      r2 = src2[0]; g2 = src2[1]; b2 = src2[2];
+
+      gimp_rgb_to_hsv_int (&r1, &g1, &b1);
+      gimp_rgb_to_hsv_int (&r2, &g2, &b2);
+
+      b1 = b2;
+
+      /*  set the destination  */
+      gimp_hsv_to_rgb_int (&r1, &g1, &b1);
+
+      dest[0] = r1; dest[1] = g1; dest[2] = b1;
+
+      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;
+    }
+}
+
+
+static inline void
+color_only_pixels (const guchar *src1,
+                   const guchar *src2,
+                   guchar       *dest,
+                   guint         length,
+                   guint         bytes1,
+                   guint         bytes2)
+{
+  const guint has_alpha1 = HAS_ALPHA (bytes1);
+  const guint has_alpha2 = HAS_ALPHA (bytes2);
+
+  /*  assumes inputs are only 4 byte RGBA pixels  */
+  while (length--)
+    {
+      gint r1, g1, b1;
+      gint r2, g2, b2;
+
+      r1 = src1[0]; g1 = src1[1]; b1 = src1[2];
+      r2 = src2[0]; g2 = src2[1]; b2 = src2[2];
+
+      gimp_rgb_to_hsl_int (&r1, &g1, &b1);
+      gimp_rgb_to_hsl_int (&r2, &g2, &b2);
+
+      /*  transfer hue and saturation to the source pixel  */
+      r1 = r2;
+      g1 = g2;
+
+      /*  set the destination  */
+      gimp_hsl_to_rgb_int (&r1, &g1, &b1);
+
+      dest[0] = r1; dest[1] = g1; dest[2] = b1;
+
+      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;
+    }
+}
+
+static inline void
+dodge_pixels (const guchar *src1,
+              const guchar *src2,
+              guchar           *dest,
+              guint         length,
+              guint         bytes1,
+              guint         bytes2)
+{
+  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);
+  while (length --)
+    {
+      guint b;
+
+      for (b = 0; b < alpha; b++)
+        {
+          guint tmp;
+
+          tmp = src1[b] << 8;
+          tmp /= 256 - src2[b];
+
+          dest[b] = (guchar) MIN (tmp, 255);
+        }
+
+      if (has_alpha1 && has_alpha2)
+        dest[alpha] = MIN (src1[alpha], src2[alpha]);
+      else if (has_alpha2)
+        dest[alpha] = src2[alpha];
+
+      src1 += bytes1;
+      src2 += bytes2;
+      dest += bytes2;
+    }
+}
+
+
+static inline void
+burn_pixels (const guchar *src1,
+             const guchar *src2,
+             guchar       *dest,
+             guint         length,
+             guint         bytes1,
+             guint         bytes2)
+{
+  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);
+
+  while (length --)
+    {
+      guint b;
+
+      for (b = 0; b < alpha; b++)
+        {
+          /* FIXME: Is the burn effect supposed to be dependant on the sign
+           * of this temporary variable?
+           */
+          gint tmp;
+
+          tmp = (255 - src1[b]) << 8;
+          tmp /= src2[b] + 1;
+
+          dest[b] = (guchar) CLAMP (255 - tmp, 0, 255);
+        }
+
+      if (has_alpha1 && has_alpha2)
+        dest[alpha] = MIN (src1[alpha], src2[alpha]);
+      else if (has_alpha2)
+        dest[alpha] = src2[alpha];
+
+      src1 += bytes1;
+      src2 += bytes2;
+      dest += bytes2;
+    }
+}
+
+
+static inline void
+hardlight_pixels (const guchar *src1,
+                  const guchar *src2,
+                  guchar       *dest,
+                  guint         length,
+                  guint         bytes1,
+                  guint         bytes2)
+{
+  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);
+
+  while (length --)
+    {
+      guint b;
+
+      for (b = 0; b < alpha; b++)
+        {
+          guint tmp;
+
+          if (src2[b] > 128)
+            {
+              tmp = (((gint)255 - src1[b]) *
+                     ((gint)255 - ((src2[b] - 128) << 1)));
+              dest[b] = (guchar) MIN (255 - (tmp >> 8), 255);
+            }
+          else
+            {
+              tmp = (gint) src1[b] * ((gint)src2[b] << 1);
+              dest[b] = (guchar) MIN (tmp >> 8, 255);
+            }
+        }
+
+      if (has_alpha1 && has_alpha2)
+        dest[alpha] = MIN (src1[alpha], src2[alpha]);
+      else if (has_alpha2)
+        dest[alpha] = src2[alpha];
+
+      src1 += bytes1;
+      src2 += bytes2;
+      dest += bytes2;
+    }
+}
+
+
+static inline void
+softlight_pixels (const guchar *src1,
+                  const guchar *src2,
+                  guchar       *dest,
+                  guint         length,
+                  guint         bytes1,
+                  guint         bytes2)
+{
+  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);
+
+  while (length --)
+    {
+      guint b;
+
+        for (b = 0; b < alpha; b++)
+        {
+          guint tmp1, tmp2, tmp3;
+
+          /* Mix multiply and screen */
+         guint tmpM = INT_MULT (src1[b], src2[b], tmpM);
+         guint tmpS = 255 - INT_MULT((255 - src1[b]), (255 - src2[b]), tmp1);
+
+          dest[b] = INT_MULT ((255 - src1[b]), tmpM, tmp2) +
+            INT_MULT (src1[b], tmpS, tmp3);
+        }
+
+      if (has_alpha1 && has_alpha2)
+        dest[alpha] = MIN (src1[alpha], src2[alpha]);
+      else if (has_alpha2)
+        dest[alpha] = src2[alpha];
+
+      src1 += bytes1;
+      src2 += bytes2;
+      dest += bytes2;
+    }
+}
+
+
+static inline void
+grain_extract_pixels (const guchar *src1,
+                      const guchar *src2,
+                      guchar       *dest,
+                      guint         length,
+                      guint         bytes1,
+                      guint         bytes2)
+{
+  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);
+
+  while (length --)
+    {
+      guint b;
+
+      for (b = 0; b < alpha; b++)
+        {
+          gint diff = src1[b] - src2[b] + 128;
+
+          dest[b] = (guchar) CLAMP (diff, 0, 255);
+        }
+
+      if (has_alpha1 && has_alpha2)
+        dest[alpha] = MIN (src1[alpha], src2[alpha]);
+      else if (has_alpha2)
+        dest[alpha] = src2[alpha];
+
+      src1 += bytes1;
+      src2 += bytes2;
+      dest += bytes2;
+    }
+}
+
+
+static inline void
+grain_merge_pixels (const guchar *src1,
+                    const guchar *src2,
+                    guchar       *dest,
+                    guint         length,
+                    guint         bytes1,
+                    guint         bytes2)
+{
+  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);
+
+  while (length --)
+    {
+      guint  b;
+
+      for (b = 0; b < alpha; b++)
+        {
+          /* Add, re-center and clip. */
+          gint sum = src1[b] + src2[b] - 128;
+
+          dest[b] = (guchar) CLAMP (sum, 0, 255);
+        }
+
+      if (has_alpha1 && has_alpha2)
+        dest[alpha] = MIN (src1[alpha], src2[alpha]);
+      else if (has_alpha2)
+        dest[alpha] = src2[alpha];
+
+      src1 += bytes1;
+      src2 += bytes2;
+      dest += bytes2;
+    }
+}
+
+
+
+/**********************************
+ * Layer mode interface functions *
+ **********************************/
+
+void
+layer_modes_setup (void)
+{
+  GRand *gr;
+  gint   i;
+
+  /*  generate a table of random seeds  */
+  gr = g_rand_new_with_seed (RANDOM_SEED);
+
+  for (i = 0; i < RANDOM_TABLE_SIZE; i++)
+    random_table[i] = g_rand_int (gr);
+
+  for (i = 0; i < 256; i++)
+    add_lut[i] = i;
+
+  for (i = 256; i <= 510; i++)
+    add_lut[i] = 255;
+
+  g_rand_free (gr);
+}
+
+void
+layer_normal_mode (struct apply_layer_mode_struct *alms)
+{
+  /*  assumes we're applying src2 TO src1  */
+  *(alms->dest) = alms->src2;
+}
+
+void
+layer_dissolve_mode (struct apply_layer_mode_struct *alms)
+{
+  const guint has_alpha1 = HAS_ALPHA (alms->bytes1);
+  const guint has_alpha2 = HAS_ALPHA (alms->bytes2);
+  guint       dest_bytes;
+
+  /*  Since dissolve requires an alpha channel...  */
+  if (has_alpha2)
+    dest_bytes = alms->bytes2;
+  else
+    dest_bytes = alms->bytes2 + 1;
+
+  dissolve_pixels (alms->src2, alms->mask, *(alms->dest),
+                   alms->x, alms->y,
+                   alms->opacity, alms->length,
+                   alms->bytes2, dest_bytes,
+                   has_alpha2);
+
+  alms->combine = has_alpha1 ? COMBINE_INTEN_A_INTEN_A : COMBINE_INTEN_INTEN_A;
+}
+
+void
+layer_multiply_mode (struct apply_layer_mode_struct *alms)
+{
+  multiply_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+                   alms->bytes1, alms->bytes2);
+}
+
+void
+layer_divide_mode (struct apply_layer_mode_struct *alms)
+{
+  divide_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+                 alms->bytes1, alms->bytes2);
+}
+
+void
+layer_screen_mode (struct apply_layer_mode_struct *alms)
+{
+  screen_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+                 alms->bytes1, alms->bytes2);
+}
+
+void
+layer_overlay_mode (struct apply_layer_mode_struct *alms)
+{
+  overlay_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+                  alms->bytes1, alms->bytes2);
+}
+
+void
+layer_difference_mode (struct apply_layer_mode_struct *alms)
+{
+  difference_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+                     alms->bytes1, alms->bytes2);
+}
+
+void
+layer_addition_mode (struct apply_layer_mode_struct *alms)
+{
+  add_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+              alms->bytes1, alms->bytes2);
+}
+
+void
+layer_subtract_mode (struct apply_layer_mode_struct *alms)
+{
+  subtract_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+                   alms->bytes1, alms->bytes2);
+}
+
+void
+layer_darken_only_mode (struct apply_layer_mode_struct *alms)
+{
+  darken_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+                 alms->bytes1, alms->bytes2);
+}
+
+void
+layer_lighten_only_mode (struct apply_layer_mode_struct *alms)
+{
+  lighten_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+                  alms->bytes1, alms->bytes2);
+}
+
+void
+layer_hue_mode (struct apply_layer_mode_struct *alms)
+{
+  /*  only works on RGB color images  */
+  if (alms->bytes1 > 2)
+    hue_only_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+                     alms->bytes1, alms->bytes2);
+  else
+    *(alms->dest) = alms->src2;
+}
+
+void
+layer_saturation_mode (struct apply_layer_mode_struct *alms)
+{
+  /*  only works on RGB color images  */
+  if (alms->bytes1 > 2)
+    saturation_only_pixels (alms->src1, alms->src2, *(alms->dest),
+                            alms->length, alms->bytes1, alms->bytes2);
+  else
+    *(alms->dest) = alms->src2;
+}
+
+void
+layer_value_mode (struct apply_layer_mode_struct *alms)
+{
+  /*  only works on RGB color images  */
+  if (alms->bytes1 > 2)
+    value_only_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+                       alms->bytes1, alms->bytes2);
+  else
+    *(alms->dest) = alms->src2;
+}
+
+void
+layer_color_mode (struct apply_layer_mode_struct *alms)
+{
+  /*  only works on RGB color images  */
+  if (alms->bytes1 > 2)
+    color_only_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+                       alms->bytes1, alms->bytes2);
+  else
+    *(alms->dest) = alms->src2;
+}
+
+void
+layer_behind_mode (struct apply_layer_mode_struct *alms)
+{
+  *(alms->dest) = alms->src2;
+  if (HAS_ALPHA (alms->bytes1))
+    alms->combine = BEHIND_INTEN;
+  else
+    alms->combine = NO_COMBINATION;
+}
+
+void
+layer_replace_mode (struct apply_layer_mode_struct *alms)
+{
+  *(alms->dest) = alms->src2;
+  alms->combine = REPLACE_INTEN;
+}
+
+void
+layer_erase_mode (struct apply_layer_mode_struct *alms)
+{
+  *(alms->dest) = alms->src2;
+  /*  If both sources have alpha channels, call erase function.
+   *  Otherwise, just combine in the normal manner
+   */
+  alms->combine =
+    (HAS_ALPHA (alms->bytes1) && HAS_ALPHA (alms->bytes2)) ?  ERASE_INTEN : 0;
+}
+
+void
+layer_anti_erase_mode (struct apply_layer_mode_struct *alms)
+{
+  *(alms->dest) = alms->src2;
+  alms->combine =
+    (HAS_ALPHA (alms->bytes1) && HAS_ALPHA (alms->bytes2)) ? ANTI_ERASE_INTEN : 0;
+}
+
+void
+layer_color_erase_mode (struct apply_layer_mode_struct *alms)
+{
+  *(alms->dest) = alms->src2;
+  alms->combine =
+    (HAS_ALPHA (alms->bytes1) && HAS_ALPHA (alms->bytes2)) ? COLOR_ERASE_INTEN : 0;
+}
+
+void
+layer_dodge_mode (struct apply_layer_mode_struct *alms)
+{
+  dodge_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+                alms->bytes1, alms->bytes2);
+}
+
+void
+layer_burn_mode (struct apply_layer_mode_struct *alms)
+{
+  burn_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+               alms->bytes1, alms->bytes2);
+}
+
+void
+layer_hardlight_mode (struct apply_layer_mode_struct *alms)
+{
+  hardlight_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+                    alms->bytes1, alms->bytes2);
+}
+
+void
+layer_softlight_mode (struct apply_layer_mode_struct *alms)
+{
+  softlight_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+                    alms->bytes1, alms->bytes2);
+}
+
+void
+layer_grain_extract_mode (struct apply_layer_mode_struct *alms)
+{
+  grain_extract_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+                        alms->bytes1, alms->bytes2);
+}
+
+void
+layer_grain_merge_mode (struct apply_layer_mode_struct *alms)
+{
+  grain_merge_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
+                      alms->bytes1, alms->bytes2);
+}

Added: trunk/app/paint-funcs/layer-modes.h
==============================================================================
--- (empty file)
+++ trunk/app/paint-funcs/layer-modes.h	Mon Oct 13 18:51:32 2008
@@ -0,0 +1,81 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C); 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __LAYER_MODES_H__
+#define __LAYER_MODES_H__
+
+/* FIXME: This function should not be called directly but
+ * through layer_dissolve_mode function
+ */
+void dissolve_pixels (const guchar *src,
+                      const guchar *mask,
+                      guchar       *dest,
+                      gint          x,
+                      gint          y,
+                      gint          opacity,
+                      gint          length,
+                      gint          sb,
+                      gint          db,
+                      gboolean      has_alpha);
+
+struct apply_layer_mode_struct
+{
+  guint              bytes1 : 3;
+  guint              bytes2 : 3;
+  guchar            *src1;
+  guchar            *src2;
+  const guchar      *mask;
+  guchar           **dest;
+  gint               x;
+  gint               y;
+  guint              opacity;
+  guint              length;
+  CombinationMode    combine;
+};
+
+void layer_modes_setup        (void);
+
+void layer_normal_mode        (struct apply_layer_mode_struct *alms);
+void layer_dissolve_mode      (struct apply_layer_mode_struct *alms);
+void layer_multiply_mode      (struct apply_layer_mode_struct *alms);
+void layer_divide_mode        (struct apply_layer_mode_struct *alms);
+void layer_screen_mode        (struct apply_layer_mode_struct *alms);
+void layer_overlay_mode       (struct apply_layer_mode_struct *alms);
+void layer_difference_mode    (struct apply_layer_mode_struct *alms);
+void layer_addition_mode      (struct apply_layer_mode_struct *alms);
+void layer_subtract_mode      (struct apply_layer_mode_struct *alms);
+void layer_darken_only_mode   (struct apply_layer_mode_struct *alms);
+void layer_lighten_only_mode  (struct apply_layer_mode_struct *alms);
+void layer_hue_mode           (struct apply_layer_mode_struct *alms);
+void layer_saturation_mode    (struct apply_layer_mode_struct *alms);
+void layer_value_mode         (struct apply_layer_mode_struct *alms);
+void layer_color_mode         (struct apply_layer_mode_struct *alms);
+void layer_behind_mode        (struct apply_layer_mode_struct *alms);
+void layer_replace_mode       (struct apply_layer_mode_struct *alms);
+void layer_erase_mode         (struct apply_layer_mode_struct *alms);
+void layer_anti_erase_mode    (struct apply_layer_mode_struct *alms);
+void layer_color_erase_mode   (struct apply_layer_mode_struct *alms);
+void layer_dodge_mode         (struct apply_layer_mode_struct *alms);
+void layer_burn_mode          (struct apply_layer_mode_struct *alms);
+void layer_hardlight_mode     (struct apply_layer_mode_struct *alms);
+void layer_softlight_mode     (struct apply_layer_mode_struct *alms);
+void layer_grain_extract_mode (struct apply_layer_mode_struct *alms);
+void layer_grain_merge_mode   (struct apply_layer_mode_struct *alms);
+
+#endif
+

Modified: trunk/app/paint-funcs/paint-funcs-generic.h
==============================================================================
--- trunk/app/paint-funcs/paint-funcs-generic.h	(original)
+++ trunk/app/paint-funcs/paint-funcs-generic.h	Mon Oct 13 18:51:32 2008
@@ -25,49 +25,6 @@
 #define __PAINT_FUNCS_GENERIC_H__
 
 
-#define INT_MULT(a,b,t)  ((t) = (a) * (b) + 0x80, ((((t) >> 8) + (t)) >> 8))
-
-/* This version of INT_MULT3 is very fast, but suffers from some
-   slight roundoff errors.  It returns the correct result 99.987
-   percent of the time */
-#define INT_MULT3(a,b,c,t)  ((t) = (a) * (b) * (c) + 0x7F5B, \
-                            ((((t) >> 7) + (t)) >> 16))
-/*
-  This version of INT_MULT3 always gives the correct result, but runs at
-  approximatly one third the speed. */
-/*  #define INT_MULT3(a,b,c,t) (((a) * (b) * (c) + 32512) / 65025.0)
- */
-
-#define INT_BLEND(a,b,alpha,tmp)  (INT_MULT((a) - (b), alpha, tmp) + (b))
-
-#define RANDOM_TABLE_SIZE  4096
-
-/* A drawable has an alphachannel if contains either 4 or 2 bytes data
- * aka GRAYA and RGBA and thus the macro below works. This will have
- * to change if we support bigger formats. We'll do it so for now because
- * 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
-{
-  guint              bytes1 : 3;
-  guint              bytes2 : 3;
-  guchar            *src1;
-  guchar            *src2;
-  const guchar      *mask;
-  guchar           **dest;
-  gint               x;
-  gint               y;
-  guint              opacity;
-  guint              length;
-  CombinationMode    combine;
-};
-
-static guchar  add_lut[511];
-static gint32  random_table[RANDOM_TABLE_SIZE];
-
 void
 color_pixels (guchar       *dest,
               const guchar *color,
@@ -255,988 +212,156 @@
   for (i = 0; i < w; i++)
     {
       const guchar *p = pat + ((i + x) % pattern->width) * pattern->bytes;
-      guint         b;
-
-      for (b = 0; b < alpha; b++)
-        dest[b] = p[b];
-
-      if (HAS_ALPHA (bytes))
-        {
-          if (mask)
-            dest[alpha] = *mask++;
-          else
-            dest[alpha] = OPAQUE_OPACITY;
-
-          if (HAS_ALPHA (pattern->bytes))
-            dest[alpha] = (guchar) (dest[alpha] *
-                                    p[alpha] / (gdouble) OPAQUE_OPACITY);
-        }
-
-      dest += bytes;
-    }
-}
-
-/*
- * blend_pixels patched 8-24-05 to fix bug #163721.  Note that this change
- * causes the function to treat src1 and src2 asymmetrically.  This gives the
- * right behavior for the smudge tool, which is the only user of this function
- * at the time of patching.  If you want to use the function for something
- * else, caveat emptor.
- */
-inline void
-blend_pixels (const guchar *src1,
-              const guchar *src2,
-              guchar       *dest,
-              guchar        blend,
-              guint         w,
-              guint         bytes)
-{
-  if (HAS_ALPHA (bytes))
-    {
-      const guint blend1 = 255 - blend;
-      const guint blend2 = blend + 1;
-      const guint c      = bytes - 1;
-
-      while (w--)
-        {
-          const gint  a1 = blend1 * src1[c];
-          const gint  a2 = blend2 * src2[c];
-          const gint  a  = a1 + a2;
-          guint       b;
-
-          if (!a)
-            {
-              for (b = 0; b < bytes; b++)
-                dest[b] = 0;
-            }
-          else
-            {
-              for (b = 0; b < c; b++)
-                dest[b] =
-                  src1[b] + (src1[b] * a1 + src2[b] * a2 - a * src1[b]) / a;
-
-              dest[c] = a >> 8;
-            }
-
-          src1 += bytes;
-          src2 += bytes;
-          dest += bytes;
-        }
-    }
-  else
-    {
-      const guchar blend1 = 255 - blend;
-
-      while (w--)
-        {
-          guint b;
-
-          for (b = 0; b < bytes; b++)
-            dest[b] =
-              src1[b] + (src1[b] * blend1 + src2[b] * blend - src1[b] * 255) / 255;
-
-          src1 += bytes;
-          src2 += bytes;
-          dest += bytes;
-        }
-    }
-}
-
-inline void
-shade_pixels (const guchar *src,
-              guchar       *dest,
-              const guchar *col,
-              guchar        blend,
-              guint         w,
-              guint         bytes,
-              gboolean      has_alpha)
-{
-  const guchar blend2 = (255 - blend);
-  const guint  alpha = (has_alpha) ? bytes - 1 : bytes;
-
-  while (w--)
-    {
-      guint b;
-
-      for (b = 0; b < alpha; b++)
-        dest[b] = (src[b] * blend2 + col[b] * blend) / 255;
-
-      if (has_alpha)
-        dest[alpha] = src[alpha];  /* alpha channel */
-
-      src += bytes;
-      dest += bytes;
-    }
-}
-
-
-inline void
-extract_alpha_pixels (const guchar *src,
-                      const guchar *mask,
-                      guchar       *dest,
-                      guint         w,
-                      guint         bytes)
-{
-  const guint alpha = bytes - 1;
-
-  if (mask)
-    {
-      const guchar *m = mask;
-
-      while (w--)
-        {
-          gint tmp;
-
-          *dest++ = INT_MULT(src[alpha], *m, tmp);
-          m++;
-          src += bytes;
-        }
-    }
-  else
-    {
-      while (w--)
-        {
-          gint tmp;
-
-          *dest++ = INT_MULT(src[alpha], OPAQUE_OPACITY, tmp);
-          src += bytes;
-        }
-    }
-}
-
-
-static inline void
-darken_pixels (const guchar *src1,
-               const guchar *src2,
-               guchar       *dest,
-               guint         length,
-               guint         bytes1,
-               guint         bytes2)
-{
-  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);
-
-  while (length--)
-    {
-      guint b;
-
-      for (b = 0; b < alpha; b++)
-        {
-          guchar s1 = src1[b];
-          guchar s2 = src2[b];
-
-          dest[b] = (s1 < s2) ? s1 : s2;
-        }
-
-      if (has_alpha1 && has_alpha2)
-        dest[alpha] = MIN (src1[alpha], src2[alpha]);
-      else if (has_alpha2)
-        dest[alpha] = src2[alpha];
-
-      src1 += bytes1;
-      src2 += bytes2;
-      dest += bytes2;
-    }
-}
-
-
-static inline void
-lighten_pixels (const guchar *src1,
-                const guchar *src2,
-                guchar       *dest,
-                guint         length,
-                guint         bytes1,
-                guint         bytes2)
-{
-  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);
-
-  while (length--)
-    {
-      guint b;
-
-      for (b = 0; b < alpha; b++)
-        {
-          guchar s1 = src1[b];
-          guchar s2 = src2[b];
-
-          dest[b] = (s1 < s2) ? s2 : s1;
-        }
-
-      if (has_alpha1 && has_alpha2)
-        dest[alpha] = MIN (src1[alpha], src2[alpha]);
-      else if (has_alpha2)
-        dest[alpha] = src2[alpha];
-
-      src1 += bytes1;
-      src2 += bytes2;
-      dest += bytes2;
-    }
-}
-
-
-static inline void
-hue_only_pixels (const guchar *src1,
-                 const guchar *src2,
-                 guchar       *dest,
-                 guint         length,
-                 guint         bytes1,
-                 guint         bytes2)
-{
-  const guint has_alpha1 = HAS_ALPHA (bytes1);
-  const guint has_alpha2 = HAS_ALPHA (bytes2);
-
-  /*  assumes inputs are only 4 byte RGBA pixels  */
-  while (length--)
-    {
-      gint r1, g1, b1;
-      gint r2, g2, b2;
-
-      r1 = src1[0]; g1 = src1[1]; b1 = src1[2];
-      r2 = src2[0]; g2 = src2[1]; b2 = src2[2];
-
-      gimp_rgb_to_hsv_int (&r1, &g1, &b1);
-      gimp_rgb_to_hsv_int (&r2, &g2, &b2);
-
-      r1 = r2;
-
-      /*  set the destination  */
-      gimp_hsv_to_rgb_int (&r1, &g1, &b1);
-
-      dest[0] = r1; dest[1] = g1; dest[2] = b1;
-
-      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;
-    }
-}
-
-
-static inline void
-saturation_only_pixels (const guchar *src1,
-                        const guchar *src2,
-                        guchar       *dest,
-                        guint         length,
-                        guint         bytes1,
-                        guint         bytes2)
-{
-  const guint has_alpha1 = HAS_ALPHA (bytes1);
-  const guint has_alpha2 = HAS_ALPHA (bytes2);
-
-  /*  assumes inputs are only 4 byte RGBA pixels  */
-  while (length--)
-    {
-      gint r1, g1, b1;
-      gint r2, g2, b2;
-
-      r1 = src1[0]; g1 = src1[1]; b1 = src1[2];
-      r2 = src2[0]; g2 = src2[1]; b2 = src2[2];
-
-      gimp_rgb_to_hsv_int (&r1, &g1, &b1);
-      gimp_rgb_to_hsv_int (&r2, &g2, &b2);
-
-      g1 = g2;
-
-      /*  set the destination  */
-      gimp_hsv_to_rgb_int (&r1, &g1, &b1);
-
-      dest[0] = r1; dest[1] = g1; dest[2] = b1;
-
-      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;
-    }
-}
-
-
-static inline void
-value_only_pixels (const guchar *src1,
-                   const guchar *src2,
-                   guchar       *dest,
-                   guint         length,
-                   guint         bytes1,
-                   guint         bytes2)
-{
-  const guint has_alpha1 = HAS_ALPHA (bytes1);
-  const guint has_alpha2 = HAS_ALPHA (bytes2);
-
-  /*  assumes inputs are only 4 byte RGBA pixels  */
-  while (length--)
-    {
-      gint r1, g1, b1;
-      gint r2, g2, b2;
-
-      r1 = src1[0]; g1 = src1[1]; b1 = src1[2];
-      r2 = src2[0]; g2 = src2[1]; b2 = src2[2];
-
-      gimp_rgb_to_hsv_int (&r1, &g1, &b1);
-      gimp_rgb_to_hsv_int (&r2, &g2, &b2);
-
-      b1 = b2;
-
-      /*  set the destination  */
-      gimp_hsv_to_rgb_int (&r1, &g1, &b1);
-
-      dest[0] = r1; dest[1] = g1; dest[2] = b1;
-
-      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;
-    }
-}
-
-
-static inline void
-color_only_pixels (const guchar *src1,
-                   const guchar *src2,
-                   guchar       *dest,
-                   guint         length,
-                   guint         bytes1,
-                   guint         bytes2)
-{
-  const guint has_alpha1 = HAS_ALPHA (bytes1);
-  const guint has_alpha2 = HAS_ALPHA (bytes2);
-
-  /*  assumes inputs are only 4 byte RGBA pixels  */
-  while (length--)
-    {
-      gint r1, g1, b1;
-      gint r2, g2, b2;
-
-      r1 = src1[0]; g1 = src1[1]; b1 = src1[2];
-      r2 = src2[0]; g2 = src2[1]; b2 = src2[2];
-
-      gimp_rgb_to_hsl_int (&r1, &g1, &b1);
-      gimp_rgb_to_hsl_int (&r2, &g2, &b2);
-
-      /*  transfer hue and saturation to the source pixel  */
-      r1 = r2;
-      g1 = g2;
-
-      /*  set the destination  */
-      gimp_hsl_to_rgb_int (&r1, &g1, &b1);
-
-      dest[0] = r1; dest[1] = g1; dest[2] = b1;
-
-      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;
-    }
-}
-
-
-static inline void
-multiply_pixels (const guchar *src1,
-                 const guchar *src2,
-                 guchar       *dest,
-                 guint         length,
-                 guint         bytes1,
-                 guint         bytes2)
-{
-  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);
-
-  if (has_alpha1 && has_alpha2)
-    {
-      while (length --)
-        {
-          guint b;
-
-          for (b = 0; b < alpha; b++)
-            {
-              guint tmp;
-
-              dest[b] = INT_MULT(src1[b], src2[b], tmp);
-            }
-
-          dest[alpha] = MIN (src1[alpha], src2[alpha]);
-
-          src1 += bytes1;
-          src2 += bytes2;
-          dest += bytes2;
-        }
-    }
-  else if (has_alpha2)
-    {
-      while (length --)
-        {
-          guint b;
-
-          for (b = 0; b < alpha; b++)
-            {
-              guint tmp;
-
-              dest[b] = INT_MULT(src1[b], src2[b], tmp);
-            }
-
-          dest[alpha] = src2[alpha];
-
-          src1 += bytes1;
-          src2 += bytes2;
-          dest += bytes2;
-        }
-    }
-  else
-    {
-      while (length --)
-        {
-          guint b;
-
-          for (b = 0; b < alpha; b++)
-            {
-              guint tmp;
-
-              dest[b] = INT_MULT (src1[b], src2[b], tmp);
-            }
-
-          src1 += bytes1;
-          src2 += bytes2;
-          dest += bytes2;
-        }
-    }
-}
-
-
-static inline void
-divide_pixels (const guchar *src1,
-               const guchar *src2,
-               guchar       *dest,
-               guint         length,
-               guint         bytes1,
-               guint         bytes2)
-{
-  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);
-  while (length--)
-    {
-      guint b;
-
-      for (b = 0; b < alpha; b++)
-        {
-          guint result = ((src1[b] * 256) / (1 + src2[b]));
-
-          dest[b] = MIN (result, 255);
-        }
-
-      if (has_alpha1 && has_alpha2)
-        dest[alpha] = MIN (src1[alpha], src2[alpha]);
-      else if (has_alpha2)
-        dest[alpha] = src2[alpha];
-
-      src1 += bytes1;
-      src2 += bytes2;
-      dest += bytes2;
-    }
-}
-
-
-static inline void
-screen_pixels (const guchar *src1,
-               const guchar *src2,
-               guchar       *dest,
-               guint         length,
-               guint         bytes1,
-               guint         bytes2)
-{
-  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);
-
-  while (length --)
-    {
-      guint b;
-
-      for (b = 0; b < alpha; b++)
-        {
-          guint tmp;
-
-          dest[b] = 255 - INT_MULT((255 - src1[b]), (255 - src2[b]), tmp);
-        }
-
-      if (has_alpha1 && has_alpha2)
-        dest[alpha] = MIN (src1[alpha], src2[alpha]);
-      else if (has_alpha2)
-        dest[alpha] = src2[alpha];
-
-      src1 += bytes1;
-      src2 += bytes2;
-      dest += bytes2;
-    }
-}
-
-
-static inline void
-overlay_pixels (const guchar *src1,
-                const guchar *src2,
-                guchar       *dest,
-                guint         length,
-                guint         bytes1,
-                guint         bytes2)
-{
-  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);
-
-  while (length --)
-    {
-      guint b;
-
-      for (b = 0; b < alpha; b++)
-        {
-          guint tmp, tmpM;
-
-          dest[b] = INT_MULT(src1[b], src1[b] + INT_MULT (2 * src2[b],
-                                                          255 - src1[b],
-                                                          tmpM), tmp);
-        }
-
-      if (has_alpha1 && has_alpha2)
-        dest[alpha] = MIN (src1[alpha], src2[alpha]);
-      else if (has_alpha2)
-        dest[alpha] = src2[alpha];
-
-      src1 += bytes1;
-      src2 += bytes2;
-      dest += bytes2;
-    }
-}
-
-
-static inline void
-dodge_pixels (const guchar *src1,
-              const guchar *src2,
-              guchar           *dest,
-              guint         length,
-              guint         bytes1,
-              guint         bytes2)
-{
-  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);
-  while (length --)
-    {
-      guint b;
-
-      for (b = 0; b < alpha; b++)
-        {
-          guint tmp;
-
-          tmp = src1[b] << 8;
-          tmp /= 256 - src2[b];
-
-          dest[b] = (guchar) MIN (tmp, 255);
-        }
-
-      if (has_alpha1 && has_alpha2)
-        dest[alpha] = MIN (src1[alpha], src2[alpha]);
-      else if (has_alpha2)
-        dest[alpha] = src2[alpha];
-
-      src1 += bytes1;
-      src2 += bytes2;
-      dest += bytes2;
-    }
-}
-
-
-static inline void
-burn_pixels (const guchar *src1,
-             const guchar *src2,
-             guchar       *dest,
-             guint         length,
-             guint         bytes1,
-             guint         bytes2)
-{
-  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);
-
-  while (length --)
-    {
-      guint b;
-
-      for (b = 0; b < alpha; b++)
-        {
-          /* FIXME: Is the burn effect supposed to be dependant on the sign
-           * of this temporary variable?
-           */
-          gint tmp;
-
-          tmp = (255 - src1[b]) << 8;
-          tmp /= src2[b] + 1;
-
-          dest[b] = (guchar) CLAMP (255 - tmp, 0, 255);
-        }
-
-      if (has_alpha1 && has_alpha2)
-        dest[alpha] = MIN (src1[alpha], src2[alpha]);
-      else if (has_alpha2)
-        dest[alpha] = src2[alpha];
-
-      src1 += bytes1;
-      src2 += bytes2;
-      dest += bytes2;
-    }
-}
-
-
-static inline void
-hardlight_pixels (const guchar *src1,
-                  const guchar *src2,
-                  guchar       *dest,
-                  guint         length,
-                  guint         bytes1,
-                  guint         bytes2)
-{
-  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);
-
-  while (length --)
-    {
-      guint b;
-
-      for (b = 0; b < alpha; b++)
-        {
-          guint tmp;
-
-          if (src2[b] > 128)
-            {
-              tmp = (((gint)255 - src1[b]) *
-                     ((gint)255 - ((src2[b] - 128) << 1)));
-              dest[b] = (guchar) MIN (255 - (tmp >> 8), 255);
-            }
-          else
-            {
-              tmp = (gint) src1[b] * ((gint)src2[b] << 1);
-              dest[b] = (guchar) MIN (tmp >> 8, 255);
-            }
-        }
-
-      if (has_alpha1 && has_alpha2)
-        dest[alpha] = MIN (src1[alpha], src2[alpha]);
-      else if (has_alpha2)
-        dest[alpha] = src2[alpha];
-
-      src1 += bytes1;
-      src2 += bytes2;
-      dest += bytes2;
-    }
-}
-
-
-static inline void
-softlight_pixels (const guchar *src1,
-                  const guchar *src2,
-                  guchar       *dest,
-                  guint         length,
-                  guint         bytes1,
-                  guint         bytes2)
-{
-  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);
-
-  while (length --)
-    {
-      guint b;
-
-        for (b = 0; b < alpha; b++)
-        {
-          guint tmp1, tmp2, tmp3;
-
-          /* Mix multiply and screen */
-         guint tmpM = INT_MULT (src1[b], src2[b], tmpM);
-         guint tmpS = 255 - INT_MULT((255 - src1[b]), (255 - src2[b]), tmp1);
-
-          dest[b] = INT_MULT ((255 - src1[b]), tmpM, tmp2) +
-            INT_MULT (src1[b], tmpS, tmp3);
-        }
-
-      if (has_alpha1 && has_alpha2)
-        dest[alpha] = MIN (src1[alpha], src2[alpha]);
-      else if (has_alpha2)
-        dest[alpha] = src2[alpha];
-
-      src1 += bytes1;
-      src2 += bytes2;
-      dest += bytes2;
-    }
-}
-
-
-static inline void
-grain_extract_pixels (const guchar *src1,
-                      const guchar *src2,
-                      guchar       *dest,
-                      guint         length,
-                      guint         bytes1,
-                      guint         bytes2)
-{
-  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);
-
-  while (length --)
-    {
-      guint b;
+      guint         b;
 
       for (b = 0; b < alpha; b++)
+        dest[b] = p[b];
+
+      if (HAS_ALPHA (bytes))
         {
-          gint diff = src1[b] - src2[b] + 128;
+          if (mask)
+            dest[alpha] = *mask++;
+          else
+            dest[alpha] = OPAQUE_OPACITY;
 
-          dest[b] = (guchar) CLAMP (diff, 0, 255);
+          if (HAS_ALPHA (pattern->bytes))
+            dest[alpha] = (guchar) (dest[alpha] *
+                                    p[alpha] / (gdouble) OPAQUE_OPACITY);
         }
 
-      if (has_alpha1 && has_alpha2)
-        dest[alpha] = MIN (src1[alpha], src2[alpha]);
-      else if (has_alpha2)
-        dest[alpha] = src2[alpha];
-
-      src1 += bytes1;
-      src2 += bytes2;
-      dest += bytes2;
+      dest += bytes;
     }
 }
 
-
-static inline void
-grain_merge_pixels (const guchar *src1,
-                    const guchar *src2,
-                    guchar       *dest,
-                    guint         length,
-                    guint         bytes1,
-                    guint         bytes2)
+/*
+ * blend_pixels patched 8-24-05 to fix bug #163721.  Note that this change
+ * causes the function to treat src1 and src2 asymmetrically.  This gives the
+ * right behavior for the smudge tool, which is the only user of this function
+ * at the time of patching.  If you want to use the function for something
+ * else, caveat emptor.
+ */
+inline void
+blend_pixels (const guchar *src1,
+              const guchar *src2,
+              guchar       *dest,
+              guchar        blend,
+              guint         w,
+              guint         bytes)
 {
-  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);
-
-  while (length --)
+  if (HAS_ALPHA (bytes))
     {
-      guint  b;
+      const guint blend1 = 255 - blend;
+      const guint blend2 = blend + 1;
+      const guint c      = bytes - 1;
 
-      for (b = 0; b < alpha; b++)
+      while (w--)
         {
-          /* Add, re-center and clip. */
-          gint sum = src1[b] + src2[b] - 128;
+          const gint  a1 = blend1 * src1[c];
+          const gint  a2 = blend2 * src2[c];
+          const gint  a  = a1 + a2;
+          guint       b;
 
-          dest[b] = (guchar) CLAMP (sum, 0, 255);
-        }
+          if (!a)
+            {
+              for (b = 0; b < bytes; b++)
+                dest[b] = 0;
+            }
+          else
+            {
+              for (b = 0; b < c; b++)
+                dest[b] =
+                  src1[b] + (src1[b] * a1 + src2[b] * a2 - a * src1[b]) / a;
 
-      if (has_alpha1 && has_alpha2)
-        dest[alpha] = MIN (src1[alpha], src2[alpha]);
-      else if (has_alpha2)
-        dest[alpha] = src2[alpha];
+              dest[c] = a >> 8;
+            }
 
-      src1 += bytes1;
-      src2 += bytes2;
-      dest += bytes2;
+          src1 += bytes;
+          src2 += bytes;
+          dest += bytes;
+        }
     }
-}
-
-
-static inline void
-add_pixels (const guchar *src1,
-            const guchar *src2,
-            guchar       *dest,
-            guint         length,
-            guint         bytes1,
-            guint         bytes2)
-{
-  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);
-
-  while (length --)
+  else
     {
-      guint b;
+      const guchar blend1 = 255 - blend;
 
-      for (b = 0; b < alpha; b++)
-          dest[b] = add_lut[src1[b] + src2[b]];
+      while (w--)
+        {
+          guint b;
 
-      if (has_alpha1 && has_alpha2)
-        dest[alpha] = MIN (src1[alpha], src2[alpha]);
-      else if (has_alpha2)
-        dest[alpha] = src2[alpha];
+          for (b = 0; b < bytes; b++)
+            dest[b] =
+              src1[b] + (src1[b] * blend1 + src2[b] * blend - src1[b] * 255) / 255;
 
-      src1 += bytes1;
-      src2 += bytes2;
-      dest += bytes2;
+          src1 += bytes;
+          src2 += bytes;
+          dest += bytes;
+        }
     }
 }
 
+inline void
+shade_pixels (const guchar *src,
+              guchar       *dest,
+              const guchar *col,
+              guchar        blend,
+              guint         w,
+              guint         bytes,
+              gboolean      has_alpha)
+{
+  const guchar blend2 = (255 - blend);
+  const guint  alpha = (has_alpha) ? bytes - 1 : bytes;
 
-static inline void
-subtract_pixels (const guchar *src1,
-                 const guchar *src2,
-                 guchar       *dest,
-                 guint         length,
-                 guint         bytes1,
-                 guint         bytes2)
-{
-  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);
-
-  while (length --)
+  while (w--)
     {
       guint b;
 
       for (b = 0; b < alpha; b++)
-        {
-          gint diff = src1[b] - src2[b];
-
-          dest[b] = (diff < 0) ? 0 : diff;
-        }
+        dest[b] = (src[b] * blend2 + col[b] * blend) / 255;
 
-      if (has_alpha1 && has_alpha2)
-        dest[alpha] = MIN (src1[alpha], src2[alpha]);
-      else if (has_alpha2)
-        dest[alpha] = src2[alpha];
+      if (has_alpha)
+        dest[alpha] = src[alpha];  /* alpha channel */
 
-      src1 += bytes1;
-      src2 += bytes2;
-      dest += bytes2;
+      src += bytes;
+      dest += bytes;
     }
 }
 
 
-static inline void
-difference_pixels (const guchar *src1,
-                   const guchar *src2,
-                   guchar       *dest,
-                   guint         length,
-                   guint         bytes1,
-                   guint         bytes2)
+inline void
+extract_alpha_pixels (const guchar *src,
+                      const guchar *mask,
+                      guchar       *dest,
+                      guint         w,
+                      guint         bytes)
 {
-  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);
+  const guint alpha = bytes - 1;
 
-  while (length --)
+  if (mask)
     {
-      guint b;
+      const guchar *m = mask;
 
-      for (b = 0; b < alpha; b++)
+      while (w--)
         {
-          gint diff = src1[b] - src2[b];
+          gint tmp;
 
-          dest[b] = (diff < 0) ? -diff : diff;
+          *dest++ = INT_MULT(src[alpha], *m, tmp);
+          m++;
+          src += bytes;
         }
-
-      if (has_alpha1 && has_alpha2)
-        dest[alpha] = MIN (src1[alpha], src2[alpha]);
-      else if (has_alpha2)
-        dest[alpha] = src2[alpha];
-
-      src1 += bytes1;
-      src2 += bytes2;
-      dest += bytes2;
     }
-}
-
-
-static inline void
-dissolve_pixels (const guchar *src,
-                 const guchar *mask,
-                 guchar       *dest,
-                 gint          x,
-                 gint          y,
-                 gint          opacity,
-                 gint          length,
-                 gint          sb,
-                 gint          db,
-                 gboolean      has_alpha)
-{
-  const gint  alpha = db - 1;
-  gint        b;
-  GRand      *gr;
-
-  gr = g_rand_new_with_seed (random_table[y % RANDOM_TABLE_SIZE]);
-
-  /* Ignore x random values so we get a deterministic result */
-  for (b = 0; b < x; b ++)
-    g_rand_int (gr);
-
-  while (length--)
+  else
     {
-      gint    combined_opacity;
-      gint32  rand_val;
-
-      /*  preserve the intensity values  */
-      for (b = 0; b < alpha; b++)
-        dest[b] = src[b];
-
-      /*  dissolve if random value is >= opacity  */
-      rand_val = g_rand_int_range (gr, 0, 255);
-
-      if (mask)
+      while (w--)
         {
-          if (has_alpha)
-            combined_opacity = opacity * src[alpha] * *mask / (255 * 255);
-          else
-            combined_opacity = opacity * *mask / 255;
+          gint tmp;
 
-          mask++;
-        }
-      else
-        {
-          if (has_alpha)
-            combined_opacity = opacity * src[alpha] / 255;
-          else
-            combined_opacity = opacity;
+          *dest++ = INT_MULT(src[alpha], OPAQUE_OPACITY, tmp);
+          src += bytes;
         }
-
-      dest[alpha] = (rand_val >= combined_opacity) ? 0 : OPAQUE_OPACITY;
-
-      src  += sb;
-      dest += db;
     }
-
-  g_rand_free (gr);
-
 }
 
+
 static inline void
 replace_pixels (const guchar   *src1,
                 const guchar   *src2,
@@ -1882,226 +1007,4 @@
 }
 
 
-static void
-layer_normal_mode (struct apply_layer_mode_struct *alms)
-{
-  /*  assumes we're applying src2 TO src1  */
-  *(alms->dest) = alms->src2;
-}
-
-static void
-layer_dissolve_mode (struct apply_layer_mode_struct *alms)
-{
-  const guint has_alpha1 = HAS_ALPHA (alms->bytes1);
-  const guint has_alpha2 = HAS_ALPHA (alms->bytes2);
-  guint       dest_bytes;
-
-  /*  Since dissolve requires an alpha channel...  */
-  if (has_alpha2)
-    dest_bytes = alms->bytes2;
-  else
-    dest_bytes = alms->bytes2 + 1;
-
-  dissolve_pixels (alms->src2, alms->mask, *(alms->dest),
-                   alms->x, alms->y,
-                   alms->opacity, alms->length,
-                   alms->bytes2, dest_bytes,
-                   has_alpha2);
-
-  alms->combine = has_alpha1 ? COMBINE_INTEN_A_INTEN_A : COMBINE_INTEN_INTEN_A;
-}
-
-static void
-layer_multiply_mode (struct apply_layer_mode_struct *alms)
-{
-  multiply_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
-                   alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_divide_mode (struct apply_layer_mode_struct *alms)
-{
-  divide_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
-                 alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_screen_mode (struct apply_layer_mode_struct *alms)
-{
-  screen_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
-                 alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_overlay_mode (struct apply_layer_mode_struct *alms)
-{
-  overlay_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
-                  alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_difference_mode (struct apply_layer_mode_struct *alms)
-{
-  difference_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
-                     alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_addition_mode (struct apply_layer_mode_struct *alms)
-{
-  add_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
-              alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_subtract_mode (struct apply_layer_mode_struct *alms)
-{
-  subtract_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
-                   alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_darken_only_mode (struct apply_layer_mode_struct *alms)
-{
-  darken_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
-                 alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_lighten_only_mode (struct apply_layer_mode_struct *alms)
-{
-  lighten_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
-                  alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_hue_mode (struct apply_layer_mode_struct *alms)
-{
-  /*  only works on RGB color images  */
-  if (alms->bytes1 > 2)
-    hue_only_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
-                     alms->bytes1, alms->bytes2);
-  else
-    *(alms->dest) = alms->src2;
-}
-
-static void
-layer_saturation_mode (struct apply_layer_mode_struct *alms)
-{
-  /*  only works on RGB color images  */
-  if (alms->bytes1 > 2)
-    saturation_only_pixels (alms->src1, alms->src2, *(alms->dest),
-                            alms->length, alms->bytes1, alms->bytes2);
-  else
-    *(alms->dest) = alms->src2;
-}
-
-static void
-layer_value_mode (struct apply_layer_mode_struct *alms)
-{
-  /*  only works on RGB color images  */
-  if (alms->bytes1 > 2)
-    value_only_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
-                       alms->bytes1, alms->bytes2);
-  else
-    *(alms->dest) = alms->src2;
-}
-
-static void
-layer_color_mode (struct apply_layer_mode_struct *alms)
-{
-  /*  only works on RGB color images  */
-  if (alms->bytes1 > 2)
-    color_only_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
-                       alms->bytes1, alms->bytes2);
-  else
-    *(alms->dest) = alms->src2;
-}
-
-static void
-layer_behind_mode (struct apply_layer_mode_struct *alms)
-{
-  *(alms->dest) = alms->src2;
-  if (HAS_ALPHA (alms->bytes1))
-    alms->combine = BEHIND_INTEN;
-  else
-    alms->combine = NO_COMBINATION;
-}
-
-static void
-layer_replace_mode (struct apply_layer_mode_struct *alms)
-{
-  *(alms->dest) = alms->src2;
-  alms->combine = REPLACE_INTEN;
-}
-
-static void
-layer_erase_mode (struct apply_layer_mode_struct *alms)
-{
-  *(alms->dest) = alms->src2;
-  /*  If both sources have alpha channels, call erase function.
-   *  Otherwise, just combine in the normal manner
-   */
-  alms->combine =
-    (HAS_ALPHA (alms->bytes1) && HAS_ALPHA (alms->bytes2)) ?  ERASE_INTEN : 0;
-}
-
-static void
-layer_anti_erase_mode (struct apply_layer_mode_struct *alms)
-{
-  *(alms->dest) = alms->src2;
-  alms->combine =
-    (HAS_ALPHA (alms->bytes1) && HAS_ALPHA (alms->bytes2)) ? ANTI_ERASE_INTEN : 0;
-}
-
-static void
-layer_color_erase_mode (struct apply_layer_mode_struct *alms)
-{
-  *(alms->dest) = alms->src2;
-  alms->combine =
-    (HAS_ALPHA (alms->bytes1) && HAS_ALPHA (alms->bytes2)) ? COLOR_ERASE_INTEN : 0;
-}
-
-static void
-layer_dodge_mode (struct apply_layer_mode_struct *alms)
-{
-  dodge_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
-                alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_burn_mode (struct apply_layer_mode_struct *alms)
-{
-  burn_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
-               alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_hardlight_mode (struct apply_layer_mode_struct *alms)
-{
-  hardlight_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
-                    alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_softlight_mode (struct apply_layer_mode_struct *alms)
-{
-  softlight_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
-                    alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_grain_extract_mode (struct apply_layer_mode_struct *alms)
-{
-  grain_extract_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
-                        alms->bytes1, alms->bytes2);
-}
-
-static void
-layer_grain_merge_mode (struct apply_layer_mode_struct *alms)
-{
-  grain_merge_pixels (alms->src1, alms->src2, *(alms->dest), alms->length,
-                      alms->bytes1, alms->bytes2);
-}
-
 #endif  /*  __PAINT_FUNCS_GENERIC_H__  */

Added: trunk/app/paint-funcs/paint-funcs-utils.h
==============================================================================
--- (empty file)
+++ trunk/app/paint-funcs/paint-funcs-utils.h	Mon Oct 13 18:51:32 2008
@@ -0,0 +1,46 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __PAINT_FUNCS_UTILS_H__
+#define __PAINT_FUNCS_UTILS_H__
+
+
+#define INT_MULT(a,b,t)  ((t) = (a) * (b) + 0x80, ((((t) >> 8) + (t)) >> 8))
+
+/* This version of INT_MULT3 is very fast, but suffers from some
+   slight roundoff errors.  It returns the correct result 99.987
+   percent of the time */
+#define INT_MULT3(a,b,c,t)  ((t) = (a) * (b) * (c) + 0x7F5B, \
+                            ((((t) >> 7) + (t)) >> 16))
+/*
+  This version of INT_MULT3 always gives the correct result, but runs at
+  approximatly one third the speed. */
+/*  #define INT_MULT3(a,b,c,t) (((a) * (b) * (c) + 32512) / 65025.0)
+ */
+
+#define INT_BLEND(a,b,alpha,tmp)  (INT_MULT((a) - (b), alpha, tmp) + (b))
+
+/* A drawable has an alphachannel if contains either 4 or 2 bytes data
+ * aka GRAYA and RGBA and thus the macro below works. This will have
+ * to change if we support bigger formats. We'll do it so for now because
+ * masking is always cheaper than passing parameters over the stack.      */
+/* FIXME: Move to a global place */
+#define HAS_ALPHA(bytes) (~bytes & 1)
+
+
+#endif  /*  __PAINT_FUNCS_UTILS_H__  */

Modified: trunk/app/paint-funcs/paint-funcs.c
==============================================================================
--- trunk/app/paint-funcs/paint-funcs.c	(original)
+++ trunk/app/paint-funcs/paint-funcs.c	Mon Oct 13 18:51:32 2008
@@ -37,10 +37,11 @@
 #include "composite/gimp-composite.h"
 
 #include "paint-funcs.h"
+#include "layer-modes.h"
+#include "paint-funcs-utils.h"
 #include "paint-funcs-generic.h"
 
 
-#define RANDOM_SEED   314159265
 #define EPSILON       0.0001
 
 #define LOG_1_255     -5.541263545    /*  log (1.0 / 255.0)  */
@@ -248,22 +249,7 @@
 void
 paint_funcs_setup (void)
 {
-  GRand *gr;
-  gint   i;
-
-  /*  generate a table of random seeds  */
-  gr = g_rand_new_with_seed (RANDOM_SEED);
-
-  for (i = 0; i < RANDOM_TABLE_SIZE; i++)
-    random_table[i] = g_rand_int (gr);
-
-  for (i = 0; i < 256; i++)
-    add_lut[i] = i;
-
-  for (i = 256; i <= 510; i++)
-    add_lut[i] = 255;
-
-  g_rand_free (gr);
+  layer_modes_setup ();
 }
 
 void
@@ -668,40 +654,6 @@
     }
 }
 
-/*orig #define alphify(src2_alpha,new_alpha) \
-        if (new_alpha == 0 || src2_alpha == 0)                                                        \
-          {                                                                                        \
-            for (b = 0; b < alpha; b++)                                                                \
-              dest[b] = src1 [b];                                                                \
-          }                                                                                        \
-        else if (src2_alpha == new_alpha){                                                        \
-          for (b = 0; b < alpha; b++)                                                                \
-            dest [b] = affect [b] ? src2 [b] : src1 [b];                                        \
-        } else {                                                                                \
-          ratio = (float) src2_alpha / new_alpha;                                                \
-          compl_ratio = 1.0 - ratio;                                                                \
-                                                                                                  \
-          for (b = 0; b < alpha; b++)                                                                \
-            dest[b] = affect[b] ?                                                                \
-              (guchar) (src2[b] * ratio + src1[b] * compl_ratio + EPSILON) : src1[b];        \
-        }*/
-
-/*shortened #define alphify(src2_alpha,new_alpha) \
-        if (src2_alpha != 0 && new_alpha != 0)                                                        \
-          {                                                                                        \
-            if (src2_alpha == new_alpha){                                                        \
-              for (b = 0; b < alpha; b++)                                                        \
-              dest [b] = affect [b] ? src2 [b] : src1 [b];                                        \
-            } else {                                                                                \
-              ratio = (float) src2_alpha / new_alpha;                                                \
-              compl_ratio = 1.0 - ratio;                                                        \
-                                                                                                  \
-              for (b = 0; b < alpha; b++)                                                        \
-                dest[b] = affect[b] ?                                                                \
-                  (guchar) (src2[b] * ratio + src1[b] * compl_ratio + EPSILON) : src1[b];\
-            }                                                                                   \
-          }*/
-
 #define alphify(src2_alpha,new_alpha) \
         if (src2_alpha != 0 && new_alpha != 0)                                                        \
           {                                                                                        \
@@ -720,26 +672,6 @@
             }    \
           }
 
-/*special #define alphify4(src2_alpha,new_alpha) \
-        if (src2_alpha != 0 && new_alpha != 0)                                                        \
-          {                                                                                        \
-            if (src2_alpha == new_alpha){                                                        \
-              dest [0] = affect [0] ? src2 [0] : src1 [0];                                        \
-              dest [1] = affect [1] ? src2 [1] : src1 [1];                                        \
-              dest [2] = affect [2] ? src2 [2] : src1 [2];                                        \
-            } else {                                                                                \
-              ratio = (float) src2_alpha / new_alpha;                                                \
-              compl_ratio = 1.0 - ratio;                                                        \
-                                                                                                  \
-              dest[0] = affect[0] ?                                                                \
-                (guchar) (src2[0] * ratio + src1[0] * compl_ratio + EPSILON) : src1[0];  \
-              dest[1] = affect[1] ?                                                                \
-                (guchar) (src2[1] * ratio + src1[1] * compl_ratio + EPSILON) : src1[1];  \
-              dest[2] = affect[2] ?                                                                \
-                (guchar) (src2[2] * ratio + src1[2] * compl_ratio + EPSILON) : src1[2];  \
-            }                                                                                   \
-          }*/
-
 void
 combine_inten_a_and_inten_pixels (const guchar   *src1,
                                   const guchar   *src2,



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