diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc index 0e956c7..e80bcd2 100644 --- a/poppler/SplashOutputDev.cc +++ b/poppler/SplashOutputDev.cc @@ -1145,6 +1145,10 @@ struct SplashTransparencyGroup { GfxColorSpace *blendingColorSpace; GBool isolated; + //----- for knockout + GBool knockedout; + SplashBitmap *shape; + //----- saved state SplashBitmap *origBitmap; Splash *origSplash; @@ -3585,6 +3589,8 @@ void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox, transpGroup->ty = ty; transpGroup->blendingColorSpace = blendingColorSpace; transpGroup->isolated = isolated; + transpGroup->shape = (knockout) ? SplashBitmap::copy(bitmap) : NULL; + transpGroup->knockedout = gFalse; transpGroup->next = transpGroupStack; transpGroupStack = transpGroup; @@ -3637,8 +3643,10 @@ void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox, if (colorMode == splashModeXBGR8) color[3] = 255; splash->clear(color, 0); } else { + SplashBitmap *shape = (knockout) ? transpGroup->shape : (transpGroup->next != NULL && transpGroup->next->shape != NULL) ? + transpGroup->next->shape : transpGroup->origBitmap; splash->blitTransparent(transpGroup->origBitmap, tx, ty, 0, 0, w, h); - splash->setInNonIsolatedGroup(transpGroup->origBitmap, tx, ty); + splash->setInNonIsolatedGroup(shape, tx, ty); } transpGroup->tBitmap = bitmap; state->shiftCTM(-tx, -ty); @@ -3672,14 +3680,22 @@ void SplashOutputDev::paintTransparencyGroup(GfxState *state, double *bbox) { // - the clip path was set in the parent's state) if (tx < bitmap->getWidth() && ty < bitmap->getHeight()) { splash->setOverprintMask(0xffffffff, gFalse); - splash->composite(tBitmap, 0, 0, tx, ty, + if (transpGroupStack->next != NULL && transpGroupStack->next->knockedout) { + splash->blitTransparent(tBitmap, 0, 0, tx, ty, + tBitmap->getWidth(), tBitmap->getHeight(), gFalse); + } else { + if (transpGroupStack->next != NULL && transpGroupStack->next->shape != NULL) + transpGroupStack->next->knockedout = gTrue; + splash->composite(tBitmap, 0, 0, tx, ty, tBitmap->getWidth(), tBitmap->getHeight(), gFalse, !isolated); + } } - // pop the stack transpGroup = transpGroupStack; transpGroupStack = transpGroup->next; + if (transpGroup->shape) + delete transpGroup->shape; delete transpGroup; delete tBitmap; diff --git a/splash/Splash.cc b/splash/Splash.cc index 0e2058c..396e595 100644 --- a/splash/Splash.cc +++ b/splash/Splash.cc @@ -5189,9 +5189,9 @@ 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 fClearAlpha) { SplashColorPtr p, sp; - Guchar *q; + Guchar *q, *sq; int x, y, mask, srcMask; if (src->mode != bitmap->mode) { @@ -5275,7 +5275,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 (fClearAlpha) + memset(q, 0x00, w); + else { + sq = &src->alpha[(ySrc + y) * src->width + xSrc]; + for (x = 0; x < w; x++) { + if (*sq != 0) + *q = *sq; + q++; sq++; + } + } } } diff --git a/splash/Splash.h b/splash/Splash.h index 53bfa81..3e418cf 100644 --- a/splash/Splash.h +++ b/splash/Splash.h @@ -225,7 +225,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 fClearAlpha = gTrue); //----- misc diff --git a/splash/SplashBitmap.cc b/splash/SplashBitmap.cc index ab5176e..db86d9d 100644 --- a/splash/SplashBitmap.cc +++ b/splash/SplashBitmap.cc @@ -111,6 +111,25 @@ SplashBitmap::SplashBitmap(int widthA, int heightA, int rowPadA, } } +SplashBitmap *SplashBitmap::copy(SplashBitmap *src) { + SplashBitmap *result = new SplashBitmap(src->getWidth(), src->getHeight(), src->getRowPad(), + src->getMode(), src->getAlphaPtr() != NULL, src->getRowSize() >= 0); + Guchar *dataSource = src->getDataPtr(); + Guchar *dataDest = result->getDataPtr(); + int amount = src->getRowSize(); + if (amount < 0) { + dataSource = dataSource + (src->getHeight() - 1) * amount; + dataDest = dataDest + (src->getHeight() - 1) * amount; + amount *= -src->getHeight(); + } else { + amount *= src->getHeight(); + } + memcpy(dataDest, dataSource, amount); + if (src->getAlphaPtr() != NULL) + memcpy(result->getAlphaPtr(), src->getAlphaPtr(), src->getWidth() * src->getHeight()); + return result; +} + SplashBitmap::~SplashBitmap() { if (data) { if (rowSize < 0) { diff --git a/splash/SplashBitmap.h b/splash/SplashBitmap.h index 8bcc941..7fd31a4 100644 --- a/splash/SplashBitmap.h +++ b/splash/SplashBitmap.h @@ -51,6 +51,7 @@ public: SplashBitmap(int widthA, int heightA, int rowPad, SplashColorMode modeA, GBool alphaA, GBool topDown = gTrue); + static SplashBitmap *copy(SplashBitmap *src); ~SplashBitmap();