summaryrefslogtreecommitdiff
path: root/source/fitz/draw-blend.c
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2017-07-14 17:22:19 +0200
committerRobin Watts <robin.watts@artifex.com>2017-07-17 19:32:06 +0100
commit6dc533a774c732b0292e5b566766f3a000cd45fb (patch)
tree68887d7488d143faec0500ba420b9f5fdbe1ec2b /source/fitz/draw-blend.c
parent3ef06faf300d7a840ecd66a8861c5bda585fc020 (diff)
downloadmupdf-6dc533a774c732b0292e5b566766f3a000cd45fb.tar.xz
Complement subtractive colors before applying blend modes.
(Incorporates fixes from Tor, Michael and Robin).
Diffstat (limited to 'source/fitz/draw-blend.c')
-rw-r--r--source/fitz/draw-blend.c390
1 files changed, 235 insertions, 155 deletions
diff --git a/source/fitz/draw-blend.c b/source/fitz/draw-blend.c
index f955e5f9..d819107a 100644
--- a/source/fitz/draw-blend.c
+++ b/source/fitz/draw-blend.c
@@ -235,85 +235,75 @@ fz_hue_rgb(unsigned char *rr, unsigned char *rg, unsigned char *rb, int br, int
fz_saturation_rgb(rr, rg, rb, tr, tg, tb, br, bg, bb);
}
-void
-fz_blend_pixel(unsigned char dp[3], unsigned char bp[3], unsigned char sp[3], int blendmode)
-{
- int k;
- /* non-separable blend modes */
- switch (blendmode)
- {
- case FZ_BLEND_HUE: fz_hue_rgb(&dp[0], &dp[1], &dp[2], bp[0], bp[1], bp[2], sp[0], sp[1], sp[2]); return;
- case FZ_BLEND_SATURATION: fz_saturation_rgb(&dp[0], &dp[1], &dp[2], bp[0], bp[1], bp[2], sp[0], sp[1], sp[2]); return;
- case FZ_BLEND_COLOR: fz_color_rgb(&dp[0], &dp[1], &dp[2], bp[0], bp[1], bp[2], sp[0], sp[1], sp[2]); return;
- case FZ_BLEND_LUMINOSITY: fz_luminosity_rgb(&dp[0], &dp[1], &dp[2], bp[0], bp[1], bp[2], sp[0], sp[1], sp[2]); return;
- }
- /* separable blend modes */
- for (k = 0; k < 3; k++)
- {
- switch (blendmode)
- {
- default:
- case FZ_BLEND_NORMAL: dp[k] = sp[k]; break;
- case FZ_BLEND_MULTIPLY: dp[k] = fz_mul255(bp[k], sp[k]); break;
- case FZ_BLEND_SCREEN: dp[k] = fz_screen_byte(bp[k], sp[k]); break;
- case FZ_BLEND_OVERLAY: dp[k] = fz_overlay_byte(bp[k], sp[k]); break;
- case FZ_BLEND_DARKEN: dp[k] = fz_darken_byte(bp[k], sp[k]); break;
- case FZ_BLEND_LIGHTEN: dp[k] = fz_lighten_byte(bp[k], sp[k]); break;
- case FZ_BLEND_COLOR_DODGE: dp[k] = fz_color_dodge_byte(bp[k], sp[k]); break;
- case FZ_BLEND_COLOR_BURN: dp[k] = fz_color_burn_byte(bp[k], sp[k]); break;
- case FZ_BLEND_HARD_LIGHT: dp[k] = fz_hard_light_byte(bp[k], sp[k]); break;
- case FZ_BLEND_SOFT_LIGHT: dp[k] = fz_soft_light_byte(bp[k], sp[k]); break;
- case FZ_BLEND_DIFFERENCE: dp[k] = fz_difference_byte(bp[k], sp[k]); break;
- case FZ_BLEND_EXCLUSION: dp[k] = fz_exclusion_byte(bp[k], sp[k]); break;
- }
- }
-}
-
/* Blending loops */
static inline void
-fz_blend_separable(byte * restrict bp, int bal, const byte * restrict sp, int sal, int n1, int w, int blendmode)
+fz_blend_separable(byte * restrict bp, int bal, const byte * restrict sp, int sal, int n1, int w, int blendmode, int complement)
{
int k;
do
{
int sa = (sal ? sp[n1] : 255);
- int ba = (bal ? bp[n1] : 255);
- int saba = fz_mul255(sa, ba);
-
- /* ugh, division to get non-premul components */
- int invsa = sa ? 255 * 256 / sa : 0;
- int invba = ba ? 255 * 256 / ba : 0;
- for (k = 0; k < n1; k++)
+ if (sa != 0)
{
- int sc = (sp[k] * invsa) >> 8;
- int bc = (bp[k] * invba) >> 8;
- int rc;
-
- switch (blendmode)
+ int ba = (bal ? bp[n1] : 255);
+ if (ba == 0)
{
- default:
- case FZ_BLEND_NORMAL: rc = sc; break;
- case FZ_BLEND_MULTIPLY: rc = fz_mul255(bc, sc); break;
- case FZ_BLEND_SCREEN: rc = fz_screen_byte(bc, sc); break;
- case FZ_BLEND_OVERLAY: rc = fz_overlay_byte(bc, sc); break;
- case FZ_BLEND_DARKEN: rc = fz_darken_byte(bc, sc); break;
- case FZ_BLEND_LIGHTEN: rc = fz_lighten_byte(bc, sc); break;
- case FZ_BLEND_COLOR_DODGE: rc = fz_color_dodge_byte(bc, sc); break;
- case FZ_BLEND_COLOR_BURN: rc = fz_color_burn_byte(bc, sc); break;
- case FZ_BLEND_HARD_LIGHT: rc = fz_hard_light_byte(bc, sc); break;
- case FZ_BLEND_SOFT_LIGHT: rc = fz_soft_light_byte(bc, sc); break;
- case FZ_BLEND_DIFFERENCE: rc = fz_difference_byte(bc, sc); break;
- case FZ_BLEND_EXCLUSION: rc = fz_exclusion_byte(bc, sc); break;
+ memcpy(bp, sp, n1 + (sal && bal));
+ if (bal && !sal)
+ bp[n1+1] = 255;
}
+ else
+ {
+ int saba = fz_mul255(sa, ba);
- bp[k] = fz_mul255(255 - sa, bp[k]) + fz_mul255(255 - ba, sp[k]) + fz_mul255(saba, rc);
- }
+ /* ugh, division to get non-premul components */
+ int invsa = sa ? 255 * 256 / sa : 0;
+ int invba = ba ? 255 * 256 / ba : 0;
- if (bal)
- bp[k] = ba + sa - saba;
+ for (k = 0; k < n1; k++)
+ {
+ int sc = (sp[k] * invsa) >> 8;
+ int bc = (bp[k] * invba) >> 8;
+ int rc;
+
+ if (complement)
+ {
+ sc = 255 - sc;
+ bc = 255 - bc;
+ }
+
+ switch (blendmode)
+ {
+ default:
+ case FZ_BLEND_NORMAL: rc = sc; break;
+ case FZ_BLEND_MULTIPLY: rc = fz_mul255(bc, sc); break;
+ case FZ_BLEND_SCREEN: rc = fz_screen_byte(bc, sc); break;
+ case FZ_BLEND_OVERLAY: rc = fz_overlay_byte(bc, sc); break;
+ case FZ_BLEND_DARKEN: rc = fz_darken_byte(bc, sc); break;
+ case FZ_BLEND_LIGHTEN: rc = fz_lighten_byte(bc, sc); break;
+ case FZ_BLEND_COLOR_DODGE: rc = fz_color_dodge_byte(bc, sc); break;
+ case FZ_BLEND_COLOR_BURN: rc = fz_color_burn_byte(bc, sc); break;
+ case FZ_BLEND_HARD_LIGHT: rc = fz_hard_light_byte(bc, sc); break;
+ case FZ_BLEND_SOFT_LIGHT: rc = fz_soft_light_byte(bc, sc); break;
+ case FZ_BLEND_DIFFERENCE: rc = fz_difference_byte(bc, sc); break;
+ case FZ_BLEND_EXCLUSION: rc = fz_exclusion_byte(bc, sc); break;
+ }
+
+ if (complement)
+ {
+ rc = 255 - rc;
+ }
+
+ bp[k] = fz_mul255(255 - sa, bp[k]) + fz_mul255(255 - ba, sp[k]) + fz_mul255(saba, rc);
+ }
+
+ if (bal)
+ bp[k] = ba + sa - saba;
+ }
+ }
sp += n1 + sal;
bp += n1 + bal;
}
@@ -326,31 +316,43 @@ fz_blend_nonseparable_gray(byte * restrict bp, int bal, const byte * restrict sp
do
{
int sa = (sal ? sp[n] : 255);
- int ba = (bal ? bp[n] : 255);
- int saba = fz_mul255(sa, ba);
- /* ugh, division to get non-premul components */
- int invsa = sa ? 255 * 256 / sa : 0;
- int invba = ba ? 255 * 256 / ba : 0;
+ if (sa != 0)
+ {
+ int ba = (bal ? bp[n] : 255);
+ if (ba == 0)
+ {
+ memcpy(bp, sp, n + (sal && bal));
+ if (bal && !sal)
+ bp [n + 1] = 255;
+ }
+ else
+ {
+ int saba = fz_mul255(sa, ba);
- int sg = (sp[0] * invsa) >> 8;
- int bg = (bp[0] * invba) >> 8;
+ /* ugh, division to get non-premul components */
+ int invsa = sa ? 255 * 256 / sa : 0;
+ int invba = ba ? 255 * 256 / ba : 0;
- switch (blendmode)
- {
- default:
- case FZ_BLEND_HUE:
- case FZ_BLEND_SATURATION:
- case FZ_BLEND_COLOR:
- bp[0] = fz_mul255(bp[n], bg);
- break;
- case FZ_BLEND_LUMINOSITY:
- bp[0] = fz_mul255(bp[n], sg);
- break;
- }
- if (bal)
- bp[n] = ba + sa - saba;
+ int sg = (sp[0] * invsa) >> 8;
+ int bg = (bp[0] * invba) >> 8;
+ switch (blendmode)
+ {
+ default:
+ case FZ_BLEND_HUE:
+ case FZ_BLEND_SATURATION:
+ case FZ_BLEND_COLOR:
+ bp[0] = fz_mul255(bp[n], bg);
+ break;
+ case FZ_BLEND_LUMINOSITY:
+ bp[0] = fz_mul255(bp[n], sg);
+ break;
+ }
+ if (bal)
+ bp[n] = ba + sa - saba;
+ }
+ }
sp += n + sal;
bp += n + bal;
} while (--w);
@@ -364,61 +366,91 @@ fz_blend_nonseparable(byte * restrict bp, int bal, const byte * restrict sp, int
unsigned char rr, rg, rb;
int sa = (sal ? sp[n] : 255);
- int ba = (bal ? bp[n] : 255);
- int saba = fz_mul255(sa, ba);
- /* ugh, division to get non-premul components */
- int invsa = sa ? 255 * 256 / sa : 0;
- int invba = ba ? 255 * 256 / ba : 0;
+ if (sa != 0)
+ {
+ int ba = (bal ? bp[n] : 255);
+ if (ba == 0)
+ {
+ memcpy(bp, sp, n + (sal && bal));
+ if (bal && !sal)
+ bp [n + 1] = 255;
+ }
+ else
+ {
+ int saba = fz_mul255(sa, ba);
- int sr = (sp[0] * invsa) >> 8;
- int sg = (sp[1] * invsa) >> 8;
- int sb = (sp[2] * invsa) >> 8;
+ /* ugh, division to get non-premul components */
+ int invsa = sa ? 255 * 256 / sa : 0;
+ int invba = ba ? 255 * 256 / ba : 0;
- int br = (bp[0] * invba) >> 8;
- int bg = (bp[1] * invba) >> 8;
- int bb = (bp[2] * invba) >> 8;
+ int sr = (sp[0] * invsa) >> 8;
+ int sg = (sp[1] * invsa) >> 8;
+ int sb = (sp[2] * invsa) >> 8;
- switch (blendmode)
- {
- default:
- case FZ_BLEND_HUE:
- fz_hue_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb);
- break;
- case FZ_BLEND_SATURATION:
- fz_saturation_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb);
- break;
- case FZ_BLEND_COLOR:
- fz_color_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb);
- break;
- case FZ_BLEND_LUMINOSITY:
- fz_luminosity_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb);
- break;
- }
+ int br = (bp[0] * invba) >> 8;
+ int bg = (bp[1] * invba) >> 8;
+ int bb = (bp[2] * invba) >> 8;
- bp[0] = fz_mul255(255 - sa, bp[0]) + fz_mul255(255 - ba, sp[0]) + fz_mul255(saba, rr);
- bp[1] = fz_mul255(255 - sa, bp[1]) + fz_mul255(255 - ba, sp[1]) + fz_mul255(saba, rg);
- bp[2] = fz_mul255(255 - sa, bp[2]) + fz_mul255(255 - ba, sp[2]) + fz_mul255(saba, rb);
- if (bal)
- bp[n] = ba + sa - saba;
+ if (n == 4)
+ {
+ sr = 255 - sr;
+ sg = 255 - sg;
+ sb = 255 - sb;
+ br = 255 - br;
+ bg = 255 - bg;
+ bb = 255 - bb;
+ }
- /* Black */
- if (n == 4)
- {
- int sk = (sp[3] * invsa) >> 8;
- int bk = (bp[3] * invba) >> 8;
+ switch (blendmode)
+ {
+ default:
+ case FZ_BLEND_HUE:
+ fz_hue_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb);
+ break;
+ case FZ_BLEND_SATURATION:
+ fz_saturation_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb);
+ break;
+ case FZ_BLEND_COLOR:
+ fz_color_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb);
+ break;
+ case FZ_BLEND_LUMINOSITY:
+ fz_luminosity_rgb(&rr, &rg, &rb, br, bg, bb, sr, sg, sb);
+ break;
+ }
- switch (blendmode)
- {
- default:
- case FZ_BLEND_HUE:
- case FZ_BLEND_SATURATION:
- case FZ_BLEND_COLOR:
- bp[3] = fz_mul255(bp[n], bk);
- break;
- case FZ_BLEND_LUMINOSITY:
- bp[3] = fz_mul255(bp[n], sk);
- break;
+ if (n == 4)
+ {
+ rr = 255 - rr;
+ rg = 255 - rg;
+ rb = 255 - rb;
+ }
+
+ bp[0] = fz_mul255(255 - sa, bp[0]) + fz_mul255(255 - ba, sp[0]) + fz_mul255(saba, rr);
+ bp[1] = fz_mul255(255 - sa, bp[1]) + fz_mul255(255 - ba, sp[1]) + fz_mul255(saba, rg);
+ bp[2] = fz_mul255(255 - sa, bp[2]) + fz_mul255(255 - ba, sp[2]) + fz_mul255(saba, rb);
+ if (bal)
+ bp[n] = ba + sa - saba;
+
+ /* Black */
+ if (n == 4)
+ {
+ int sk = (sp[3] * invsa) >> 8;
+ int bk = (bp[3] * invba) >> 8;
+
+ switch (blendmode)
+ {
+ default:
+ case FZ_BLEND_HUE:
+ case FZ_BLEND_SATURATION:
+ case FZ_BLEND_COLOR:
+ bp[3] = fz_mul255(bp[n], bk);
+ break;
+ case FZ_BLEND_LUMINOSITY:
+ bp[3] = fz_mul255(bp[n], sk);
+ break;
+ }
+ }
}
}
sp += n + sal;
@@ -428,7 +460,7 @@ fz_blend_nonseparable(byte * restrict bp, int bal, const byte * restrict sp, int
}
static inline void
-fz_blend_separable_nonisolated(byte * restrict bp, int bal, const byte * restrict sp, int sal, int n1, int w, int blendmode, const byte * restrict hp, int alpha)
+fz_blend_separable_nonisolated(byte * restrict bp, int bal, const byte * restrict sp, int sal, int n1, int w, int blendmode, int complement, const byte * restrict hp, int alpha)
{
int k;
@@ -476,9 +508,7 @@ fz_blend_separable_nonisolated(byte * restrict bp, int bal, const byte * restric
/* Just copy pixels (allowing for change in
* premultiplied alphas) */
for (k = 0; k < n1; k++)
- {
bp[k] = fz_mul255((sp[k] * invsa) >> 8, haa);
- }
if (bal)
bp[n1] = haa;
break;
@@ -522,6 +552,12 @@ fz_blend_separable_nonisolated(byte * restrict bp, int bal, const byte * restric
int bc = (bp[k] * invba + 128) >> 8;
int rc;
+ if (complement)
+ {
+ sc = 255 - sc;
+ bc = 255 - bc;
+ }
+
/* Uncomposite (see above) */
sc = (((sc-bc) * invha + 128)>>8) + bc;
if (sc < 0) sc = 0;
@@ -543,10 +579,17 @@ fz_blend_separable_nonisolated(byte * restrict bp, int bal, const byte * restric
case FZ_BLEND_DIFFERENCE: rc = fz_difference_byte(bc, sc); break;
case FZ_BLEND_EXCLUSION: rc = fz_exclusion_byte(bc, sc); break;
}
+
/* Composition formula, as given in pdf_reference17.pdf:
* rc = ( 1 - (ha/ra)) * bc + (ha/ra) * ((1-ba)*sc + ba * rc)
*/
rc = bc + fz_mul255(sa, fz_mul255(255 - ba, sc) + fz_mul255(ba, rc) - bc);
+
+ if (complement)
+ {
+ rc = 255 - rc;
+ }
+
if (rc < 0) rc = 0;
if (rc > 255) rc = 255;
bp[k] = fz_mul255(rc, ra);
@@ -634,7 +677,7 @@ fz_blend_nonseparable_nonisolated(byte * restrict bp, int bal, const byte * rest
if (ba == 0)
{
- memcpy(bp, sp, n + (bal && sal));
+ memcpy(bp, sp, n + (sal && bal));
if (bal && !sal)
bp[n] = 255;
}
@@ -674,6 +717,16 @@ fz_blend_nonseparable_nonisolated(byte * restrict bp, int bal, const byte * rest
int bg = (bp[1] * invba) >> 8;
int bb = (bp[2] * invba) >> 8;
+ if (n == 4)
+ {
+ sr = 255 - sr;
+ sg = 255 - sg;
+ sb = 255 - sb;
+ br = 255 - br;
+ bg = 255 - bg;
+ bb = 255 - bb;
+ }
+
/* Uncomposite */
sr = (((sr - br)*invha) >> 8) + br;
sg = (((sg - bg)*invha) >> 8) + bg;
@@ -699,6 +752,14 @@ fz_blend_nonseparable_nonisolated(byte * restrict bp, int bal, const byte * rest
rr = fz_mul255(255 - haa, bp[0]) + fz_mul255(fz_mul255(255 - ba, sr), haa) + fz_mul255(baha, rr);
rg = fz_mul255(255 - haa, bp[1]) + fz_mul255(fz_mul255(255 - ba, sg), haa) + fz_mul255(baha, rg);
rb = fz_mul255(255 - haa, bp[2]) + fz_mul255(fz_mul255(255 - ba, sb), haa) + fz_mul255(baha, rb);
+
+ if (n == 4)
+ {
+ rr = 255 - rr;
+ rg = 255 - rg;
+ rb = 255 - rb;
+ }
+
bp[0] = fz_mul255(ra, rr);
bp[1] = fz_mul255(ra, rg);
bp[2] = fz_mul255(ra, rb);
@@ -733,14 +794,15 @@ fz_blend_nonseparable_nonisolated(byte * restrict bp, int bal, const byte * rest
}
void
-fz_blend_pixmap(fz_pixmap * restrict dst, fz_pixmap * restrict src, int alpha, int blendmode, int isolated, const fz_pixmap * restrict shape)
+fz_blend_pixmap(fz_context *ctx, fz_pixmap * restrict dst, fz_pixmap * restrict src, int alpha, int blendmode, int isolated, const fz_pixmap * restrict shape)
{
- const unsigned char *sp;
+ unsigned char *sp;
unsigned char *dp;
fz_irect bbox;
fz_irect bbox2;
int x, y, w, h, n;
int da, sa;
+ int complement;
/* TODO: fix this hack! */
if (isolated && alpha < 255)
@@ -774,6 +836,7 @@ fz_blend_pixmap(fz_pixmap * restrict dst, fz_pixmap * restrict src, int alpha, i
if (w == 0 || h == 0)
return;
+ complement = fz_colorspace_is_subtractive(ctx, src->colorspace);
n = src->n;
sp = src->samples + (unsigned int)((y - src->y) * src->stride + (x - src->x) * src->n);
sa = src->alpha;
@@ -783,6 +846,9 @@ fz_blend_pixmap(fz_pixmap * restrict dst, fz_pixmap * restrict src, int alpha, i
n -= sa;
assert(n == dst->n - da);
+ if (blendmode >= FZ_BLEND_HUE && (complement ? n != 4 : n != 1 && n != 3))
+ fz_throw(ctx, FZ_ERROR_GENERIC, "can only use non-separable blend modes on gray or RGB colors");
+
if (!isolated)
{
const unsigned char *hp = shape->samples + (unsigned int)((y - shape->y) * shape->stride + (x - shape->x));
@@ -790,6 +856,7 @@ fz_blend_pixmap(fz_pixmap * restrict dst, fz_pixmap * restrict src, int alpha, i
while (h--)
{
if (blendmode >= FZ_BLEND_HUE)
+ {
if (da)
if (sa)
if (n == 1)
@@ -812,17 +879,23 @@ fz_blend_pixmap(fz_pixmap * restrict dst, fz_pixmap * restrict src, int alpha, i
fz_blend_nonseparable_nonisolated_gray(dp, 0, sp, 0, n, w, blendmode, hp, alpha);
else
fz_blend_nonseparable_nonisolated(dp, 0, sp, 0, n, w, blendmode, hp, alpha);
+ }
else
- if (da)
- if (sa)
- fz_blend_separable_nonisolated(dp, 1, sp, 1, n, w, blendmode, hp, alpha);
- else
- fz_blend_separable_nonisolated(dp, 1, sp, 0, n, w, blendmode, hp, alpha);
+ {
+ if (complement)
+ fz_blend_separable_nonisolated(dp, da, sp, sa, n, w, blendmode, 1, hp, alpha);
else
- if (sa)
- fz_blend_separable_nonisolated(dp, 0, sp, 1, n, w, blendmode, hp, alpha);
+ if (da)
+ if (sa)
+ fz_blend_separable_nonisolated(dp, 1, sp, 1, n, w, blendmode, 0, hp, alpha);
+ else
+ fz_blend_separable_nonisolated(dp, 1, sp, 0, n, w, blendmode, 0, hp, alpha);
else
- fz_blend_separable_nonisolated(dp, 0, sp, 0, n, w, blendmode, hp, alpha);
+ if (sa)
+ fz_blend_separable_nonisolated(dp, 0, sp, 1, n, w, blendmode, 0, hp, alpha);
+ else
+ fz_blend_separable_nonisolated(dp, 0, sp, 0, n, w, blendmode, 0, hp, alpha);
+ }
sp += src->stride;
dp += dst->stride;
hp += shape->stride;
@@ -833,6 +906,7 @@ fz_blend_pixmap(fz_pixmap * restrict dst, fz_pixmap * restrict src, int alpha, i
while (h--)
{
if (blendmode >= FZ_BLEND_HUE)
+ {
if (da)
if (sa)
if (n == 1)
@@ -855,17 +929,23 @@ fz_blend_pixmap(fz_pixmap * restrict dst, fz_pixmap * restrict src, int alpha, i
fz_blend_nonseparable_gray(dp, 0, sp, 0, n, w, blendmode);
else
fz_blend_nonseparable(dp, 0, sp, 0, n, w, blendmode);
+ }
else
- if (da)
- if (sa)
- fz_blend_separable(dp, 1, sp, 1, n, w, blendmode);
- else
- fz_blend_separable(dp, 1, sp, 0, n, w, blendmode);
+ {
+ if (complement)
+ fz_blend_separable(dp, da, sp, sa, n, w, blendmode, 1);
else
- if (sa)
- fz_blend_separable(dp, 0, sp, 1, n, w, blendmode);
+ if (da)
+ if (sa)
+ fz_blend_separable(dp, 1, sp, 1, n, w, blendmode, 0);
+ else
+ fz_blend_separable(dp, 1, sp, 0, n, w, blendmode, 0);
else
- fz_blend_separable(dp, 0, sp, 0, n, w, blendmode);
+ if (sa)
+ fz_blend_separable(dp, 0, sp, 1, n, w, blendmode, 0);
+ else
+ fz_blend_separable(dp, 0, sp, 0, n, w, blendmode, 0);
+ }
sp += src->stride;
dp += dst->stride;
}