[poppler] Branch 'xpdf303merge' - 12 commits - Makefile.am poppler/CairoOutputDev.cc poppler/CairoOutputDev.h poppler/Gfx.cc poppler/OutputDev.cc poppler/OutputDev.h poppler/TextOutputDev.cc poppler/TextOutputDev.h regtest/backends regtest/.gitignore utils/CMakeLists.txt utils/.gitignore utils/Makefile.am utils/pdfextract.1 utils/pdfextract.cc utils/pdfmerge.1

Carlos Garcia Campos carlosgc at kemper.freedesktop.org
Sat Sep 24 02:25:10 PDT 2011


 Makefile.am                  |    2 
 poppler/CairoOutputDev.cc    |    8 +-
 poppler/CairoOutputDev.h     |    6 -
 poppler/Gfx.cc               |   40 ++++++++---
 poppler/OutputDev.cc         |    6 -
 poppler/OutputDev.h          |    4 -
 poppler/TextOutputDev.cc     |  145 +++++++++++++++++--------------------------
 poppler/TextOutputDev.h      |   21 ++----
 regtest/.gitignore           |    1 
 regtest/backends/__init__.py |    6 -
 regtest/backends/cairo.py    |    4 -
 regtest/backends/splash.py   |    4 -
 utils/.gitignore             |    2 
 utils/CMakeLists.txt         |    2 
 utils/Makefile.am            |    2 
 utils/pdfextract.1           |   49 ++++++++++++++
 utils/pdfextract.cc          |    4 +
 utils/pdfmerge.1             |   33 +++++++++
 18 files changed, 209 insertions(+), 130 deletions(-)

New commits:
commit f62c2f002c782d3a7887525f031d266aca6eb582
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Sat Sep 24 11:20:13 2011 +0200

    xpdf303: Parse ActualText in Gfx instead of output devices
    
    Remove beginMarkedContent and endMarkedcontent and add beginActualText
    and endActualText. ActualText is parsed in Gfx, that already handles the
    marked content stack, so that text output dev doesn't need to handle it
    too. The text string is passed to beginActualText(). This change is not
    an exact merge of xpdf code, I've tried to keep our implementation.

diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index ba29f0b..2ab9a11 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -1324,16 +1324,16 @@ void CairoOutputDev::endTextObject(GfxState *state) {
   }
 }
 
-void CairoOutputDev::beginMarkedContent(char *name, Dict *properties)
+void CairoOutputDev::beginActualText(GfxState *state, GooString *text)
 {
   if (text)
-    actualText->beginMC(properties);
+    actualText->begin(state, text);
 }
 
-void CairoOutputDev::endMarkedContent(GfxState *state)
+void CairoOutputDev::endActualText(GfxState *state)
 {
   if (text)
-    actualText->endMC(state);
+    actualText->end(state);
 }
 
 static inline int splashRound(SplashCoord x) {
diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h
index 722ce97..2d67ae1 100644
--- a/poppler/CairoOutputDev.h
+++ b/poppler/CairoOutputDev.h
@@ -184,6 +184,8 @@ public:
 		double dx, double dy,
 		double originX, double originY,
 		CharCode code, int nBytes, Unicode *u, int uLen);
