[poppler] poppler/SplashOutputDev.cc splash/SplashBitmap.cc splash/SplashBitmap.h splash/Splash.cc splash/Splash.h

Albert Astals Cid aacid at kemper.freedesktop.org
Sun Apr 29 07:04:05 PDT 2012


 poppler/SplashOutputDev.cc |   31 ++++++++++++++++++++++++++++---
 splash/Splash.cc           |   21 ++++++++++++++++++---
 splash/Splash.h            |    6 ++++--
 splash/SplashBitmap.cc     |   22 +++++++++++++++++++++-
 splash/SplashBitmap.h      |    2 ++
 5 files changed, 73 insertions(+), 9 deletions(-)

New commits:
commit be41f1c7905d695d17e19ced83a1018531d00199
Author: Albert Astals Cid <aacid at kde.org>
Date:   Sun Apr 29 16:02:45 2012 +0200

    SplashOutputDev: Fix rendering of knockout groups
    
    Bug #12185

diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc
index 0e956c7..ce666b9 100644
--- a/poppler/SplashOutputDev.cc
+++ b/poppler/SplashOutputDev.cc
@@ -1145,6 +1145,11 @@ struct SplashTransparencyGroup {
   GfxColorSpace *blendingColorSpace;
   GBool isolated;
 
+  //----- for knockout
+  SplashBitmap *shape;
+  GBool knockout;
+  SplashCoord knockoutOpacity;
+
   //----- saved state
   SplashBitmap *origBitmap;
   Splash *origSplash;
@@ -1631,10 +1636,16 @@ void SplashOutputDev::updateBlendMode(GfxState *state) {
 
 void SplashOutputDev::updateFillOpacity(GfxState *state) {
   splash->setFillAlpha((SplashCoord)state->getFillOpacity());
+  if (transpGroupStack != NULL && (SplashCoord)state->getFillOpacity() < transpGroupStack->knockoutOpacity) {
+    transpGroupStack->knockoutOpacity = (SplashCoord)state->getFillOpacity();
+  }
 }
 
 void SplashOutputDev::updateStrokeOpacity(GfxState *state) {
   splash->setStrokeAlpha((SplashCoord)state->getStrokeOpacity());
+  if (transpGroupStack != NULL && (SplashCoord)state->getStrokeOpacity() < transpGroupStack->knockoutOpacity) {
+    transpGroupStack->knockoutOpacity = (SplashCoord)state->getStrokeOpacity();
+  }
 }
 
 void SplashOutputDev::updateFillOverprint(GfxState *state) {
@@ -3585,6 +3596,9 @@ void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox,
   transpGroup->ty = ty;
   transpGroup->blendingColorSpace = blendingColorSpace;
   transpGroup->isolated = isolated;
+  transpGroup->shape = (knockout) ? SplashBitmap::copy(bitmap) : NULL;
+  transpGroup->knockout = gFalse; 
+  transpGroup->knockoutOpacity = 1.0;
   transpGroup->next = transpGroupStack;
   transpGroupStack = transpGroup;
 
@@ -3637,8 +3651,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);
@@ -3671,15 +3687,24 @@ void SplashOutputDev::paintTransparencyGroup(GfxState *state, double *bbox) {
   // paint the transparency group onto the parent bitmap
   // - the clip path was set in the parent's state)
   if (tx < bitmap->getWidth() && ty < bitmap->getHeight()) {
+    SplashCoord knockoutOpacity = (transpGroupStack->next != NULL) ? transpGroupStack->next->knockoutOpacity
+                                                                   : transpGroupStack->knockoutOpacity;
     splash->setOverprintMask(0xffffffff, gFalse);
     splash->composite(tBitmap, 0, 0, tx, ty,
-		      tBitmap->getWidth(), tBitmap->getHeight(),
-		      gFalse, !isolated);
+	      tBitmap->getWidth(), tBitmap->getHeight(),
+	      gFalse, !isolated, transpGroupStack->next != NULL && transpGroupStack->next->knockout, knockoutOpacity);
+    if (transpGroupStack->next != NULL && transpGroupStack->next->shape != NULL) {
+      transpGroupStack->next->knockout = gTrue;
+    }
   }
 
   // pop the stack
   transpGroup = transpGroupStack;
   transpGroupStack = transpGroup->next;
+  if (transpGroupStack != NULL && transpGroup->knockoutOpacity < transpGroupStack->knockoutOpacity) {
+    transpGroupStack->knockoutOpacity = transpGroup->knockoutOpacity;
+  }
+  delete transpGroup->shape;
   delete transpGroup;
 
   delete tBitmap;
diff --git a/splash/Splash.cc b/splash/Splash.cc
index 0e2058c..047bbe8 100644
--- a/splash/Splash.cc
+++ b/splash/Splash.cc
@@ -135,6 +135,10 @@ struct SplashPipe {
   // non-isolated group alpha0
   Guchar *alpha0Ptr;
 
+  // knockout groups
+  GBool knockout;
+  Guchar knockoutOpacity;
+
   // soft mask
   SplashColorPtr softMaskPtr;
 
@@ -240,7 +244,8 @@ inline void Splash::updateModY(int y) {
 inline void Splash::pipeInit(SplashPipe *pipe, int x, int y,
 			     SplashPattern *pattern, SplashColorPtr cSrc,
 			     Guchar aInput, GBool usesShape,
-			     GBool nonIsolatedGroup) {
+			     GBool nonIsolatedGroup,
+			     GBool knockout, Guchar knockoutOpacity) {
   pipeSetXY(pipe, x, y);
   pipe->pattern = NULL;
 
@@ -260,6 +265,10 @@ inline void Splash::pipeInit(SplashPipe *pipe, int x, int y,
   pipe->aInput = aInput;
   pipe->usesShape = usesShape;
 
+  // knockout
+  pipe->knockout = knockout;
+  pipe->knockoutOpacity = knockoutOpacity;
+
   // result alpha
   if (aInput == 255 && !state->softMask && !usesShape &&
       !state->inNonIsolatedGroup && !nonIsolatedGroup) {
@@ -500,6 +509,10 @@ void Splash::pipeRun(SplashPipe *pipe) {
 	  break;
 	}
 	cSrc = cSrcNonIso;
+        // knockout: remove backdrop color
+        if (pipe->knockout && pipe->shape >= pipe->knockoutOpacity) {
+          aDest = 0;
+        }
       }
     } else {
       cSrc = pipe->cSrc;
@@ -4651,7 +4664,8 @@ void Splash::blitImageClipped(SplashBitmap *src, GBool srcAlpha,
 
 SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc,
 			      int xDest, int yDest, int w, int h,
-			      GBool noClip, GBool nonIsolated) {
+			      GBool noClip, GBool nonIsolated,
+			      GBool knockout, SplashCoord knockoutOpacity) {
   SplashPipe pipe;
   SplashColor pixel;
   Guchar alpha;
@@ -4664,7 +4678,8 @@ SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc,
 
   if (src->alpha) {
     pipeInit(&pipe, xDest, yDest, NULL, pixel,
-	     (Guchar)splashRound(state->fillAlpha * 255), gTrue, nonIsolated);
+	     (Guchar)splashRound(state->fillAlpha * 255), gTrue, nonIsolated,
+	     knockout, (Guchar)splashRound(knockoutOpacity * 255));
     if (noClip) {
       for (y = 0; y < h; ++y) {
 	pipeSetXY(&pipe, xDest, yDest + y);
diff --git a/splash/Splash.h b/splash/Splash.h
index 53bfa81..bc82faa 100644
--- a/splash/Splash.h
+++ b/splash/Splash.h
@@ -215,7 +215,8 @@ public:
   // object.
   SplashError composite(SplashBitmap *src, int xSrc, int ySrc,
 			int xDest, int yDest, int w, int h,
-			GBool noClip, GBool nonIsolated);
+			GBool noClip, GBool nonIsolated,
+			GBool knockout = gFalse, SplashCoord knockoutOpacity = 1.0);
 
   // Composite this Splash object onto a background color.  The
   // background alpha is assumed to be 1.
@@ -274,7 +275,8 @@ private:
   void pipeInit(SplashPipe *pipe, int x, int y,
 		SplashPattern *pattern, SplashColorPtr cSrc,
 		Guchar aInput, GBool usesShape,
-		GBool nonIsolatedGroup);
+		GBool nonIsolatedGroup,
+		GBool knockout = gFalse, Guchar knockoutOpacity = 255);
   void pipeRun(SplashPipe *pipe);
   void pipeRunSimpleMono1(SplashPipe *pipe);
   void pipeRunSimpleMono8(SplashPipe *pipe);
diff --git a/splash/SplashBitmap.cc b/splash/SplashBitmap.cc
index ab5176e..6d37434 100644
--- a/splash/SplashBitmap.cc
+++ b/splash/SplashBitmap.cc
@@ -19,7 +19,7 @@
 // Copyright (C) 2010 Harry Roberts <harry.roberts at midnight-labs.org>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 // Copyright (C) 2010 William Bader <williambader at hotmail.com>
-// Copyright (C) 2011 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2011, 2012 Thomas Freitag <Thomas.Freitag at alfa.de>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -111,6 +111,26 @@ 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..5ef5573 100644
--- a/splash/SplashBitmap.h
+++ b/splash/SplashBitmap.h
@@ -19,6 +19,7 @@
 // Copyright (C) 2010 Harry Roberts <harry.roberts at midnight-labs.org>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 // Copyright (C) 2010 William Bader <williambader at hotmail.com>
+// Copyright (C) 2012 Thomas Freitag <Thomas.Freitag at alfa.de>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -51,6 +52,7 @@ public:
   SplashBitmap(int widthA, int heightA, int rowPad,
 	       SplashColorMode modeA, GBool alphaA,
 	       GBool topDown = gTrue);
+  static SplashBitmap *copy(SplashBitmap *src);
 
   ~SplashBitmap();
 


More information about the poppler mailing list