[poppler] 3 commits - poppler/GfxState.cc poppler/PSOutputDev.cc poppler/Stream.cc poppler/Stream.h

Albert Astals Cid aacid at kemper.freedesktop.org
Wed Feb 29 14:19:41 PST 2012


 poppler/GfxState.cc    |    3 
 poppler/PSOutputDev.cc |  285 ++++++++++++++++++++++++++++++++++++++++---------
 poppler/Stream.cc      |   55 ++++++++-
 poppler/Stream.h       |   39 +++++-
 4 files changed, 323 insertions(+), 59 deletions(-)

New commits:
commit aec6cb67951e56e4557a11c4fdf301e585268fe4
Author: William Bader <williambader at hotmail.com>
Date:   Wed Feb 29 23:18:16 2012 +0100

    Fix stuff lost when merging xpdf303
    
    restore the implementation of -binary
    restore the fix that level2sep and level3sep must write cmyk instead of rgb
    restore the conversion of bitmaps with all gray to mono8
    fixed the CMYK misspelling in Stream.

diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc
index ebc3553..d8e3ac3 100644
--- a/poppler/PSOutputDev.cc
+++ b/poppler/PSOutputDev.cc
@@ -3069,6 +3069,10 @@ GBool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/,
   int c, w, h, x, y, comp, i;
   int numComps;
 #endif
