[poppler] poppler/PSOutputDev.cc poppler/PSOutputDev.h poppler/SplashOutputDev.cc poppler/SplashOutputDev.h splash/Splash.cc splash/Splash.h splash/SplashState.cc splash/SplashState.h utils/pdftops.cc

Albert Astals Cid aacid at kemper.freedesktop.org
Tue Feb 14 10:38:22 PST 2012


 poppler/PSOutputDev.cc     |   67 ++++++++++--
 poppler/PSOutputDev.h      |    3 
 poppler/SplashOutputDev.cc |   62 +++++++++--
 poppler/SplashOutputDev.h  |    4 
 splash/Splash.cc           |   70 +++++++++---
 splash/Splash.h            |    4 
 splash/SplashState.cc      |    5 
 splash/SplashState.h       |  247 ++++++++++++++++++++++-----------------------
 utils/pdftops.cc           |   13 ++
 9 files changed, 308 insertions(+), 167 deletions(-)

New commits:
commit 59946e0c34e762eb5f5a13b4ae8c9ec7fb21379a
Author: Thomas Freitag <Thomas.Freitag at alfa.de>
Date:   Tue Feb 14 19:37:21 2012 +0100

    Overprint implementation in postscript and splash device
    
    It is an enhancement patch, a
    merge fix and a bug fix in one: an enhancement, because it now completes
    the implementation overprint mode and devicen in postscript, a merge
    fix, because it fixes some bugs in the overprint implementation in
    splash of xpdf 3.0.3 and has now the complete functionality (and more!)
    of my implementation back again and a bug fix, because it fixes the use
    of splash cmyk in postscript which never had worked.
    
    1. Overprint implementation in postscript
    To have a complete overprint implementation in the (pure) postscript
    device there were just two things missing: overprint mode and the
    implementation of the DeviceN colorspace in PostScript. I double checked
    my implementation with the Ghent Test Suite with GhostScript (device
    pdfwrite) and Acrobat X distiller, and all the tests now succeeds,
    either in Acrobat X distiller or in GhostScript. As overprint is a
    device dependent feature, it is up to the output device if it supports
    overprint and what features of overprint are supported, and often You
    have various configuration possibilities there. Nearly all PostScript
    output of the Ghent tests show now the desired results if converting it
    back to PDF with ghostscript pdfwrite, the implementation in ghostscript
    is complete. On the other hand a few tests failed when using Acrobat X
    distiller, all of them with the overprint mode switch. Funny, because
    overprint mode 1 is often also called the illustrator overprint mode
    because it was introduced by illustrator, but probably the destiller
    only handles EPS correctly which comes from illustrator
    
    2. Overprint implementation in postscript if using splash rasterization
    Of course the postscript overprint implementation will only work if
    pdftops doesn't decide to use splash to rasterize it because of the use
    of transparencies in the PDF. But because overprint is device dependent
    I decided to spend an additional parameter "overprint" to pdftops
    (simular to pdftoppm). Switching it on (only available if compiled with
    SPLASH_CMYK, because overprint is only in CMYK colorspace showable) will
    use the overprint implementation in splash also if rasterizing the PDF.
    
    3. Overprint implementation in splash
    The overprint implementation in splash now uses the better designed
    interface of xpdf and therefore now also works in transparency groups.
    Thanks to the developper team of xpdf. I just fixed a small bug in it,
    where it defies the technical specification. Of course it is still in
    the nature of the splash implementation that it fails if CMYK values
    should overprint spot colors, because spot colors are converted
    immediately in their CMYK alternates. And in the implementation of
    overprinting spot colors over CMYK colors I made a small assumption to
    get it running which causes undesired results if this assumption fails,
    but I didn't want to implement more and more configuration switches. I
    still plan to implement a DeviceN output in splash and make a complete
    implementation there, but this is of course a bigger task (but doable).
    The overprint switch in pdftoppm is still only available if compiled
    with the SPLASH_CMYK directive.

diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc
index ad12964..4b3ecd6 100644
--- a/poppler/PSOutputDev.cc
+++ b/poppler/PSOutputDev.cc
@@ -20,7 +20,7 @@
 // Copyright (C) 2007, 2008 Brad Hards <bradh at kde.org>
 // Copyright (C) 2008, 2009 Koji Otani <sho at bbr.jp>
 // Copyright (C) 2008, 2010 Hib Eris <hib at hiberis.nl>
-// Copyright (C) 2009-2011 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2009-2012 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2009 Till Kamppeter <till.kamppeter at gmail.com>
 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
 // Copyright (C) 2009, 2011 William Bader <williambader at hotmail.com>
