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