diff options
author | Robin Watts <robin.watts@artifex.com> | 2017-09-06 14:57:48 +0100 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2017-10-24 15:16:36 +0100 |
commit | 313c72b9b3f3c888a51c9eb02187228b9e2aad11 (patch) | |
tree | 44230ad3d852cec8608fa766dea5bfe3714a30a5 /source/fitz/draw-blend.c | |
parent | c413f4db6a54846ae85393a87fa1b53b93a966ee (diff) | |
download | mupdf-313c72b9b3f3c888a51c9eb02187228b9e2aad11.tar.xz |
Fix knockout operation.
The "blend back" at the end of the inner knockout groups was
attempting to reuse the existing blending code. This was going
wrong for all sorts of reasons (not least the uncomposition
phase) for knockout groups containing alpha, such as found on
page 7 of Altona_Technical_v20_x4.pdf.
Use a dedicated routine. This is much simpler as it doesn't have
to cope with blend modes etc.
Diffstat (limited to 'source/fitz/draw-blend.c')
-rw-r--r-- | source/fitz/draw-blend.c | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/source/fitz/draw-blend.c b/source/fitz/draw-blend.c index ac9e0492..6c2c58c7 100644 --- a/source/fitz/draw-blend.c +++ b/source/fitz/draw-blend.c @@ -1250,3 +1250,103 @@ fz_blend_pixmap(fz_context *ctx, fz_pixmap * restrict dst, fz_pixmap * restrict verify_premultiply(ctx, dst); #endif } + +static inline void +fz_blend_knockout(byte * restrict bp, int bal, const byte * restrict sp, int sal, int n1, int w, const byte * restrict hp) +{ + int k; + do + { + int ha = *hp++; + + if (ha != 0) + { + int sa = (sal ? sp[n1] : 255); + int ba = (bal ? bp[n1] : 255); + if (ba == 0 && ha == 0xFF) + { + memcpy(bp, sp, n1); + if (bal) + bp[n1] = sa; + } + else + { + int hasa = fz_mul255(ha, sa); + /* ugh, division to get non-premul components */ + int invsa = sa ? 255 * 256 / sa : 0; + int invba = ba ? 255 * 256 / ba : 0; + int ra = hasa + fz_mul255(255-ha, ba); + + /* Process colorants + spots */ + for (k = 0; k < n1; k++) + { + int sc = (sp[k] * invsa) >> 8; + int bc = (bp[k] * invba) >> 8; + int rc = fz_mul255(255 - ha, bc) + fz_mul255(ha, sc); + + bp[k] = fz_mul255(ra, rc); + } + + if (bal) + bp[k] = ra; + } + } + sp += n1 + sal; + bp += n1 + bal; + } + while (--w); +} + +void +fz_blend_pixmap_knockout(fz_context *ctx, fz_pixmap * restrict dst, fz_pixmap * restrict src, const fz_pixmap * restrict shape) +{ + unsigned char *sp; + unsigned char *dp; + fz_irect bbox; + fz_irect bbox2; + int x, y, w, h, n; + int da, sa; + const unsigned char *hp; + + fz_pixmap_bbox_no_ctx(dst, &bbox); + fz_pixmap_bbox_no_ctx(src, &bbox2); + fz_intersect_irect(&bbox, &bbox2); + + x = bbox.x0; + y = bbox.y0; + w = bbox.x1 - bbox.x0; + h = bbox.y1 - bbox.y0; + + if (w == 0 || h == 0) + return; + + n = src->n; + sp = src->samples + (unsigned int)((y - src->y) * src->stride + (x - src->x) * src->n); + sa = src->alpha; + dp = dst->samples + (unsigned int)((y - dst->y) * dst->stride + (x - dst->x) * dst->n); + da = dst->alpha; + hp = shape->samples + (unsigned int)((y - shape->y) * shape->stride + (x - shape->x)); + +#ifdef PARANOID_PREMULTIPLY + if (sa) + verify_premultiply(ctx, src); + if (da) + verify_premultiply(ctx, dst); +#endif + + n -= sa; + assert(n == dst->n - da); + + while (h--) + { + fz_blend_knockout(dp, da, sp, sa, n, w, hp); + sp += src->stride; + dp += dst->stride; + hp += shape->stride; + } + +#ifdef PARANOID_PREMULTIPLY + if (da) + verify_premultiply(ctx, dst); +#endif +} |