+  void beginActualText(GfxState *state, GooString *text);
+  void endActualText(GfxState *state);
 
   virtual GBool beginType3Char(GfxState *state, double x, double y,
 			       double dx, double dy,
@@ -205,10 +207,6 @@ public:
 
   virtual void endMaskClip(GfxState *state);
 
-  //----- grouping operators
-  virtual void beginMarkedContent(char *name, Dict *properties);
-  virtual void endMarkedContent(GfxState *state);  
-
   //----- image drawing
   virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
 			     int width, int height, GBool invert, GBool interpolate,
diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
index ae08ce3..cbdb1a3 100644
--- a/poppler/Gfx.cc
+++ b/poppler/Gfx.cc
@@ -4766,7 +4766,14 @@ void Gfx::opEndIgnoreUndef(Object args[], int numArgs) {
 // marked content operators
 //------------------------------------------------------------------------
 
+enum GfxMarkedContentKind {
+  gfxMCOptionalContent,
+  gfxMCActualText,
+  gfxMCOther
+};
+
 struct MarkedContentStack {
+  GfxMarkedContentKind kind;
   GBool ocSuppressed;       // are we ignoring content based on OptionalContent?
   MarkedContentStack *next; // next object on stack
 };
@@ -4780,6 +4787,7 @@ void Gfx::popMarkedContent() {
 void Gfx::pushMarkedContent() {
   MarkedContentStack *mc = new MarkedContentStack();
   mc->ocSuppressed = gFalse;
+  mc->kind = gfxMCOther;
   mc->next = mcStack;
   mcStack = mc;
 }
@@ -4807,9 +4815,10 @@ void Gfx::opBeginMarkedContent(Object args[], int numArgs) {
       }
       char* name1 = args[1].getName();
       Object markedContent;
+      MarkedContentStack *mc = mcStack;
+      mc->kind = gfxMCOptionalContent;
       if ( res->lookupMarkedContentNF( name1, &markedContent ) ) {
         bool visible = contentConfig->optContentIsVisible(&markedContent);
-        MarkedContentStack *mc = mcStack;
         mc->ocSuppressed = !(visible);
       } else {
 	error(errSyntaxError, getPos(), "DID NOT find {0:s}", name1);
@@ -4818,6 +4827,14 @@ void Gfx::opBeginMarkedContent(Object args[], int numArgs) {
     } else {
       error(errSyntaxError, getPos(), "insufficient arguments for Marked Content");
     }
+  } else if (args[0].isName("Span") && numArgs == 2 && args[1].isDict()) {
+    Object obj;
+    if (args[1].dictLookup("ActualText", &obj)->isString()) {
+      out->beginActualText(state, obj.getString());
+      MarkedContentStack *mc = mcStack;
+      mc->kind = gfxMCActualText;
+    }
+    obj.free();
   }
 
   if (printCommands) {
@@ -4827,19 +4844,22 @@ void Gfx::opBeginMarkedContent(Object args[], int numArgs) {
     printf("\n");
     fflush(stdout);
   }
-
-  if(numArgs == 2 && args[1].isDict ()) {
-    out->beginMarkedContent(args[0].getName(),args[1].getDict());
-  } else if(numArgs == 1) {
-    out->beginMarkedContent(args[0].getName(),NULL);
-  }
 }
 
 void Gfx::opEndMarkedContent(Object args[], int numArgs) {
+  if (!mcStack) {
+    error(errSyntaxWarning, getPos(), "Mismatched EMC operator");
+    return;
+  }
+
+  MarkedContentStack *mc = mcStack;
+  GfxMarkedContentKind mcKind = mc->kind;
+
   // pop the stack
-  if (mcStack)
-    popMarkedContent();
-  out->endMarkedContent(state);
+  popMarkedContent();
+
+  if (mcKind == gfxMCActualText)
+    out->endActualText(state);
 }
 
 void Gfx::opMarkPoint(Object args[], int numArgs) {
diff --git a/poppler/OutputDev.cc b/poppler/OutputDev.cc
index 5adc7b8..6adaea5 100644
--- a/poppler/OutputDev.cc
+++ b/poppler/OutputDev.cc
@@ -145,12 +145,6 @@ void OutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str,
   drawImage(state, ref, str, width, height, colorMap, interpolate, NULL, gFalse);
 }
 
-void OutputDev::endMarkedContent(GfxState *state) {
-}
-
-void OutputDev::beginMarkedContent(char *name, Dict *properties) {
-}
-
 void OutputDev::markPoint(char *name) {
 }
 
diff --git a/poppler/OutputDev.h b/poppler/OutputDev.h
index 0ef11ee..75f2bd0 100644
--- a/poppler/OutputDev.h
+++ b/poppler/OutputDev.h
@@ -240,6 +240,8 @@ public:
   virtual void beginTextObject(GfxState * /*state*/) {}
   virtual GBool deviceHasTextClip(GfxState * /*state*/) { return gFalse; }
   virtual void endTextObject(GfxState * /*state*/) {}
+  virtual void beginActualText(GfxState * /*state*/, GooString * /*text*/ ) {}
+  virtual void endActualText(GfxState * /*state*/) {}
 
   //----- image drawing
   virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,
@@ -264,8 +266,6 @@ public:
 
   //----- grouping operators
 
-  virtual void endMarkedContent(GfxState *state);
-  virtual void beginMarkedContent(char *name, Dict *properties);
   virtual void markPoint(char *name);
   virtual void markPoint(char *name, Dict *properties);
   
diff --git a/poppler/TextOutputDev.cc b/poppler/TextOutputDev.cc
index f06ea17..5de089f 100644
--- a/poppler/TextOutputDev.cc
+++ b/poppler/TextOutputDev.cc
@@ -5037,7 +5037,7 @@ ActualText::ActualText(TextPage *out) {
   out->incRefCnt();
   text = out;
   actualText = NULL;
-  actualTextBMCLevel = 0;
+  actualTextNBytes = 0;
 }
 
 ActualText::~ActualText() {
@@ -5049,98 +5049,73 @@ ActualText::~ActualText() {
 void ActualText::addChar(GfxState *state, double x, double y,
 			 double dx, double dy,
 			 CharCode c, int nBytes, Unicode *u, int uLen) {
-  if (actualTextBMCLevel == 0) {
+  if (!actualText) {
     text->addChar(state, x, y, dx, dy, c, nBytes, u, uLen);
-  } else {
-    // Inside ActualText span.
-    if (newActualTextSpan) {
-      actualText_x = x;
-      actualText_y = y;
-      actualText_dx = dx;
-      actualText_dy = dy;
-      newActualTextSpan = gFalse;
-    } else {
-      if (x < actualText_x)
-	actualText_x = x;
-      if (y < actualText_y)
-	actualText_y = y;
-      if (x + dx > actualText_x + actualText_dx)
-	actualText_dx = x + dx - actualText_x;
-      if (y + dy > actualText_y + actualText_dy)
-	actualText_dy = y + dy - actualText_y;
-    }
-  }
-}
-
-void ActualText::beginMC(Dict *properties) {
-  if (actualTextBMCLevel > 0) {
-    // Already inside a ActualText span.
-    actualTextBMCLevel++;
     return;
   }
 
-  Object obj;
-  if (properties && properties->lookup("ActualText", &obj)) {
-    if (obj.isString()) {
-      actualText = obj.getString();
-      actualTextBMCLevel = 1;
-      newActualTextSpan = gTrue;
-    }
+  // Inside ActualText span.
+  if (!actualTextNBytes) {
+    actualTextX0 = x;
+    actualTextY0 = y;
   }
+  actualTextX1 = x + dx;
+  actualTextY1 = y + dy;
+  actualTextNBytes += nBytes;
 }
 
-void ActualText::endMC(GfxState *state) {
-  char *uniString = NULL;
-  Unicode *uni;
-  int length, i;
-
-  if (actualTextBMCLevel > 0) {
-    actualTextBMCLevel--;
-    if (actualTextBMCLevel == 0) {
-      // ActualText span closed. Output the span text and the
-      // extents of all the glyphs inside the span
-
-      if (newActualTextSpan) {
-	// No content inside span.
-	actualText_x = state->getCurX();
-	actualText_y = state->getCurY();
-	actualText_dx = 0;
-	actualText_dy = 0;
-      }
+void ActualText::begin(GfxState *state, GooString *text) {
+  if (actualText)
+    delete actualText;
+  actualText = new GooString(text);
+  actualTextNBytes = 0;
+}
 
-      if (!actualText->hasUnicodeMarker()) {
-	if (actualText->getLength() > 0) {
-	  //non-unicode string -- assume pdfDocEncoding and
-	  //try to convert to UTF16BE
-	  uniString = pdfDocEncodingToUTF16(actualText, &length);
-	} else {
-	  length = 0;
-	}
+void ActualText::end(GfxState *state) {
+  // ActualText span closed. Output the span text and the
+  // extents of all the glyphs inside the span
+
+  if (actualTextNBytes) {
+    char *uniString = NULL;
+    Unicode *uni;
+    int length, i;
+
+    if (!actualText->hasUnicodeMarker()) {
+      if (actualText->getLength() > 0) {
+        //non-unicode string -- assume pdfDocEncoding and
+        //try to convert to UTF16BE
+        uniString = pdfDocEncodingToUTF16(actualText, &length);
       } else {
-	uniString = actualText->getCString();
-	length = actualText->getLength();
+        length = 0;
       }
-
-      if (length < 3)
-	length = 0;
-      else
-	length = length/2 - 1;
-      uni = new Unicode[length];
-      for (i = 0 ; i < length; i++)
-	uni[i] = ((uniString[2 + i*2] & 0xff)<<8)|(uniString[3 + i*2] & 0xff);
-
-      text->addChar(state,
-		    actualText_x, actualText_y,
-		    actualText_dx, actualText_dy,
-		    0, 1, uni, length);
-
-      delete [] uni;
-      if (!actualText->hasUnicodeMarker())
-	delete [] uniString;
-      delete actualText;
-      actualText = NULL;
+    } else {
+      uniString = actualText->getCString();
+      length = actualText->getLength();
     }
+
+    if (length < 3)
+      length = 0;
+    else
+      length = length/2 - 1;
+    uni = new Unicode[length];
+    for (i = 0 ; i < length; i++)
+      uni[i] = ((uniString[2 + i*2] & 0xff)<<8)|(uniString[3 + i*2] & 0xff);
+
+    // now that we have the position info for all of the text inside
+    // the marked content span, we feed the "ActualText" back through
+    // text->addChar()
+    text->addChar(state, actualTextX0, actualTextY0,
+                  actualTextX1 - actualTextX0, actualTextY1 - actualTextY0,
+                  0, actualTextNBytes, uni, length);
+
+    delete [] uni;
+    if (!actualText->hasUnicodeMarker())
+      delete [] uniString;
   }
+
+  delete actualText;
+  actualText = NULL;
+  actualTextNBytes = 0;
 }
 
 //------------------------------------------------------------------------
@@ -5241,14 +5216,14 @@ void TextOutputDev::drawChar(GfxState *state, double x, double y,
   actualText->addChar(state, x, y, dx, dy, c, nBytes, u, uLen);
 }
 
-void TextOutputDev::beginMarkedContent(char *name, Dict *properties)
+void TextOutputDev::beginActualText(GfxState *state, GooString *text)
 {
-  actualText->beginMC(properties);
+  actualText->begin(state, text);
 }
 
-void TextOutputDev::endMarkedContent(GfxState *state)
+void TextOutputDev::endActualText(GfxState *state)
 {
-  actualText->endMC(state);
+  actualText->end(state);
 }
 
 void TextOutputDev::stroke(GfxState *state) {
diff --git a/poppler/TextOutputDev.h b/poppler/TextOutputDev.h
index a85f581..dff3921 100644
--- a/poppler/TextOutputDev.h
+++ b/poppler/TextOutputDev.h
@@ -644,17 +644,18 @@ public:
   void addChar(GfxState *state, double x, double y,
 	       double dx, double dy,
 	       CharCode c, int nBytes, Unicode *u, int uLen);
-  void beginMC(Dict *properties);
-  void endMC(GfxState *state);
+  void begin(GfxState *state, GooString *text);
+  void end(GfxState *state);
 
 private:
   TextPage *text;
-  int actualTextBMCLevel;       // > 0 when inside ActualText span. Incremented
-                                // for each nested BMC inside the span.
+
   GooString *actualText;        // replacement text for the span
-  GBool newActualTextSpan;      // true at start of span. used to init the extent
-  double actualText_x, actualText_y; // extent of the text inside the span
-  double actualText_dx, actualText_dy;
+  double actualTextX0;
+  double actualTextY0;
+  double actualTextX1;
+  double actualTextY1;
+  int actualTextNBytes;
 };
   
 
@@ -720,10 +721,8 @@ public:
 			double dx, double dy,
 			double originX, double originY,
 			CharCode c, int nBytes, Unicode *u, int uLen);
-
-  //----- grouping operators
-  virtual void beginMarkedContent(char *name, Dict *properties);
-  virtual void endMarkedContent(GfxState *state);
+  virtual void beginActualText(GfxState *state, GooString *text);
+  virtual void endActualText(GfxState *state);
 
   //----- path painting
   virtual void stroke(GfxState *state);
commit a097447ed13cb021003425f85597e2628935feb2
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Sat Sep 24 09:43:05 2011 +0200

    Use new error syntax in pdfextract

diff --git a/utils/pdfextract.cc b/utils/pdfextract.cc
index c2dd2ce..1d9c855 100644
--- a/utils/pdfextract.cc
+++ b/utils/pdfextract.cc
@@ -64,7 +64,7 @@ bool extractPages (const char *srcFileName, const char *destFileName) {
   if (firstPage == 0)
     firstPage = 1;
   if (firstPage != lastPage && strstr(destFileName, "%d") == NULL) {
-    error(-1, "'%s' must contain '%%d' if more than one page should be extracted", destFileName);
+    error(errSyntaxError, -1, "'{0:s}' must contain '%%d' if more than one page should be extracted", destFileName);
     return false;
   }
   for (int pageNo = firstPage; pageNo <= lastPage; pageNo++) {
commit 718c735aed540aa49b8dde250ca886c6ad93f5b6
Merge: 6721916... 69707f0...
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Sat Sep 24 09:38:52 2011 +0200

    Merge branch 'master' into xpdf303merge

commit 69707f0a9b5a94c80817039db943fb4f26e743e3
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Sep 19 22:00:34 2011 +0930

    Update .gitignore

diff --git a/regtest/.gitignore b/regtest/.gitignore
new file mode 100644
index 0000000..0d20b64
--- /dev/null
+++ b/regtest/.gitignore
@@ -0,0 +1 @@
+*.pyc
diff --git a/utils/.gitignore b/utils/.gitignore
index d8a48f4..d18e8c9 100644
--- a/utils/.gitignore
+++ b/utils/.gitignore
@@ -2,9 +2,11 @@
 .libs
 Makefile
 Makefile.in
+pdfextract
 pdffonts
 pdfimages
 pdfinfo
+pdfmerge
 pdftohtml
 pdftoppm
 pdftops
commit 0de477817e424078cfcfcae114e7745809f0848d
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Sep 19 21:57:07 2011 +0930

    utils: Add Glyph & Cog copyright to pdfmerge and pdfextract man pages

diff --git a/utils/pdfextract.1 b/utils/pdfextract.1
index 429e66d..2760045 100644
--- a/utils/pdfextract.1
+++ b/utils/pdfextract.1
@@ -43,6 +43,7 @@ extracts all pages from sample.pdf, if i.e. sample.pdf has 3 pages, it produces
 .TP
 sample-1.pdf, sample-2.pdf, sample-3.pdf
 .SH AUTHOR
-The pdfextract software and documentation are copyright 2011 The Poppler Developers - http://poppler.freedesktop.org
+The pdfextract software and documentation are copyright 1996-2004 Glyph
+& Cog, LLC and copyright 2005-2011 The Poppler Developers - http://poppler.freedesktop.org
 .SH "SEE ALSO"
 .BR pdfmerge (1),
diff --git a/utils/pdfmerge.1 b/utils/pdfmerge.1
index a6571d1..aecf555 100644
--- a/utils/pdfmerge.1
+++ b/utils/pdfmerge.1
@@ -27,6 +27,7 @@ pdfmerge sample1.pdf sample2.pdf sample.pdf
 .TP
 merges all pages from sample1.pdf and sample2.pdf (in that order) and creates sample.pdf
 .SH AUTHOR
-The pdfmerge software and documentation are copyright 2011 The Poppler Developers - http://poppler.freedesktop.org
+The pdfmerge software and documentation are copyright 1996-2004 Glyph & Cog, LLC
+and copyright 2005-2011 The Poppler Developers - http://poppler.freedesktop.org
 .SH "SEE ALSO"
 .BR pdfextract (1),
commit ce7372db64ee807dc2b491e121fbe557dbf697e8
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Sep 19 22:04:27 2011 +0930

    regtest: render cairo at 72ppi
    
    For consistency with splash. It is faster and easier to compare with splash results.

diff --git a/regtest/backends/cairo.py b/regtest/backends/cairo.py
index 0ec361f..a990ddf 100644
--- a/regtest/backends/cairo.py
+++ b/regtest/backends/cairo.py
@@ -28,8 +28,8 @@ class Cairo(Backend):
 
     def create_refs(self, doc_path, refs_path):
         out_path = os.path.join(refs_path, 'cairo')
-        p1 = subprocess.Popen([self._pdftocairo, '-cropbox', '-e', '-png', doc_path, out_path], stderr = subprocess.PIPE)
-        p2 = subprocess.Popen([self._pdftocairo, '-cropbox', '-o', '-png', doc_path, out_path], stderr = subprocess.PIPE)
+        p1 = subprocess.Popen([self._pdftocairo, '-cropbox', '-r', '72', '-e', '-png', doc_path, out_path], stderr = subprocess.PIPE)
+        p2 = subprocess.Popen([self._pdftocairo, '-cropbox', '-r', '72', '-o', '-png', doc_path, out_path], stderr = subprocess.PIPE)
         return self._check_exit_status2(p1, p2, out_path)
 
     def _create_diff(self, ref_path, result_path):
commit 6cf7330089c4dcc1099906d9c37c3607a2a1eeba
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Mon Sep 19 18:42:35 2011 +0200

    regtest: Ignore checksums of crashed, failed and stderr files
    
    They shouldn't have a checksum, but it might happen with md5 files
    generated with previous versions.

diff --git a/regtest/backends/__init__.py b/regtest/backends/__init__.py
index f54be80..2e90759 100644
--- a/regtest/backends/__init__.py
+++ b/regtest/backends/__init__.py
@@ -71,14 +71,14 @@ class Backend:
         for line in md5_file.readlines():
             md5sum, ref_path = line.strip('\n').split(' ', 1)
             basename = os.path.basename(ref_path)
+            if not self.__should_have_checksum(basename):
+                continue
+
             if not basename in tests:
                 retval = False
                 print("%s found in md5 ref file but missing in output dir %s" % (basename, out_path))
                 continue
 
-            if not self.__should_have_checksum(basename):
-                continue
-
             result_path = os.path.join(out_path, basename)
             f = open(result_path, 'rb')
             matched = md5sum == md5(f.read()).hexdigest()
commit 6512bf1c5dab37058460882fec3407b396830981
Author: Albert Astals Cid <aacid at kde.org>
Date:   Sun Sep 18 18:38:32 2011 +0200

    Render at 72 instead of 150, it's faster :D

diff --git a/regtest/backends/splash.py b/regtest/backends/splash.py
index bc5e448..5fbfba6 100644
--- a/regtest/backends/splash.py
+++ b/regtest/backends/splash.py
@@ -28,8 +28,8 @@ class Splash(Backend):
 
     def create_refs(self, doc_path, refs_path):
         out_path = os.path.join(refs_path, 'splash')
-        p1 = subprocess.Popen([self._pdftoppm, '-cropbox', '-e', '-png', doc_path, out_path], stderr = subprocess.PIPE)
-        p2 = subprocess.Popen([self._pdftoppm, '-cropbox', '-o', '-png', doc_path, out_path], stderr = subprocess.PIPE)
+        p1 = subprocess.Popen([self._pdftoppm, '-cropbox', '-r', '72', '-e', '-png', doc_path, out_path], stderr = subprocess.PIPE)
+        p2 = subprocess.Popen([self._pdftoppm, '-cropbox', '-r', '72', '-o', '-png', doc_path, out_path], stderr = subprocess.PIPE)
         return self._check_exit_status2(p1, p2, out_path)
 
     def _create_diff(self, ref_path, result_path):
commit b828f63ed3896a22f3fe7ddbe2ec2f549d7a2c62
Author: Albert Astals Cid <aacid at kde.org>
Date:   Sun Sep 18 18:20:47 2011 +0200

    install pdfextract and pdfmerge manpages

diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt
index 90030cd..a36616d 100644
--- a/utils/CMakeLists.txt
+++ b/utils/CMakeLists.txt
@@ -109,6 +109,7 @@ set(pdfextract_SOURCES ${common_srcs}
 add_executable(pdfextract ${pdfextract_SOURCES})
 target_link_libraries(pdfextract ${common_libs})
 install(TARGETS pdfextract DESTINATION bin)
+install(FILES pdfextract.1 DESTINATION share/man/man1)
 
 # pdfmerge
 set(pdfmerge_SOURCES ${common_srcs}
@@ -117,3 +118,4 @@ set(pdfmerge_SOURCES ${common_srcs}
 add_executable(pdfmerge ${pdfmerge_SOURCES})
 target_link_libraries(pdfmerge ${common_libs})
 install(TARGETS pdfmerge DESTINATION bin)
+install(FILES pdfmerge.1 DESTINATION share/man/man1)
commit 986759dfbe85998c85ee9b0825c7522395567531
Author: Thomas Freitag <Thomas.Freitag at kabelmail.de>
Date:   Sun Sep 18 18:19:30 2011 +0200

    pdfextract and pdfmerge man pages

diff --git a/utils/Makefile.am b/utils/Makefile.am
index 30328f2..ac2a15e 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -62,6 +62,8 @@ dist_man1_MANS =				\
 	pdftops.1				\
 	pdftotext.1				\
 	pdftohtml.1				\
+	pdfextract.1				\
+	pdfmerge.1				\
 	$(pdftoppm_manpage)			\
 	$(pdftocairo_manpage)
 
diff --git a/utils/pdfextract.1 b/utils/pdfextract.1
new file mode 100644
index 0000000..429e66d
--- /dev/null
+++ b/utils/pdfextract.1
@@ -0,0 +1,48 @@
+.\" Copyright 2011 The Poppler Developers - http://poppler.freedesktop.org
+.TH pdfextract 1 "15 September 2011"
+.SH NAME
+pdfextract \- Portable Document Format (PDF) page extractor
+.SH SYNOPSIS
+.B pdfextract
+[options]
+.I PDF-file PDF-page-pattern
+.SH DESCRIPTION
+.B pdfextract
+extract single pages from a Portable Document Format (PDF).
+.PP
+pdfextract reads the PDF file
+.IR PDF-file ,
+extracts one or more pages, and writes one PDF file for each page to
+.IR PDF-page-pattern,
+PDF-page-pattern should contain
+.B %d
+.%d is replaced by the page number
+.TP
+The PDF-file should not be encrypted.
+.SH OPTIONS
+.TP
+.BI \-f " number"
+Specifies the first page to extract. If -f is omitted, extraction starts with page 1.
+.TP
+.BI \-l " number"
+Specifies the last page to extract. if -p is omitted, extraction ends with the last page.
+.TP
+.B \-v
+Print copyright and version information.
+.TP
+.B \-h
+Print usage information.
+.RB ( \-help
+and
+.B \-\-help
+are equivalent.)
+.SH EXAMPLE
+pdfextract sample.pdf sample-%d.pdf
+.TP
+extracts all pages from sample.pdf, if i.e. sample.pdf has 3 pages, it produces
+.TP
+sample-1.pdf, sample-2.pdf, sample-3.pdf
+.SH AUTHOR
+The pdfextract software and documentation are copyright 2011 The Poppler Developers - http://poppler.freedesktop.org
+.SH "SEE ALSO"
+.BR pdfmerge (1),
diff --git a/utils/pdfmerge.1 b/utils/pdfmerge.1
new file mode 100644
index 0000000..a6571d1
--- /dev/null
+++ b/utils/pdfmerge.1
@@ -0,0 +1,32 @@
+.\" Copyright 2011 The Poppler Developers - http://poppler.freedesktop.org
+.TH pdfmerge 1 "15 September 2011"
+.SH NAME
+pdfmerge \- Portable Document Format (PDF) page merger
+.SH SYNOPSIS
+.B pdfmerge
+[options]
+.I PDF-sourcefile1..PDF-sourcefilen PDF-destfile
+.SH DESCRIPTION
+.B pdfmerge
+merges several PDF (Portable Document Format)  files in order of their occurence on command line to one PDF result file.
+.TP
+Neither of the PDF-sourcefile1 to PDF-sourcefilen should be encrypted.
+.SH OPTIONS
+.TP
+.B \-v
+Print copyright and version information.
+.TP
+.B \-h
+Print usage information.
+.RB ( \-help
+and
+.B \-\-help
+are equivalent.)
+.SH EXAMPLE
+pdfmerge sample1.pdf sample2.pdf sample.pdf
+.TP
+merges all pages from sample1.pdf and sample2.pdf (in that order) and creates sample.pdf
+.SH AUTHOR
+The pdfmerge software and documentation are copyright 2011 The Poppler Developers - http://poppler.freedesktop.org
+.SH "SEE ALSO"
+.BR pdfextract (1),
commit 90da1af542fd7f3cecef31b15da6971345b38209
Author: Thomas Freitag <Thomas.Freitag at kabelmail.de>
Date:   Sun Sep 18 18:19:04 2011 +0200

    Complain if %d is not present and it should

diff --git a/utils/pdfextract.cc b/utils/pdfextract.cc
index c8c4749..d6a7eb5 100644
--- a/utils/pdfextract.cc
+++ b/utils/pdfextract.cc
@@ -63,6 +63,10 @@ bool extractPages (const char *srcFileName, const char *destFileName) {
     lastPage = doc->getNumPages();
   if (firstPage == 0)
     firstPage = 1;
+  if (firstPage != lastPage && strstr(destFileName, "%d") == NULL) {
+    error(-1, "'%s' must contain '%%d' if more than one page should be extracted", destFileName);
+    return false;
+  }
   for (int pageNo = firstPage; pageNo <= lastPage; pageNo++) {
     sprintf (pathName, destFileName, pageNo);
     GooString *gpageName = new GooString (pathName);
commit 40e066a84ddb3a5c41805c095659af5f5704d6d8
Author: suzuki toshiya <mpsuzuki at hiroshima-u.ac.jp>
Date:   Sun Sep 18 18:16:14 2011 +0200

    qt_subdir is unneeded

diff --git a/Makefile.am b/Makefile.am
index 3d2b68f..60c82dc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -29,7 +29,7 @@ if BUILD_UTILS
 utils_subdir = utils
 endif
 
-SUBDIRS = goo fofi $(splash_subdir) poppler $(utils_subdir) $(glib_subdir) $(qt_subdir) test $(qt4_subdir) $(cpp_subdir)
+SUBDIRS = goo fofi $(splash_subdir) poppler $(utils_subdir) $(glib_subdir) test $(qt4_subdir) $(cpp_subdir)
 
 EXTRA_DIST =					\
 	README-XPDF				\


More information about the poppler mailing list