@@ -161,6 +161,8 @@ static const char *prolog[] = {
   "  /pdfStroke [0] def",
   "  /pdfFillOP false def",
   "  /pdfStrokeOP false def",
+  "~3sn",
+  "  /pdfOPM false def",
   "~123sn",
   "  /pdfLastFill false def",
   "  /pdfLastStroke false def",
@@ -253,6 +255,9 @@ static const char *prolog[] = {
   "    /pdfLastStroke true def /pdfLastFill false def",
   "  } if",
   "} def",
+  "~3n",
+  "/opm { dup /pdfOPM exch def",
+  "      setoverprintmode } def",
   "~23n",
   "/cs { /pdfFillXform exch def dup /pdfFillCS exch def",
   "      setcolorspace } def",
@@ -284,6 +289,9 @@ static const char *prolog[] = {
   "    /pdfLastStroke true def /pdfLastFill false def",
   "  } if",
   "} def",
+  "~3s",
+  "/opm { dup /pdfOPM exch def",
+  "      setoverprintmode } def",
   "~23s",
   "/k { 4 copy 4 array astore /pdfFill exch def setcmykcolor",
   "     /pdfLastFill true def /pdfLastStroke false def } def",
@@ -378,6 +386,12 @@ static const char *prolog[] = {
   "      pdfStrokeOP setoverprint",
   "    } ifelse",
   "  } if",
+  "~3sn",
+  "  /pdfOPM where {",
+  "    pop",
+  "    pdfOPM setoverprintmode",
+  "  } if",
+  "~23sn",
   "} def",
   "~123sn",
   "/cm { concat } def",
@@ -3054,6 +3068,7 @@ GBool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/,
   double m0, m1, m2, m3, m4, m5;
   int nStripes, stripeH, stripeY;
   int c, w, h, x, y, comp, i;
+  int numComps;
 #endif
 
   if (globalParams->getPSAlwaysRasterize()) {
@@ -3089,13 +3104,13 @@ GBool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/,
   delete state;
 
   // set up the SplashOutputDev
-  if (mono || level == psLevel1) {
+  if (mono) {
     paperColor[0] = 0xff;
     splashOut = new SplashOutputDev(splashModeMono8, 1, gFalse,
 				    paperColor, gFalse,
 				    globalParams->getAntialiasPrinting());
 #if SPLASH_CMYK
-  } else if (level == psLevel1Sep) {
+  } else if (level == psLevel1Sep || globalParams->getOverprintPreview()) {
     paperColor[0] = paperColor[1] = paperColor[2] = paperColor[3] = 0;
     splashOut = new SplashOutputDev(splashModeCMYK8, 1, gFalse,
 				    paperColor, gFalse,
@@ -3210,6 +3225,10 @@ GBool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/,
     case psLevel3Sep:
       if (mono) {
 	writePS("/DeviceGray setcolorspace\n");
+#if SPLASH_CMYK
+      } else if (globalParams->getOverprintPreview()) {
+	writePS("/DeviceCMYK setcolorspace\n");
+#endif      
       } else {
 	writePS("/DeviceRGB setcolorspace\n");
       }
@@ -3220,8 +3239,15 @@ GBool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/,
       writePS("  /BitsPerComponent 8\n");
       if (mono) {
 	writePS("  /Decode [0 1]\n");
+	numComps = 1;
+#if SPLASH_CMYK
+      } else if (globalParams->getOverprintPreview()) {
+	writePS("  /Decode [0 1 0 1 0 1 0 1]\n");
+	numComps = 4;
+#endif      
       } else {
 	writePS("  /Decode [0 1 0 1 0 1]\n");
+	numComps = 3;
       }
       writePS("  /DataSource currentfile\n");
       if (globalParams->getPSASCIIHex()) {
@@ -3234,7 +3260,7 @@ GBool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/,
       writePS("image\n");
       obj.initNull();
       p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize();
-      str0 = new MemStream((char *)p, 0, w * h * (mono ? 1 : 3), &obj);
+      str0 = new MemStream((char *)p, 0, w * h * numComps, &obj);
       str = new RunLengthEncoder(str0);
       if (globalParams->getPSASCIIHex()) {
 	str = new ASCIIHexEncoder(str);
@@ -3811,6 +3837,12 @@ void PSOutputDev::updateStrokeOverprint(GfxState *state) {
   }
 }
 
+void PSOutputDev::updateOverprintMode(GfxState *state) {
+  if (level >= psLevel3) {
+    writePSFmt("{0:s} opm\n", state->getOverprintMode() ? "true" : "false");
+  }
+}
+
 void PSOutputDev::updateTransfer(GfxState *state) {
   Function **funcs;
   int i;
@@ -6211,7 +6243,7 @@ void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace,
     numComps = baseCS->getNComps();
     lookup = indexedCS->getLookup();
     writePSFmt(" {0:d} <\n", n);
-    if (baseCS->getMode() == csDeviceN) {
+    if (baseCS->getMode() == csDeviceN && level != psLevel3 && level != psLevel3Sep) {
       func = ((GfxDeviceNColorSpace *)baseCS)->getTintTransformFunc();
       baseCS->getDefaultRanges(low, range, indexedCS->getIndexHigh());
       if (((GfxDeviceNColorSpace *)baseCS)->getAlt()->getMode() == csLab) {
@@ -6294,12 +6326,29 @@ void PSOutputDev::dumpColorSpaceL2(GfxColorSpace *colorSpace,
     break;
 
   case csDeviceN:
-    // DeviceN color spaces are a Level 3 PostScript feature.
     deviceNCS = (GfxDeviceNColorSpace *)colorSpace;
-    dumpColorSpaceL2(deviceNCS->getAlt(), gFalse, updateColors, map01);
-    if (genXform) {
-      writePS(" ");
+    if (level == psLevel3 || level == psLevel3Sep) {      
+      writePS("[/DeviceN\n");
+      writePS("  [ ");
+      for (i = 0; i < deviceNCS->getNComps(); i++) {
+        writePSString(deviceNCS->getColorantName(i));
+        writePS(" ");
+      }
+      writePS("]\n");
+      dumpColorSpaceL2(deviceNCS->getAlt(), gFalse, updateColors, map01);
+      writePS("\n");
       cvtFunction(deviceNCS->getTintTransformFunc());
+      writePS("]\n");
+      if (genXform) {
+        writePS(" {}");
+      }
+    } else {
+      // DeviceN color spaces are a Level 3 PostScript feature.
+      dumpColorSpaceL2(deviceNCS->getAlt(), gFalse, updateColors, map01);
+      if (genXform) {
+        writePS(" ");
+        cvtFunction(deviceNCS->getTintTransformFunc());
+      }
     }
     break;
 
diff --git a/poppler/PSOutputDev.h b/poppler/PSOutputDev.h
index b2bd028..ed23c5c 100644
--- a/poppler/PSOutputDev.h
+++ b/poppler/PSOutputDev.h
@@ -17,7 +17,7 @@
 // Copyright (C) 2005 Kristian Høgsberg <krh at redhat.com>
 // Copyright (C) 2006-2008 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2007 Brad Hards <bradh at kde.org>
-// Copyright (C) 2009-2011 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2009-2012 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2009 Till Kamppeter <till.kamppeter at gmail.com>
 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
 // Copyright (C) 2009, 2011 William Bader <williambader at hotmail.com>
@@ -203,6 +203,7 @@ public:
   virtual void updateStrokeColor(GfxState *state);
   virtual void updateFillOverprint(GfxState *state);
   virtual void updateStrokeOverprint(GfxState *state);
+  virtual void updateOverprintMode(GfxState *state);
   virtual void updateTransfer(GfxState *state);
 
   //----- update text state
diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc
index 246a37d..ae35106 100644
--- a/poppler/SplashOutputDev.cc
+++ b/poppler/SplashOutputDev.cc
@@ -20,7 +20,7 @@
 // Copyright (C) 2006 Scott Turner <scotty1024 at mac.com>
 // Copyright (C) 2007 Koji Otani <sho at bbr.jp>
 // Copyright (C) 2009 Petr Gajdos <pgajdos at novell.com>
-// Copyright (C) 2009-2011 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2009-2012 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
 // Copyright (C) 2009 William Bader <williambader at hotmail.com>
 // Copyright (C) 2010 Patrick Spendrin <ps_ml at gmx.de>
@@ -1549,7 +1549,6 @@ SplashPattern *SplashOutputDev::getColor(GfxCMYK *cmyk) {
   color[1] = colToByte(cmyk->m);
   color[2] = colToByte(cmyk->y);
   color[3] = colToByte(cmyk->k);
-  // return createOverprintPattern(colorSpace, color, gFalse);
   return new SplashSolidColor(color);
 }
 #endif
@@ -1557,17 +1556,26 @@ SplashPattern *SplashOutputDev::getColor(GfxCMYK *cmyk) {
 void SplashOutputDev::setOverprintMask(GfxColorSpace *colorSpace,
 				       GBool overprintFlag,
 				       int overprintMode,
-				       GfxColor *singleColor) {
+				       GfxColor *singleColor,
+				       GBool grayIndexed) {
 #if SPLASH_CMYK
   Guint mask;
   GfxCMYK cmyk;
+  GBool additive = gFalse;
+  int i;
 
+  if (colorSpace->getMode() == csIndexed) {
+    setOverprintMask(((GfxIndexedColorSpace *)colorSpace)->getBase(),
+		     overprintFlag,
+		     overprintMode,
+		     singleColor,
+		     grayIndexed);
+		return;
+	}
   if (overprintFlag && globalParams->getOverprintPreview()) {
     mask = colorSpace->getOverprintMask();
     if (singleColor && overprintMode &&
-	(colorSpace->getMode() == csDeviceCMYK ||
-	 (colorSpace->getMode() == csICCBased &&
-	  colorSpace->getNComps() == 4))) {
+	colorSpace->getMode() == csDeviceCMYK) {
       colorSpace->getCMYK(singleColor, &cmyk);
       if (cmyk.c == 0) {
 	mask &= ~1;
@@ -1582,10 +1590,30 @@ void SplashOutputDev::setOverprintMask(GfxColorSpace *colorSpace,
 	mask &= ~8;
       }
     }
+    if (grayIndexed) {
+      mask &= ~7;
+    } else if (colorSpace->getMode() == csSeparation) {
+      GfxSeparationColorSpace *deviceSep = (GfxSeparationColorSpace *)colorSpace;
+      additive = deviceSep->getName()->cmp("All") != 0 && mask == 0x0f && !deviceSep->isNonMarking();
+    } else if (colorSpace->getMode() == csDeviceN) {
+      GfxDeviceNColorSpace *deviceNCS = (GfxDeviceNColorSpace *)colorSpace;
+      additive = mask == 0x0f && !deviceNCS->isNonMarking();
+      for (i = 0; i < deviceNCS->getNComps() && additive; i++) {
+        if (deviceNCS->getColorantName(i)->cmp("Cyan") == 0) {
+          additive = gFalse;
+        } else if (deviceNCS->getColorantName(i)->cmp("Magenta") == 0) {
+          additive = gFalse;
+        } else if (deviceNCS->getColorantName(i)->cmp("Yellow") == 0) {
+          additive = gFalse;
+        } else if (deviceNCS->getColorantName(i)->cmp("Black") == 0) {
+          additive = gFalse;
+        }
+      }
+    }
   } else {
     mask = 0xffffffff;
   }
-  splash->setOverprintMask(mask);
+  splash->setOverprintMask(mask, additive);
 #endif
 }
 
@@ -2950,13 +2978,11 @@ void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
   GfxRGB rgb;
 #if SPLASH_CMYK
   GfxCMYK cmyk;
+  GBool grayIndexed = gFalse;
 #endif
   Guchar pix;
   int n, i;
 
-  setOverprintMask(colorMap->getColorSpace(), state->getFillOverprint(),
-		   state->getOverprintMode(), NULL);
-
   ctm = state->getCTM();
   for (i = 0; i < 6; ++i) {
     if (!isfinite(ctm[i])) return;
@@ -3018,10 +3044,14 @@ void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
       break;
 #if SPLASH_CMYK
     case splashModeCMYK8:
+      grayIndexed = colorMap->getColorSpace()->getMode() != csDeviceGray;
       imgData.lookup = (SplashColorPtr)gmallocn(n, 4);
       for (i = 0; i < n; ++i) {
 	pix = (Guchar)i;
 	colorMap->getCMYK(&pix, &cmyk);
+	if (cmyk.c != 0 || cmyk.m != 0 || cmyk.y != 0) {
+	  grayIndexed = gFalse;
+	}
 	imgData.lookup[4*i] = colToByte(cmyk.c);
 	imgData.lookup[4*i+1] = colToByte(cmyk.m);
 	imgData.lookup[4*i+2] = colToByte(cmyk.y);
@@ -3032,6 +3062,14 @@ void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
     }
   }
 
+#if SPLASH_CMYK
+  setOverprintMask(colorMap->getColorSpace(), state->getFillOverprint(),
+		   state->getOverprintMode(), NULL, grayIndexed);
+#else		   
+  setOverprintMask(colorMap->getColorSpace(), state->getFillOverprint(),
+		   state->getOverprintMode(), NULL);
+#endif		   
+
   if (colorMode == splashModeMono1) {
     srcMode = splashModeMono8;
   } else {
@@ -3638,7 +3676,7 @@ 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()) {
-    splash->setOverprintMask(0xffffffff);
+    splash->setOverprintMask(0xffffffff, gFalse);
     splash->composite(tBitmap, 0, 0, tx, ty,
 		      tBitmap->getWidth(), tBitmap->getHeight(),
 		      gFalse, !isolated);
@@ -4076,6 +4114,8 @@ GBool SplashOutputDev::univariateShadedFill(GfxState *state, SplashUnivariatePat
   state->closePath();
   path = convertPath(state, state->getPath(), gTrue);
 
+  setOverprintMask(pattern->getShading()->getColorSpace(), state->getFillOverprint(),
+		   state->getOverprintMode(), state->getFillColor());
   retVal = (splash->shadedFill(path, pattern->getShading()->getHasBBox(), pattern) == splashOk);
   state->clearPath();
   setVectorAntialias(vaa);
diff --git a/poppler/SplashOutputDev.h b/poppler/SplashOutputDev.h
index 230e751..91e678f 100644
--- a/poppler/SplashOutputDev.h
+++ b/poppler/SplashOutputDev.h
@@ -14,7 +14,7 @@
 // under GPL version 2 or later
 //
 // Copyright (C) 2005 Takashi Iwai <tiwai at suse.de>
-// Copyright (C) 2009-2011 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2009-2012 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 // Copyright (C) 2011 Andreas Hartmetz <ahartmetz at gmail.com>
@@ -359,7 +359,7 @@ private:
   SplashPattern *getColor(GfxCMYK *cmyk);
 #endif
   void setOverprintMask(GfxColorSpace *colorSpace, GBool overprintFlag,
-			int overprintMode, GfxColor *singleColor);
+			int overprintMode, GfxColor *singleColor, GBool grayIndexed = gFalse);
   SplashPath *convertPath(GfxState *state, GfxPath *path,
 			  GBool dropEmptySubpaths);
   void doUpdateFont(GfxState *state);
diff --git a/splash/Splash.cc b/splash/Splash.cc
index fcab28c..76a80f7 100644
--- a/splash/Splash.cc
+++ b/splash/Splash.cc
@@ -13,7 +13,7 @@
 //
 // Copyright (C) 2005-2011 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2005 Marco Pesenti Gritti <mpg at redhat.com>
-// Copyright (C) 2010, 2011 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2010-2012 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 // Copyright (C) 2011 William Bader <williambader at hotmail.com>
 //
@@ -48,6 +48,7 @@
 #include "SplashFont.h"
 #include "SplashGlyphBitmap.h"
 #include "Splash.h"
+#include <algorithm>
 
 //------------------------------------------------------------------------
 
@@ -383,16 +384,24 @@ void Splash::pipeRun(SplashPipe *pipe) {
 #if SPLASH_CMYK
     case splashModeCMYK8:
       if (state->overprintMask & 1) {
-	pipe->destColorPtr[0] = state->cmykTransferC[pipe->cSrc[0]];
+	pipe->destColorPtr[0] = (state->overprintAdditive) ? 
+              std::min<int>(pipe->destColorPtr[0] + state->cmykTransferC[pipe->cSrc[0]], 255) :
+              state->cmykTransferC[pipe->cSrc[0]];
       }
       if (state->overprintMask & 2) {
-	pipe->destColorPtr[1] = state->cmykTransferM[pipe->cSrc[1]];
+	pipe->destColorPtr[1] = (state->overprintAdditive) ? 
+              std::min<int>(pipe->destColorPtr[1] + state->cmykTransferM[pipe->cSrc[1]], 255) :
+              state->cmykTransferC[pipe->cSrc[1]];
       }
       if (state->overprintMask & 4) {
-	pipe->destColorPtr[2] = state->cmykTransferY[pipe->cSrc[2]];
+	pipe->destColorPtr[2] = (state->overprintAdditive) ? 
+              std::min<int>(pipe->destColorPtr[2] + state->cmykTransferY[pipe->cSrc[2]], 255) :
+              state->cmykTransferC[pipe->cSrc[2]];
       }
       if (state->overprintMask & 8) {
-	pipe->destColorPtr[3] = state->cmykTransferK[pipe->cSrc[3]];
+	pipe->destColorPtr[3] = (state->overprintAdditive) ? 
+              std::min<int>(pipe->destColorPtr[3] + state->cmykTransferK[pipe->cSrc[3]], 255) :
+              state->cmykTransferC[pipe->cSrc[3]];
       }
       pipe->destColorPtr += 4;
       break;
@@ -708,16 +717,24 @@ void Splash::pipeRun(SplashPipe *pipe) {
 #if SPLASH_CMYK
     case splashModeCMYK8:
       if (state->overprintMask & 1) {
-	pipe->destColorPtr[0] = cResult0;
+	pipe->destColorPtr[0] = (state->overprintAdditive) ? 
+              std::min<int>(pipe->destColorPtr[0] + cResult0, 255) :
+              cResult0;
       }
       if (state->overprintMask & 2) {
-	pipe->destColorPtr[1] = cResult1;
+	pipe->destColorPtr[1] = (state->overprintAdditive) ? 
+              std::min<int>(pipe->destColorPtr[1] + cResult1, 255) :
+              cResult1;
       }
       if (state->overprintMask & 4) {
-	pipe->destColorPtr[2] = cResult2;
+	pipe->destColorPtr[2] = (state->overprintAdditive) ? 
+              std::min<int>(pipe->destColorPtr[2] + cResult2, 255) :
+              cResult2;
       }
       if (state->overprintMask & 8) {
-	pipe->destColorPtr[3] = cResult3;
+	pipe->destColorPtr[3] = (state->overprintAdditive) ? 
+              std::min<int>(pipe->destColorPtr[3] + cResult3, 255) :
+              cResult3;
       }
       pipe->destColorPtr += 4;
       break;
@@ -811,16 +828,24 @@ void Splash::pipeRunSimpleBGR8(SplashPipe *pipe) {
 void Splash::pipeRunSimpleCMYK8(SplashPipe *pipe) {
   //----- write destination pixel
   if (state->overprintMask & 1) {
-    pipe->destColorPtr[0] = state->cmykTransferC[pipe->cSrc[0]];
+    pipe->destColorPtr[0] = (state->overprintAdditive) ? 
+              std::min<int>(pipe->destColorPtr[0] + state->cmykTransferC[pipe->cSrc[0]], 255) :
+              state->cmykTransferC[pipe->cSrc[0]];
   }
   if (state->overprintMask & 2) {
-    pipe->destColorPtr[1] = state->cmykTransferM[pipe->cSrc[1]];
+    pipe->destColorPtr[1] = (state->overprintAdditive) ? 
+              std::min<int>(pipe->destColorPtr[1] + state->cmykTransferM[pipe->cSrc[1]], 255) :
+              state->cmykTransferC[pipe->cSrc[1]];
   }
   if (state->overprintMask & 4) {
-    pipe->destColorPtr[2] = state->cmykTransferY[pipe->cSrc[2]];
+    pipe->destColorPtr[2] = (state->overprintAdditive) ? 
+              std::min<int>(pipe->destColorPtr[2] + state->cmykTransferY[pipe->cSrc[2]], 255) :
+              state->cmykTransferC[pipe->cSrc[2]];
   }
   if (state->overprintMask & 8) {
-    pipe->destColorPtr[3] = state->cmykTransferK[pipe->cSrc[3]];
+    pipe->destColorPtr[3] = (state->overprintAdditive) ? 
+              std::min<int>(pipe->destColorPtr[3] + state->cmykTransferK[pipe->cSrc[3]], 255) :
+              state->cmykTransferC[pipe->cSrc[3]];
   }
   pipe->destColorPtr += 4;
   *pipe->destAlphaPtr++ = 255;
@@ -1084,16 +1109,24 @@ void Splash::pipeRunAACMYK8(SplashPipe *pipe) {
 
   //----- write destination pixel
   if (state->overprintMask & 1) {
-    pipe->destColorPtr[0] = cResult0;
+    pipe->destColorPtr[0] = (state->overprintAdditive && pipe->shape != 0) ? 
+              std::min<int>(pipe->destColorPtr[0] + cResult0, 255) :
+              cResult0;
   }
   if (state->overprintMask & 2) {
-    pipe->destColorPtr[1] = cResult1;
+    pipe->destColorPtr[1] = (state->overprintAdditive && pipe->shape != 0) ? 
+              std::min<int>(pipe->destColorPtr[1] + cResult1, 255) :
+              cResult1;
   }
   if (state->overprintMask & 4) {
-    pipe->destColorPtr[2] = cResult2;
+    pipe->destColorPtr[2] = (state->overprintAdditive && pipe->shape != 0) ? 
+              std::min<int>(pipe->destColorPtr[2] + cResult2, 255) :
+              cResult2;
   }
   if (state->overprintMask & 8) {
-    pipe->destColorPtr[3] = cResult3;
+    pipe->destColorPtr[3] = (state->overprintAdditive && pipe->shape != 0) ? 
+              std::min<int>(pipe->destColorPtr[3] + cResult3, 255) :
+              cResult3;
   }
   pipe->destColorPtr += 4;
   *pipe->destAlphaPtr++ = aResult;
@@ -1606,8 +1639,9 @@ void Splash::setTransfer(Guchar *red, Guchar *green, Guchar *blue,
   state->setTransfer(red, green, blue, gray);
 }
 
-void Splash::setOverprintMask(Guint overprintMask) {
+void Splash::setOverprintMask(Guint overprintMask, GBool additive) {
   state->overprintMask = overprintMask;
+  state->overprintAdditive = additive;
 }
 
 //------------------------------------------------------------------------
diff --git a/splash/Splash.h b/splash/Splash.h
index 3c2bf9f..53bfa81 100644
--- a/splash/Splash.h
+++ b/splash/Splash.h
@@ -13,7 +13,7 @@
 //
 // Copyright (C) 2005 Marco Pesenti Gritti <mpg at redhat.com>
 // Copyright (C) 2007, 2011 Albert Astals Cid <aacid at kde.org>
-// Copyright (C) 2010, 2011 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2010-2012 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 //
 // To see a description of the changes please see the Changelog file that
@@ -146,7 +146,7 @@ public:
   void setInNonIsolatedGroup(SplashBitmap *alpha0BitmapA,
 			     int alpha0XA, int alpha0YA);
   void setTransfer(Guchar *red, Guchar *green, Guchar *blue, Guchar *gray);
-  void setOverprintMask(Guint overprintMask);
+  void setOverprintMask(Guint overprintMask, GBool additive);
 
   //----- state save/restore
 
diff --git a/splash/SplashState.cc b/splash/SplashState.cc
index 7b632b8..e258f66 100644
--- a/splash/SplashState.cc
+++ b/splash/SplashState.cc
@@ -11,7 +11,7 @@
 // All changes made under the Poppler project to this file are licensed
 // under GPL version 2 or later
 //
-// Copyright (C) 2009, 2011 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2009, 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
@@ -86,6 +86,7 @@ SplashState::SplashState(int width, int height, GBool vectorAntialias,
     cmykTransferK[i] = (Guchar)i;
   }
   overprintMask = 0xffffffff;
+  overprintAdditive = gFalse;
   next = NULL;
 }
 
@@ -131,6 +132,7 @@ SplashState::SplashState(int width, int height, GBool vectorAntialias,
     cmykTransferK[i] = (Guchar)i;
   }
   overprintMask = 0xffffffff;
+  overprintAdditive = gFalse;
   next = NULL;
 }
 
@@ -173,6 +175,7 @@ SplashState::SplashState(SplashState *state) {
   memcpy(cmykTransferY, state->cmykTransferY, 256);
   memcpy(cmykTransferK, state->cmykTransferK, 256);
   overprintMask = state->overprintMask;
+  overprintAdditive = state->overprintAdditive;
   next = NULL;
 }
 
diff --git a/splash/SplashState.h b/splash/SplashState.h
index 214bffa..01e7772 100644
--- a/splash/SplashState.h
+++ b/splash/SplashState.h
@@ -1,122 +1,122 @@
-//========================================================================
-//
-// SplashState.h
-//
-//========================================================================
-
-//========================================================================
-//
-// Modified under the Poppler project - http://poppler.freedesktop.org
-//
-// All changes made under the Poppler project to this file are licensed
-// under GPL version 2 or later
-//
-// Copyright (C) 2011 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
-//
-//========================================================================
-
-#ifndef SPLASHSTATE_H
-#define SPLASHSTATE_H
-
-#ifdef USE_GCC_PRAGMAS
-#pragma interface
-#endif
-
-#include "SplashTypes.h"
-
-class SplashPattern;
-class SplashScreen;
-class SplashClip;
-class SplashBitmap;
-
-//------------------------------------------------------------------------
-// line cap values
-//------------------------------------------------------------------------
-
-#define splashLineCapButt       0
-#define splashLineCapRound      1
-#define splashLineCapProjecting 2
-
-//------------------------------------------------------------------------
-// line join values
-//------------------------------------------------------------------------
-
-#define splashLineJoinMiter     0
-#define splashLineJoinRound     1
-#define splashLineJoinBevel     2
-
-//------------------------------------------------------------------------
-// SplashState
-//------------------------------------------------------------------------
-
-class SplashState {
-public:
-
-  // Create a new state object, initialized with default settings.
-  SplashState(int width, int height, GBool vectorAntialias,
-	      SplashScreenParams *screenParams);
-  SplashState(int width, int height, GBool vectorAntialias,
-	      SplashScreen *screenA);
-
-  // Copy a state object.
-  SplashState *copy() { return new SplashState(this); }
-
-  ~SplashState();
-
-  // Set the stroke pattern.  This does not copy <strokePatternA>.
-  void setStrokePattern(SplashPattern *strokePatternA);
-
-  // Set the fill pattern.  This does not copy <fillPatternA>.
-  void setFillPattern(SplashPattern *fillPatternA);
-
-  // Set the screen.  This does not copy <screenA>.
-  void setScreen(SplashScreen *screenA);
-
-  // Set the line dash pattern.  This copies the <lineDashA> array.
-  void setLineDash(SplashCoord *lineDashA, int lineDashLengthA,
-		   SplashCoord lineDashPhaseA);
-
-  // Set the soft mask bitmap.
-  void setSoftMask(SplashBitmap *softMaskA);
-
-  // Set the overprint parametes.
-  void setFillOverprint(GBool fillOverprintA) { fillOverprint = fillOverprintA; }
-  void setStrokeOverprint(GBool strokeOverprintA) { strokeOverprint = strokeOverprintA; }
-  void setOverprintMode(int overprintModeA) { overprintMode = overprintModeA; }
-
+//========================================================================
+//
+// SplashState.h
+//
+//========================================================================
+
+//========================================================================
+//
+// Modified under the Poppler project - http://poppler.freedesktop.org
+//
+// All changes made under the Poppler project to this file are licensed
+// under GPL version 2 or later
+//
+// 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
+//
+//========================================================================
+
+#ifndef SPLASHSTATE_H
+#define SPLASHSTATE_H
+
+#ifdef USE_GCC_PRAGMAS
+#pragma interface
+#endif
+
+#include "SplashTypes.h"
+
+class SplashPattern;
+class SplashScreen;
+class SplashClip;
+class SplashBitmap;
+
+//------------------------------------------------------------------------
+// line cap values
+//------------------------------------------------------------------------
+
+#define splashLineCapButt       0
+#define splashLineCapRound      1
+#define splashLineCapProjecting 2
+
+//------------------------------------------------------------------------
+// line join values
+//------------------------------------------------------------------------
+
+#define splashLineJoinMiter     0
+#define splashLineJoinRound     1
+#define splashLineJoinBevel     2
+
+//------------------------------------------------------------------------
+// SplashState
+//------------------------------------------------------------------------
+
+class SplashState {
+public:
+
+  // Create a new state object, initialized with default settings.
+  SplashState(int width, int height, GBool vectorAntialias,
+	      SplashScreenParams *screenParams);
+  SplashState(int width, int height, GBool vectorAntialias,
+	      SplashScreen *screenA);
+
+  // Copy a state object.
+  SplashState *copy() { return new SplashState(this); }
+
+  ~SplashState();
+
+  // Set the stroke pattern.  This does not copy <strokePatternA>.
+  void setStrokePattern(SplashPattern *strokePatternA);
+
+  // Set the fill pattern.  This does not copy <fillPatternA>.
+  void setFillPattern(SplashPattern *fillPatternA);
+
+  // Set the screen.  This does not copy <screenA>.
+  void setScreen(SplashScreen *screenA);
+
+  // Set the line dash pattern.  This copies the <lineDashA> array.
+  void setLineDash(SplashCoord *lineDashA, int lineDashLengthA,
+		   SplashCoord lineDashPhaseA);
+
+  // Set the soft mask bitmap.
+  void setSoftMask(SplashBitmap *softMaskA);
+
+  // Set the overprint parametes.
+  void setFillOverprint(GBool fillOverprintA) { fillOverprint = fillOverprintA; }
+  void setStrokeOverprint(GBool strokeOverprintA) { strokeOverprint = strokeOverprintA; }
+  void setOverprintMode(int overprintModeA) { overprintMode = overprintModeA; }
+
   // Set the transfer function.
   void setTransfer(Guchar *red, Guchar *green, Guchar *blue, Guchar *gray);
 
-private:
-
-  SplashState(SplashState *state);
-
-  SplashCoord matrix[6];
-  SplashPattern *strokePattern;
-  SplashPattern *fillPattern;
-  SplashScreen *screen;
-  SplashBlendFunc blendFunc;
-  SplashCoord strokeAlpha;
-  SplashCoord fillAlpha;
-  SplashCoord lineWidth;
-  int lineCap;
-  int lineJoin;
-  SplashCoord miterLimit;
-  SplashCoord flatness;
-  SplashCoord *lineDash;
-  int lineDashLength;
-  SplashCoord lineDashPhase;
-  GBool strokeAdjust;
-  SplashClip *clip;
-  SplashBitmap *softMask;
-  GBool deleteSoftMask;
-  GBool inNonIsolatedGroup;
-  GBool fillOverprint;
-  GBool strokeOverprint;
-  int overprintMode;
+private:
+
+  SplashState(SplashState *state);
+
+  SplashCoord matrix[6];
+  SplashPattern *strokePattern;
+  SplashPattern *fillPattern;
+  SplashScreen *screen;
+  SplashBlendFunc blendFunc;
+  SplashCoord strokeAlpha;
+  SplashCoord fillAlpha;
+  SplashCoord lineWidth;
+  int lineCap;
+  int lineJoin;
+  SplashCoord miterLimit;
+  SplashCoord flatness;
+  SplashCoord *lineDash;
+  int lineDashLength;
+  SplashCoord lineDashPhase;
+  GBool strokeAdjust;
+  SplashClip *clip;
+  SplashBitmap *softMask;
+  GBool deleteSoftMask;
+  GBool inNonIsolatedGroup;
+  GBool fillOverprint;
+  GBool strokeOverprint;
+  int overprintMode;
   Guchar rgbTransferR[256],
          rgbTransferG[256],
          rgbTransferB[256];
@@ -126,10 +126,11 @@ private:
          cmykTransferY[256],
          cmykTransferK[256];
   Guint overprintMask;
-
-  SplashState *next;		// used by Splash class
-
-  friend class Splash;
-};
-
-#endif
+  GBool overprintAdditive;
+
+  SplashState *next;		// used by Splash class
+
+  friend class Splash;
+};
+
+#endif
diff --git a/utils/pdftops.cc b/utils/pdftops.cc
index 542838b..5cf3410 100644
--- a/utils/pdftops.cc
+++ b/utils/pdftops.cc
@@ -21,6 +21,7 @@
 // Copyright (C) 2009 Sanjoy Mahajan <sanjoy at mit.edu>
 // Copyright (C) 2009, 2011 William Bader <williambader at hotmail.com>
 // Copyright (C) 2010 Hib Eris <hib at hiberis.nl>
+// 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
@@ -106,6 +107,9 @@ static char userPassword[33] = "\001";
 static GBool quiet = gFalse;
 static GBool printVersion = gFalse;
 static GBool printHelp = gFalse;
+#if SPLASH_CMYK
+static GBool overprint = gFalse;
+#endif
 
 static const ArgDesc argDesc[] = {
   {"-f",          argInt,      &firstPage,      0,
@@ -170,6 +174,10 @@ static const ArgDesc argDesc[] = {
    "owner password (for encrypted files)"},
   {"-upw",        argString,   userPassword,    sizeof(userPassword),
    "user password (for encrypted files)"},
+#if SPLASH_CMYK
+  {"-overprint",argFlag,   &overprint,      0,
+   "enable overprint"},
+#endif
   {"-q",          argFlag,     &quiet,          0,
    "don't print any messages or errors"},
   {"-v",          argFlag,     &printVersion,   0,
@@ -260,6 +268,11 @@ int main(int argc, char *argv[]) {
       goto err0;
     }
   }
+#if SPLASH_CMYK
+  if (overprint) {
+    globalParams->setOverprintPreview(gTrue);
+  }
+#endif  
   if (expand) {
     globalParams->setPSExpandSmaller(gTrue);
   }


More information about the poppler mailing list