+  char hexBuf[32*2 + 2];	// 32 values X 2 chars/value + line ending + null
+  Guchar digit;
+  GBool useBinary;
+  GBool isGray;
 
   if (globalParams->getPSAlwaysRasterize()) {
     rasterize = gTrue;
@@ -3104,18 +3108,22 @@ GBool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/,
 
   // set up the SplashOutputDev
   if (mono || level == psLevel1) {
+    numComps = 1;
     paperColor[0] = 0xff;
     splashOut = new SplashOutputDev(splashModeMono8, 1, gFalse,
 				    paperColor, gFalse,
 				    globalParams->getAntialiasPrinting());
 #if SPLASH_CMYK
-  } else if (level == psLevel1Sep || globalParams->getOverprintPreview()) {
+  } else if (level == psLevel1Sep || level == psLevel2Sep ||
+	     level == psLevel3Sep || globalParams->getOverprintPreview()) {
+    numComps = 4;
     paperColor[0] = paperColor[1] = paperColor[2] = paperColor[3] = 0;
     splashOut = new SplashOutputDev(splashModeCMYK8, 1, gFalse,
 				    paperColor, gFalse,
 				    globalParams->getAntialiasPrinting());
 #endif
   } else {
+    numComps = 3;
     paperColor[0] = paperColor[1] = paperColor[2] = 0xff;
     splashOut = new SplashOutputDev(splashModeRGB8, 1, gFalse,
 				    paperColor, gFalse,
@@ -3166,44 +3174,182 @@ GBool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/,
 	       m0, m1, m2, m3, m4, m5);
     switch (level) {
     case psLevel1:
-      writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1\n",
-		 w, h, w, -h, h);
+      useBinary = globalParams->getPSBinary();
+      writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1{5:s}\n",
+		 w, h, w, -h, h,
+		 useBinary ? "Bin" : "");
       p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize();
       i = 0;
-      for (y = 0; y < h; ++y) {
-	for (x = 0; x < w; ++x) {
-	  writePSFmt("{0:02x}", *p++);
-	  if (++i == 32) {
-	    writePSChar('\n');
-	    i = 0;
+      if (useBinary) {
+	for (y = 0; y < h; ++y) {
+	  for (x = 0; x < w; ++x) {
+	    hexBuf[i++] = *p++;
+	    if (i >= 64) {
+	      writePSBuf(hexBuf, i);
+	      i = 0;
+	    }
+	  }
+	}
+      } else {
+	for (y = 0; y < h; ++y) {
+	  for (x = 0; x < w; ++x) {
+	    digit = *p / 16;
+	    hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
+	    digit = *p++ % 16;
+	    hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
+	    if (i >= 64) {
+	      hexBuf[i++] = '\n';
+	      writePSBuf(hexBuf, i);
+	      i = 0;
+	    }
 	  }
 	}
       }
       if (i != 0) {
-	writePSChar('\n');
+        if (!useBinary) {
+	  hexBuf[i++] = '\n';
+        }
+        writePSBuf(hexBuf, i);
       }
       break;
     case psLevel1Sep:
-      writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1Sep\n",
-		 w, h, w, -h, h);
+      useBinary = globalParams->getPSBinary();
+      p = bitmap->getDataPtr();
+      // Check for an all gray image
+      isGray = gTrue;
+      for (y = 0; y < h; ++y) {
+	for (x = 0; x < w; ++x) {
+	  if (p[4*x] != p[4*x + 1] || p[4*x] != p[4*x + 2]) {
+	    isGray = gFalse;
+	    y = h;
+	    break;
+	  }
+	}
+	p += bitmap->getRowSize();
+      }
+      writePSFmt("{0:d} {1:d} 8 [{2:d} 0 0 {3:d} 0 {4:d}] pdfIm1{5:s}{6:s}\n",
+		 w, h, w, -h, h,
+		 isGray ? "" : "Sep",
+		 useBinary ? "Bin" : "");
       p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize();
       i = 0;
       col[0] = col[1] = col[2] = col[3] = 0;
-      for (y = 0; y < h; ++y) {
-	for (comp = 0; comp < 4; ++comp) {
-	  for (x = 0; x < w; ++x) {
-	    writePSFmt("{0:02x}", p[4*x + comp]);
-	    col[comp] |= p[4*x + comp];
-	    if (++i == 32) {
-	      writePSChar('\n');
-	      i = 0;
+      if (isGray) {
+        int g;
+        if ((psProcessBlack & processColors) == 0) {
+	  // Check if the image uses black
+	  for (y = 0; y < h; ++y) {
+	    for (x = 0; x < w; ++x) {
+	      if (p[4*x] > 0 || p[4*x + 3] > 0) {
+	        col[3] = 1;
+	        y = h;
+	        break;
+	      }
 	    }
+            p -= bitmap->getRowSize();
 	  }
-	}
-	p -= bitmap->getRowSize();
+          p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize();
+        }
+        for (y = 0; y < h; ++y) {
+	  if (useBinary) {
+	    // Binary gray image
+	    for (x = 0; x < w; ++x) {
+	      g = p[4*x] + p[4*x + 3];
+	      g = 255 - g;
+	      if (g < 0) g = 0;
+	      hexBuf[i++] = (Guchar) g;
+	      if (i >= 64) {
+	        writePSBuf(hexBuf, i);
+	        i = 0;
+	      }
+	    }
+	  } else {
+	    // Hex gray image
+	    for (x = 0; x < w; ++x) {
+	      g = p[4*x] + p[4*x + 3];
+	      g = 255 - g;
+	      if (g < 0) g = 0;
+	      digit = g / 16;
+	      hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
+	      digit = g % 16;
+	      hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
+	      if (i >= 64) {
+	        hexBuf[i++] = '\n';
+	        writePSBuf(hexBuf, i);
+	        i = 0;
+	      }
+	    }
+          }
+          p -= bitmap->getRowSize();
+        }
+      } else if (((psProcessCyan | psProcessMagenta | psProcessYellow | psProcessBlack) & ~processColors) != 0) {
+	// Color image, need to check color flags for each dot
+        for (y = 0; y < h; ++y) {
+          for (comp = 0; comp < 4; ++comp) {
+	    if (useBinary) {
+	      // Binary color image
+	      for (x = 0; x < w; ++x) {
+	        col[comp] |= p[4*x + comp];
+	        hexBuf[i++] = p[4*x + comp];
+	        if (i >= 64) {
+	          writePSBuf(hexBuf, i);
+	          i = 0;
+	        }
+	      }
+	    } else {
+	      // Gray color image
+	      for (x = 0; x < w; ++x) {
+	        col[comp] |= p[4*x + comp];
+	        digit = p[4*x + comp] / 16;
+	        hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
+	        digit = p[4*x + comp] % 16;
+	        hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
+	        if (i >= 64) {
+	          hexBuf[i++] = '\n';
+	          writePSBuf(hexBuf, i);
+	          i = 0;
+	        }
+	      }
+	    }
+          }
+          p -= bitmap->getRowSize();
+        }
+      } else {
+	// Color image, do not need to check color flags
+        for (y = 0; y < h; ++y) {
+          for (comp = 0; comp < 4; ++comp) {
+	    if (useBinary) {
+	      // Binary color image
+	      for (x = 0; x < w; ++x) {
+	        hexBuf[i++] = p[4*x + comp];
+	        if (i >= 64) {
+	          writePSBuf(hexBuf, i);
+	          i = 0;
+	        }
+	      }
+	    } else {
+	      // Hex color image
+	      for (x = 0; x < w; ++x) {
+	        digit = p[4*x + comp] / 16;
+	        hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
+	        digit = p[4*x + comp] % 16;
+	        hexBuf[i++] = digit + ((digit >= 10)? 'a' - 10: '0');
+	        if (i >= 64) {
+	          hexBuf[i++] = '\n';
+	          writePSBuf(hexBuf, i);
+	          i = 0;
+	        }
+	      }
+	    }
+          }
+          p -= bitmap->getRowSize();
+        }
       }
       if (i != 0) {
-	writePSChar('\n');
+        if (!useBinary) {
+          hexBuf[i++] = '\n';
+        }
+        writePSBuf(hexBuf, i);
       }
       if (col[0]) {
 	processColors |= psProcessCyan;
@@ -3222,51 +3368,92 @@ GBool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/,
     case psLevel2Sep:
     case psLevel3:
     case psLevel3Sep:
-      if (mono) {
-	writePS("/DeviceGray setcolorspace\n");
-#if SPLASH_CMYK
-      } else if (globalParams->getOverprintPreview()) {
-	writePS("/DeviceCMYK setcolorspace\n");
-#endif      
+      obj.initNull();
+      p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize();
+      str0 = new MemStream((char *)p, 0, w * h * numComps, &obj);
+      // Check for a color image that uses only gray
+      if (numComps == 4) {
+        int compCyan;
+        isGray = gTrue;
+        while ((compCyan = str0->getChar()) != EOF) {
+	  if (str0->getChar() != compCyan ||
+	      str0->getChar() != compCyan) {
+	    isGray = gFalse;
+	    break;
+	  }
+	  str0->getChar();
+	}
+      } else if (numComps == 3) {
+	int compRed;
+	isGray = gTrue;
+	while ((compRed = str0->getChar()) != EOF) {
+	  if (str0->getChar() != compRed ||
+	      str0->getChar() != compRed) {
+	    isGray = gFalse;
+	    break;
+	  }
+	}
       } else {
+        isGray = gFalse;
+      }
+      str0->reset();
+      if (isGray && numComps == 4) {
+	str = new RunLengthEncoder(new CMYKGrayEncoder(str0));
+	numComps = 1;
+      } else if (isGray && numComps == 3) {
+	str = new RunLengthEncoder(new RGBGrayEncoder(str0));
+	numComps = 1;
+      } else {
+	str = new RunLengthEncoder(str0);
+      }
+      if (numComps == 1) {
+	writePS("/DeviceGray setcolorspace\n");
+      } else if (numComps == 3) {
 	writePS("/DeviceRGB setcolorspace\n");
+      } else {
+	writePS("/DeviceCMYK setcolorspace\n");
       }
       writePS("<<\n  /ImageType 1\n");
       writePSFmt("  /Width {0:d}\n", bitmap->getWidth());
       writePSFmt("  /Height {0:d}\n", bitmap->getHeight());
       writePSFmt("  /ImageMatrix [{0:d} 0 0 {1:d} 0 {2:d}]\n", w, -h, h);
       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 {
+      if (numComps == 1) {
+	writePS("  /Decode [1 0]\n");
+      } else if (numComps == 3) {
 	writePS("  /Decode [0 1 0 1 0 1]\n");
-	numComps = 3;
+      } else {
+	writePS("  /Decode [0 1 0 1 0 1 0 1]\n");
       }
       writePS("  /DataSource currentfile\n");
-      if (globalParams->getPSASCIIHex()) {
+      useBinary = globalParams->getPSBinary();
+      if (useBinary) {
+	/* nothing to do */;
+      } else if (globalParams->getPSASCIIHex()) {
 	writePS("    /ASCIIHexDecode filter\n");
       } else {
 	writePS("    /ASCII85Decode filter\n");
       }
       writePS("    /RunLengthDecode filter\n");
       writePS(">>\n");
-      writePS("image\n");
-      obj.initNull();
-      p = bitmap->getDataPtr() + (h - 1) * bitmap->getRowSize();
-      str0 = new MemStream((char *)p, 0, w * h * numComps, &obj);
-      str = new RunLengthEncoder(str0);
-      if (globalParams->getPSASCIIHex()) {
+      if (useBinary) {
+	/* nothing to do */;
+      } else if (globalParams->getPSASCIIHex()) {
 	str = new ASCIIHexEncoder(str);
       } else {
 	str = new ASCII85Encoder(str);
       }
       str->reset();
+      if (useBinary) {
+	// Count the bytes to write a document comment
+	int len = 0;
+	while (str->getChar() != EOF) {
+	  len++;
+	}
+	str->reset();
+	writePSFmt("%%BeginData: {0:d} Binary Bytes\n", len+6+1);
+      }
+      writePS("image\n");
       while ((c = str->getChar()) != EOF) {
 	writePSChar(c);
       }
@@ -3274,7 +3461,10 @@ GBool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/,
       delete str;
       delete str0;
       writePSChar('\n');
-      processColors |= mono ? psProcessBlack : psProcessCMYK;
+      if (useBinary) {
+	writePS("%%EndData\n");
+      }
+      processColors |= (numComps == 1) ? psProcessBlack : psProcessCMYK;
       break;
     }
     writePS("grestore\n");
diff --git a/poppler/Stream.cc b/poppler/Stream.cc
index 04aac31..8bb12bd 100644
--- a/poppler/Stream.cc
+++ b/poppler/Stream.cc
@@ -22,7 +22,7 @@
 // Copyright (C) 2009 Stefan Thomas <thomas at eload24.com>
 // Copyright (C) 2010 Hib Eris <hib at hiberis.nl>
 // Copyright (C) 2010 Tomas Hoger <thoger at redhat.com>
-// Copyright (C) 2011 William Bader <williambader at hotmail.com>
+// Copyright (C) 2011, 2012 William Bader <williambader at hotmail.com>
 // Copyright (C) 2012 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2012 Oliver Sander <sander at mi.fu-berlin.de>
 //
@@ -5160,27 +5160,27 @@ GBool RunLengthEncoder::fillBuf() {
 }
 
 //------------------------------------------------------------------------
-// CMKYGrayEncoder
+// CMYKGrayEncoder
 //------------------------------------------------------------------------
 
-CMKYGrayEncoder::CMKYGrayEncoder(Stream *strA):
+CMYKGrayEncoder::CMYKGrayEncoder(Stream *strA):
     FilterStream(strA) {
   bufPtr = bufEnd = buf;
   eof = gFalse;
 }
 
-CMKYGrayEncoder::~CMKYGrayEncoder() {
+CMYKGrayEncoder::~CMYKGrayEncoder() {
   if (str->isEncoder())
     delete str;
 }
 
-void CMKYGrayEncoder::reset() {
+void CMYKGrayEncoder::reset() {
   str->reset();
   bufPtr = bufEnd = buf;
   eof = gFalse;
 }
 
-GBool CMKYGrayEncoder::fillBuf() {
+GBool CMYKGrayEncoder::fillBuf() {
   int c0, c1, c2, c3;
   int i;
 
@@ -5201,3 +5201,46 @@ GBool CMKYGrayEncoder::fillBuf() {
   *bufEnd++ = (char) i;
   return gTrue;
 }
+
+//------------------------------------------------------------------------
+// RGBGrayEncoder
+//------------------------------------------------------------------------
+
+RGBGrayEncoder::RGBGrayEncoder(Stream *strA):
+    FilterStream(strA) {
+  bufPtr = bufEnd = buf;
+  eof = gFalse;
+}
+
+RGBGrayEncoder::~RGBGrayEncoder() {
+  if (str->isEncoder())
+    delete str;
+}
+
+void RGBGrayEncoder::reset() {
+  str->reset();
+  bufPtr = bufEnd = buf;
+  eof = gFalse;
+}
+
+GBool RGBGrayEncoder::fillBuf() {
+  int c0, c1, c2;
+  int i;
+
+  if (eof) {
+    return gFalse;
+  }
+  c0 = str->getChar();
+  c1 = str->getChar();
+  c2 = str->getChar();
+  if (c2 == EOF) {
+    eof = gTrue;
+    return gFalse;
+  }
+  i = 255 - (3 * c0 + 6 * c1 + c2) / 10;
+  if (i < 0) i = 0;
+  bufPtr = bufEnd = buf;
+  *bufEnd++ = (char) i;
+  return gTrue;
+}
+
diff --git a/poppler/Stream.h b/poppler/Stream.h
index 33165aa..a270fdf 100644
--- a/poppler/Stream.h
+++ b/poppler/Stream.h
@@ -19,7 +19,7 @@
 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
 // Copyright (C) 2009 Stefan Thomas <thomas at eload24.com>
 // Copyright (C) 2010 Hib Eris <hib at hiberis.nl>
-// Copyright (C) 2011 William Bader <williambader at hotmail.com>
+// Copyright (C) 2011, 2012 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
@@ -1179,14 +1179,43 @@ private:
 };
 
 //------------------------------------------------------------------------
-// CMKYGrayEncoder
+// CMYKGrayEncoder
 //------------------------------------------------------------------------
 
-class CMKYGrayEncoder: public FilterStream {
+class CMYKGrayEncoder: public FilterStream {
 public:
 
-  CMKYGrayEncoder(Stream *strA);
-  virtual ~CMKYGrayEncoder();
+  CMYKGrayEncoder(Stream *strA);
+  virtual ~CMYKGrayEncoder();
+  virtual StreamKind getKind() { return strWeird; }
+  virtual void reset();
+  virtual int getChar()
+    { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); }
+  virtual int lookChar()
+    { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); }
+  virtual GooString *getPSFilter(int /*psLevel*/, const char * /*indent*/) { return NULL; }
+  virtual GBool isBinary(GBool /*last = gTrue*/) { return gFalse; }
+  virtual GBool isEncoder() { return gTrue; }
+
+private:
+
+  char buf[2];
+  char *bufPtr;
+  char *bufEnd;
+  GBool eof;
+
+  GBool fillBuf();
+};
+
+//------------------------------------------------------------------------
+// RGBGrayEncoder
+//------------------------------------------------------------------------
+
+class RGBGrayEncoder: public FilterStream {
+public:
+
+  RGBGrayEncoder(Stream *strA);
+  virtual ~RGBGrayEncoder();
   virtual StreamKind getKind() { return strWeird; }
   virtual void reset();
   virtual int getChar()
commit e977925a1eb15083e6b020b31da77ddef9d5df02
Author: William Bader <williambader at hotmail.com>
Date:   Wed Feb 29 23:12:24 2012 +0100

    Fix double alloc
    
    xpdf303 merge glitch

diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc
index 0c48b5a..ebc3553 100644
--- a/poppler/PSOutputDev.cc
+++ b/poppler/PSOutputDev.cc
@@ -1249,7 +1249,6 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
   fontIDSize = 64;
   fontIDLen = 0;
   fontIDs = (Ref *)gmallocn(fontIDSize, sizeof(Ref));
-  fontIDs = (Ref *)gmallocn(fontIDSize, sizeof(Ref));
   for (i = 0; i < 14; ++i) {
     fontNames->add(new GooString(psBase14SubstFonts[i].psName), 1);
   }
commit e13efe04facdc10f3acffece3b057544f018f40c
Author: William Bader <williambader at hotmail.com>
Date:   Wed Feb 29 23:10:43 2012 +0100

    Fix memory leak
    
    Wrong merge from xpdf303

diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc
index b33e9be..75c87e9 100644
--- a/poppler/GfxState.cc
+++ b/poppler/GfxState.cc
@@ -23,6 +23,7 @@
 // Copyright (C) 2010 Paweł Wiejacha <pawel.wiejacha at gmail.com>
 // Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 // Copyright (C) 2011 Andrea Canciani <ranma42 at gmail.com>
+// Copyright (C) 2012 William Bader <williambader at hotmail.com>
 //
 // 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
@@ -4836,6 +4837,7 @@ GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode,
 
   // initialize
   for (k = 0; k < gfxColorMaxComps; ++k) {
+    lookup[k] = NULL;
     lookup2[k] = NULL;
   }
   byte_lookup = NULL;
@@ -5024,6 +5026,7 @@ GfxImageColorMap::~GfxImageColorMap() {
 
   delete colorSpace;
   for (i = 0; i < gfxColorMaxComps; ++i) {
+    gfree(lookup[i]);
     gfree(lookup2[i]);
   }
   gfree(byte_lookup);


More information about the poppler mailing list