summaryrefslogtreecommitdiff
path: root/draw/blendmodes.c
diff options
context:
space:
mode:
authorTor Andersson <tor@ghostscript.com>2010-03-15 18:14:33 +0100
committerTor Andersson <tor@ghostscript.com>2010-03-15 18:14:33 +0100
commit3b68bd0604f5fd069a6b0e3bdf7bdb6c8e2ceef2 (patch)
treea95bef22d24f88bcef63f10361fe0a97198db719 /draw/blendmodes.c
parenteaa6bdb3618ce9354382fbb0e8e00f15f5f5eddc (diff)
downloadmupdf-3b68bd0604f5fd069a6b0e3bdf7bdb6c8e2ceef2.tar.xz
Rename fitzdraw directory to draw.
Diffstat (limited to 'draw/blendmodes.c')
-rw-r--r--draw/blendmodes.c211
1 files changed, 211 insertions, 0 deletions
diff --git a/draw/blendmodes.c b/draw/blendmodes.c
new file mode 100644
index 00000000..973d79ab
--- /dev/null
+++ b/draw/blendmodes.c
@@ -0,0 +1,211 @@
+#include "fitz.h"
+
+typedef unsigned char byte;
+
+/*
+PDF 1.4 blend modes, except Normal and Multiply which are Over and In respectively.
+Only the actual blend routines are here, not the node rendering logic which lives in render.c.
+These are slow.
+*/
+
+
+/* These functions apply to a single component, 0-255 range typically */
+
+static int
+fz_screen_byte(int bd, int s)
+{
+ return bd + s - fz_mul255(bd, s);
+}
+
+
+static int
+fz_hardlight_byte(int bd, int s)
+{
+ int s2 = s << 1;
+ if (s <= 127)
+ return fz_mul255(bd, s2);
+ else
+ return fz_screen_byte(bd, s2);
+}
+
+
+static int
+fz_overlay_byte(int bd, int s)
+{
+ return fz_hardlight_byte(s, bd); // note swapped order
+}
+
+
+static int
+fz_darken_byte(int bd, int s)
+{
+ return MIN(bd, s);
+}
+
+
+static int
+fz_lighten_byte(int bd, int s)
+{
+ return MAX(bd, s);
+}
+
+
+static int
+fz_colordodge_byte(int bd, int s)
+{
+ if (s < 255)
+ return MIN(255, 255 * bd / (255 - s));
+ else
+ return 255;
+}
+
+
+static int
+fz_colorburn_byte(int bd, int s)
+{
+ if (s > 0)
+ return 255 - MIN(255, 255 * (255 - bd) / s);
+ else
+ return 0;
+}
+
+
+static int
+fz_softlight_byte(int bd, int s)
+{
+ /* review this */
+ if (s < 128) {
+ return bd - fz_mul255(fz_mul255((255 - (s<<1)), bd), 255 - bd);
+ }
+ else {
+ int dbd;
+ if (bd < 64)
+ dbd = fz_mul255(fz_mul255((bd << 4) - 12, bd) + 4, bd);
+ else
+ dbd = (int)sqrtf(255.0f * bd);
+ return bd + fz_mul255(((s<<1) - 255), (dbd - bd));
+ }
+}
+
+
+static int
+fz_difference_byte(int bd, int s)
+{
+ return ABS(bd - s);
+}
+
+
+static int
+fz_exclusion_byte(int bd, int s)
+{
+ return bd + s - (fz_mul255(bd, s)<<1);
+}
+
+
+/* Non-separable blend modes */
+
+
+static int
+lum(int r, int g, int b)
+{
+ /* 0.3, 0.59, 0.11 in 16.16 fixed point */
+ return (19662 * r + 38666 * g + 7208 * b) >> 16;
+}
+
+
+static void
+clipcolor(int r, int g, int b, int *dr, int *dg, int *db)
+{
+ int l = lum(r, g, b);
+ int n = MIN(MIN(r, g), b);
+ int x = MAX(MAX(r, g), b);
+ if (n < 0) {
+ *dr = l + 255 * (r - l) / (l - n);
+ *dg = l + 255 * (g - l) / (l - n);
+ *db = l + 255 * (b - l) / (l - n);
+ }
+ else {
+ *dr = l + 255 * (255 - l) / (x - l);
+ *dg = l + 255 * (255 - l) / (x - l);
+ *db = l + 255 * (255 - l) / (x - l);
+ }
+}
+
+
+static void
+setlum(int r, int g, int b, int l, int *dr, int *dg, int *db)
+{
+ int d = 255 - lum(r, g, b);
+ clipcolor(r + d, g + d, b + d, dr, dg, db);
+}
+
+
+static int
+sat(int r, int g, int b)
+{
+ return MAX(MAX(r, g), b) - MIN(MIN(r, g), b);
+}
+
+
+static void
+setsat(int r, int g, int b, int s, int *dr, int *dg, int *db)
+{
+ int *m[3] = { &r, &g, &b }; /* min, med, max */
+ int *t;
+#define SWAP(a, b) (t = a, a = b, b = t)
+ if (*m[0] > *m[1])
+ SWAP(m[0], m[1]);
+ if (*m[0] > *m[2])
+ SWAP(m[0], m[2]);
+ if (*m[1] > *m[2])
+ SWAP(m[1], m[2]);
+
+ if (*m[2] > *m[0]) {
+ *m[1] = (*m[1] - *m[0]) * s / (*m[2] - *m[0]);
+ *m[2] = s;
+ }
+ else {
+ *m[1] = 0;
+ *m[2] = 0;
+ }
+ *dr = r;
+ *dg = g;
+ *db = b;
+}
+
+
+static void
+fz_hue_rgb(int *bdr, int *bdg, int *bdb, int sr, int sg, int sb)
+{
+ int tr, tg, tb;
+ setsat(sr, sg, sb, sat(*bdr, *bdg, *bdb), &tr, &tg, &tb);
+ setlum(tr, tg, tb, lum(*bdr, *bdg, *bdb), bdr, bdg, bdb);
+}
+
+
+static void
+fz_saturation_rgb(int *bdr, int *bdg, int *bdb, int sr, int sg, int sb)
+{
+ int tr, tg, tb;
+ setsat(*bdr, *bdg, *bdb, sat(sr, sg, sb), &tr, &tg, &tb);
+ setlum(tr, tg, tb, lum(*bdr, *bdg, *bdb), bdr, bdg, bdb);
+}
+
+
+static void
+fz_color_rgb(int *bdr, int *bdg, int *bdb, int sr, int sg, int sb)
+{
+ setlum(sr, sg, sb, lum(*bdr, *bdg, *bdb), bdr, bdg, bdb);
+}
+
+
+static void
+fz_luminosity_rgb(int *bdr, int *bdg, int *bdb, int sr, int sg, int sb)
+{
+ setlum(*bdr, *bdg, *bdb, lum(sr, sg, sb), bdr, bdg, bdb);
+}
+
+
+//fz_separable_blend(, fz_blendkind mode)
+//{
+ //}