diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc index 2ca42a4..962354f 100644 --- a/poppler/SplashOutputDev.cc +++ b/poppler/SplashOutputDev.cc @@ -1195,6 +1195,8 @@ struct SplashTransparencyGroup { SplashBitmap *shape; GBool knockout; SplashCoord knockoutOpacity; + GBool useBlendFunc; + SplashBlendFunc blendFunc; //----- saved state SplashBitmap *origBitmap; @@ -3812,6 +3814,8 @@ void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox, transpGroup->isolated = isolated; transpGroup->shape = (knockout && !isolated) ? SplashBitmap::copy(bitmap) : NULL; transpGroup->knockout = gFalse; + transpGroup->useBlendFunc = gFalse; + transpGroup->blendFunc = splash->getBlendFunc(); transpGroup->knockoutOpacity = 1.0; transpGroup->next = transpGroupStack; transpGroupStack = transpGroup; @@ -3868,8 +3872,12 @@ void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox, } else { SplashBitmap *shape = (knockout) ? transpGroup->shape : (transpGroup->next != NULL && transpGroup->next->shape != NULL) ? transpGroup->next->shape : transpGroup->origBitmap; + int shapeTx = (knockout) ? tx : + (transpGroup->next != NULL && transpGroup->next->shape != NULL) ? transpGroup->next->tx + tx : tx; + int shapeTy = (knockout) ? ty : + (transpGroup->next != NULL && transpGroup->next->shape != NULL) ? transpGroup->next->ty + ty : ty; splash->blitTransparent(transpGroup->origBitmap, tx, ty, 0, 0, w, h); - splash->setInNonIsolatedGroup(shape, tx, ty); + splash->setInNonIsolatedGroup(shape, shapeTx, shapeTy); } transpGroup->tBitmap = bitmap; state->shiftCTMAndClip(-tx, -ty); @@ -3905,9 +3913,39 @@ void SplashOutputDev::paintTransparencyGroup(GfxState *state, double *bbox) { SplashCoord knockoutOpacity = (transpGroupStack->next != NULL) ? transpGroupStack->next->knockoutOpacity : transpGroupStack->knockoutOpacity; splash->setOverprintMask(0xffffffff, gFalse); - splash->composite(tBitmap, 0, 0, tx, ty, + if (transpGroupStack->next != NULL && transpGroupStack->next->shape != NULL && splash->getBlendFunc() != NULL) { + if (transpGroupStack->next->useBlendFunc && transpGroupStack->next->blendFunc != splash->getBlendFunc()) { + // create the temporary bitmap + SplashBitmap *tmpBitmap = SplashBitmap::copy(transpGroupStack->next->origBitmap); + Splash *tmpSplash = new Splash(tmpBitmap, vectorAntialias, + splash->getScreen()); + tmpSplash->setInNonIsolatedGroup(transpGroupStack->next->shape, transpGroupStack->next->tx, transpGroupStack->next->ty); + tmpSplash->setBlendFunc(transpGroupStack->next->blendFunc); + tmpSplash->composite(bitmap, 0, 0, transpGroupStack->next->tx, transpGroupStack->next->ty, + bitmap->getWidth(), bitmap->getHeight(), + gFalse, !isolated, gFalse, knockoutOpacity); + splash->blitTransparent(tmpBitmap, transpGroupStack->next->tx, transpGroupStack->next->ty, 0, 0, bitmap->getWidth(), bitmap->getHeight(), gTrue); + delete tmpSplash; + delete tmpBitmap; + splash->composite(tBitmap, 0, 0, tx, ty, + tBitmap->getWidth(), tBitmap->getHeight(), + gFalse, !isolated, gTrue, knockoutOpacity); + transpGroupStack->next->useBlendFunc = gFalse; + } else { + splash->blitTransparent(tBitmap, 0, 0, tx, ty, tBitmap->getWidth(), tBitmap->getHeight(), gTrue); + transpGroupStack->next->useBlendFunc = gTrue; + transpGroupStack->next->blendFunc = splash->getBlendFunc(); + } + } else { + SplashBlendFunc formerBlendFunc = splash->getBlendFunc(); + if (transpGroupStack->shape != NULL && transpGroupStack->useBlendFunc) { + splash->setBlendFunc(transpGroupStack->blendFunc); + } + splash->composite(tBitmap, 0, 0, tx, ty, tBitmap->getWidth(), tBitmap->getHeight(), gFalse, !isolated, transpGroupStack->next != NULL && transpGroupStack->next->knockout, knockoutOpacity); + splash->setBlendFunc(formerBlendFunc); + } if (transpGroupStack->next != NULL && transpGroupStack->next->shape != NULL) { transpGroupStack->next->knockout = gTrue; } diff --git a/splash/Splash.cc b/splash/Splash.cc index 6bb0dfe..d597bea 100644 --- a/splash/Splash.cc +++ b/splash/Splash.cc @@ -446,39 +446,68 @@ void Splash::pipeRun(SplashPipe *pipe) { //----- read destination pixel + Guchar *destColorPtr; + if (pipe->shape && state->blendFunc && pipe->knockout && alpha0Bitmap != NULL) { + destColorPtr = alpha0Bitmap->data + (alpha0Y+pipe->y)*alpha0Bitmap->rowSize; + switch (bitmap->mode) { + case splashModeMono1: + destColorPtr += (alpha0X+pipe->x) / 8; + break; + case splashModeMono8: + destColorPtr += (alpha0X+pipe->x); + break; + case splashModeRGB8: + case splashModeBGR8: + destColorPtr += (alpha0X+pipe->x) * 3; + break; + case splashModeXBGR8: +#if SPLASH_CMYK + case splashModeCMYK8: +#endif + destColorPtr += (alpha0X+pipe->x) * 4; + break; +#if SPLASH_CMYK + case splashModeDeviceN8: + destColorPtr += (alpha0X+pipe->x) * (SPOT_NCOMPS + 4); + break; +#endif + } + } else { + destColorPtr = pipe->destColorPtr; + } switch (bitmap->mode) { case splashModeMono1: - cDest[0] = (*pipe->destColorPtr & pipe->destColorMask) ? 0xff : 0x00; + cDest[0] = (*destColorPtr & pipe->destColorMask) ? 0xff : 0x00; break; case splashModeMono8: - cDest[0] = *pipe->destColorPtr; + cDest[0] = *destColorPtr; break; case splashModeRGB8: - cDest[0] = pipe->destColorPtr[0]; - cDest[1] = pipe->destColorPtr[1]; - cDest[2] = pipe->destColorPtr[2]; + cDest[0] = destColorPtr[0]; + cDest[1] = destColorPtr[1]; + cDest[2] = destColorPtr[2]; break; case splashModeXBGR8: - cDest[0] = pipe->destColorPtr[2]; - cDest[1] = pipe->destColorPtr[1]; - cDest[2] = pipe->destColorPtr[0]; + cDest[0] = destColorPtr[2]; + cDest[1] = destColorPtr[1]; + cDest[2] = destColorPtr[0]; cDest[3] = 255; break; case splashModeBGR8: - cDest[0] = pipe->destColorPtr[2]; - cDest[1] = pipe->destColorPtr[1]; - cDest[2] = pipe->destColorPtr[0]; + cDest[0] = destColorPtr[2]; + cDest[1] = destColorPtr[1]; + cDest[2] = destColorPtr[0]; break; #if SPLASH_CMYK case splashModeCMYK8: - cDest[0] = pipe->destColorPtr[0]; - cDest[1] = pipe->destColorPtr[1]; - cDest[2] = pipe->destColorPtr[2]; - cDest[3] = pipe->destColorPtr[3]; + cDest[0] = destColorPtr[0]; + cDest[1] = destColorPtr[1]; + cDest[2] = destColorPtr[2]; + cDest[3] = destColorPtr[3]; break; case splashModeDeviceN8: for (cp = 0; cp < SPOT_NCOMPS + 4; cp++) - cDest[cp] = pipe->destColorPtr[cp]; + cDest[cp] = destColorPtr[cp]; break; #endif } @@ -5711,7 +5740,7 @@ GBool Splash::gouraudTriangleShadedFill(SplashGouraudColor *shading) } SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc, - int xDest, int yDest, int w, int h) { + int xDest, int yDest, int w, int h, GBool knockout) { SplashColorPtr p, sp; Guchar *q; int x, y, mask, srcMask; @@ -5807,7 +5836,16 @@ SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc, if (bitmap->alpha) { for (y = 0; y < h; ++y) { q = &bitmap->alpha[(yDest + y) * bitmap->width + xDest]; - memset(q, 0x00, w); + if (knockout) { + p = &src->alpha[(ySrc + y) * src->width + xSrc]; + for (x = 0; x < w; ++x, ++q, ++p) { + if (*p > *q) { + *q = *p; + } + } + } else { + memset(q, 0x00, w); + } } } diff --git a/splash/Splash.h b/splash/Splash.h index cf98e6c..491e01e 100644 --- a/splash/Splash.h +++ b/splash/Splash.h @@ -231,7 +231,7 @@ public: // this Splash object. The destination alpha values are all set to // zero. SplashError blitTransparent(SplashBitmap *src, int xSrc, int ySrc, - int xDest, int yDest, int w, int h); + int xDest, int yDest, int w, int h, GBool knockout = gFalse); void blitImage(SplashBitmap *src, GBool srcAlpha, int xDest, int yDest); //----- misc