pixman: Branch 'master' - 37 commits

Søren Sandmann Pedersen sandmann at kemper.freedesktop.org
Tue Jun 23 11:48:41 PDT 2009


 pixman/pixman-combine.c.template |  874 +++++++++++++++++++++++++++++++++++----
 pixman/pixman-combine.h.template |    4 
 pixman/pixman.h                  |   16 
 test/Makefile.am                 |    4 
 test/composite-test.c            |  120 ++++-
 test/screen-test.c               |   44 +
 6 files changed, 969 insertions(+), 93 deletions(-)

New commits:
commit ca4ff13027b76d0ac7398f159a731f7606b7bd51
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Tue Jun 23 14:39:49 2009 -0400

    Remove FLASH_SUBTRACT blend mode.
    
    We may resurrect it later, but leave it out for now, as the closest
    thing we have to a spec:
    
    http://www.kaourantin.net/2005/09/some-word-on-blend-modes-in-flash.html
    
    claims that alpha values should be subtracted, whereas real-world flash
    files indicate that they shouldn't.

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index f80e1a9..ee724d9 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -1015,77 +1015,6 @@ PdfNonSeparableBlendMode (HSLLuminosity)
 #undef Min
 #undef PdfNonSeparableBlendMode
 
-/*
- * Flash Subtract:
- * This is the only blend mode present in Adobe Flash that is not part of 
- * the PDF specification. It has been reverse engineered from looking at 
- * Flash files. Some information can be found at
- * http://www.kaourantin.net/2005/09/some-word-on-blend-modes-in-flash.html
- */
-#define Subtract(res, Color)						\
-    do {								\
-      comp1_t dc, sc;							\
-      dc = Color (d);							\
-      sc = Color (s);							\
-      if (sc >= dc)							\
-	res = 0;							\
-      else								\
-	res = dc - sc;							\
-    } while (0)
-
-static void
-fbCombineFlashSubtractU (pixman_implementation_t *imp, pixman_op_t op,
-			 comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
-{
-    int i;
-
-    for (i = 0; i < width; ++i) {
-	comp4_t d, s;
-	comp4_t r, g, b;
-
-	d = *(dest + i);
-	s = combineMask (src, mask, i);
-
-	Subtract (r, Red);
-	Subtract (g, Green);
-	Subtract (b, Blue);
-
-	*(dest + i) = (Alpha (d) << A_SHIFT)
-	    | (r << R_SHIFT)
-	    | (g << G_SHIFT)
-	    | b;
-    }
-}
-
-static void
-fbCombineFlashSubtractC (pixman_implementation_t *imp, pixman_op_t op,
-			 comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
-{
-    int i;
-
-    for (i = 0; i < width; ++i) {
-	comp4_t d, s, m;
-	comp4_t r, g, b;
-
-	d = *(dest + i);
-	s = *(src + i);
-	m = *(mask + i);
-
-	fbCombineMaskValueC (&s, &m);
-
-	Subtract (r, Red);
-	Subtract (g, Green);
-	Subtract (b, Blue);
-
-	*(dest + i) = (Alpha (d) << A_SHIFT)
-	    | (r << R_SHIFT)
-	    | (g << G_SHIFT)
-	    | b;
-    }
-}
-
-#undef Subtract
-
 /* Overlay
  *
  * All of the disjoint composing functions
@@ -2071,7 +2000,6 @@ _pixman_setup_combiner_functions_width (pixman_implementation_t *imp)
     imp->combine_width[PIXMAN_OP_HSL_SATURATION] = fbCombineHSLSaturationU;
     imp->combine_width[PIXMAN_OP_HSL_COLOR] = fbCombineHSLColorU;
     imp->combine_width[PIXMAN_OP_HSL_LUMINOSITY] = fbCombineHSLLuminosityU;
-    imp->combine_width[PIXMAN_OP_FLASH_SUBTRACT] = fbCombineFlashSubtractU;
 
     /* Component alpha combiners */
     imp->combine_width_ca[PIXMAN_OP_CLEAR] = fbCombineClearC;
@@ -2132,7 +2060,6 @@ _pixman_setup_combiner_functions_width (pixman_implementation_t *imp)
     imp->combine_width_ca[PIXMAN_OP_HSL_SATURATION] = fbCombineHSLSaturationC;
     imp->combine_width_ca[PIXMAN_OP_HSL_COLOR] = fbCombineHSLColorC;
     imp->combine_width_ca[PIXMAN_OP_HSL_LUMINOSITY] = fbCombineHSLLuminosityC;
-    imp->combine_width_ca[PIXMAN_OP_FLASH_SUBTRACT] = fbCombineFlashSubtractC;
 }
 
 
diff --git a/pixman/pixman.h b/pixman/pixman.h
index 93e3d11..0d602c8 100644
--- a/pixman/pixman.h
+++ b/pixman/pixman.h
@@ -383,7 +383,6 @@ typedef enum
     PIXMAN_OP_HSL_SATURATION		= 0x3c,
     PIXMAN_OP_HSL_COLOR			= 0x3d,
     PIXMAN_OP_HSL_LUMINOSITY		= 0x3e,
-    PIXMAN_OP_FLASH_SUBTRACT	      	= 0x3f,
 
     PIXMAN_OP_NONE,
     PIXMAN_OP_LAST = PIXMAN_OP_NONE
commit 5dab62a2f922a515634d65b133aeb089e855b399
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Tue Jun 23 17:12:39 2009 +0200

    Fix BlendColorBurn
    
    It should return 0 when sa == 0

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index 7c8efd9..f80e1a9 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -564,7 +564,7 @@ static inline comp4_t
 BlendColorBurn (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
 {
     if (sca == 0) {
-	return DivOne (sa * da);
+	return 0;
     } else {
 	comp4_t sada = sa * da;
 	comp4_t rca = (da - dca) * sa * sa / sca;
commit e3a94e892850f91d2cb0463dc2c86f7217deb8a4
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Sat Jun 20 20:19:57 2009 -0400

    Add screen-test.c test program

diff --git a/test/Makefile.am b/test/Makefile.am
index be76dc8..01d065b 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -24,6 +24,7 @@ TESTPROGRAMS +=			\
 	composite-test		\
 	gradient-test		\
 	alpha-test		\
+	screen-test		\
 	trap-test
 
 noinst_PROGRAMS = $(TESTPROGRAMS)
@@ -48,5 +49,8 @@ clip_in_SOURCES = clip-in.c utils.c utils.h
 trap_test_LDADD = $(GTK_LDADD)
 trap_test_SOURCES = trap-test.c utils.c utils.h
 
+screen_test_LDADD = $(GTK_LDADD)
+screen_test_SOURCES = screen-test.c utils.c utils.h
+
 endif
 
diff --git a/test/screen-test.c b/test/screen-test.c
new file mode 100644
index 0000000..5e02eee
--- /dev/null
+++ b/test/screen-test.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "pixman.h"
+#include "utils.h"
+
+int
+main (int argc, char **argv)
+{
+#define WIDTH 40
+#define HEIGHT 40
+    
+    uint32_t *src1 = malloc (WIDTH * HEIGHT * 4);
+    uint32_t *src2 = malloc (WIDTH * HEIGHT * 4);
+    uint32_t *src3 = malloc (WIDTH * HEIGHT * 4);
+    uint32_t *dest = malloc (3 * WIDTH * 2 * HEIGHT * 4);
+    pixman_image_t *simg1, *simg2, *simg3, *dimg;
+
+    int i;
+
+    for (i = 0; i < WIDTH * HEIGHT; ++i)
+    {
+	src1[i] = 0x7ff00000;
+	src2[i] = 0x7f00ff00;
+	src3[i] = 0x7f0000ff;
+    }
+
+    for (i = 0; i < 3 * WIDTH * 2 * HEIGHT; ++i)
+    {
+	dest[i] = 0x0;
+    }
+
+    simg1 = pixman_image_create_bits (PIXMAN_a8r8g8b8, WIDTH, HEIGHT, src1, WIDTH * 4);
+    simg2 = pixman_image_create_bits (PIXMAN_a8r8g8b8, WIDTH, HEIGHT, src2, WIDTH * 4);
+    simg3 = pixman_image_create_bits (PIXMAN_a8r8g8b8, WIDTH, HEIGHT, src3, WIDTH * 4);
+    dimg  = pixman_image_create_bits (PIXMAN_a8r8g8b8, 3 * WIDTH, 2 * HEIGHT, dest, 3 * WIDTH * 4);
+
+    pixman_image_composite (PIXMAN_OP_SCREEN, simg1, NULL, dimg, 0, 0, 0, 0, WIDTH, HEIGHT / 4, WIDTH, HEIGHT);
+    pixman_image_composite (PIXMAN_OP_SCREEN, simg2, NULL, dimg, 0, 0, 0, 0, (WIDTH/2), HEIGHT / 4 + HEIGHT / 2, WIDTH, HEIGHT);
+    pixman_image_composite (PIXMAN_OP_SCREEN, simg3, NULL, dimg, 0, 0, 0, 0, (4 * WIDTH) / 3, HEIGHT, WIDTH, HEIGHT);
+
+    show_image (dimg);
+    
+    return 0;
+}
commit 16873f6d1baa3b0c26b31e71ad6d36d53efaf9e3
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Wed Jun 17 11:46:01 2009 -0400

    Make the composite test window bigger by default.
    
    Also rearrange the squares to better match typical aspect ratios.

diff --git a/test/composite-test.c b/test/composite-test.c
index 95dbe40..50db4f6 100644
--- a/test/composite-test.c
+++ b/test/composite-test.c
@@ -4,8 +4,8 @@
 #include "pixman.h"
 #include "utils.h"
 
-#define WIDTH	100
-#define HEIGHT	100
+#define WIDTH	60
+#define HEIGHT	60
 
 typedef struct {
     const char *name;
@@ -13,37 +13,37 @@ typedef struct {
 } Operator;
 
 static const Operator operators[] = {
-    { "PIXMAN_OP_CLEAR", PIXMAN_OP_CLEAR },
-    { "PIXMAN_OP_SRC", PIXMAN_OP_SRC },
-    { "PIXMAN_OP_DST", PIXMAN_OP_DST },
-    { "PIXMAN_OP_OVER", PIXMAN_OP_OVER },
-    { "PIXMAN_OP_OVER_REVERSE", PIXMAN_OP_OVER_REVERSE },
-    { "PIXMAN_OP_IN", PIXMAN_OP_IN },
-    { "PIXMAN_OP_IN_REVERSE", PIXMAN_OP_IN_REVERSE },
-    { "PIXMAN_OP_OUT", PIXMAN_OP_OUT },
-    { "PIXMAN_OP_OUT_REVERSE", PIXMAN_OP_OUT_REVERSE },
-    { "PIXMAN_OP_ATOP", PIXMAN_OP_ATOP },
-    { "PIXMAN_OP_ATOP_REVERSE", PIXMAN_OP_ATOP_REVERSE },
-    { "PIXMAN_OP_XOR", PIXMAN_OP_XOR },
-    { "PIXMAN_OP_ADD", PIXMAN_OP_ADD },
-    { "PIXMAN_OP_SATURATE", PIXMAN_OP_SATURATE },
-
-    { "PIXMAN_OP_MULTIPLY", PIXMAN_OP_MULTIPLY },
-    { "PIXMAN_OP_SCREEN", PIXMAN_OP_SCREEN },
-    { "PIXMAN_OP_OVERLAY", PIXMAN_OP_OVERLAY },
-    { "PIXMAN_OP_DARKEN", PIXMAN_OP_DARKEN },
-    { "PIXMAN_OP_LIGHTEN", PIXMAN_OP_LIGHTEN },
-    { "PIXMAN_OP_COLOR_DODGE", PIXMAN_OP_COLOR_DODGE },
-    { "PIXMAN_OP_COLOR_BURN", PIXMAN_OP_COLOR_BURN },
-    { "PIXMAN_OP_HARD_LIGHT", PIXMAN_OP_HARD_LIGHT },
-    { "PIXMAN_OP_SOFT_LIGHT", PIXMAN_OP_SOFT_LIGHT },
-    { "PIXMAN_OP_DIFFERENCE", PIXMAN_OP_DIFFERENCE },
-    { "PIXMAN_OP_EXCLUSION", PIXMAN_OP_EXCLUSION },
-    { "PIXMAN_OP_HSL_HUE", PIXMAN_OP_HSL_HUE },
-    { "PIXMAN_OP_HSL_SATURATION", PIXMAN_OP_HSL_SATURATION },
-    { "PIXMAN_OP_HSL_COLOR", PIXMAN_OP_HSL_COLOR },
-    { "PIXMAN_OP_HSL_LUMINOSITY", PIXMAN_OP_HSL_LUMINOSITY },
-    { "PIXMAN_OP_FLASH_SUBTRACT", PIXMAN_OP_FLASH_SUBTRACT }
+    { "CLEAR", PIXMAN_OP_CLEAR },
+    { "SRC", PIXMAN_OP_SRC },
+    { "DST", PIXMAN_OP_DST },
+    { "OVER", PIXMAN_OP_OVER },
+    { "OVER_REVERSE", PIXMAN_OP_OVER_REVERSE },
+    { "IN", PIXMAN_OP_IN },
+    { "IN_REVERSE", PIXMAN_OP_IN_REVERSE },
+    { "OUT", PIXMAN_OP_OUT },
+    { "OUT_REVERSE", PIXMAN_OP_OUT_REVERSE },
+    { "ATOP", PIXMAN_OP_ATOP },
+    { "ATOP_REVERSE", PIXMAN_OP_ATOP_REVERSE },
+    { "XOR", PIXMAN_OP_XOR },
+    { "ADD", PIXMAN_OP_ADD },
+    { "SATURATE", PIXMAN_OP_SATURATE },
+
+    { "MULTIPLY", PIXMAN_OP_MULTIPLY },
+    { "SCREEN", PIXMAN_OP_SCREEN },
+    { "OVERLAY", PIXMAN_OP_OVERLAY },
+    { "DARKEN", PIXMAN_OP_DARKEN },
+    { "LIGHTEN", PIXMAN_OP_LIGHTEN },
+    { "COLOR_DODGE", PIXMAN_OP_COLOR_DODGE },
+    { "COLOR_BURN", PIXMAN_OP_COLOR_BURN },
+    { "HARD_LIGHT", PIXMAN_OP_HARD_LIGHT },
+    { "SOFT_LIGHT", PIXMAN_OP_SOFT_LIGHT },
+    { "DIFFERENCE", PIXMAN_OP_DIFFERENCE },
+    { "EXCLUSION", PIXMAN_OP_EXCLUSION },
+    { "HSL_HUE", PIXMAN_OP_HSL_HUE },
+    { "HSL_SATURATION", PIXMAN_OP_HSL_SATURATION },
+    { "HSL_COLOR", PIXMAN_OP_HSL_COLOR },
+    { "HSL_LUMINOSITY", PIXMAN_OP_HSL_LUMINOSITY },
+    { "FLASH_SUBTRACT", PIXMAN_OP_FLASH_SUBTRACT }
 };
 
 static uint32_t
@@ -95,10 +95,13 @@ main (int argc, char **argv)
     gtk_init (&argc, &argv);
 
     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+    gtk_window_set_default_size (window, 800, 600);
+    
     g_signal_connect (window, "delete-event",
 		      G_CALLBACK (gtk_main_quit),
 		      NULL);
-    table = gtk_table_new (G_N_ELEMENTS (operators) / 4, 4, TRUE);
+    table = gtk_table_new (G_N_ELEMENTS (operators) / 6, 6, TRUE);
 
     for (i = 0; i < WIDTH * HEIGHT; ++i)
         src[i] = 0x7f7f0000; /* red */
@@ -140,7 +143,7 @@ main (int argc, char **argv)
 	gtk_widget_show (image);
 
 	gtk_table_attach_defaults (GTK_TABLE (table), vbox,
-				   i % 4, (i % 4) + 1, i / 4, (i / 4) + 1);
+				   i % 6, (i % 6) + 1, i / 6, (i / 6) + 1);
 	gtk_widget_show (vbox);
 
 	g_object_unref (pixbuf);
commit eb4fd0477a4f3acd111fc9132f2dec7f1f63f3e1
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Thu Jun 18 15:24:33 2009 +0200

    Use floating point in SetLum

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index 9ae55d1..7c8efd9 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -866,14 +866,14 @@ fbCombine ## name ## C (pixman_implementation_t *imp, pixman_op_t op, \
 static void
 SetLum (comp4_t dest[3], comp4_t src[3], comp4_t sa, comp4_t lum)
 {
-  int a, l, min, max;
-  int tmp[3];
+  double a, l, min, max;
+  double tmp[3];
   
-  a = sa;
-  l = lum;
-  tmp[0] = src[0];
-  tmp[1] = src[1];
-  tmp[2] = src[2];
+  a = sa * (1.0 / MASK);
+  l = lum * (1.0 / MASK);
+  tmp[0] = src[0] * (1.0 / MASK);
+  tmp[1] = src[1] * (1.0 / MASK);
+  tmp[2] = src[2] * (1.0 / MASK);
   l = l - Lum (tmp);
   tmp[0] += l;
   tmp[1] += l;
@@ -885,18 +885,18 @@ SetLum (comp4_t dest[3], comp4_t src[3], comp4_t sa, comp4_t lum)
   max = Max (tmp);
 
   if (min < 0) {
-    tmp[0] = l + (tmp[0] - l) / 4 * l / (l - min) * 4;
-    tmp[1] = l + (tmp[1] - l) / 4 * l / (l - min) * 4;
-    tmp[2] = l + (tmp[2] - l) / 4 * l / (l - min) * 4;
+    tmp[0] = l + (tmp[0] - l) * l / (l - min);
+    tmp[1] = l + (tmp[1] - l) * l / (l - min);
+    tmp[2] = l + (tmp[2] - l) * l / (l - min);
   }
   if (max > a) {
-    tmp[0] = l + (tmp[0] - l) / 4 * (a - l) / (max - l) * 4;
-    tmp[1] = l + (tmp[1] - l) / 4 * (a - l) / (max - l) * 4;
-    tmp[2] = l + (tmp[2] - l) / 4 * (a - l) / (max - l) * 4;
+    tmp[0] = l + (tmp[0] - l) * (a - l) / (max - l);
+    tmp[1] = l + (tmp[1] - l) * (a - l) / (max - l);
+    tmp[2] = l + (tmp[2] - l) * (a - l) / (max - l);
   }
-  dest[0] = tmp[0];
-  dest[1] = tmp[1];
-  dest[2] = tmp[2];
+  dest[0] = tmp[0] * MASK + 0.5;
+  dest[1] = tmp[1] * MASK + 0.5;
+  dest[2] = tmp[2] * MASK + 0.5;
 }
 
 static void
commit 96d5044c0c4a9e34deb97655679f1d688c192c99
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Wed Jun 17 17:40:52 2009 +0200

    Do not use combineMask in component-alpha functions

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index b17740e..9ae55d1 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -390,7 +390,7 @@ fbCombineMultiplyC (pixman_implementation_t *imp, pixman_op_t op,
     int i;
     for (i = 0; i < width; ++i) {
         comp4_t m = *(mask + i);
-        comp4_t s = combineMask (src, mask, i);
+        comp4_t s = *(src + i);
 	comp4_t d = *(dest + i);
 	comp4_t r = d;
 	comp4_t dest_ia = Alpha (~d);
@@ -438,7 +438,7 @@ fbCombine ## name ## C (pixman_implementation_t *imp, pixman_op_t op, \
     int i;					    \
     for (i = 0; i < width; ++i) {		    \
 	comp4_t m = *(mask + i);		    \
-	comp4_t s = combineMask (src, mask, i);	    \
+	comp4_t s = *(src + i);                     \
 	comp4_t d = *(dest + i);		    \
 	comp1_t da = Alpha(d);  		    \
 	comp1_t ida = ~da;			    \
@@ -820,7 +820,7 @@ fbCombine ## name ## C (pixman_implementation_t *imp, pixman_op_t op, \
     int i;					    \
     for (i = 0; i < width; ++i) {		    \
 	comp4_t m = *(mask + i);		    \
-	comp4_t s = combineMask (src, mask, i);	    \
+	comp4_t s = *(src + i);                     \
 	comp4_t d = *(dest + i);		    \
 	comp1_t sa = Alpha(s);			    \
 	comp1_t da = Alpha(d);  		    \
@@ -1068,7 +1068,7 @@ fbCombineFlashSubtractC (pixman_implementation_t *imp, pixman_op_t op,
 	comp4_t r, g, b;
 
 	d = *(dest + i);
-	s = combineMask (src, mask, i);
+	s = *(src + i);
 	m = *(mask + i);
 
 	fbCombineMaskValueC (&s, &m);
commit bf356c6d8cdbabf2faf4b6d77f94ccd3bd0459fb
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Wed Jun 17 16:59:45 2009 +0200

    Fix typo

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index 080c067..b17740e 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -1009,7 +1009,7 @@ BlendHSLLuminosity (comp4_t c[3], comp4_t dc[3], comp4_t da, comp4_t sc[3], comp
 
 PdfNonSeparableBlendMode (HSLLuminosity)
 
-#undef Set
+#undef Sat
 #undef Lum
 #undef Max
 #undef Min
commit cdae71ee85c74f702a8f0b999432e4d6d5caf766
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Wed Jun 17 10:46:44 2009 +0200

    [TEST] Update composite-test to test more operators

diff --git a/test/composite-test.c b/test/composite-test.c
index 393e15d..95dbe40 100644
--- a/test/composite-test.c
+++ b/test/composite-test.c
@@ -1,3 +1,4 @@
+#include <gtk/gtk.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include "pixman.h"
@@ -6,6 +7,45 @@
 #define WIDTH	100
 #define HEIGHT	100
 
+typedef struct {
+    const char *name;
+    pixman_op_t op;
+} Operator;
+
+static const Operator operators[] = {
+    { "PIXMAN_OP_CLEAR", PIXMAN_OP_CLEAR },
+    { "PIXMAN_OP_SRC", PIXMAN_OP_SRC },
+    { "PIXMAN_OP_DST", PIXMAN_OP_DST },
+    { "PIXMAN_OP_OVER", PIXMAN_OP_OVER },
+    { "PIXMAN_OP_OVER_REVERSE", PIXMAN_OP_OVER_REVERSE },
+    { "PIXMAN_OP_IN", PIXMAN_OP_IN },
+    { "PIXMAN_OP_IN_REVERSE", PIXMAN_OP_IN_REVERSE },
+    { "PIXMAN_OP_OUT", PIXMAN_OP_OUT },
+    { "PIXMAN_OP_OUT_REVERSE", PIXMAN_OP_OUT_REVERSE },
+    { "PIXMAN_OP_ATOP", PIXMAN_OP_ATOP },
+    { "PIXMAN_OP_ATOP_REVERSE", PIXMAN_OP_ATOP_REVERSE },
+    { "PIXMAN_OP_XOR", PIXMAN_OP_XOR },
+    { "PIXMAN_OP_ADD", PIXMAN_OP_ADD },
+    { "PIXMAN_OP_SATURATE", PIXMAN_OP_SATURATE },
+
+    { "PIXMAN_OP_MULTIPLY", PIXMAN_OP_MULTIPLY },
+    { "PIXMAN_OP_SCREEN", PIXMAN_OP_SCREEN },
+    { "PIXMAN_OP_OVERLAY", PIXMAN_OP_OVERLAY },
+    { "PIXMAN_OP_DARKEN", PIXMAN_OP_DARKEN },
+    { "PIXMAN_OP_LIGHTEN", PIXMAN_OP_LIGHTEN },
+    { "PIXMAN_OP_COLOR_DODGE", PIXMAN_OP_COLOR_DODGE },
+    { "PIXMAN_OP_COLOR_BURN", PIXMAN_OP_COLOR_BURN },
+    { "PIXMAN_OP_HARD_LIGHT", PIXMAN_OP_HARD_LIGHT },
+    { "PIXMAN_OP_SOFT_LIGHT", PIXMAN_OP_SOFT_LIGHT },
+    { "PIXMAN_OP_DIFFERENCE", PIXMAN_OP_DIFFERENCE },
+    { "PIXMAN_OP_EXCLUSION", PIXMAN_OP_EXCLUSION },
+    { "PIXMAN_OP_HSL_HUE", PIXMAN_OP_HSL_HUE },
+    { "PIXMAN_OP_HSL_SATURATION", PIXMAN_OP_HSL_SATURATION },
+    { "PIXMAN_OP_HSL_COLOR", PIXMAN_OP_HSL_COLOR },
+    { "PIXMAN_OP_HSL_LUMINOSITY", PIXMAN_OP_HSL_LUMINOSITY },
+    { "PIXMAN_OP_FLASH_SUBTRACT", PIXMAN_OP_FLASH_SUBTRACT }
+};
+
 static uint32_t
 reader (const void *src, int size)
 {
@@ -44,40 +84,85 @@ writer (void *src, uint32_t value, int size)
 int
 main (int argc, char **argv)
 {
-    uint32_t *src = malloc (WIDTH * HEIGHT * 4);
+    GtkWidget *window, *swindow;
+    GtkWidget *table;
     uint32_t *dest = malloc (WIDTH * HEIGHT * 4);
+    uint32_t *src = malloc (WIDTH * HEIGHT * 4);
     pixman_image_t *src_img;
     pixman_image_t *dest_img;
     int i;
 
-    for (i = 0; i < WIDTH * HEIGHT; ++i)
-	src[i] = 0x7f7f0000; /* red */
+    gtk_init (&argc, &argv);
+
+    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+    g_signal_connect (window, "delete-event",
+		      G_CALLBACK (gtk_main_quit),
+		      NULL);
+    table = gtk_table_new (G_N_ELEMENTS (operators) / 4, 4, TRUE);
 
     for (i = 0; i < WIDTH * HEIGHT; ++i)
-	dest[i] = 0x7f00007f; /* blue */
-    
+        src[i] = 0x7f7f0000; /* red */
+
     src_img = pixman_image_create_bits (PIXMAN_a8r8g8b8,
 					WIDTH, HEIGHT,
 					src,
 					WIDTH * 4);
+    pixman_image_set_accessors (src_img, reader, writer);
 
     dest_img = pixman_image_create_bits (PIXMAN_a8r8g8b8,
 					 WIDTH, HEIGHT,
 					 dest,
 					 WIDTH * 4);
-
-    pixman_image_set_accessors (src_img, reader, writer);
     pixman_image_set_accessors (dest_img, reader, writer);
-    
-    pixman_image_composite (PIXMAN_OP_OVER, src_img, NULL, dest_img,
-			    0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
 
-    show_image (dest_img);
-    
+    for (i = 0; i < G_N_ELEMENTS (operators); ++i) {
+        int j;
+	GtkWidget *image;
+	GdkPixbuf *pixbuf;
+	GtkWidget *vbox;
+	GtkWidget *label;
+
+	vbox = gtk_vbox_new (FALSE, 0);
+
+	label = gtk_label_new (operators[i].name);
+	gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 6);
+	gtk_widget_show (label);
+
+	for (j = 0; j < WIDTH * HEIGHT; ++j)
+	    dest[j] = 0x7f00007f; /* blue */
+
+	pixman_image_composite (operators[i].op, src_img, NULL, dest_img,
+				0, 0, 0, 0, 0, 0, WIDTH, HEIGHT);
+	pixbuf = pixbuf_from_argb32 (pixman_image_get_data (dest_img), TRUE,
+				     WIDTH, HEIGHT, WIDTH * 4);
+	image = gtk_image_new_from_pixbuf (pixbuf);
+	gtk_box_pack_start (GTK_BOX (vbox), image, FALSE, FALSE, 0);
+	gtk_widget_show (image);
+
+	gtk_table_attach_defaults (GTK_TABLE (table), vbox,
+				   i % 4, (i % 4) + 1, i / 4, (i / 4) + 1);
+	gtk_widget_show (vbox);
+
+	g_object_unref (pixbuf);
+    }
+
     pixman_image_unref (src_img);
-    pixman_image_unref (dest_img);
     free (src);
+    pixman_image_unref (dest_img);
     free (dest);
-    
+
+    swindow = gtk_scrolled_window_new (NULL, NULL);
+    gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (swindow),
+				    GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+    gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (swindow), table);
+    gtk_widget_show (table);
+
+    gtk_container_add (GTK_CONTAINER (window), swindow);
+    gtk_widget_show (swindow);
+
+    gtk_widget_show (window);
+
+    gtk_main ();
+
     return 0;
 }
commit c35685255f07a5a1f656d3153b5534876481b65b
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Sat Nov 29 15:12:45 2008 -0500

    Fix ColorDodge and ColorBurn to conform to the spec

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index 01bbc31..080c067 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -542,7 +542,7 @@ static inline comp4_t
 BlendColorDodge (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
 {
     if (sca >= sa) {
-	return dca == 0 ? 0 : DivOne (sa * da);
+	return DivOne (sa * da);
     } else {
 	comp4_t rca = dca * sa * sa / (sa - sca);
 	return DivOne (rca > sa * da ? sa * da : rca);
@@ -564,7 +564,7 @@ static inline comp4_t
 BlendColorBurn (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
 {
     if (sca == 0) {
-	return (da == dca) ? DivOne (sa * da) : 0;
+	return DivOne (sa * da);
     } else {
 	comp4_t sada = sa * da;
 	comp4_t rca = (da - dca) * sa * sa / sca;
commit 49a4fc09694d241f6b9f725a084c27eba3e31d00
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Sat Nov 29 15:11:07 2008 -0500

    Remove optimizations that I'm not convinced are correct

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index cbbcde7..01bbc31 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -391,23 +391,15 @@ fbCombineMultiplyC (pixman_implementation_t *imp, pixman_op_t op,
     for (i = 0; i < width; ++i) {
         comp4_t m = *(mask + i);
         comp4_t s = combineMask (src, mask, i);
+	comp4_t d = *(dest + i);
+	comp4_t r = d;
+	comp4_t dest_ia = Alpha (~d);
 
 	fbCombineMaskValueC (&s, &m);
 
-        if (m == 0)
-	    continue;
-
-	m = ~m;
-	if (m != 0)
-	{
-	    comp4_t d = *(dest + i);
-	    comp4_t r = d;
-	    comp4_t dest_ia = Alpha (~d);
-	    
-	    FbByteAddMulC (r, m, s, dest_ia);
-	    FbByteMulC (d, s);
-	    FbByteAdd (r, d);
-	}
+	FbByteAddMulC (r, ~m, s, dest_ia);
+	FbByteMulC (d, s);
+	FbByteAdd (r, d);
 
 	*(dest + i) = r;
     }
@@ -454,9 +446,6 @@ fbCombine ## name ## C (pixman_implementation_t *imp, pixman_op_t op, \
 						    \
 	fbCombineMaskValueC (&s, &m);		    \
 						    \
-        if (m == 0)				    \
-	    continue;				    \
-						    \
 	result = d;				    \
 	FbByteAddMulC (result, ~m, s, ida);	    \
 						    \
commit 3fb71f8b41dedd55982eccd16b8518cce10258fa
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Sat Nov 29 15:02:04 2008 -0500

    Fix some more problems in MultiplyC

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index f981392..cbbcde7 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -405,7 +405,8 @@ fbCombineMultiplyC (pixman_implementation_t *imp, pixman_op_t op,
 	    comp4_t dest_ia = Alpha (~d);
 	    
 	    FbByteAddMulC (r, m, s, dest_ia);
-	    FbByteMulAddC (r, s, d);
+	    FbByteMulC (d, s);
+	    FbByteAdd (r, d);
 	}
 
 	*(dest + i) = r;
commit 254e62159b4a8652c1dd9c47d0e5e0d0ff2ced3a
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Sat Nov 29 14:53:57 2008 -0500

    Fix various problems in FbCombineMultiplyC
    
    Don't read the destination unless we have to.  fbByteMulAddC()
    produces its result in its first argument, not its last.

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index ca3f351..f981392 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -391,20 +391,21 @@ fbCombineMultiplyC (pixman_implementation_t *imp, pixman_op_t op,
     for (i = 0; i < width; ++i) {
         comp4_t m = *(mask + i);
         comp4_t s = combineMask (src, mask, i);
-        comp4_t d = *(dest + i);
-	comp4_t r = d;
-	comp4_t dest_ia = Alpha (~d);
+
+	fbCombineMaskValueC (&s, &m);
 
         if (m == 0)
 	    continue;
 
-	fbCombineMaskValueC (&s, &m);
-
 	m = ~m;
 	if (m != 0)
 	{
+	    comp4_t d = *(dest + i);
+	    comp4_t r = d;
+	    comp4_t dest_ia = Alpha (~d);
+	    
 	    FbByteAddMulC (r, m, s, dest_ia);
-	    FbByteMulAddC (s, d, r);
+	    FbByteMulAddC (r, s, d);
 	}
 
 	*(dest + i) = r;
commit a158d7f14f4b987e9e6380ffe896dbcfd41799ec
Author: Søren Sandmann Pedersen <sandmann at redhat.com>
Date:   Wed Nov 26 13:52:00 2008 -0500

    Add some comments about the linearity of the non-separable blend modes

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index 5e86011..ca3f351 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -683,9 +683,7 @@ PdfSeparableBlendMode (Exclusion)
  * 
  * Lum (C) = 0.3 × Cred + 0.59 × Cgreen + 0.11 × Cblue
  *
- * SetLum (C, l):
- *   d = l – Lum (C)
- *   C += d
+ * ClipColor (C):
  *   l = Lum (C)
  *   min = Cmin
  *   max = Cmax
@@ -695,6 +693,11 @@ PdfSeparableBlendMode (Exclusion)
  *     C = l + ( ( ( C – l ) × ( 1 – l ) ) ⁄ ( max – l ) )
  *   return C
  *
+ * SetLum (C, l):
+ *   d = l – Lum (C)
+ *   C += d
+ *   return ClipColor (C)
+ *
  * Sat (C) = Max (C) - Min (C)
  *
  * SetSat (C, s):
@@ -707,6 +710,79 @@ PdfSeparableBlendMode (Exclusion)
  *  return C
  */
 
+/* For premultiplied colors, we need to know what happens when C is
+ * multiplied by a real number. Lum and Sat are linear:
+ *
+ *    Lum (r × C) = r × Lum (C)		Sat (r * C) = r * Sat (C)
+ *
+ * If we extend ClipColor with an extra argument a and change
+ *
+ *        if x >= 1.0
+ *
+ * into
+ *
+ *        if x >= a
+ *
+ * then ClipColor is also linear:
+ *
+ *    r * ClipColor (C, a) = ClipColor (rC, ra);
+ *
+ * for positive r.
+ *
+ * Similarly, we can extend SetLum with an extra argument that is just passed
+ * on to ClipColor:
+ *
+ *   r * SetLum ( C, l, a)
+ *
+ *   = r × ClipColor ( C + l - Lum (C), a)
+ *
+ *   = ClipColor ( r * C + r × l - r * Lum (C), r * a)
+ *
+ *   = SetLum ( r * C, r * l, r * a)
+ *
+ * Finally, SetSat:
+ *
+ *    r * SetSat (C, s) = SetSat (x * C, r * s)
+ *
+ * The above holds for all non-zero x, because they x'es in the fraction for
+ * C_mid cancel out. Specifically, it holds for x = r:
+ *
+ *    r * SetSat (C, s) = SetSat (rC, rs)
+ *  
+ */
+
+/* So, for the non-separable PDF blend modes, we have (using s, d for non-premultiplied
+ * colors, and S, D for premultiplied:
+ *
+ *   Color:
+ *
+ *     a_s * a_d * B(s, d)
+ *   = a_s * a_d * SetLum (S/a_s, Lum (D/a_d), 1)
+ *   = SetLum (S * a_d, a_s * Lum (D), a_s * a_d)
+ *
+ *
+ *   Luminosity:
+ *
+ *     a_s * a_d * B(s, d)
+ *   = a_s * a_d * SetLum (D/a_d, Lum(S/a_s), 1)
+ *   = SetLum (a_s * D, a_d * Lum(S), a_s * a_d)
+ *
+ *
+ *   Saturation:
+ *
+ *     a_s * a_d * B(s, d)
+ *   = a_s * a_d * SetLum (SetSat (D/a_d, Sat (S/a_s)), Lum (D/a_d), 1)
+ *   = SetLum (a_s * a_d * SetSat (D/a_d, Sat (S/a_s)), a_s * Lum (D), a_s * a_d)
+ *   = SetLum (SetSat (a_s * D, a_d * Sat (S), a_s * Lum (D), a_s * a_d))
+ *
+ *   Hue:
+ *
+ *     a_s * a_d * B(s, d)
+ *   = a_s * a_d * SetLum (SetSat (S/a_s, Sat (D/a_d)), Lum (D/a_d), 1)
+ *   = a_s * a_d * SetLum (SetSat (a_d * S, a_s * Sat (D)), a_s * Lum (D), a_s * a_d)
+ *
+ */
+    
 #define Min(c) (c[0] < c[1] ? (c[0] < c[2] ? c[0] : c[2]) : (c[1] < c[2] ? c[1] : c[2]))
 #define Max(c) (c[0] > c[1] ? (c[0] > c[2] ? c[0] : c[2]) : (c[1] > c[2] ? c[1] : c[2]))
 #define Lum(c) ((c[0] * 30 + c[1] * 59 + c[2] * 11) / 100)
commit cae5062d3bf16d32cf675ccb0030e29cc940b25e
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Nov 25 22:53:37 2008 +0100

    fix component-alpha versions to set source to 0 when mask is 0

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index 0e62744..5e86011 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -450,10 +450,11 @@ fbCombine ## name ## C (pixman_implementation_t *imp, pixman_op_t op, \
 	comp1_t ida = ~da;			    \
 	comp4_t result;				    \
 						    \
+	fbCombineMaskValueC (&s, &m);		    \
+						    \
         if (m == 0)				    \
 	    continue;				    \
 						    \
-	fbCombineMaskValueC (&s, &m);		    \
 	result = d;				    \
 	FbByteAddMulC (result, ~m, s, ida);	    \
 						    \
commit 9df72ebdb8280c7ca3b2696c3f7f48b69438502b
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Nov 25 22:50:54 2008 +0100

    remove debugging leftovers

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index 9aee4ab..0e62744 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -826,7 +826,6 @@ SetLum (comp4_t dest[3], comp4_t src[3], comp4_t sa, comp4_t lum)
     tmp[1] = l + (tmp[1] - l) / 4 * (a - l) / (max - l) * 4;
     tmp[2] = l + (tmp[2] - l) / 4 * (a - l) / (max - l) * 4;
   }
-  if (Max (tmp) > sa) while (1);
   dest[0] = tmp[0];
   dest[1] = tmp[1];
   dest[2] = tmp[2];
@@ -878,7 +877,6 @@ SetSat (comp4_t dest[3], comp4_t src[3], comp4_t sat)
   } else {
     dest[0] = dest[1] = dest[2] = 0;
   }
-  if (Max (dest) > 255 * 255) while (1);		    \
 }
 
 /*
commit 19aae37bfb8fb349258675dd96872c5ba65dcce1
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Nov 25 22:50:17 2008 +0100

    correct subtract implementation

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index 17e184c..9aee4ab 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -1005,8 +1005,7 @@ fbCombineFlashSubtractC (pixman_implementation_t *imp, pixman_op_t op,
 	s = combineMask (src, mask, i);
 	m = *(mask + i);
 
-	fbCombineMaskC (&s, &m);
-	m = ~m;
+	fbCombineMaskValueC (&s, &m);
 
 	Subtract (r, Red);
 	Subtract (g, Green);
commit f130d99c94edbf5aeebeb317df64dbd7a6d20efd
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Nov 23 18:36:32 2008 +0100

    fix Multiply component-alpha version

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index 80cf419..17e184c 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -392,26 +392,19 @@ fbCombineMultiplyC (pixman_implementation_t *imp, pixman_op_t op,
         comp4_t m = *(mask + i);
         comp4_t s = combineMask (src, mask, i);
         comp4_t d = *(dest + i);
-	comp4_t r = s;
-        comp4_t src_ia = Alpha (~s);
+	comp4_t r = d;
 	comp4_t dest_ia = Alpha (~d);
 
         if (m == 0)
 	    continue;
 
-	if (m == ~0)
+	fbCombineMaskValueC (&s, &m);
+
+	m = ~m;
+	if (m != 0)
 	{
-	    FbByteAddMul (r, dest_ia, d, src_ia);
-	    fbCombineMaskC (&s, &m);
-	    FbByteMul (s, dest_ia);
-	    fbCombineMaskValueC (&r, &m);
-	    r += s;
-	    m = ~m;
-	    FbByteMulAddC(d, m, r);
-	    d = r;
-	} else {
-	    r = s;
-	    fbCombineMaskValueC (&r, &m);
+	    FbByteAddMulC (r, m, s, dest_ia);
+	    FbByteMulAddC (s, d, r);
 	}
 
 	*(dest + i) = r;
@@ -1014,7 +1007,6 @@ fbCombineFlashSubtractC (pixman_implementation_t *imp, pixman_op_t op,
 
 	fbCombineMaskC (&s, &m);
 	m = ~m;
-	fbCombineMaskC (&d, &m);
 
 	Subtract (r, Red);
 	Subtract (g, Green);
commit 4bb1eac4e7c6c785da3c2b2b1836c83446befc80
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Nov 23 18:34:50 2008 +0100

    fix comment

diff --git a/pixman/pixman-combine.h.template b/pixman/pixman-combine.h.template
index 6828fea..9f64e85 100644
--- a/pixman/pixman-combine.h.template
+++ b/pixman/pixman-combine.h.template
@@ -135,7 +135,7 @@
     } while (0)
 
 /*
-  x_c = (x_c * a) / 255 + y
+  x_c = (x_c * a_c) / 255 + y
 */
 #define FbByteMulAddC(x, a, y) do {                                     \
         comp4_t t;                                                      \
commit 73810b320ec5eab5bcbd9137f012cf0e4bf6867f
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Nov 23 17:03:50 2008 +0100

    fix component-alpha versions for seperable blend modes

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index a8b00bf..80cf419 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -453,7 +453,6 @@ fbCombine ## name ## C (pixman_implementation_t *imp, pixman_op_t op, \
 	comp4_t m = *(mask + i);		    \
 	comp4_t s = combineMask (src, mask, i);	    \
 	comp4_t d = *(dest + i);		    \
-	comp1_t sa = Alpha(s);			    \
 	comp1_t da = Alpha(d);  		    \
 	comp1_t ida = ~da;			    \
 	comp4_t result;				    \
@@ -461,23 +460,15 @@ fbCombine ## name ## C (pixman_implementation_t *imp, pixman_op_t op, \
         if (m == 0)				    \
 	    continue;				    \
 						    \
-	if (m == ~0)	    			    \
-	{					    \
-	    result =				    \
-		(DivOne (sa * da) << A_SHIFT) +					\
-		(Blend ## name (Red (d), da, Red (s), sa) << R_SHIFT) +		\
-		(Blend ## name (Green (d), da, Green (s), sa) << G_SHIFT) +	\
-		(Blend ## name (Blue (d), da, Blue (s), sa));			\
-	    fbCombineMaskValueC (&result, &m);	    \
-	    fbCombineMaskC (&s, &m);		    \
-	    FbByteMul (s, ida);			    \
-	    m = ~m;				    \
-	    FbByteMulAddC(d, m, s);		    \
-	    result += d;			    \
-	} else {				    \
-	    result = s;				    \
-	    fbCombineMaskValueC (&result, &m);	    \
-	}					    \
+	fbCombineMaskValueC (&s, &m);		    \
+	result = d;				    \
+	FbByteAddMulC (result, ~m, s, ida);	    \
+						    \
+	result +=				    \
+	    (DivOne (Alpha (m) * da) << A_SHIFT) +				\
+	    (Blend ## name (Red (d), da, Red (s), Red (m)) << R_SHIFT) +	\
+	    (Blend ## name (Green (d), da, Green (s), Green (m)) << G_SHIFT) +	\
+	    (Blend ## name (Blue (d), da, Blue (s), Blue (m)));			\
 						    \
 	*(dest + i) = result;			    \
     }						    \
commit 4b921c1d910a5d78ca4784a6879789a5af6718d3
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Nov 23 16:23:22 2008 +0100

    rename operator SUBTRACT to FLASH_SUBTRACT
    
    Also document it and move it out of the PDF blend modes to make clear
    that it is not in any way related to PDF.

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index 78eac3d..a8b00bf 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -691,72 +691,6 @@ PdfSeparableBlendMode (Exclusion)
 
 #undef PdfSeparableBlendMode
 
-#define Subtract(res, Color)						\
-    do {								\
-      comp1_t dc, sc;							\
-      dc = Color (d);							\
-      sc = Color (s);							\
-      if (sc >= dc)							\
-	res = 0;							\
-      else								\
-	res = dc - sc;							\
-    } while (0)
-
-static void
-fbCombineSubtractU (pixman_implementation_t *imp, pixman_op_t op,
-		    comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
-{
-    int i;
-
-    for (i = 0; i < width; ++i) {
-	comp4_t d, s;
-	comp4_t r, g, b;
-
-	d = *(dest + i);
-	s = combineMask (src, mask, i);
-
-	Subtract (r, Red);
-	Subtract (g, Green);
-	Subtract (b, Blue);
-
-	*(dest + i) = (Alpha (d) << A_SHIFT)
-	    | (r << R_SHIFT)
-	    | (g << G_SHIFT)
-	    | b;
-    }
-}
-
-static void
-fbCombineSubtractC (pixman_implementation_t *imp, pixman_op_t op,
-		    comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
-{
-    int i;
-
-    for (i = 0; i < width; ++i) {
-	comp4_t d, s, m;
-	comp4_t r, g, b;
-
-	d = *(dest + i);
-	s = combineMask (src, mask, i);
-	m = *(mask + i);
-
-	fbCombineMaskC (&s, &m);
-	m = ~m;
-	fbCombineMaskC (&d, &m);
-
-	Subtract (r, Red);
-	Subtract (g, Green);
-	Subtract (b, Blue);
-
-	*(dest + i) = (Alpha (d) << A_SHIFT)
-	    | (r << R_SHIFT)
-	    | (g << G_SHIFT)
-	    | b;
-    }
-}
-
-#undef Subtract
-
 /*
  * PDF nonseperable blend modes are implemented using the following functions
  * to operate in HSL space, with Cmax, Cmid, Cmin referring to the max, mid 
@@ -794,7 +728,7 @@ fbCombineSubtractC (pixman_implementation_t *imp, pixman_op_t op,
 #define Sat(c) (Max (c) - Min (c))
 
 #define PdfNonSeparableBlendMode(name)		    \
-static FASTCALL void				    \
+static void				    \
 fbCombine ## name ## U (pixman_implementation_t *imp, pixman_op_t op, \
 			comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width) \
 {						    \
@@ -1031,6 +965,79 @@ PdfNonSeparableBlendMode (HSLLuminosity)
 #undef Min
 #undef PdfNonSeparableBlendMode
 
+/*
+ * Flash Subtract:
+ * This is the only blend mode present in Adobe Flash that is not part of 
+ * the PDF specification. It has been reverse engineered from looking at 
+ * Flash files. Some information can be found at
+ * http://www.kaourantin.net/2005/09/some-word-on-blend-modes-in-flash.html
+ */
+#define Subtract(res, Color)						\
+    do {								\
+      comp1_t dc, sc;							\
+      dc = Color (d);							\
+      sc = Color (s);							\
+      if (sc >= dc)							\
+	res = 0;							\
+      else								\
+	res = dc - sc;							\
+    } while (0)
+
+static void
+fbCombineFlashSubtractU (pixman_implementation_t *imp, pixman_op_t op,
+			 comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+{
+    int i;
+
+    for (i = 0; i < width; ++i) {
+	comp4_t d, s;
+	comp4_t r, g, b;
+
+	d = *(dest + i);
+	s = combineMask (src, mask, i);
+
+	Subtract (r, Red);
+	Subtract (g, Green);
+	Subtract (b, Blue);
+
+	*(dest + i) = (Alpha (d) << A_SHIFT)
+	    | (r << R_SHIFT)
+	    | (g << G_SHIFT)
+	    | b;
+    }
+}
+
+static void
+fbCombineFlashSubtractC (pixman_implementation_t *imp, pixman_op_t op,
+			 comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+{
+    int i;
+
+    for (i = 0; i < width; ++i) {
+	comp4_t d, s, m;
+	comp4_t r, g, b;
+
+	d = *(dest + i);
+	s = combineMask (src, mask, i);
+	m = *(mask + i);
+
+	fbCombineMaskC (&s, &m);
+	m = ~m;
+	fbCombineMaskC (&d, &m);
+
+	Subtract (r, Red);
+	Subtract (g, Green);
+	Subtract (b, Blue);
+
+	*(dest + i) = (Alpha (d) << A_SHIFT)
+	    | (r << R_SHIFT)
+	    | (g << G_SHIFT)
+	    | b;
+    }
+}
+
+#undef Subtract
+
 /* Overlay
  *
  * All of the disjoint composing functions
@@ -2012,11 +2019,11 @@ _pixman_setup_combiner_functions_width (pixman_implementation_t *imp)
     imp->combine_width[PIXMAN_OP_SOFT_LIGHT] = fbCombineSoftLightU;
     imp->combine_width[PIXMAN_OP_DIFFERENCE] = fbCombineDifferenceU;
     imp->combine_width[PIXMAN_OP_EXCLUSION] = fbCombineExclusionU;
-    imp->combine_width[PIXMAN_OP_SUBTRACT] = fbCombineSubtractU;
     imp->combine_width[PIXMAN_OP_HSL_HUE] = fbCombineHSLHueU;
     imp->combine_width[PIXMAN_OP_HSL_SATURATION] = fbCombineHSLSaturationU;
     imp->combine_width[PIXMAN_OP_HSL_COLOR] = fbCombineHSLColorU;
     imp->combine_width[PIXMAN_OP_HSL_LUMINOSITY] = fbCombineHSLLuminosityU;
+    imp->combine_width[PIXMAN_OP_FLASH_SUBTRACT] = fbCombineFlashSubtractU;
 
     /* Component alpha combiners */
     imp->combine_width_ca[PIXMAN_OP_CLEAR] = fbCombineClearC;
@@ -2073,11 +2080,11 @@ _pixman_setup_combiner_functions_width (pixman_implementation_t *imp)
     imp->combine_width_ca[PIXMAN_OP_SOFT_LIGHT] = fbCombineSoftLightC;
     imp->combine_width_ca[PIXMAN_OP_DIFFERENCE] = fbCombineDifferenceC;
     imp->combine_width_ca[PIXMAN_OP_EXCLUSION] = fbCombineExclusionC;
-    imp->combine_width_ca[PIXMAN_OP_SUBTRACT] = fbCombineSubtractC;
     imp->combine_width_ca[PIXMAN_OP_HSL_HUE] = fbCombineHSLHueC;
     imp->combine_width_ca[PIXMAN_OP_HSL_SATURATION] = fbCombineHSLSaturationC;
     imp->combine_width_ca[PIXMAN_OP_HSL_COLOR] = fbCombineHSLColorC;
     imp->combine_width_ca[PIXMAN_OP_HSL_LUMINOSITY] = fbCombineHSLLuminosityC;
+    imp->combine_width_ca[PIXMAN_OP_FLASH_SUBTRACT] = fbCombineFlashSubtractC;
 }
 
 
diff --git a/pixman/pixman.h b/pixman/pixman.h
index b9ecde0..93e3d11 100644
--- a/pixman/pixman.h
+++ b/pixman/pixman.h
@@ -379,11 +379,11 @@ typedef enum
     PIXMAN_OP_SOFT_LIGHT                = 0x38,
     PIXMAN_OP_DIFFERENCE                = 0x39,
     PIXMAN_OP_EXCLUSION                 = 0x3a,
-    PIXMAN_OP_SUBTRACT			= 0x3b,
-    PIXMAN_OP_HSL_HUE			= 0x3c,
-    PIXMAN_OP_HSL_SATURATION		= 0x3d,
-    PIXMAN_OP_HSL_COLOR			= 0x3e,
-    PIXMAN_OP_HSL_LUMINOSITY		= 0x3f,
+    PIXMAN_OP_HSL_HUE			= 0x3b,
+    PIXMAN_OP_HSL_SATURATION		= 0x3c,
+    PIXMAN_OP_HSL_COLOR			= 0x3d,
+    PIXMAN_OP_HSL_LUMINOSITY		= 0x3e,
+    PIXMAN_OP_FLASH_SUBTRACT	      	= 0x3f,
 
     PIXMAN_OP_NONE,
     PIXMAN_OP_LAST = PIXMAN_OP_NONE
commit 7cbfe3ba214006dda5fa6d21871ef6fc61067005
Author: Benjamin Otte <otte at gnome.org>
Date:   Sun Nov 23 15:42:53 2008 +0100

    rework blend-mode documentation to match current code better

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index 41e174c..78eac3d 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -336,12 +336,32 @@ fbCombineSaturateU (pixman_implementation_t *imp, pixman_op_t op,
     }
 }
 
-
-/* Multiply
+/* 
+ * PDF blend modes:
+ * The following blend modes have been taken from the PDF ISO 32000
+ * specification, which at this point in time is available from
+ * http://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf
+ * The relevant chapters are 11.3.5 and 11.3.6.
+ * The formula for computing the final pixel color given in 11.3.6 is:
+ * αr × Cr = (1 – αs) × αb × Cb + (1 – αb) × αs × Cs + αb × αs × B(Cb, Cs)
+ * with B() being the blend function.
+ * Note that OVER is a special case of this operation, using B(Cb, Cs) = Cs
+ *
+ * These blend modes should match the SVG filter draft specification, as 
+ * it has been designed to mirror ISO 32000. Note that at the current point
+ * no released draft exists that shows this, as the formulas have not been
+ * updated yet after the release of ISO 32000.
  *
- * Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
- * Da'  = Sa.Da + Sa.(1 - Da) + Da.(1 - Sa)
- *      = Sa + Da - Sa.Da 
+ * The default implementation here uses the PdfSeparableBlendMode and 
+ * PdfNonSeparableBlendMode macros, which take the blend function as an 
+ * argument. Note that this implementation operates on premultiplied colors,
+ * while the PDF specification does not. Therefore the code uses the formula
+ * ar.Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as)
+ */
+
+/* 
+ * Multiply
+ * B(Dca, ad, Sca, as) = Dca.Sca
  */
 
 static void
@@ -463,11 +483,9 @@ fbCombine ## name ## C (pixman_implementation_t *imp, pixman_op_t op, \
     }						    \
 }
 
-/* Screen
- *
- * Dca' = (Sca.Da + Dca.Sa - Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
- *      = Sca + Dca - Sca.Dca
- * Da'  = Sa + Da - Sa.Da 
+/*
+ * Screen
+ * B(Dca, ad, Sca, as) = Dca.sa + Sca.da - Dca.Sca
  */
 
 static inline comp4_t
@@ -478,13 +496,13 @@ BlendScreen (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
 
 PdfSeparableBlendMode (Screen)
 
-/* Overlay
- *
- * if 2.Dca < Da
- *     Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
+/*
+ * Overlay
+ * B(Dca, ab, Sca, as) = 
+ *   if 2.Dca < Da
+ *     2.Sca.Dca
  *   otherwise
- *     Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa)
- * Da' = Sa + Da - Sa.Da
+ *     Sa.Da - 2.(Da - Dca).(Sa - Sca)
  */
 
 static inline comp4_t
@@ -501,10 +519,9 @@ BlendOverlay (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
 
 PdfSeparableBlendMode (Overlay)
 
-/* Darken
- *
- * Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
- * Da'  = Sa + Da - Sa.Da 
+/*
+ * Darken
+ * B(Dca, ab, Sca, as) = min (Sca.Da, Dca.Sa)
  */
 
 static inline comp4_t
@@ -519,10 +536,9 @@ BlendDarken (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
 
 PdfSeparableBlendMode (Darken)
 
-/* Lighten
- *
- * Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
- * Da'  = Sa + Da - Sa.Da
+/*
+ * Lighten
+ * B(Dca, ab, Sca, as) = max (Sca.Da, Dca.Sa)
  */
 
 static inline comp4_t
@@ -537,14 +553,13 @@ BlendLighten (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
 
 PdfSeparableBlendMode (Lighten)
 
-/* Color dodge
- *
- * if Sca == Sa
- *   Dca' = (Dca != 0).Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa)
- * otherwise
- *   Dca' = Da.Sa. min (Dca / Da / (1 - Sca/Sa))
- *
- * Da'  = Sa + Da - Sa.Da
+/*
+ * Color dodge
+ * B(Dca, ab, Sca, as) = 
+ *   if Sca == Sa
+ *     (Dca != 0).Sa.Da
+ *   otherwise
+ *     Da.Sa. min (Dca / Da / (1 - Sca/Sa))
  */ 
 
 static inline comp4_t
@@ -560,38 +575,36 @@ BlendColorDodge (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
 
 PdfSeparableBlendMode (ColorDodge)
 
-/* Color burn
- *
- * if Sca. == 0
- *   Dca' = (Da == Dca).SaDa + Sca.(1 - Da) + Dca.(1 - Sa)
- * otherwise
- *   Dca' = Sa.Da.(1 - min (1, (1 - Dca/Da).Sa / Sca)) + Sca.(1 - Da) + Dca.(1 - Sa)
- *
- * Da' = Sa + Da - Sa.Da
+/*
+ * Color burn
+ * B(Dca, ab, Sca, as) = 
+ *   if Sca. == 0
+ *     (Da == Dca).SaDa
+ *   otherwise
+ *     Sa.Da.(1 - min (1, (1 - Dca/Da).Sa / Sca))
  */
 
 static inline comp4_t
 BlendColorBurn (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
 {
     if (sca == 0) {
-      return (da == dca) ? DivOne (sa * da) : 0;
+	return (da == dca) ? DivOne (sa * da) : 0;
     } else {
-      comp4_t sada = sa * da;
-      comp4_t rca = (da - dca) * sa * sa / sca;
-      return DivOne (rca > sada ? 0 : sada - rca);
+	comp4_t sada = sa * da;
+	comp4_t rca = (da - dca) * sa * sa / sca;
+	return DivOne (rca > sada ? 0 : sada - rca);
     }
 }
 
 PdfSeparableBlendMode (ColorBurn)
 
-/* Hard light
- *
- * if 2.Sca < Sa
- *   Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
- * otherwise
- *   Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa)
- *
- * Da'  = Sa + Da - Sa.Da
+/*
+ * Hard light
+ * B(Dca, ab, Sca, as) = 
+ *   if 2.Sca < Sa
+ *     2.Sca.Dca
+ *   otherwise
+ *     Sa.Da - 2.(Da - Dca).(Sa - Sca)
  */
 static inline comp4_t
 BlendHardLight (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
@@ -604,38 +617,15 @@ BlendHardLight (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
 
 PdfSeparableBlendMode (HardLight)
 
-/* Soft light
- *
- * original definition (taken from PDF spec):
- * 
- * if (Sc <= 0.5)
- *   Dc' = Dc - ( 1 - 2 . Sc ) . Dc . ( 1 - Dc )
- * else
- *   Dc' = Dc + ( 2 . Sc - 1 ) . ( F(Dc) - Dc )
- *
- * with
- * if (x < 0.25)
- *   F(x) = ( ( 16 . x - 12 ) . x + 4 ) . x
- * else
- *   F(x) = SQRT (x)
- *
- * ==>
- *
- * if (Sc <= 0.5)
- *   Dc' = Dc - ( 1 - 2 . Sc ) . Dc . ( 1 - Dc )
- * otherwise if (Dc < 0.25)
- *   Dc' = Dc + ( 2 . Sc - 1 ) . ( ((16 . Dc - 12) . Dc + 4) - Dc )
- * otherwise
- *   Dc' = Dc + ( 2 . Sc - 1 ) . ( SQRT(Dc) - Dc )
- *
- * ==> 
- *
- * if (2.Sca <= Sa)
- *   Dca' = Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) 
- * otherwise if Dca.4 <= Da
- *   Dca' = Dca.(Sa + (2.Sca - Sa).((16.Dca/Da - 12).Dca/Da + 3) + Sc.(1 - Da) + Dca.(1 - Sa)
- * otherwise
- *   Dca' = (Dca.Sa + (SQRT (Dca/Da).Da - Dca).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa)
+/*
+ * Soft light
+ * B(Dca, ab, Sca, as) = 
+ *   if (2.Sca <= Sa)
+ *     Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa))
+ *   otherwise if Dca.4 <= Da
+ *     Dca.(Sa + (2.Sca - Sa).((16.Dca/Da - 12).Dca/Da + 3)
+ *   otherwise
+ *     (Dca.Sa + (SQRT (Dca/Da).Da - Dca).(2.Sca - Sa))
  */
 
 static inline comp4_t
@@ -664,12 +654,9 @@ BlendSoftLight (comp4_t dca_org, comp4_t da_org, comp4_t sca_org, comp4_t sa_org
 
 PdfSeparableBlendMode (SoftLight)
 
-/* Difference
- *
- * Dca' = abs(Dca.Sa - Sca.Da) + Sca.(1 - Da) + Dca.(1 - Sa)
- *	= Sca + Dca - 2.min(Sca.Da, Dca.Sa)
- *
- * Da'  = Sa + Da - Sa.Da
+/*
+ * Difference
+ * B(Dca, ab, Sca, as) = abs (Dca.Sa - Sca.Da)
  */
 
 static inline comp4_t
@@ -686,11 +673,9 @@ BlendDifference (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
 
 PdfSeparableBlendMode (Difference)
 
-/* Exclusion
- *
- * Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
- *
- * Da'  = Sa + Da - Sa.Da
+/*
+ * Exclusion
+ * B(Dca, ab, Sca, as) = (Sca.Da + Dca.Sa - 2.Sca.Dca)
  */
 
 /* This can be made faster by writing it directly and not using
@@ -772,6 +757,37 @@ fbCombineSubtractC (pixman_implementation_t *imp, pixman_op_t op,
 
 #undef Subtract
 
+/*
+ * PDF nonseperable blend modes are implemented using the following functions
+ * to operate in HSL space, with Cmax, Cmid, Cmin referring to the max, mid 
+ * and min value of the red, green and blue components.
+ * 
+ * Lum (C) = 0.3 × Cred + 0.59 × Cgreen + 0.11 × Cblue
+ *
+ * SetLum (C, l):
+ *   d = l – Lum (C)
+ *   C += d
+ *   l = Lum (C)
+ *   min = Cmin
+ *   max = Cmax
+ *   if n < 0.0
+ *     C = l + ( ( ( C – l ) × l ) ⁄ ( l – min ) )
+ *   if x > 1.0
+ *     C = l + ( ( ( C – l ) × ( 1 – l ) ) ⁄ ( max – l ) )
+ *   return C
+ *
+ * Sat (C) = Max (C) - Min (C)
+ *
+ * SetSat (C, s):
+ *  if Cmax > Cmin
+ *    Cmid = ( ( ( Cmid – Cmin ) × s ) ⁄ ( Cmax – Cmin ) )
+ *    Cmax = s
+ *  else
+ *    Cmid = Cmax = 0.0
+ *  Cmin = 0.0
+ *  return C
+ */
+
 #define Min(c) (c[0] < c[1] ? (c[0] < c[2] ? c[0] : c[2]) : (c[1] < c[2] ? c[1] : c[2]))
 #define Max(c) (c[0] > c[1] ? (c[0] > c[2] ? c[0] : c[2]) : (c[1] > c[2] ? c[1] : c[2]))
 #define Lum(c) ((c[0] * 30 + c[1] * 59 + c[2] * 11) / 100)
@@ -947,6 +963,10 @@ SetSat (comp4_t dest[3], comp4_t src[3], comp4_t sat)
   if (Max (dest) > 255 * 255) while (1);		    \
 }
 
+/*
+ * Hue:
+ * B(Cb, Cs) = SetLum (SetSat (Cs, Sat (Cb)), Lum (Cb))
+ */
 static inline void
 BlendHSLHue (comp4_t c[3], comp4_t dc[3], comp4_t da, comp4_t sc[3], comp4_t sa)
 {
@@ -959,6 +979,10 @@ BlendHSLHue (comp4_t c[3], comp4_t dc[3], comp4_t da, comp4_t sc[3], comp4_t sa)
 
 PdfNonSeparableBlendMode (HSLHue)
 
+/*
+ * Saturation:
+ * B(Cb, Cs) = SetLum (SetSat (Cb, Sat (Cs)), Lum (Cb))
+ */
 static inline void
 BlendHSLSaturation (comp4_t c[3], comp4_t dc[3], comp4_t da, comp4_t sc[3], comp4_t sa)
 {
@@ -971,6 +995,10 @@ BlendHSLSaturation (comp4_t c[3], comp4_t dc[3], comp4_t da, comp4_t sc[3], comp
 
 PdfNonSeparableBlendMode (HSLSaturation)
 
+/*
+ * Color:
+ * B(Cb, Cs) = SetLum (Cs, Lum (Cb))
+ */
 static inline void
 BlendHSLColor (comp4_t c[3], comp4_t dc[3], comp4_t da, comp4_t sc[3], comp4_t sa)
 {
@@ -982,6 +1010,10 @@ BlendHSLColor (comp4_t c[3], comp4_t dc[3], comp4_t da, comp4_t sc[3], comp4_t s
 
 PdfNonSeparableBlendMode (HSLColor)
 
+/*
+ * Luminosity:
+ * B(Cb, Cs) = SetLum (Cb, Lum (Cs))
+ */
 static inline void
 BlendHSLLuminosity (comp4_t c[3], comp4_t dc[3], comp4_t da, comp4_t sc[3], comp4_t sa)
 {
commit f26c9ec438c97515ae874711859e012971ea920a
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Nov 19 21:07:13 2008 +0100

    typo fix: Seperable => Separable

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index 05ef9bf..41e174c 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -398,8 +398,8 @@ fbCombineMultiplyC (pixman_implementation_t *imp, pixman_op_t op,
     }
 }
 
-#define PdfSeperableBlendMode(name)		    \
-static void				    \
+#define PdfSeparableBlendMode(name)		    \
+static void					    \
 fbCombine ## name ## U (pixman_implementation_t *imp, pixman_op_t op, \
                         comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width) \
 {						    \
@@ -476,7 +476,7 @@ BlendScreen (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
   return DivOne (sca * da + dca * sa - sca * dca);
 }
 
-PdfSeperableBlendMode (Screen)
+PdfSeparableBlendMode (Screen)
 
 /* Overlay
  *
@@ -499,7 +499,7 @@ BlendOverlay (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
     return DivOne (rca);
 }
 
-PdfSeperableBlendMode (Overlay)
+PdfSeparableBlendMode (Overlay)
 
 /* Darken
  *
@@ -517,7 +517,7 @@ BlendDarken (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
     return DivOne (s > d ? d : s);
 }
 
-PdfSeperableBlendMode (Darken)
+PdfSeparableBlendMode (Darken)
 
 /* Lighten
  *
@@ -535,7 +535,7 @@ BlendLighten (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
     return DivOne (s > d ? s : d);
 }
 
-PdfSeperableBlendMode (Lighten)
+PdfSeparableBlendMode (Lighten)
 
 /* Color dodge
  *
@@ -558,7 +558,7 @@ BlendColorDodge (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
     }
 }
 
-PdfSeperableBlendMode (ColorDodge)
+PdfSeparableBlendMode (ColorDodge)
 
 /* Color burn
  *
@@ -582,7 +582,7 @@ BlendColorBurn (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
     }
 }
 
-PdfSeperableBlendMode (ColorBurn)
+PdfSeparableBlendMode (ColorBurn)
 
 /* Hard light
  *
@@ -602,7 +602,7 @@ BlendHardLight (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
 	return DivOne (sa * da - 2 * (da - dca) * (sa - sca));
 }
 
-PdfSeperableBlendMode (HardLight)
+PdfSeparableBlendMode (HardLight)
 
 /* Soft light
  *
@@ -662,7 +662,7 @@ BlendSoftLight (comp4_t dca_org, comp4_t da_org, comp4_t sca_org, comp4_t sa_org
     return rca * MASK + 0.5;
 }
 
-PdfSeperableBlendMode (SoftLight)
+PdfSeparableBlendMode (SoftLight)
 
 /* Difference
  *
@@ -684,7 +684,7 @@ BlendDifference (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
 	return DivOne (scada - dcasa);
 }
 
-PdfSeperableBlendMode (Difference)
+PdfSeparableBlendMode (Difference)
 
 /* Exclusion
  *
@@ -694,7 +694,7 @@ PdfSeperableBlendMode (Difference)
  */
 
 /* This can be made faster by writing it directly and not using
- * PdfSeperableBlendMode, but that's a performance optimization */
+ * PdfSeparableBlendMode, but that's a performance optimization */
 
 static inline comp4_t
 BlendExclusion (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
@@ -702,9 +702,9 @@ BlendExclusion (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
     return DivOne (sca * da + dca * sa - 2 * dca * sca);
 }
 
-PdfSeperableBlendMode (Exclusion)
+PdfSeparableBlendMode (Exclusion)
 
-#undef PdfSeperableBlendMode
+#undef PdfSeparableBlendMode
 
 #define Subtract(res, Color)						\
     do {								\
@@ -777,8 +777,8 @@ fbCombineSubtractC (pixman_implementation_t *imp, pixman_op_t op,
 #define Lum(c) ((c[0] * 30 + c[1] * 59 + c[2] * 11) / 100)
 #define Sat(c) (Max (c) - Min (c))
 
-#define PdfNonSeperableBlendMode(name)		    \
-static void				    \
+#define PdfNonSeparableBlendMode(name)		    \
+static FASTCALL void				    \
 fbCombine ## name ## U (pixman_implementation_t *imp, pixman_op_t op, \
 			comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width) \
 {						    \
@@ -957,7 +957,7 @@ BlendHSLHue (comp4_t c[3], comp4_t dc[3], comp4_t da, comp4_t sc[3], comp4_t sa)
     SetLum (c, c, sa * da, Lum (dc) * sa);
 }
 
-PdfNonSeperableBlendMode (HSLHue)
+PdfNonSeparableBlendMode (HSLHue)
 
 static inline void
 BlendHSLSaturation (comp4_t c[3], comp4_t dc[3], comp4_t da, comp4_t sc[3], comp4_t sa)
@@ -969,7 +969,7 @@ BlendHSLSaturation (comp4_t c[3], comp4_t dc[3], comp4_t da, comp4_t sc[3], comp
     SetLum (c, c, sa * da, Lum (dc) * sa);
 }
 
-PdfNonSeperableBlendMode (HSLSaturation)
+PdfNonSeparableBlendMode (HSLSaturation)
 
 static inline void
 BlendHSLColor (comp4_t c[3], comp4_t dc[3], comp4_t da, comp4_t sc[3], comp4_t sa)
@@ -980,7 +980,7 @@ BlendHSLColor (comp4_t c[3], comp4_t dc[3], comp4_t da, comp4_t sc[3], comp4_t s
     SetLum (c, c, sa * da, Lum (dc) * sa);
 }
 
-PdfNonSeperableBlendMode (HSLColor)
+PdfNonSeparableBlendMode (HSLColor)
 
 static inline void
 BlendHSLLuminosity (comp4_t c[3], comp4_t dc[3], comp4_t da, comp4_t sc[3], comp4_t sa)
@@ -991,13 +991,13 @@ BlendHSLLuminosity (comp4_t c[3], comp4_t dc[3], comp4_t da, comp4_t sc[3], comp
     SetLum (c, c, sa * da, Lum (sc) * da);
 }
 
-PdfNonSeperableBlendMode (HSLLuminosity)
+PdfNonSeparableBlendMode (HSLLuminosity)
 
 #undef Set
 #undef Lum
 #undef Max
 #undef Min
-#undef PdfNonSeperableBlendMode
+#undef PdfNonSeparableBlendMode
 
 /* Overlay
  *
commit ea17e2e2e43e578b3799fe9a6f7533569aed880c
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Nov 19 21:06:06 2008 +0100

    remove semicolon at end of macro

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index c52b5e8..05ef9bf 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -715,7 +715,7 @@ PdfSeperableBlendMode (Exclusion)
 	res = 0;							\
       else								\
 	res = dc - sc;							\
-    } while (0);
+    } while (0)
 
 static void
 fbCombineSubtractU (pixman_implementation_t *imp, pixman_op_t op,
commit ecf9f83ac64236b0834d268e6235306ab84fb749
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Nov 19 21:05:16 2008 +0100

    remove a leftover debugging statement
    
    That was an assertion check by infinite loop

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index cca9f9e..c52b5e8 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -496,7 +496,6 @@ BlendOverlay (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
 	rca = 2 * sca * dca;
     else
 	rca = sa * da - 2 * (da - dca) * (sa - sca);
-    while (rca > (sa * da));
     return DivOne (rca);
 }
 
commit c061b4dd16af52383afae470e845bd43a552d925
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Nov 13 17:40:10 2008 +0100

    invent a Subtract operator for component alpha
    
    This seems to make sense, and as I can't test it against Adobe's Flash
    player as that one can't do component alpha, this one looks best.

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index fc5429d..cca9f9e 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -707,12 +707,6 @@ PdfSeperableBlendMode (Exclusion)
 
 #undef PdfSeperableBlendMode
 
-static void
-fbCombineSubtractU (pixman_implementation_t *imp, pixman_op_t op,
-		    comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
-{
-    int i;
-
 #define Subtract(res, Color)						\
     do {								\
       comp1_t dc, sc;							\
@@ -724,6 +718,12 @@ fbCombineSubtractU (pixman_implementation_t *imp, pixman_op_t op,
 	res = dc - sc;							\
     } while (0);
 
+static void
+fbCombineSubtractU (pixman_implementation_t *imp, pixman_op_t op,
+		    comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+{
+    int i;
+
     for (i = 0; i < width; ++i) {
 	comp4_t d, s;
 	comp4_t r, g, b;
@@ -740,10 +740,39 @@ fbCombineSubtractU (pixman_implementation_t *imp, pixman_op_t op,
 	    | (g << G_SHIFT)
 	    | b;
     }
+}
 
-#undef Subtract
+static void
+fbCombineSubtractC (pixman_implementation_t *imp, pixman_op_t op,
+		    comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+{
+    int i;
+
+    for (i = 0; i < width; ++i) {
+	comp4_t d, s, m;
+	comp4_t r, g, b;
+
+	d = *(dest + i);
+	s = combineMask (src, mask, i);
+	m = *(mask + i);
+
+	fbCombineMaskC (&s, &m);
+	m = ~m;
+	fbCombineMaskC (&d, &m);
+
+	Subtract (r, Red);
+	Subtract (g, Green);
+	Subtract (b, Blue);
+
+	*(dest + i) = (Alpha (d) << A_SHIFT)
+	    | (r << R_SHIFT)
+	    | (g << G_SHIFT)
+	    | b;
+    }
 }
 
+#undef Subtract
+
 #define Min(c) (c[0] < c[1] ? (c[0] < c[2] ? c[0] : c[2]) : (c[1] < c[2] ? c[1] : c[2]))
 #define Max(c) (c[0] > c[1] ? (c[0] > c[2] ? c[0] : c[2]) : (c[1] > c[2] ? c[1] : c[2]))
 #define Lum(c) ((c[0] * 30 + c[1] * 59 + c[2] * 11) / 100)
@@ -783,7 +812,7 @@ fbCombine ## name ## U (pixman_implementation_t *imp, pixman_op_t op, \
     }						    \
 }						    \
 						    \
-static FASTCALL void				    \
+static void				    \
 fbCombine ## name ## C (pixman_implementation_t *imp, pixman_op_t op, \
 			comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width) \
 {						    \
@@ -2013,6 +2042,7 @@ _pixman_setup_combiner_functions_width (pixman_implementation_t *imp)
     imp->combine_width_ca[PIXMAN_OP_SOFT_LIGHT] = fbCombineSoftLightC;
     imp->combine_width_ca[PIXMAN_OP_DIFFERENCE] = fbCombineDifferenceC;
     imp->combine_width_ca[PIXMAN_OP_EXCLUSION] = fbCombineExclusionC;
+    imp->combine_width_ca[PIXMAN_OP_SUBTRACT] = fbCombineSubtractC;
     imp->combine_width_ca[PIXMAN_OP_HSL_HUE] = fbCombineHSLHueC;
     imp->combine_width_ca[PIXMAN_OP_HSL_SATURATION] = fbCombineHSLSaturationC;
     imp->combine_width_ca[PIXMAN_OP_HSL_COLOR] = fbCombineHSLColorC;
commit 93e32235e6a72bfea14d36a0407fbbe6482e20d9
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Nov 13 17:34:19 2008 +0100

    add non-seperable versions for component alpha

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index 7711c18..fc5429d 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -781,8 +781,58 @@ fbCombine ## name ## U (pixman_implementation_t *imp, pixman_op_t op, \
 	    (DivOne (c[1]) << G_SHIFT) +	    \
 	    (DivOne (c[2]));			    \
     }						    \
+}						    \
+						    \
+static FASTCALL void				    \
+fbCombine ## name ## C (pixman_implementation_t *imp, pixman_op_t op, \
+			comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width) \
+{						    \
+    int i;					    \
+    for (i = 0; i < width; ++i) {		    \
+	comp4_t m = *(mask + i);		    \
+	comp4_t s = combineMask (src, mask, i);	    \
+	comp4_t d = *(dest + i);		    \
+	comp1_t sa = Alpha(s);			    \
+	comp1_t da = Alpha(d);  		    \
+	comp1_t ida = ~da;			    \
+	comp4_t result;				    \
+						    \
+        if (m == 0)				    \
+	    continue;				    \
+						    \
+	if (m == ~0)	    			    \
+	{					    \
+	    comp4_t sc[3], dc[3], c[3];		    \
+						    \
+	    result = d;				    \
+	    dc[0] = Red (d);			    \
+	    sc[0] = Red (s);			    \
+	    dc[1] = Green (d);			    \
+	    sc[1] = Green (s);			    \
+	    dc[2] = Blue (d);			    \
+	    sc[2] = Blue (s);			    \
+	    Blend ## name (c, dc, da, sc, sa);	    \
+	    result =				    \
+		(DivOne (sa * da) << A_SHIFT) +	    \
+		(DivOne (c[0]) << R_SHIFT) +	    \
+		(DivOne (c[1]) << G_SHIFT) +	    \
+		(DivOne (c[2]));		    \
+	    fbCombineMaskValueC (&result, &m);	    \
+	    fbCombineMaskC (&s, &m);		    \
+	    FbByteMul (s, ida);			    \
+	    m = ~m;				    \
+	    FbByteMulAddC(d, m, s);		    \
+	    result += d;			    \
+	} else {				    \
+	    result = s;				    \
+	    fbCombineMaskValueC (&result, &m);	    \
+	}					    \
+						    \
+	*(dest + i) = result;			    \
+    }						    \
 }
 
+
 static void
 SetLum (comp4_t dest[3], comp4_t src[3], comp4_t sa, comp4_t lum)
 {
@@ -1963,6 +2013,10 @@ _pixman_setup_combiner_functions_width (pixman_implementation_t *imp)
     imp->combine_width_ca[PIXMAN_OP_SOFT_LIGHT] = fbCombineSoftLightC;
     imp->combine_width_ca[PIXMAN_OP_DIFFERENCE] = fbCombineDifferenceC;
     imp->combine_width_ca[PIXMAN_OP_EXCLUSION] = fbCombineExclusionC;
+    imp->combine_width_ca[PIXMAN_OP_HSL_HUE] = fbCombineHSLHueC;
+    imp->combine_width_ca[PIXMAN_OP_HSL_SATURATION] = fbCombineHSLSaturationC;
+    imp->combine_width_ca[PIXMAN_OP_HSL_COLOR] = fbCombineHSLColorC;
+    imp->combine_width_ca[PIXMAN_OP_HSL_LUMINOSITY] = fbCombineHSLLuminosityC;
 }
 
 
commit 239cc46aa77b4be71d738c0136a5465796a29886
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Nov 13 17:29:00 2008 +0100

    add component-alpha versions of the seperable blend-modes

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index 980ca1c..7711c18 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -13,6 +13,86 @@
 #define Green(x) (((x) >> G_SHIFT) & MASK)
 #define Blue(x) ((x) & MASK)
 
+/*** per channel helper functions ***/
+
+static void
+fbCombineMaskC (comp4_t *src, comp4_t *mask)
+{
+    comp4_t a = *mask;
+
+    comp4_t	x;
+    comp2_t	xa;
+
+    if (!a)
+    {
+	*(src) = 0;
+	return;
+    }
+
+    x = *(src);
+    if (a == ~0)
+    {
+	x = x >> A_SHIFT;
+	x |= x << G_SHIFT;
+	x |= x << R_SHIFT;
+	*(mask) = x;
+	return;
+    }
+
+    xa = x >> A_SHIFT;
+    FbByteMulC(x, a);
+    *(src) = x;
+    FbByteMul(a, xa);
+    *(mask) = a;
+}
+
+static void
+fbCombineMaskValueC (comp4_t *src, const comp4_t *mask)
+{
+    comp4_t a = *mask;
+    comp4_t	x;
+
+    if (!a)
+    {
+	*(src) = 0;
+	return;
+    }
+
+    if (a == ~0)
+	return;
+
+    x = *(src);
+    FbByteMulC(x, a);
+    *(src) =x;
+}
+
+static void
+fbCombineMaskAlphaC (const comp4_t *src, comp4_t *mask)
+{
+    comp4_t a = *(mask);
+    comp4_t	x;
+
+    if (!a)
+	return;
+
+    x = *(src) >> A_SHIFT;
+    if (x == MASK)
+	return;
+    if (a == ~0)
+    {
+	x = x >> A_SHIFT;
+	x |= x << G_SHIFT;
+	x |= x << R_SHIFT;
+	*(mask) = x;
+	return;
+    }
+
+    FbByteMul(a, x);
+    *(mask) = a;
+}
+
+
+
 /*
  * There are two ways of handling alpha -- either as a single unified value or
  * a separate value for each component, hence each macro must have two
@@ -283,38 +363,43 @@ fbCombineMultiplyU (pixman_implementation_t *imp, pixman_op_t op,
     }
 }
 
-/* Screen
- *
- * Dca' = (Sca.Da + Dca.Sa - Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
- *      = Sca + Dca - Sca.Dca
- * Da'  = Sa + Da - Sa.Da 
- */
-
 static void
-fbCombineScreenU (pixman_implementation_t *imp, pixman_op_t op,
-		  comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+fbCombineMultiplyC (pixman_implementation_t *imp, pixman_op_t op,
+                    comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
 {
     int i;
     for (i = 0; i < width; ++i) {
+        comp4_t m = *(mask + i);
         comp4_t s = combineMask (src, mask, i);
         comp4_t d = *(dest + i);
-	comp4_t p = s;
-	comp4_t a, r, g, b;
+	comp4_t r = s;
+        comp4_t src_ia = Alpha (~s);
+	comp4_t dest_ia = Alpha (~d);
 
-	FbByteMulC (p, d);
+        if (m == 0)
+	    continue;
 
-	a = Alpha (s)	+ Alpha (d) - Alpha (p);
-	r = Red(s)	+ Red (d)   - Red (p);
-	g = Green (s)	+ Green (d) - Green (p);
-	b = Blue (s)	+ Blue (d)  - Blue (p);
+	if (m == ~0)
+	{
+	    FbByteAddMul (r, dest_ia, d, src_ia);
+	    fbCombineMaskC (&s, &m);
+	    FbByteMul (s, dest_ia);
+	    fbCombineMaskValueC (&r, &m);
+	    r += s;
+	    m = ~m;
+	    FbByteMulAddC(d, m, r);
+	    d = r;
+	} else {
+	    r = s;
+	    fbCombineMaskValueC (&r, &m);
+	}
 
-	/* no clamping required, values don't overflow */
-	*(dest + i) = (a << A_SHIFT) | (r << R_SHIFT) | (g << G_SHIFT) | b;
+	*(dest + i) = r;
     }
 }
 
-#define PdfSeperableBlendMode(name)				      \
-static void							      \
+#define PdfSeperableBlendMode(name)		    \
+static void				    \
 fbCombine ## name ## U (pixman_implementation_t *imp, pixman_op_t op, \
                         comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width) \
 {						    \
@@ -337,8 +422,62 @@ fbCombine ## name ## U (pixman_implementation_t *imp, pixman_op_t op, \
 	    (Blend ## name (Green (d), da, Green (s), sa) << G_SHIFT) + \
 	    (Blend ## name (Blue (d), da, Blue (s), sa)); \
     }						    \
+}						    \
+						    \
+static void				    \
+fbCombine ## name ## C (pixman_implementation_t *imp, pixman_op_t op, \
+			comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width) \
+{						    \
+    int i;					    \
+    for (i = 0; i < width; ++i) {		    \
+	comp4_t m = *(mask + i);		    \
+	comp4_t s = combineMask (src, mask, i);	    \
+	comp4_t d = *(dest + i);		    \
+	comp1_t sa = Alpha(s);			    \
+	comp1_t da = Alpha(d);  		    \
+	comp1_t ida = ~da;			    \
+	comp4_t result;				    \
+						    \
+        if (m == 0)				    \
+	    continue;				    \
+						    \
+	if (m == ~0)	    			    \
+	{					    \
+	    result =				    \
+		(DivOne (sa * da) << A_SHIFT) +					\
+		(Blend ## name (Red (d), da, Red (s), sa) << R_SHIFT) +		\
+		(Blend ## name (Green (d), da, Green (s), sa) << G_SHIFT) +	\
+		(Blend ## name (Blue (d), da, Blue (s), sa));			\
+	    fbCombineMaskValueC (&result, &m);	    \
+	    fbCombineMaskC (&s, &m);		    \
+	    FbByteMul (s, ida);			    \
+	    m = ~m;				    \
+	    FbByteMulAddC(d, m, s);		    \
+	    result += d;			    \
+	} else {				    \
+	    result = s;				    \
+	    fbCombineMaskValueC (&result, &m);	    \
+	}					    \
+						    \
+	*(dest + i) = result;			    \
+    }						    \
+}
+
+/* Screen
+ *
+ * Dca' = (Sca.Da + Dca.Sa - Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
+ *      = Sca + Dca - Sca.Dca
+ * Da'  = Sa + Da - Sa.Da 
+ */
+
+static inline comp4_t
+BlendScreen (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
+{
+  return DivOne (sca * da + dca * sa - sca * dca);
 }
 
+PdfSeperableBlendMode (Screen)
+
 /* Overlay
  *
  * if 2.Dca < Da
@@ -611,7 +750,7 @@ fbCombineSubtractU (pixman_implementation_t *imp, pixman_op_t op,
 #define Sat(c) (Max (c) - Min (c))
 
 #define PdfNonSeperableBlendMode(name)		    \
-static FASTCALL void				    \
+static void				    \
 fbCombine ## name ## U (pixman_implementation_t *imp, pixman_op_t op, \
 			comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width) \
 {						    \
@@ -1121,82 +1260,6 @@ fbCombineConjointXorU (pixman_implementation_t *imp, pixman_op_t op,
 /********************************************************************************/
 
 static void
-fbCombineMaskC (comp4_t *src, comp4_t *mask)
-{
-    comp4_t a = *mask;
-
-    comp4_t	x;
-    comp2_t	xa;
-
-    if (!a)
-    {
-	*(src) = 0;
-	return;
-    }
-
-    x = *(src);
-    if (a == ~0)
-    {
-	x = x >> A_SHIFT;
-	x |= x << G_SHIFT;
-	x |= x << R_SHIFT;
-	*(mask) = x;
-	return;
-    }
-
-    xa = x >> A_SHIFT;
-    FbByteMulC(x, a);
-    *(src) = x;
-    FbByteMul(a, xa);
-    *(mask) = a;
-}
-
-static void
-fbCombineMaskValueC (comp4_t *src, const comp4_t *mask)
-{
-    comp4_t a = *mask;
-    comp4_t	x;
-
-    if (!a)
-    {
-	*(src) = 0;
-	return;
-    }
-
-    if (a == ~0)
-	return;
-
-    x = *(src);
-    FbByteMulC(x, a);
-    *(src) =x;
-}
-
-static void
-fbCombineMaskAlphaC (const comp4_t *src, comp4_t *mask)
-{
-    comp4_t a = *(mask);
-    comp4_t	x;
-
-    if (!a)
-	return;
-
-    x = *(src) >> A_SHIFT;
-    if (x == MASK)
-	return;
-    if (a == ~0)
-    {
-	x = x >> A_SHIFT;
-	x |= x << G_SHIFT;
-	x |= x << R_SHIFT;
-	*(mask) = x;
-	return;
-    }
-
-    FbByteMul(a, x);
-    *(mask) = a;
-}
-
-static void
 fbCombineClearC (pixman_implementation_t *imp, pixman_op_t op,
 		 comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
 {
@@ -1888,5 +1951,18 @@ _pixman_setup_combiner_functions_width (pixman_implementation_t *imp)
     imp->combine_width_ca[PIXMAN_OP_CONJOINT_ATOP] = fbCombineConjointAtopC;
     imp->combine_width_ca[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = fbCombineConjointAtopReverseC;
     imp->combine_width_ca[PIXMAN_OP_CONJOINT_XOR] = fbCombineConjointXorC;
+
+    imp->combine_width_ca[PIXMAN_OP_MULTIPLY] = fbCombineMultiplyC;
+    imp->combine_width_ca[PIXMAN_OP_SCREEN] = fbCombineScreenC;
+    imp->combine_width_ca[PIXMAN_OP_OVERLAY] = fbCombineOverlayC;
+    imp->combine_width_ca[PIXMAN_OP_DARKEN] = fbCombineDarkenC;
+    imp->combine_width_ca[PIXMAN_OP_LIGHTEN] = fbCombineLightenC;
+    imp->combine_width_ca[PIXMAN_OP_COLOR_DODGE] = fbCombineColorDodgeC;
+    imp->combine_width_ca[PIXMAN_OP_COLOR_BURN] = fbCombineColorBurnC;
+    imp->combine_width_ca[PIXMAN_OP_HARD_LIGHT] = fbCombineHardLightC;
+    imp->combine_width_ca[PIXMAN_OP_SOFT_LIGHT] = fbCombineSoftLightC;
+    imp->combine_width_ca[PIXMAN_OP_DIFFERENCE] = fbCombineDifferenceC;
+    imp->combine_width_ca[PIXMAN_OP_EXCLUSION] = fbCombineExclusionC;
 }
 
+
commit 2f57b6f4e9020654ad175a593b17ff07fc3f5cbd
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Nov 13 16:12:22 2008 +0100

    rewrite nonseperable blend modes the same way as seperable ones

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index 9dd0a7f..980ca1c 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -566,6 +566,8 @@ BlendExclusion (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
 
 PdfSeperableBlendMode (Exclusion)
 
+#undef PdfSeperableBlendMode
+
 static void
 fbCombineSubtractU (pixman_implementation_t *imp, pixman_op_t op,
 		    comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
@@ -608,41 +610,39 @@ fbCombineSubtractU (pixman_implementation_t *imp, pixman_op_t op,
 #define Lum(c) ((c[0] * 30 + c[1] * 59 + c[2] * 11) / 100)
 #define Sat(c) (Max (c) - Min (c))
 
-#define FbBlendLoop				    \
+#define PdfNonSeperableBlendMode(name)		    \
+static FASTCALL void				    \
+fbCombine ## name ## U (pixman_implementation_t *imp, pixman_op_t op, \
+			comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width) \
+{						    \
     int i;					    \
-    for (i = 0; i < width; i++)	{		    \
-        comp4_t s = combineMask (src, mask, i);	    \
-	comp4_t d = *(dest + i);		    \
-	comp4_t sa, da, a, isa, ida;	 	    \
+    for (i = 0; i < width; ++i) {		    \
+        comp4_t s = combineMask (src, mask, i);     \
+        comp4_t d = *(dest + i);		    \
+        comp1_t sa = Alpha(s);			    \
+        comp1_t isa = ~sa;			    \
+        comp1_t da = Alpha(d);	  		    \
+        comp1_t ida = ~da;			    \
+	comp4_t	result;				    \
 	comp4_t sc[3], dc[3], c[3];		    \
 						    \
-	da = Alpha (d);				    \
-	sa = Alpha (s);				    \
-	ida = Alpha (~d);			    \
-	isa = Alpha (~s);			    \
+	result = d;				    \
+        FbByteAddMul(result, isa, s, ida);	    \
 	dc[0] = Red (d);			    \
 	sc[0] = Red (s);			    \
 	dc[1] = Green (d);			    \
 	sc[1] = Green (s);			    \
 	dc[2] = Blue (d);			    \
 	sc[2] = Blue (s);			    \
+	Blend ## name (c, dc, da, sc, sa);	    \
 						    \
-	a = sa + da - DivOne (sa * da);		    \
-	FbBlendOp (c, dc, sc);			    \
-						    \
-	c[0] += isa * dc[0] + ida * sc[0];	    \
-	c[1] += isa * dc[1] + ida * sc[1];	    \
-	c[2] += isa * dc[2] + ida * sc[2];	    \
-	c[0] = DivOne (c[0]);			    \
-	c[1] = DivOne (c[1]);			    \
-	c[2] = DivOne (c[2]);			    \
-						    \
-	if (Max (c) > a) while (1);		    \
-	*(dest + i) = (a << A_SHIFT)		    \
-	    | ((c[0] & MASK) << R_SHIFT)	    \
-	    | ((c[1] & MASK) << G_SHIFT)	    \
-	    |  (c[2] & MASK);			    \
-    } while (0);
+	*(dest + i) = result +			    \
+	    (DivOne (sa * da) << A_SHIFT) +	    \
+	    (DivOne (c[0]) << R_SHIFT) +	    \
+	    (DivOne (c[1]) << G_SHIFT) +	    \
+	    (DivOne (c[2]));			    \
+    }						    \
+}
 
 static void
 SetLum (comp4_t dest[3], comp4_t src[3], comp4_t sa, comp4_t lum)
@@ -730,81 +730,57 @@ SetSat (comp4_t dest[3], comp4_t src[3], comp4_t sat)
   if (Max (dest) > 255 * 255) while (1);		    \
 }
 
-#define FbBlendOp(c, dc, sc)						\
-    do {								\
-      c[0] = sc[0] * da;						\
-      c[1] = sc[1] * da;						\
-      c[2] = sc[2] * da;						\
-      SetSat (c, c, Sat (dc) * sa);			  		\
-      SetLum (c, c, sa * da, Lum (dc) * sa);				\
-    } while (0);
-
-static void
-fbCombineHSLHueU (pixman_implementation_t *imp, pixman_op_t op,
-		  comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+static inline void
+BlendHSLHue (comp4_t c[3], comp4_t dc[3], comp4_t da, comp4_t sc[3], comp4_t sa)
 {
-    FbBlendLoop
+    c[0] = sc[0] * da;
+    c[1] = sc[1] * da;
+    c[2] = sc[2] * da;
+    SetSat (c, c, Sat (dc) * sa);
+    SetLum (c, c, sa * da, Lum (dc) * sa);
 }
 
-#undef FbBlendOp
+PdfNonSeperableBlendMode (HSLHue)
 
-#define FbBlendOp(c, dc, sc)						\
-    do {								\
-      c[0] = dc[0] * sa;						\
-      c[1] = dc[1] * sa;						\
-      c[2] = dc[2] * sa;						\
-      SetSat (c, c, Sat (sc) * da);					\
-      SetLum (c, c, da * sa, Lum (dc) * sa);					\
-    } while (0);
-
-static void
-fbCombineHSLSaturationU (pixman_implementation_t *imp, pixman_op_t op,
-			 comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+static inline void
+BlendHSLSaturation (comp4_t c[3], comp4_t dc[3], comp4_t da, comp4_t sc[3], comp4_t sa)
 {
-    FbBlendLoop
+    c[0] = dc[0] * sa;
+    c[1] = dc[1] * sa;
+    c[2] = dc[2] * sa;
+    SetSat (c, c, Sat (sc) * da);
+    SetLum (c, c, sa * da, Lum (dc) * sa);
 }
 
-#undef FbBlendOp
+PdfNonSeperableBlendMode (HSLSaturation)
 
-#define FbBlendOp(c, dc, sc)						\
-    do {								\
-      c[0] = sc[0] * da;						\
-      c[1] = sc[1] * da;						\
-      c[2] = sc[2] * da;						\
-      SetLum (c, c, sa * da, Lum (dc) * sa);				\
-    } while (0);
-
-static void
-fbCombineHSLColorU (pixman_implementation_t *imp, pixman_op_t op,
-		    comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+static inline void
+BlendHSLColor (comp4_t c[3], comp4_t dc[3], comp4_t da, comp4_t sc[3], comp4_t sa)
 {
-    FbBlendLoop
+    c[0] = sc[0] * da;
+    c[1] = sc[1] * da;
+    c[2] = sc[2] * da;
+    SetLum (c, c, sa * da, Lum (dc) * sa);
 }
 
-#undef FbBlendOp
+PdfNonSeperableBlendMode (HSLColor)
 
-#define FbBlendOp(c, dc, sc)						\
-    do {								\
-      c[0] = dc[0] * sa;						\
-      c[1] = dc[1] * sa;						\
-      c[2] = dc[2] * sa;						\
-      SetLum (c, c, da * sa, Lum (sc) * da);			  	\
-    } while (0);
-
-static void
-fbCombineHSLLuminosityU (pixman_implementation_t *imp, pixman_op_t op,
-			 comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+static inline void
+BlendHSLLuminosity (comp4_t c[3], comp4_t dc[3], comp4_t da, comp4_t sc[3], comp4_t sa)
 {
-    FbBlendLoop
+    c[0] = dc[0] * sa;
+    c[1] = dc[1] * sa;
+    c[2] = dc[2] * sa;
+    SetLum (c, c, sa * da, Lum (sc) * da);
 }
 
-#undef FbBlendOp
+PdfNonSeperableBlendMode (HSLLuminosity)
 
 #undef Set
 #undef Lum
 #undef Max
 #undef Min
-#undef FbBlendLoop
+#undef PdfNonSeperableBlendMode
 
 /* Overlay
  *
commit fd1bec2859f775feaff329315cdf16ad27ec4728
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Nov 13 15:13:17 2008 +0100

    clean up seperable blend modes
    
    The code is now shorter and faster than before

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index 45f8313..9dd0a7f 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -313,39 +313,31 @@ fbCombineScreenU (pixman_implementation_t *imp, pixman_op_t op,
     }
 }
 
-#define FbBlendLoop				    \
+#define PdfSeperableBlendMode(name)				      \
+static void							      \
+fbCombine ## name ## U (pixman_implementation_t *imp, pixman_op_t op, \
+                        comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width) \
+{						    \
     int i;					    \
-    for (i = 0; i < width; i++)	{		    \
+    for (i = 0; i < width; ++i) {		    \
         comp4_t s = combineMask (src, mask, i);     \
-	comp4_t d = *(dest + i);		    \
-	comp4_t a, r, g, b;			    \
-	comp4_t sada, sca, dca, sa, da, isa, ida;   \
-						    \
-	da = Alpha (d);				    \
-	sa = Alpha (s);				    \
-	ida = Alpha (~d);			    \
-	isa = Alpha (~s);			    \
-	sada = sa * da;				    \
-						    \
-	a = sa + da - DivOne (sada);		    \
+        comp4_t d = *(dest + i);		    \
+        comp1_t sa = Alpha(s);			    \
+        comp1_t isa = ~sa;			    \
+        comp1_t da = Alpha(d);	  		    \
+        comp1_t ida = ~da;			    \
+	comp4_t	result;				    \
 						    \
-	sca = Red (s);				    \
-	dca = Red (d);				    \
-	FbBlendOp (r);				    \
+	result = d;				    \
+        FbByteAddMul(result, isa, s, ida);	    \
 						    \
-	sca = Green (s);			    \
-	dca = Green (d);			    \
-	FbBlendOp (g);				    \
-						    \
-	sca = Blue (s);				    \
-	dca = Blue (d);				    \
-	FbBlendOp (b);				    \
-						    \
-	*(dest + i) = (a << A_SHIFT)		    \
-	    | ((r & MASK) << R_SHIFT)		    \
-	    | ((g & MASK) << G_SHIFT)		    \
-	    |  (b & MASK);			    \
-    } while (0);
+	*(dest + i) = result +			    \
+	    (DivOne (sa * da) << A_SHIFT) +	    \
+	    (Blend ## name (Red (d), da, Red (s), sa) << R_SHIFT) + \
+	    (Blend ## name (Green (d), da, Green (s), sa) << G_SHIFT) + \
+	    (Blend ## name (Blue (d), da, Blue (s), sa)); \
+    }						    \
+}
 
 /* Overlay
  *
@@ -356,24 +348,20 @@ fbCombineScreenU (pixman_implementation_t *imp, pixman_op_t op,
  * Da' = Sa + Da - Sa.Da
  */
 
-#define FbBlendOp(rca)							\
-    do {								\
-	if (2 * dca  < da)						\
-	    rca = 2 * sca * dca;					\
-	else								\
-	    rca = sada - 2 * (da - dca) * (sa - sca);			\
-	rca += sca * ida + dca * isa;					\
-	rca = DivOne (rca);						\
-    } while (0);
-
-static void
-fbCombineOverlayU (pixman_implementation_t *imp, pixman_op_t op,
-		   comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+static inline comp4_t
+BlendOverlay (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
 {
-    FbBlendLoop
+    comp4_t rca;
+
+    if (2 * dca < da)
+	rca = 2 * sca * dca;
+    else
+	rca = sa * da - 2 * (da - dca) * (sa - sca);
+    while (rca > (sa * da));
+    return DivOne (rca);
 }
 
-#undef FbBlendOp
+PdfSeperableBlendMode (Overlay)
 
 /* Darken
  *
@@ -381,23 +369,17 @@ fbCombineOverlayU (pixman_implementation_t *imp, pixman_op_t op,
  * Da'  = Sa + Da - Sa.Da 
  */
 
-#define FbBlendOp(rca)							\
-    do {								\
-	rca = sca * da;							\
-	if (rca > dca * sa)						\
-	    rca = dca * sa;						\
-	rca += sca * ida + dca * isa;					\
-	rca = DivOne (rca);						\
-    } while (0);
-
-static void
-fbCombineDarkenU (pixman_implementation_t *imp, pixman_op_t op,
-		  comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+static inline comp4_t
+BlendDarken (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
 {
-    FbBlendLoop
+    comp4_t s, d;
+    
+    s = sca * da;
+    d = dca * sa;
+    return DivOne (s > d ? d : s);
 }
 
-#undef FbBlendOp
+PdfSeperableBlendMode (Darken)
 
 /* Lighten
  *
@@ -405,23 +387,17 @@ fbCombineDarkenU (pixman_implementation_t *imp, pixman_op_t op,
  * Da'  = Sa + Da - Sa.Da
  */
 
-#define FbBlendOp(rca)							\
-    do {								\
-	rca = sca * da;							\
-	if (rca < dca * sa)						\
-	    rca = dca * sa;						\
-	rca += sca * ida + dca * isa;					\
-	rca = DivOne (rca);						\
-    } while (0);
-
-static void
-fbCombineLightenU (pixman_implementation_t *imp, pixman_op_t op,
-		   comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+static inline comp4_t
+BlendLighten (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
 {
-    FbBlendLoop
+    comp4_t s, d;
+    
+    s = sca * da;
+    d = dca * sa;
+    return DivOne (s > d ? s : d);
 }
 
-#undef FbBlendOp
+PdfSeperableBlendMode (Lighten)
 
 /* Color dodge
  *
@@ -433,26 +409,18 @@ fbCombineLightenU (pixman_implementation_t *imp, pixman_op_t op,
  * Da'  = Sa + Da - Sa.Da
  */ 
 
-#define FbBlendOp(rca)							\
-    do {								\
-	if (sca >= sa) {						\
-	    rca = dca == 0 ? 0 : sada;				    	\
-	} else {                                                        \
-	    rca = dca * sa * sa / (sa - sca);				\
-	    rca = rca > sada ? sada : rca;				\
-	}								\
-	rca += sca * ida + dca * isa;					\
-	rca = DivOne (rca);						\
-    } while (0);
-
-static void
-fbCombineColorDodgeU (pixman_implementation_t *imp, pixman_op_t op,
-		      comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+static inline comp4_t
+BlendColorDodge (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
 {
-    FbBlendLoop
+    if (sca >= sa) {
+	return dca == 0 ? 0 : DivOne (sa * da);
+    } else {
+	comp4_t rca = dca * sa * sa / (sa - sca);
+	return DivOne (rca > sa * da ? sa * da : rca);
+    }
 }
 
-#undef FbBlendOp
+PdfSeperableBlendMode (ColorDodge)
 
 /* Color burn
  *
@@ -464,26 +432,19 @@ fbCombineColorDodgeU (pixman_implementation_t *imp, pixman_op_t op,
  * Da' = Sa + Da - Sa.Da
  */
 
-#define FbBlendOp(rca)							\
-    do {								\
-	if (sca == 0) {		  					\
-	  rca = (da == dca) ? sada : 0;					\
-	} else {							\
-	  rca = (da - dca) * sa * sa / sca;				\
-	  rca = sada - (rca > sada ? sada : rca);			\
-	}								\
-	rca += sca * ida + dca * isa;					\
-	rca = DivOne (rca);						\
-    } while (0);
-
-static void
-fbCombineColorBurnU (pixman_implementation_t *imp, pixman_op_t op,
-		     comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+static inline comp4_t
+BlendColorBurn (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
 {
-    FbBlendLoop
+    if (sca == 0) {
+      return (da == dca) ? DivOne (sa * da) : 0;
+    } else {
+      comp4_t sada = sa * da;
+      comp4_t rca = (da - dca) * sa * sa / sca;
+      return DivOne (rca > sada ? 0 : sada - rca);
+    }
 }
 
-#undef FbBlendOp
+PdfSeperableBlendMode (ColorBurn)
 
 /* Hard light
  *
@@ -494,25 +455,16 @@ fbCombineColorBurnU (pixman_implementation_t *imp, pixman_op_t op,
  *
  * Da'  = Sa + Da - Sa.Da
  */
-
-#define FbBlendOp(rca)							\
-    do {								\
-	if (2 * sca < sa)						\
-	    rca = 2 * sca * dca;					\
-	else 								\
-	    rca = sada - 2 * (da - dca) * (sa - sca);			\
-	rca += sca * ida + dca * isa;					\
-	rca = DivOne (rca);						\
-    } while (0);
-
-static void
-fbCombineHardLightU (pixman_implementation_t *imp, pixman_op_t op,
-		     comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+static inline comp4_t
+BlendHardLight (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
 {
-    FbBlendLoop
+    if (2 * sca < sa)
+	return DivOne (2 * sca * dca);
+    else
+	return DivOne (sa * da - 2 * (da - dca) * (sa - sca));
 }
 
-#undef FbBlendOp
+PdfSeperableBlendMode (HardLight)
 
 /* Soft light
  *
@@ -548,33 +500,31 @@ fbCombineHardLightU (pixman_implementation_t *imp, pixman_op_t op,
  *   Dca' = (Dca.Sa + (SQRT (Dca/Da).Da - Dca).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa)
  */
 
-#define FbBlendOp(rca)									\
-    do {										\
-	if (2 * sca < sa) { 								\
-	    if (da == 0)	  							\
-	    	rca = dca * sa;								\
-	    else 									\
-		rca = dca * sa - dca * (da - dca) * (sa - 2 * sca) / da;		\
-	} else if (da == 0) {								\
-	    rca = 0;									\
-	} else if (4 * dca <= da) { 			      				\
-	    int dc = dca * MASK / da;							\
-	    rca = dca * sa + (int) (2 * sca - sa) * (int) dca * ((16 * dc - 12 * MASK) * dc + 3 * MASK * MASK) / (MASK * MASK); \
-        } else {									\
-	    rca = dca * sa + ((comp4_t) (sqrt (dca * da) - dca)) * (2 * sca - sa);    	\
-	}										\
-	rca += sca * ida + dca * isa;							\
-	rca = DivOne (rca);		   						\
-    } while (0);
-
-static void
-fbCombineSoftLightU (pixman_implementation_t *imp, pixman_op_t op,
-		     comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
-{
-    FbBlendLoop
+static inline comp4_t
+BlendSoftLight (comp4_t dca_org, comp4_t da_org, comp4_t sca_org, comp4_t sa_org)
+{
+    double dca = dca_org * (1.0 / MASK);
+    double da = da_org * (1.0 / MASK);
+    double sca = sca_org * (1.0 / MASK);
+    double sa = sa_org * (1.0 / MASK);
+    double rca;
+
+    if (2 * sca < sa) {
+	if (da == 0)
+	    rca = dca * sa;
+	else
+	    rca = dca * sa - dca * (da - dca) * (sa - 2 * sca) / da;
+    } else if (da == 0) {
+	rca = 0;
+    } else if (4 * dca <= da) {
+	rca = dca * sa + (2 * sca - sa) * dca * ((16 * dca / da - 12) * dca / da + 3);
+    } else {
+	rca = dca * sa + (sqrt (dca * da) - dca) * (2 * sca - sa);
+    }
+    return rca * MASK + 0.5;
 }
 
-#undef FbBlendOp
+PdfSeperableBlendMode (SoftLight)
 
 /* Difference
  *
@@ -584,26 +534,19 @@ fbCombineSoftLightU (pixman_implementation_t *imp, pixman_op_t op,
  * Da'  = Sa + Da - Sa.Da
  */
 
-#define FbBlendOp(rca)							\
-    do {								\
-	comp4_t dcasa = dca * sa;					\
-	rca = sca * da;							\
-	if (rca < dcasa)						\
-	    rca = dcasa - rca;						\
-	else 								\
-	    rca -= dcasa;						\
-	rca += sca * ida + dca * isa;					\
-	rca = DivOne (rca);						\
-    } while (0);
-
-static void
-fbCombineDifferenceU (pixman_implementation_t *imp, pixman_op_t op,
-		      comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+static inline comp4_t
+BlendDifference (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
 {
-    FbBlendLoop
+    comp4_t dcasa = dca * sa;
+    comp4_t scada = sca * da;
+
+    if (scada < dcasa)
+	return DivOne (dcasa - scada);
+    else
+	return DivOne (scada - dcasa);
 }
 
-#undef FbBlendOp
+PdfSeperableBlendMode (Difference)
 
 /* Exclusion
  *
@@ -612,24 +555,18 @@ fbCombineDifferenceU (pixman_implementation_t *imp, pixman_op_t op,
  * Da'  = Sa + Da - Sa.Da
  */
 
-#define FbBlendOp(rca)							\
-    do {								\
-	rca = dca * MASK + sca * (MASK - 2 * dca); 		   	\
-	rca = DivOne (rca);						\
-    } while (0);
+/* This can be made faster by writing it directly and not using
+ * PdfSeperableBlendMode, but that's a performance optimization */
 
-static void
-fbCombineExclusionU (pixman_implementation_t *imp, pixman_op_t op,
-		     comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+static inline comp4_t
+BlendExclusion (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa)
 {
-    FbBlendLoop
+    return DivOne (sca * da + dca * sa - 2 * dca * sca);
 }
 
-#undef FbBlendOp
-
-#undef FbBlendLoop
+PdfSeperableBlendMode (Exclusion)
 
-static FASTCALL void
+static void
 fbCombineSubtractU (pixman_implementation_t *imp, pixman_op_t op,
 		    comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
 {
@@ -802,7 +739,7 @@ SetSat (comp4_t dest[3], comp4_t src[3], comp4_t sat)
       SetLum (c, c, sa * da, Lum (dc) * sa);				\
     } while (0);
 
-static FASTCALL void
+static void
 fbCombineHSLHueU (pixman_implementation_t *imp, pixman_op_t op,
 		  comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
 {
@@ -820,7 +757,7 @@ fbCombineHSLHueU (pixman_implementation_t *imp, pixman_op_t op,
       SetLum (c, c, da * sa, Lum (dc) * sa);					\
     } while (0);
 
-static FASTCALL void
+static void
 fbCombineHSLSaturationU (pixman_implementation_t *imp, pixman_op_t op,
 			 comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
 {
@@ -837,7 +774,7 @@ fbCombineHSLSaturationU (pixman_implementation_t *imp, pixman_op_t op,
       SetLum (c, c, sa * da, Lum (dc) * sa);				\
     } while (0);
 
-static FASTCALL void
+static void
 fbCombineHSLColorU (pixman_implementation_t *imp, pixman_op_t op,
 		    comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
 {
@@ -854,7 +791,7 @@ fbCombineHSLColorU (pixman_implementation_t *imp, pixman_op_t op,
       SetLum (c, c, da * sa, Lum (sc) * da);			  	\
     } while (0);
 
-static FASTCALL void
+static void
 fbCombineHSLLuminosityU (pixman_implementation_t *imp, pixman_op_t op,
 			 comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
 {
@@ -1927,10 +1864,10 @@ _pixman_setup_combiner_functions_width (pixman_implementation_t *imp)
     imp->combine_width[PIXMAN_OP_DIFFERENCE] = fbCombineDifferenceU;
     imp->combine_width[PIXMAN_OP_EXCLUSION] = fbCombineExclusionU;
     imp->combine_width[PIXMAN_OP_SUBTRACT] = fbCombineSubtractU;
-    imp->combine_width[PIXMAN_OP_HUE] = fbCombineHSLHueU;
-    imp->combine_width[PIXMAN_OP_SATURATION] = fbCombineHSLSaturationU;
-    imp->combine_width[PIXMAN_OP_COLOR] = fbCombineHSLColorU;
-    imp->combine_width[PIXMAN_OP_LUMINOSITY] = fbCombineHSLLuminosityU;
+    imp->combine_width[PIXMAN_OP_HSL_HUE] = fbCombineHSLHueU;
+    imp->combine_width[PIXMAN_OP_HSL_SATURATION] = fbCombineHSLSaturationU;
+    imp->combine_width[PIXMAN_OP_HSL_COLOR] = fbCombineHSLColorU;
+    imp->combine_width[PIXMAN_OP_HSL_LUMINOSITY] = fbCombineHSLLuminosityU;
 
     /* Component alpha combiners */
     imp->combine_width_ca[PIXMAN_OP_CLEAR] = fbCombineClearC;
commit e8b4394a409cda48b6598847292b768ad027dbf0
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Nov 12 19:26:13 2008 +0100

    prefix HSL operators with HSL
    
    This is necessary to distinguish SATURATE from PDF's HSL SATURATION

diff --git a/pixman/pixman.h b/pixman/pixman.h
index 9f36386..b9ecde0 100644
--- a/pixman/pixman.h
+++ b/pixman/pixman.h
@@ -380,10 +380,10 @@ typedef enum
     PIXMAN_OP_DIFFERENCE                = 0x39,
     PIXMAN_OP_EXCLUSION                 = 0x3a,
     PIXMAN_OP_SUBTRACT			= 0x3b,
-    PIXMAN_OP_HUE			= 0x3c,
-    PIXMAN_OP_SATURATION		= 0x3d,
-    PIXMAN_OP_COLOR			= 0x3e,
-    PIXMAN_OP_LUMINOSITY		= 0x4f,
+    PIXMAN_OP_HSL_HUE			= 0x3c,
+    PIXMAN_OP_HSL_SATURATION		= 0x3d,
+    PIXMAN_OP_HSL_COLOR			= 0x3e,
+    PIXMAN_OP_HSL_LUMINOSITY		= 0x3f,
 
     PIXMAN_OP_NONE,
     PIXMAN_OP_LAST = PIXMAN_OP_NONE
commit f08263a25181a5f18991490629ca2e9582836ac6
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Nov 12 19:12:12 2008 +0100

    remove invert operator
    
    src INVERT dest == (white IN src) DIFFERENCE dest

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index 6838840..45f8313 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -666,27 +666,6 @@ fbCombineSubtractU (pixman_implementation_t *imp, pixman_op_t op,
 #undef Subtract
 }
 
-static FASTCALL void
-fbCombineInvertU (pixman_implementation_t *imp, pixman_op_t op,
-		  comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
-{
-    int i;
-
-    for (i = 0; i < width; ++i) {
-      comp4_t inv, d, s;
-      comp1_t a, ia;
-
-      d = *(dest + i);
-      s = combineMask (src, mask, i);
-      a = Alpha (s);
-      inv = ~d | A_MASK;
-      ia = ~a;
-
-      FbByteAddMul (inv, a, d, ia);
-      *(dest + i) = inv;
-    }
-}
-
 #define Min(c) (c[0] < c[1] ? (c[0] < c[2] ? c[0] : c[2]) : (c[1] < c[2] ? c[1] : c[2]))
 #define Max(c) (c[0] > c[1] ? (c[0] > c[2] ? c[0] : c[2]) : (c[1] > c[2] ? c[1] : c[2]))
 #define Lum(c) ((c[0] * 30 + c[1] * 59 + c[2] * 11) / 100)
@@ -1948,7 +1927,6 @@ _pixman_setup_combiner_functions_width (pixman_implementation_t *imp)
     imp->combine_width[PIXMAN_OP_DIFFERENCE] = fbCombineDifferenceU;
     imp->combine_width[PIXMAN_OP_EXCLUSION] = fbCombineExclusionU;
     imp->combine_width[PIXMAN_OP_SUBTRACT] = fbCombineSubtractU;
-    imp->combine_width[PIXMAN_OP_INVERT] = fbCombineInvertU;
     imp->combine_width[PIXMAN_OP_HUE] = fbCombineHSLHueU;
     imp->combine_width[PIXMAN_OP_SATURATION] = fbCombineHSLSaturationU;
     imp->combine_width[PIXMAN_OP_COLOR] = fbCombineHSLColorU;
diff --git a/pixman/pixman.h b/pixman/pixman.h
index c3a1ac3..9f36386 100644
--- a/pixman/pixman.h
+++ b/pixman/pixman.h
@@ -380,11 +380,10 @@ typedef enum
     PIXMAN_OP_DIFFERENCE                = 0x39,
     PIXMAN_OP_EXCLUSION                 = 0x3a,
     PIXMAN_OP_SUBTRACT			= 0x3b,
-    PIXMAN_OP_INVERT			= 0x3c,
-    PIXMAN_OP_HUE			= 0x3d,
-    PIXMAN_OP_SATURATION		= 0x3e,
-    PIXMAN_OP_COLOR			= 0x3f,
-    PIXMAN_OP_LUMINOSITY		= 0x40,
+    PIXMAN_OP_HUE			= 0x3c,
+    PIXMAN_OP_SATURATION		= 0x3d,
+    PIXMAN_OP_COLOR			= 0x3e,
+    PIXMAN_OP_LUMINOSITY		= 0x4f,
 
     PIXMAN_OP_NONE,
     PIXMAN_OP_LAST = PIXMAN_OP_NONE
commit 755638d73cfc5879bd440f0148e982e562509fd0
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Oct 23 21:20:23 2008 +0200

    add nonseperable blend modes from PDF spec

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index 2d38823..6838840 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -342,7 +342,7 @@ fbCombineScreenU (pixman_implementation_t *imp, pixman_op_t op,
 	FbBlendOp (b);				    \
 						    \
 	*(dest + i) = (a << A_SHIFT)		    \
-	    | ((r & MASK) << R_SHIFT)               \
+	    | ((r & MASK) << R_SHIFT)		    \
 	    | ((g & MASK) << G_SHIFT)		    \
 	    |  (b & MASK);			    \
     } while (0);
@@ -687,7 +687,211 @@ fbCombineInvertU (pixman_implementation_t *imp, pixman_op_t op,
     }
 }
 
-/*
+#define Min(c) (c[0] < c[1] ? (c[0] < c[2] ? c[0] : c[2]) : (c[1] < c[2] ? c[1] : c[2]))
+#define Max(c) (c[0] > c[1] ? (c[0] > c[2] ? c[0] : c[2]) : (c[1] > c[2] ? c[1] : c[2]))
+#define Lum(c) ((c[0] * 30 + c[1] * 59 + c[2] * 11) / 100)
+#define Sat(c) (Max (c) - Min (c))
+
+#define FbBlendLoop				    \
+    int i;					    \
+    for (i = 0; i < width; i++)	{		    \
+        comp4_t s = combineMask (src, mask, i);	    \
+	comp4_t d = *(dest + i);		    \
+	comp4_t sa, da, a, isa, ida;	 	    \
+	comp4_t sc[3], dc[3], c[3];		    \
+						    \
+	da = Alpha (d);				    \
+	sa = Alpha (s);				    \
+	ida = Alpha (~d);			    \
+	isa = Alpha (~s);			    \
+	dc[0] = Red (d);			    \
+	sc[0] = Red (s);			    \
+	dc[1] = Green (d);			    \
+	sc[1] = Green (s);			    \
+	dc[2] = Blue (d);			    \
+	sc[2] = Blue (s);			    \
+						    \
+	a = sa + da - DivOne (sa * da);		    \
+	FbBlendOp (c, dc, sc);			    \
+						    \
+	c[0] += isa * dc[0] + ida * sc[0];	    \
+	c[1] += isa * dc[1] + ida * sc[1];	    \
+	c[2] += isa * dc[2] + ida * sc[2];	    \
+	c[0] = DivOne (c[0]);			    \
+	c[1] = DivOne (c[1]);			    \
+	c[2] = DivOne (c[2]);			    \
+						    \
+	if (Max (c) > a) while (1);		    \
+	*(dest + i) = (a << A_SHIFT)		    \
+	    | ((c[0] & MASK) << R_SHIFT)	    \
+	    | ((c[1] & MASK) << G_SHIFT)	    \
+	    |  (c[2] & MASK);			    \
+    } while (0);
+
+static void
+SetLum (comp4_t dest[3], comp4_t src[3], comp4_t sa, comp4_t lum)
+{
+  int a, l, min, max;
+  int tmp[3];
+  
+  a = sa;
+  l = lum;
+  tmp[0] = src[0];
+  tmp[1] = src[1];
+  tmp[2] = src[2];
+  l = l - Lum (tmp);
+  tmp[0] += l;
+  tmp[1] += l;
+  tmp[2] += l;
+
+  /* ClipColor */
+  l = Lum (tmp);
+  min = Min (tmp);
+  max = Max (tmp);
+
+  if (min < 0) {
+    tmp[0] = l + (tmp[0] - l) / 4 * l / (l - min) * 4;
+    tmp[1] = l + (tmp[1] - l) / 4 * l / (l - min) * 4;
+    tmp[2] = l + (tmp[2] - l) / 4 * l / (l - min) * 4;
+  }
+  if (max > a) {
+    tmp[0] = l + (tmp[0] - l) / 4 * (a - l) / (max - l) * 4;
+    tmp[1] = l + (tmp[1] - l) / 4 * (a - l) / (max - l) * 4;
+    tmp[2] = l + (tmp[2] - l) / 4 * (a - l) / (max - l) * 4;
+  }
+  if (Max (tmp) > sa) while (1);
+  dest[0] = tmp[0];
+  dest[1] = tmp[1];
+  dest[2] = tmp[2];
+}
+
+static void
+SetSat (comp4_t dest[3], comp4_t src[3], comp4_t sat)
+{
+  int id[3];
+  comp4_t min, max;
+
+  if (src[0] > src[1]) {
+    if (src[0] > src[2]) {
+      id[0] = 0;
+      if (src[1] > src[2]) {
+	id[1] = 1;
+	id[2] = 2;
+      } else {
+	id[1] = 2;
+	id[2] = 1;
+      }
+    } else {
+      id[0] = 2;
+      id[1] = 0;
+      id[2] = 1;
+    }
+  } else {
+    if (src[0] > src[2]) {
+      id[0] = 1;
+      id[1] = 0;
+      id[2] = 2;
+    } else {
+      id[2] = 0;
+      if (src[1] > src[2]) {
+	id[0] = 1;
+	id[1] = 2;
+      } else {
+	id[0] = 2;
+	id[1] = 1;
+      }
+    }
+  }
+  max = dest[id[0]];
+  min = dest[id[2]];
+  if (max > min) {
+    dest[id[1]] = (dest[id[1]] - min) * sat / (max - min);
+    dest[id[0]] = sat;
+    dest[id[2]] = 0;
+  } else {
+    dest[0] = dest[1] = dest[2] = 0;
+  }
+  if (Max (dest) > 255 * 255) while (1);		    \
+}
+
+#define FbBlendOp(c, dc, sc)						\
+    do {								\
+      c[0] = sc[0] * da;						\
+      c[1] = sc[1] * da;						\
+      c[2] = sc[2] * da;						\
+      SetSat (c, c, Sat (dc) * sa);			  		\
+      SetLum (c, c, sa * da, Lum (dc) * sa);				\
+    } while (0);
+
+static FASTCALL void
+fbCombineHSLHueU (pixman_implementation_t *imp, pixman_op_t op,
+		  comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+{
+    FbBlendLoop
+}
+
+#undef FbBlendOp
+
+#define FbBlendOp(c, dc, sc)						\
+    do {								\
+      c[0] = dc[0] * sa;						\
+      c[1] = dc[1] * sa;						\
+      c[2] = dc[2] * sa;						\
+      SetSat (c, c, Sat (sc) * da);					\
+      SetLum (c, c, da * sa, Lum (dc) * sa);					\
+    } while (0);
+
+static FASTCALL void
+fbCombineHSLSaturationU (pixman_implementation_t *imp, pixman_op_t op,
+			 comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+{
+    FbBlendLoop
+}
+
+#undef FbBlendOp
+
+#define FbBlendOp(c, dc, sc)						\
+    do {								\
+      c[0] = sc[0] * da;						\
+      c[1] = sc[1] * da;						\
+      c[2] = sc[2] * da;						\
+      SetLum (c, c, sa * da, Lum (dc) * sa);				\
+    } while (0);
+
+static FASTCALL void
+fbCombineHSLColorU (pixman_implementation_t *imp, pixman_op_t op,
+		    comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+{
+    FbBlendLoop
+}
+
+#undef FbBlendOp
+
+#define FbBlendOp(c, dc, sc)						\
+    do {								\
+      c[0] = dc[0] * sa;						\
+      c[1] = dc[1] * sa;						\
+      c[2] = dc[2] * sa;						\
+      SetLum (c, c, da * sa, Lum (sc) * da);			  	\
+    } while (0);
+
+static FASTCALL void
+fbCombineHSLLuminosityU (pixman_implementation_t *imp, pixman_op_t op,
+			 comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+{
+    FbBlendLoop
+}
+
+#undef FbBlendOp
+
+#undef Set
+#undef Lum
+#undef Max
+#undef Min
+#undef FbBlendLoop
+
+/* Overlay
+ *
  * All of the disjoint composing functions
 
  The four entries in the first column indicate what source contributions
@@ -1745,6 +1949,10 @@ _pixman_setup_combiner_functions_width (pixman_implementation_t *imp)
     imp->combine_width[PIXMAN_OP_EXCLUSION] = fbCombineExclusionU;
     imp->combine_width[PIXMAN_OP_SUBTRACT] = fbCombineSubtractU;
     imp->combine_width[PIXMAN_OP_INVERT] = fbCombineInvertU;
+    imp->combine_width[PIXMAN_OP_HUE] = fbCombineHSLHueU;
+    imp->combine_width[PIXMAN_OP_SATURATION] = fbCombineHSLSaturationU;
+    imp->combine_width[PIXMAN_OP_COLOR] = fbCombineHSLColorU;
+    imp->combine_width[PIXMAN_OP_LUMINOSITY] = fbCombineHSLLuminosityU;
 
     /* Component alpha combiners */
     imp->combine_width_ca[PIXMAN_OP_CLEAR] = fbCombineClearC;
@@ -1790,3 +1998,4 @@ _pixman_setup_combiner_functions_width (pixman_implementation_t *imp)
     imp->combine_width_ca[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = fbCombineConjointAtopReverseC;
     imp->combine_width_ca[PIXMAN_OP_CONJOINT_XOR] = fbCombineConjointXorC;
 }
+
diff --git a/pixman/pixman.h b/pixman/pixman.h
index 68e8640..c3a1ac3 100644
--- a/pixman/pixman.h
+++ b/pixman/pixman.h
@@ -381,6 +381,10 @@ typedef enum
     PIXMAN_OP_EXCLUSION                 = 0x3a,
     PIXMAN_OP_SUBTRACT			= 0x3b,
     PIXMAN_OP_INVERT			= 0x3c,
+    PIXMAN_OP_HUE			= 0x3d,
+    PIXMAN_OP_SATURATION		= 0x3e,
+    PIXMAN_OP_COLOR			= 0x3f,
+    PIXMAN_OP_LUMINOSITY		= 0x40,
 
     PIXMAN_OP_NONE,
     PIXMAN_OP_LAST = PIXMAN_OP_NONE
commit e3ad87033e3771a3c54b1b8e49813a6959315cd7
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Oct 9 21:46:50 2008 +0200

    fix ColorDodge and ColorBurn to conform to the PDF spec

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index dc36ad9..2d38823 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -425,20 +425,22 @@ fbCombineLightenU (pixman_implementation_t *imp, pixman_op_t op,
 
 /* Color dodge
  *
- * if Sca.Da + Dca.Sa >= Sa.Da
- *   Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa)
+ * if Sca == Sa
+ *   Dca' = (Dca != 0).Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa)
  * otherwise
- *   Dca' = Dca.Sa/(1-Sca/Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
+ *   Dca' = Da.Sa. min (Dca / Da / (1 - Sca/Sa))
  *
  * Da'  = Sa + Da - Sa.Da
  */ 
 
 #define FbBlendOp(rca)							\
     do {								\
-	if ((sca * da + dca * sa >= sada) || (sa == sca))		\
-	    rca = sada; 						\
-	else 								\
-	    rca = sa * sa * dca / (sa - sca);				\
+	if (sca >= sa) {						\
+	    rca = dca == 0 ? 0 : sada;				    	\
+	} else {                                                        \
+	    rca = dca * sa * sa / (sa - sca);				\
+	    rca = rca > sada ? sada : rca;				\
+	}								\
 	rca += sca * ida + dca * isa;					\
 	rca = DivOne (rca);						\
     } while (0);
@@ -454,22 +456,23 @@ fbCombineColorDodgeU (pixman_implementation_t *imp, pixman_op_t op,
 
 /* Color burn
  *
- * if Sca.Da + Dca.Sa <= Sa.Da
- *   Dca' = Sca.(1 - Da) + Dca.(1 - Sa)
+ * if Sca. == 0
+ *   Dca' = (Da == Dca).SaDa + Sca.(1 - Da) + Dca.(1 - Sa)
  * otherwise
- *   Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa)
+ *   Dca' = Sa.Da.(1 - min (1, (1 - Dca/Da).Sa / Sca)) + Sca.(1 - Da) + Dca.(1 - Sa)
  *
- * Da'  = Sa + Da - Sa.Da
+ * Da' = Sa + Da - Sa.Da
  */
 
 #define FbBlendOp(rca)							\
     do {								\
-	if ((sca * da + dca * sa <= sada) || (sca == 0))		\
-	    rca = sca * ida + dca * isa;				\
-	else 								\
-	    rca = sa * (sca * da + sa * dca - sada) / sca		\
-		   + sca * ida						\
-		   + dca * isa ;					\
+	if (sca == 0) {		  					\
+	  rca = (da == dca) ? sada : 0;					\
+	} else {							\
+	  rca = (da - dca) * sa * sa / sca;				\
+	  rca = sada - (rca > sada ? sada : rca);			\
+	}								\
+	rca += sca * ida + dca * isa;					\
 	rca = DivOne (rca);						\
     } while (0);
 
commit 35bb57e7234994c4169458275e362f02cb5138aa
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Oct 9 18:00:45 2008 +0200

    use PDF algorithm for soft-light

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index b06ce5b..dc36ad9 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -518,7 +518,7 @@ fbCombineHardLightU (pixman_implementation_t *imp, pixman_op_t op,
  * if (Sc <= 0.5)
  *   Dc' = Dc - ( 1 - 2 . Sc ) . Dc . ( 1 - Dc )
  * else
- *   Dc' = Dc + ( 2 . Sc - 1 ) . ( F(Dc) – Dc )
+ *   Dc' = Dc + ( 2 . Sc - 1 ) . ( F(Dc) - Dc )
  *
  * with
  * if (x < 0.25)
@@ -526,39 +526,37 @@ fbCombineHardLightU (pixman_implementation_t *imp, pixman_op_t op,
  * else
  *   F(x) = SQRT (x)
  *
- * ==> (taken from SVG spec)
+ * ==>
+ *
+ * if (Sc <= 0.5)
+ *   Dc' = Dc - ( 1 - 2 . Sc ) . Dc . ( 1 - Dc )
+ * otherwise if (Dc < 0.25)
+ *   Dc' = Dc + ( 2 . Sc - 1 ) . ( ((16 . Dc - 12) . Dc + 4) - Dc )
+ * otherwise
+ *   Dc' = Dc + ( 2 . Sc - 1 ) . ( SQRT(Dc) - Dc )
+ *
+ * ==> 
  *
  * if (2.Sca <= Sa)
  *   Dca' = Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) 
- * otherwise if Dca.8 <= Da
- *   Dca' = Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa).(3 - 8.Dca/Da)) + Sc.(1 - Da) + Dca.(1 - Sa)
+ * otherwise if Dca.4 <= Da
+ *   Dca' = Dca.(Sa + (2.Sca - Sa).((16.Dca/Da - 12).Dca/Da + 3) + Sc.(1 - Da) + Dca.(1 - Sa)
  * otherwise
  *   Dca' = (Dca.Sa + (SQRT (Dca/Da).Da - Dca).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa)
- *   
- * ==> (used here)
- * if (2.Sca <= Sa)
- *   Dca' = Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa))
- * otherwise if Dca.8 <= Da
- *   Dca' = Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa).(3 - 8.Dca/Da))
- * otherwise
- *   Dca' = (Dca.Sa + (SQRT (Dca/Da).Da - Dca).(2.Sca - Sa))
- * Dca' += Sca.(1 - Da) + Dca.(1 - Sa);
- *
- * Da'  = Sa + Da - Sa.Da
  */
 
 #define FbBlendOp(rca)									\
     do {										\
 	if (2 * sca < sa) { 								\
-	    if (dca == da || da == 0)							\
+	    if (da == 0)	  							\
 	    	rca = dca * sa;								\
 	    else 									\
-		rca = dca * (sa - (da - dca) * (2 * sca + sa) / da);			\
+		rca = dca * sa - dca * (da - dca) * (sa - 2 * sca) / da;		\
 	} else if (da == 0) {								\
 	    rca = 0;									\
-	} else if (8 * dca <= da) { 			      				\
-	    int tmp = dca * (sa - (da - dca) * (2 * sca - sa) / da * (3 * da - 8 * dca) / da);	\
-	    rca = tmp < 0 ? -tmp : tmp;	  						\
+	} else if (4 * dca <= da) { 			      				\
+	    int dc = dca * MASK / da;							\
+	    rca = dca * sa + (int) (2 * sca - sa) * (int) dca * ((16 * dc - 12 * MASK) * dc + 3 * MASK * MASK) / (MASK * MASK); \
         } else {									\
 	    rca = dca * sa + ((comp4_t) (sqrt (dca * da) - dca)) * (2 * sca - sa);    	\
 	}										\
commit 0735aeeaeba04f0c33f22b25a191cfd1f27c271d
Author: Benjamin Otte <otte at gnome.org>
Date:   Tue Oct 7 15:13:45 2008 +0200

    Add INVERT and SUBTRACT blend modes used in Flash

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index 3cd5740..b06ce5b 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -628,6 +628,64 @@ fbCombineExclusionU (pixman_implementation_t *imp, pixman_op_t op,
 
 #undef FbBlendLoop
 
+static FASTCALL void
+fbCombineSubtractU (pixman_implementation_t *imp, pixman_op_t op,
+		    comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+{
+    int i;
+
+#define Subtract(res, Color)						\
+    do {								\
+      comp1_t dc, sc;							\
+      dc = Color (d);							\
+      sc = Color (s);							\
+      if (sc >= dc)							\
+	res = 0;							\
+      else								\
+	res = dc - sc;							\
+    } while (0);
+
+    for (i = 0; i < width; ++i) {
+	comp4_t d, s;
+	comp4_t r, g, b;
+
+	d = *(dest + i);
+	s = combineMask (src, mask, i);
+
+	Subtract (r, Red);
+	Subtract (g, Green);
+	Subtract (b, Blue);
+
+	*(dest + i) = (Alpha (d) << A_SHIFT)
+	    | (r << R_SHIFT)
+	    | (g << G_SHIFT)
+	    | b;
+    }
+
+#undef Subtract
+}
+
+static FASTCALL void
+fbCombineInvertU (pixman_implementation_t *imp, pixman_op_t op,
+		  comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+{
+    int i;
+
+    for (i = 0; i < width; ++i) {
+      comp4_t inv, d, s;
+      comp1_t a, ia;
+
+      d = *(dest + i);
+      s = combineMask (src, mask, i);
+      a = Alpha (s);
+      inv = ~d | A_MASK;
+      ia = ~a;
+
+      FbByteAddMul (inv, a, d, ia);
+      *(dest + i) = inv;
+    }
+}
+
 /*
  * All of the disjoint composing functions
 
@@ -1684,6 +1742,8 @@ _pixman_setup_combiner_functions_width (pixman_implementation_t *imp)
     imp->combine_width[PIXMAN_OP_SOFT_LIGHT] = fbCombineSoftLightU;
     imp->combine_width[PIXMAN_OP_DIFFERENCE] = fbCombineDifferenceU;
     imp->combine_width[PIXMAN_OP_EXCLUSION] = fbCombineExclusionU;
+    imp->combine_width[PIXMAN_OP_SUBTRACT] = fbCombineSubtractU;
+    imp->combine_width[PIXMAN_OP_INVERT] = fbCombineInvertU;
 
     /* Component alpha combiners */
     imp->combine_width_ca[PIXMAN_OP_CLEAR] = fbCombineClearC;
@@ -1729,4 +1789,3 @@ _pixman_setup_combiner_functions_width (pixman_implementation_t *imp)
     imp->combine_width_ca[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = fbCombineConjointAtopReverseC;
     imp->combine_width_ca[PIXMAN_OP_CONJOINT_XOR] = fbCombineConjointXorC;
 }
-
diff --git a/pixman/pixman.h b/pixman/pixman.h
index a56f55a..68e8640 100644
--- a/pixman/pixman.h
+++ b/pixman/pixman.h
@@ -379,6 +379,8 @@ typedef enum
     PIXMAN_OP_SOFT_LIGHT                = 0x38,
     PIXMAN_OP_DIFFERENCE                = 0x39,
     PIXMAN_OP_EXCLUSION                 = 0x3a,
+    PIXMAN_OP_SUBTRACT			= 0x3b,
+    PIXMAN_OP_INVERT			= 0x3c,
 
     PIXMAN_OP_NONE,
     PIXMAN_OP_LAST = PIXMAN_OP_NONE
commit 740425ab969adda1aaf36d8f52dec6f6e5303ed6
Author: Benjamin Otte <otte at gnome.org>
Date:   Wed Aug 29 23:15:33 2007 +0200

    use a pixman_op_t here
    
    This improves the readability in gdb when debugging this structure

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index 2f7f5d1..3cd5740 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -341,7 +341,7 @@ fbCombineScreenU (pixman_implementation_t *imp, pixman_op_t op,
 	dca = Blue (d);				    \
 	FbBlendOp (b);				    \
 						    \
-	*(dest + i) = (a << 24)			    \
+	*(dest + i) = (a << A_SHIFT)		    \
 	    | ((r & MASK) << R_SHIFT)               \
 	    | ((g & MASK) << G_SHIFT)		    \
 	    |  (b & MASK);			    \
commit 94e9673eaaf9e22530159f0335a0a30d2f2a0047
Author: Benjamin Otte <otte at gnome.org>
Date:   Thu Sep 25 12:53:06 2008 +0200

    Add support for extended blend mode. First pass.
    
    This adds support only for FbCombineU function.
    This work is based on equations provided in SVG 1.2 specification draft.
    
    http://www.w3.org/TR/SVG12/
    
    Based on a previous patch by Emmanuel Pacaud <emmanuel.pacaud at free.fr>

diff --git a/pixman/pixman-combine.c.template b/pixman/pixman-combine.c.template
index 7d05ce8..2f7f5d1 100644
--- a/pixman/pixman-combine.c.template
+++ b/pixman/pixman-combine.c.template
@@ -2,12 +2,17 @@
 #include <config.h>
 #endif
 
+#include <math.h>
 #include <string.h>
 
 #include "pixman-private.h"
 
 #include "pixman-combine.h"
 
+#define Red(x) (((x) >> R_SHIFT) & MASK)
+#define Green(x) (((x) >> G_SHIFT) & MASK)
+#define Blue(x) ((x) & MASK)
+
 /*
  * There are two ways of handling alpha -- either as a single unified value or
  * a separate value for each component, hence each macro must have two
@@ -252,6 +257,377 @@ fbCombineSaturateU (pixman_implementation_t *imp, pixman_op_t op,
 }
 
 
+/* Multiply
+ *
+ * Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
+ * Da'  = Sa.Da + Sa.(1 - Da) + Da.(1 - Sa)
+ *      = Sa + Da - Sa.Da 
+ */
+
+static void
+fbCombineMultiplyU (pixman_implementation_t *imp, pixman_op_t op,
+		    comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+{
+    int i;
+    for (i = 0; i < width; ++i) {
+        comp4_t s = combineMask (src, mask, i);
+        comp4_t d = *(dest + i);
+	comp4_t ss = s;
+        comp4_t src_ia = Alpha (~s);
+	comp4_t dest_ia = Alpha (~d);
+
+	FbByteAddMul (ss, dest_ia, d, src_ia);
+	FbByteMulC (d, s);
+	FbByteAdd (d, ss); 	
+	*(dest + i) = d;
+    }
+}
+
+/* Screen
+ *
+ * Dca' = (Sca.Da + Dca.Sa - Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
+ *      = Sca + Dca - Sca.Dca
+ * Da'  = Sa + Da - Sa.Da 
+ */
+
+static void
+fbCombineScreenU (pixman_implementation_t *imp, pixman_op_t op,
+		  comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+{
+    int i;
+    for (i = 0; i < width; ++i) {
+        comp4_t s = combineMask (src, mask, i);
+        comp4_t d = *(dest + i);
+	comp4_t p = s;
+	comp4_t a, r, g, b;
+
+	FbByteMulC (p, d);
+
+	a = Alpha (s)	+ Alpha (d) - Alpha (p);
+	r = Red(s)	+ Red (d)   - Red (p);
+	g = Green (s)	+ Green (d) - Green (p);
+	b = Blue (s)	+ Blue (d)  - Blue (p);
+
+	/* no clamping required, values don't overflow */
+	*(dest + i) = (a << A_SHIFT) | (r << R_SHIFT) | (g << G_SHIFT) | b;
+    }
+}
+
+#define FbBlendLoop				    \
+    int i;					    \
+    for (i = 0; i < width; i++)	{		    \
+        comp4_t s = combineMask (src, mask, i);     \
+	comp4_t d = *(dest + i);		    \
+	comp4_t a, r, g, b;			    \
+	comp4_t sada, sca, dca, sa, da, isa, ida;   \
+						    \
+	da = Alpha (d);				    \
+	sa = Alpha (s);				    \
+	ida = Alpha (~d);			    \
+	isa = Alpha (~s);			    \
+	sada = sa * da;				    \
+						    \
+	a = sa + da - DivOne (sada);		    \
+						    \
+	sca = Red (s);				    \
+	dca = Red (d);				    \
+	FbBlendOp (r);				    \
+						    \
+	sca = Green (s);			    \
+	dca = Green (d);			    \
+	FbBlendOp (g);				    \
+						    \
+	sca = Blue (s);				    \
+	dca = Blue (d);				    \
+	FbBlendOp (b);				    \
+						    \
+	*(dest + i) = (a << 24)			    \
+	    | ((r & MASK) << R_SHIFT)               \
+	    | ((g & MASK) << G_SHIFT)		    \
+	    |  (b & MASK);			    \
+    } while (0);
+
+/* Overlay
+ *
+ * if 2.Dca < Da
+ *     Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
+ *   otherwise
+ *     Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa)
+ * Da' = Sa + Da - Sa.Da
+ */
+
+#define FbBlendOp(rca)							\
+    do {								\
+	if (2 * dca  < da)						\
+	    rca = 2 * sca * dca;					\
+	else								\
+	    rca = sada - 2 * (da - dca) * (sa - sca);			\
+	rca += sca * ida + dca * isa;					\
+	rca = DivOne (rca);						\
+    } while (0);
+
+static void
+fbCombineOverlayU (pixman_implementation_t *imp, pixman_op_t op,
+		   comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+{
+    FbBlendLoop
+}
+
+#undef FbBlendOp
+
+/* Darken
+ *
+ * Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
+ * Da'  = Sa + Da - Sa.Da 
+ */
+
+#define FbBlendOp(rca)							\
+    do {								\
+	rca = sca * da;							\
+	if (rca > dca * sa)						\
+	    rca = dca * sa;						\
+	rca += sca * ida + dca * isa;					\
+	rca = DivOne (rca);						\
+    } while (0);
+
+static void
+fbCombineDarkenU (pixman_implementation_t *imp, pixman_op_t op,
+		  comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+{
+    FbBlendLoop
+}
+
+#undef FbBlendOp
+
+/* Lighten
+ *
+ * Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
+ * Da'  = Sa + Da - Sa.Da
+ */
+
+#define FbBlendOp(rca)							\
+    do {								\
+	rca = sca * da;							\
+	if (rca < dca * sa)						\
+	    rca = dca * sa;						\
+	rca += sca * ida + dca * isa;					\
+	rca = DivOne (rca);						\
+    } while (0);
+
+static void
+fbCombineLightenU (pixman_implementation_t *imp, pixman_op_t op,
+		   comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+{
+    FbBlendLoop
+}
+
+#undef FbBlendOp
+
+/* Color dodge
+ *
+ * if Sca.Da + Dca.Sa >= Sa.Da
+ *   Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa)
+ * otherwise
+ *   Dca' = Dca.Sa/(1-Sca/Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
+ *
+ * Da'  = Sa + Da - Sa.Da
+ */ 
+
+#define FbBlendOp(rca)							\
+    do {								\
+	if ((sca * da + dca * sa >= sada) || (sa == sca))		\
+	    rca = sada; 						\
+	else 								\
+	    rca = sa * sa * dca / (sa - sca);				\
+	rca += sca * ida + dca * isa;					\
+	rca = DivOne (rca);						\
+    } while (0);
+
+static void
+fbCombineColorDodgeU (pixman_implementation_t *imp, pixman_op_t op,
+		      comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+{
+    FbBlendLoop
+}
+
+#undef FbBlendOp
+
+/* Color burn
+ *
+ * if Sca.Da + Dca.Sa <= Sa.Da
+ *   Dca' = Sca.(1 - Da) + Dca.(1 - Sa)
+ * otherwise
+ *   Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa)
+ *
+ * Da'  = Sa + Da - Sa.Da
+ */
+
+#define FbBlendOp(rca)							\
+    do {								\
+	if ((sca * da + dca * sa <= sada) || (sca == 0))		\
+	    rca = sca * ida + dca * isa;				\
+	else 								\
+	    rca = sa * (sca * da + sa * dca - sada) / sca		\
+		   + sca * ida						\
+		   + dca * isa ;					\
+	rca = DivOne (rca);						\
+    } while (0);
+
+static void
+fbCombineColorBurnU (pixman_implementation_t *imp, pixman_op_t op,
+		     comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+{
+    FbBlendLoop
+}
+
+#undef FbBlendOp
+
+/* Hard light
+ *
+ * if 2.Sca < Sa
+ *   Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
+ * otherwise
+ *   Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa)
+ *
+ * Da'  = Sa + Da - Sa.Da
+ */
+
+#define FbBlendOp(rca)							\
+    do {								\
+	if (2 * sca < sa)						\
+	    rca = 2 * sca * dca;					\
+	else 								\
+	    rca = sada - 2 * (da - dca) * (sa - sca);			\
+	rca += sca * ida + dca * isa;					\
+	rca = DivOne (rca);						\
+    } while (0);
+
+static void
+fbCombineHardLightU (pixman_implementation_t *imp, pixman_op_t op,
+		     comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+{
+    FbBlendLoop
+}
+
+#undef FbBlendOp
+
+/* Soft light
+ *
+ * original definition (taken from PDF spec):
+ * 
+ * if (Sc <= 0.5)
+ *   Dc' = Dc - ( 1 - 2 . Sc ) . Dc . ( 1 - Dc )
+ * else
+ *   Dc' = Dc + ( 2 . Sc - 1 ) . ( F(Dc) – Dc )
+ *
+ * with
+ * if (x < 0.25)
+ *   F(x) = ( ( 16 . x - 12 ) . x + 4 ) . x
+ * else
+ *   F(x) = SQRT (x)
+ *
+ * ==> (taken from SVG spec)
+ *
+ * if (2.Sca <= Sa)
+ *   Dca' = Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) 
+ * otherwise if Dca.8 <= Da
+ *   Dca' = Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa).(3 - 8.Dca/Da)) + Sc.(1 - Da) + Dca.(1 - Sa)
+ * otherwise
+ *   Dca' = (Dca.Sa + (SQRT (Dca/Da).Da - Dca).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa)
+ *   
+ * ==> (used here)
+ * if (2.Sca <= Sa)
+ *   Dca' = Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa))
+ * otherwise if Dca.8 <= Da
+ *   Dca' = Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa).(3 - 8.Dca/Da))
+ * otherwise
+ *   Dca' = (Dca.Sa + (SQRT (Dca/Da).Da - Dca).(2.Sca - Sa))
+ * Dca' += Sca.(1 - Da) + Dca.(1 - Sa);
+ *
+ * Da'  = Sa + Da - Sa.Da
+ */
+
+#define FbBlendOp(rca)									\
+    do {										\
+	if (2 * sca < sa) { 								\
+	    if (dca == da || da == 0)							\
+	    	rca = dca * sa;								\
+	    else 									\
+		rca = dca * (sa - (da - dca) * (2 * sca + sa) / da);			\
+	} else if (da == 0) {								\
+	    rca = 0;									\
+	} else if (8 * dca <= da) { 			      				\
+	    int tmp = dca * (sa - (da - dca) * (2 * sca - sa) / da * (3 * da - 8 * dca) / da);	\
+	    rca = tmp < 0 ? -tmp : tmp;	  						\
+        } else {									\
+	    rca = dca * sa + ((comp4_t) (sqrt (dca * da) - dca)) * (2 * sca - sa);    	\
+	}										\
+	rca += sca * ida + dca * isa;							\
+	rca = DivOne (rca);		   						\
+    } while (0);
+
+static void
+fbCombineSoftLightU (pixman_implementation_t *imp, pixman_op_t op,
+		     comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+{
+    FbBlendLoop
+}
+
+#undef FbBlendOp
+
+/* Difference
+ *
+ * Dca' = abs(Dca.Sa - Sca.Da) + Sca.(1 - Da) + Dca.(1 - Sa)
+ *	= Sca + Dca - 2.min(Sca.Da, Dca.Sa)
+ *
+ * Da'  = Sa + Da - Sa.Da
+ */
+
+#define FbBlendOp(rca)							\
+    do {								\
+	comp4_t dcasa = dca * sa;					\
+	rca = sca * da;							\
+	if (rca < dcasa)						\
+	    rca = dcasa - rca;						\
+	else 								\
+	    rca -= dcasa;						\
+	rca += sca * ida + dca * isa;					\
+	rca = DivOne (rca);						\
+    } while (0);
+
+static void
+fbCombineDifferenceU (pixman_implementation_t *imp, pixman_op_t op,
+		      comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+{
+    FbBlendLoop
+}
+
+#undef FbBlendOp
+
+/* Exclusion
+ *
+ * Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
+ *
+ * Da'  = Sa + Da - Sa.Da
+ */
+
+#define FbBlendOp(rca)							\
+    do {								\
+	rca = dca * MASK + sca * (MASK - 2 * dca); 		   	\
+	rca = DivOne (rca);						\
+    } while (0);
+
+static void
+fbCombineExclusionU (pixman_implementation_t *imp, pixman_op_t op,
+		     comp4_t *dest, const comp4_t *src, const comp4_t *mask, int width)
+{
+    FbBlendLoop
+}
+
+#undef FbBlendOp
+
+#undef FbBlendLoop
+
 /*
  * All of the disjoint composing functions
 
@@ -1297,6 +1673,18 @@ _pixman_setup_combiner_functions_width (pixman_implementation_t *imp)
     imp->combine_width[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = fbCombineConjointAtopReverseU;
     imp->combine_width[PIXMAN_OP_CONJOINT_XOR] = fbCombineConjointXorU;
 
+    imp->combine_width[PIXMAN_OP_MULTIPLY] = fbCombineMultiplyU;
+    imp->combine_width[PIXMAN_OP_SCREEN] = fbCombineScreenU;
+    imp->combine_width[PIXMAN_OP_OVERLAY] = fbCombineOverlayU;
+    imp->combine_width[PIXMAN_OP_DARKEN] = fbCombineDarkenU;
+    imp->combine_width[PIXMAN_OP_LIGHTEN] = fbCombineLightenU;
+    imp->combine_width[PIXMAN_OP_COLOR_DODGE] = fbCombineColorDodgeU;
+    imp->combine_width[PIXMAN_OP_COLOR_BURN] = fbCombineColorBurnU;
+    imp->combine_width[PIXMAN_OP_HARD_LIGHT] = fbCombineHardLightU;
+    imp->combine_width[PIXMAN_OP_SOFT_LIGHT] = fbCombineSoftLightU;
+    imp->combine_width[PIXMAN_OP_DIFFERENCE] = fbCombineDifferenceU;
+    imp->combine_width[PIXMAN_OP_EXCLUSION] = fbCombineExclusionU;
+
     /* Component alpha combiners */
     imp->combine_width_ca[PIXMAN_OP_CLEAR] = fbCombineClearC;
     imp->combine_width_ca[PIXMAN_OP_SRC] = fbCombineSrcC;
@@ -1341,3 +1729,4 @@ _pixman_setup_combiner_functions_width (pixman_implementation_t *imp)
     imp->combine_width_ca[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = fbCombineConjointAtopReverseC;
     imp->combine_width_ca[PIXMAN_OP_CONJOINT_XOR] = fbCombineConjointXorC;
 }
+
diff --git a/pixman/pixman-combine.h.template b/pixman/pixman-combine.h.template
index f2e58a1..6828fea 100644
--- a/pixman/pixman-combine.h.template
+++ b/pixman/pixman-combine.h.template
@@ -29,6 +29,8 @@
 #define Add(x,y,i,t)   ((t) = GetComp(x,i) + GetComp(y,i),              \
                         (comp4_t) ((comp1_t) ((t) | (0 - ((t) >> G_SHIFT)))) << (i))
 
+#define DivOne(x)      (((x) + ONE_HALF + (((x) + ONE_HALF) >> G_SHIFT)) >> G_SHIFT)
+
 /*
   The methods below use some tricks to be able to do two color
   components at the same time.
diff --git a/pixman/pixman.h b/pixman/pixman.h
index a954d2c..a56f55a 100644
--- a/pixman/pixman.h
+++ b/pixman/pixman.h
@@ -368,6 +368,18 @@ typedef enum
     PIXMAN_OP_CONJOINT_ATOP_REVERSE	= 0x2a,
     PIXMAN_OP_CONJOINT_XOR		= 0x2b,
 
+    PIXMAN_OP_MULTIPLY                  = 0x30,
+    PIXMAN_OP_SCREEN                    = 0x31,
+    PIXMAN_OP_OVERLAY                   = 0x32,
+    PIXMAN_OP_DARKEN                    = 0x33,
+    PIXMAN_OP_LIGHTEN                   = 0x34,
+    PIXMAN_OP_COLOR_DODGE               = 0x35,
+    PIXMAN_OP_COLOR_BURN                = 0x36,
+    PIXMAN_OP_HARD_LIGHT                = 0x37,
+    PIXMAN_OP_SOFT_LIGHT                = 0x38,
+    PIXMAN_OP_DIFFERENCE                = 0x39,
+    PIXMAN_OP_EXCLUSION                 = 0x3a,
+
     PIXMAN_OP_NONE,
     PIXMAN_OP_LAST = PIXMAN_OP_NONE
 } pixman_op_t;


More information about the xorg-commit mailing list