[poppler] 8 commits - poppler/CairoOutputDev.h poppler/PSOutputDev.cc poppler/PSOutputDev.h qt4/src qt5/src utils/pdftocairo.1 utils/pdftocairo.cc utils/pdftops.1 utils/pdftops.cc

Adrian Johnson ajohnson at kemper.freedesktop.org
Wed Feb 5 01:13:55 PST 2014


 poppler/CairoOutputDev.h        |    4 
 poppler/PSOutputDev.cc          |  249 ++++++++++++++++++++++++----------------
 poppler/PSOutputDev.h           |   10 +
 qt4/src/poppler-ps-converter.cc |    1 
 qt5/src/poppler-ps-converter.cc |    1 
 utils/pdftocairo.1              |   26 +---
 utils/pdftocairo.cc             |   20 ++-
 utils/pdftops.1                 |   30 +---
 utils/pdftops.cc                |   24 ++-
 9 files changed, 214 insertions(+), 151 deletions(-)

New commits:
commit 4cda839cb489fe5cd4726109cb9ab8b0ba2fa563
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Tue Jan 28 06:06:09 2014 +1030

    pdftops: ensure there is always a page size in the output
    
    even if the PDF file as badly broken.

diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc
index 34b7cbd..a85fc24 100644
--- a/poppler/PSOutputDev.cc
+++ b/poppler/PSOutputDev.cc
@@ -1257,6 +1257,13 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
     if (!paperMatch) {
       w = paperWidth;
       h = paperHeight;
+      if (w < 0 || h < 0) {
+        // Unable to obtain a paper size from the document and no page size
+        // specified. In this case use A4 as the page size to ensure the PS output is
+        // valid. This will only occur if the PDF is very broken.
+        w = 595;
+        h = 842;
+      }
     } else if (noCropA) {
       w = (int)ceil(page->getMediaWidth());
       h = (int)ceil(page->getMediaHeight());
commit 45a87afdf1372911aa1ba840557e61627cdc7b4f
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Dec 29 15:16:37 2013 +1030

    cairo: clip to crop box
    
    when printing the cairo surface may larger than the crop box
    
    fixes https://bugzilla.gnome.org/show_bug.cgi?id=649886

diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h
index c9ae33d..50fdf7b 100644
--- a/poppler/CairoOutputDev.h
+++ b/poppler/CairoOutputDev.h
@@ -121,6 +121,10 @@ public:
   // text in Type 3 fonts will be drawn with drawChar/drawString.
   virtual GBool interpretType3Chars() { return gFalse; }
 
+  // Does this device need to clip pages to the crop box even when the
+  // box is the crop box?
+  virtual GBool needClipToCropBox() { return gTrue; }
+
   //----- initialization and control
 
   // Start a page.
commit 6d39a1d7b348329dd057a8e7c77bfd47921fc495
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Mon Dec 30 17:59:09 2013 +1030

    pdftocairo: ensure page size and crop box works the same as pdftops
    
    Bug 72312

diff --git a/utils/pdftocairo.1 b/utils/pdftocairo.1
index 7d17eef..c903ffa 100644
--- a/utils/pdftocairo.1
+++ b/utils/pdftocairo.1
@@ -147,7 +147,7 @@ Specifies the height of crop area in pixels (image output) or points (vector out
 Specifies the size of crop square in pixels (image output) or points (vector output)  (sets \-W and \-H)
 .TP
 .B \-cropbox
-Uses the crop box rather than media box when generating the files
+Uses the crop box rather than media box when generating the files (PNG/JPEG/TIFF only)
 .TP
 .B \-mono
 Generate a monochrome file (PNG and TIFF only).
@@ -169,32 +169,24 @@ Generate Level 3 PostScript (PS only). This enables all Level 2 features plus
 shading patterns and masked images. This is the default setting.
 .TP
 .B \-origpagesizes
-Generate a file with variable page sizes and orientations (PS and PDF
-only). The size of each page will be the original page in the PDF
-file.  If the output is PS the file will contain %%DocumentMedia and
-%%PageMedia DSC comments specifying the size of each page.  Any
-specification of the page size via \-paper, \-paperw, or \-paperh will
-get overridden as long as each page of the PDF file has a defined
-paper size.
+This option is the same as "\-paper match".
 .TP
 .BI \-paper " size"
 Set the paper size to one of "letter", "legal", "A4", or "A3"
 (PS,PDF,SVG only).  This can also be set to "match", which will set
-the paper size to match the size specified in the PDF
-file. \-origpagesizes overrides this setting if the PDF file has
-defined page sizes.
+the paper size of each page to match the size specified in the PDF
+file. If none the \-paper, \-paperw, or \-paperh options are
+specified the default is to match the paper size.
 .TP
 .BI \-paperw " size"
-Set the paper width, in points (PS,PDF,SVG only). \-origpagesizes overrides this setting
-if the PDF file has defined page sizes.
+Set the paper width, in points (PS,PDF,SVG only).
 .TP
 .BI \-paperh " size"
-Set the paper height, in points (PS,PDF,SVG only). \-origpagesizes overrides this setting
-if the PDF file has defined page sizes.
+Set the paper height, in points (PS,PDF,SVG only).
 .TP
 .B \-nocrop
-By default, output is cropped to the CropBox specified in the PDF
-file.  This option disables cropping.
+By default, printing output is cropped to the CropBox specified in the PDF
+file.  This option disables cropping (PS,PDF,SVG only).
 .TP
 .B \-expand
 Expand PDF pages smaller than the paper to fill the paper (PS,PDF,SVG only).  By
diff --git a/utils/pdftocairo.cc b/utils/pdftocairo.cc
index f67007f..59c1996 100644
--- a/utils/pdftocairo.cc
+++ b/utils/pdftocairo.cc
@@ -104,7 +104,7 @@ static GooString icc;
 
 static GBool level2 = gFalse;
 static GBool level3 = gFalse;
-static GBool doOrigPageSizes = gFalse;
+static GBool origPageSizes = gFalse;
 static char paperSize[15] = "";
 static int paperWidth = -1;
 static int paperHeight = -1;
@@ -203,7 +203,7 @@ static const ArgDesc argDesc[] = {
    "generate Level 2 PostScript (PS, EPS)"},
   {"-level3",     argFlag,     &level3,         0,
    "generate Level 3 PostScript (PS, EPS)"},
-  {"-origpagesizes",argFlag,   &doOrigPageSizes,0,
+  {"-origpagesizes",argFlag,   &origPageSizes,0,
    "conserve original page sizes (PS, PDF, SVG)"},
   {"-paper",      argString,   paperSize,       sizeof(paperSize),
    "paper size (letter, legal, A4, A3, match)"},
@@ -420,7 +420,7 @@ static void getOutputSize(double page_w, double page_h, double *width, double *h
 {
 
   if (printing) {
-    if (doOrigPageSizes) {
+    if (origPageSizes) {
       *width = page_w;
       *height = page_h;
     } else {
@@ -828,10 +828,11 @@ int main(int argc, char *argv[]) {
     checkInvalidPrintOption(transp, "-transp");
     checkInvalidPrintOption(icc.getCString()[0], "-icc");
     checkInvalidPrintOption(singleFile, "-singlefile");
+    checkInvalidPrintOption(useCropBox, "-cropbox");
   } else {
     checkInvalidImageOption(level2, "-level2");
     checkInvalidImageOption(level3, "-level3");
-    checkInvalidImageOption(doOrigPageSizes, "-origpagesizes");
+    checkInvalidImageOption(origPageSizes, "-origpagesizes");
     checkInvalidImageOption(paperSize[0], "-paper");
     checkInvalidImageOption(paperWidth > 0, "-paperw");
     checkInvalidImageOption(paperHeight > 0, "-paperh");
@@ -842,6 +843,9 @@ int main(int argc, char *argv[]) {
     checkInvalidImageOption(duplex, "-duplex");
   }
 
+  if (printing)
+    useCropBox = !noCrop;
+
   if (icc.getCString()[0] && !png) {
     fprintf(stderr, "Error: -icc may only be used with png output.\n");
     exit(99);
@@ -874,17 +878,23 @@ int main(int argc, char *argv[]) {
   if (!level2 && !level3)
     level3 = gTrue;
 
-  if (eps && (doOrigPageSizes || paperSize[0] || paperWidth > 0 || paperHeight > 0)) {
+  if (eps && (origPageSizes || paperSize[0] || paperWidth > 0 || paperHeight > 0)) {
     fprintf(stderr, "Error: page size options may not be used with eps output.\n");
     exit(99);
   }
 
   if (paperSize[0]) {
+    if (origPageSizes) {
+      fprintf(stderr, "Error: -origpagesizes and -paper may not be used together.\n");
+      exit(99);
+    }
     if (!setPSPaperSize(paperSize, paperWidth, paperHeight)) {
       fprintf(stderr, "Invalid paper size\n");
       exit(99);
     }
   }
+  if (paperWidth < 0 || paperHeight < 0)
+    origPageSizes = gTrue;
 
   globalParams = new GlobalParams();
   if (quiet) {
commit b1da7e20dcef78ef6036418b37a47ba3f8818453
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Thu Dec 19 22:18:26 2013 +1030

    pdftops: Only change paper size when different to previous size
    
    Previously this check was done in the code (removed in previous commit).
    Moving this check into the pdfSetupPaper macro preserves page independence.
    
    Bug 72312

diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc
index f1e501d..34b7cbd 100644
--- a/poppler/PSOutputDev.cc
+++ b/poppler/PSOutputDev.cc
@@ -125,12 +125,32 @@ static const char *prolog[] = {
   "  } ifelse",
   "} def",
   "/pdfSetupPaper {",
-  "  2 array astore",
+  "  % Change paper size, but only if different from previous paper size otherwise",
+  "  % duplex fails. PLRM specifies a tolerance of 5 pts when matching paper size",
+  "  % so we use the same when checking if the size changes.",
   "  /setpagedevice where {",
-  "    pop 2 dict begin",
-  "      /PageSize exch def",
-  "      /ImagingBBox null def",
-  "    currentdict end setpagedevice",
+  "    pop currentpagedevice",
+  "    /PageSize known {",
+  "      2 copy",
+  "      currentpagedevice /PageSize get aload pop",
+  "      exch 4 1 roll",
+  "      sub abs 5 gt",
+  "      3 1 roll",
+  "      sub abs 5 gt",
+  "      or",
+  "    } {",
+  "      true",
+  "    } ifelse",
+  "    {",
+  "      2 array astore",
+  "      2 dict begin",
+  "        /PageSize exch def",
+  "        /ImagingBBox null def",
+  "      currentdict end",
+  "      setpagedevice",
+  "    } {",
+  "      pop pop",
+  "    } ifelse",
   "  } {",
   "    pop",
   "  } ifelse",
commit 7ac7d3bad4b868950ee96fd9c5ece88632f8827c
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Fri Dec 20 07:19:21 2013 +1030

    pdftops: Remove origpagesizes mode and make -origpagesizes an alias for -paper match
    
    Bug 72312

diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc
index 9ebb5a0..f1e501d 100644
--- a/poppler/PSOutputDev.cc
+++ b/poppler/PSOutputDev.cc
@@ -1216,6 +1216,7 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
   mode = modeA;
   paperWidth = paperWidthA;
   paperHeight = paperHeightA;
+  noCrop = noCropA;
   imgLLX = imgLLXA;
   imgLLY = imgLLYA;
   imgURX = imgURXA;
@@ -1443,7 +1444,6 @@ void PSOutputDev::writeHeader(int firstPage, int lastPage,
   int i;
 
   switch (mode) {
-  case psModePSOrigPageSizes:
   case psModePS:
     writePS("%!PS-Adobe-3.0\n");
     break;
@@ -1485,10 +1485,6 @@ void PSOutputDev::writeHeader(int firstPage, int lastPage,
   }
 
   switch (mode) {
-  case psModePSOrigPageSizes:
-    paperMatch = gTrue;
-    prevWidth = 0;
-    prevHeight = 0;
   case psModePS:
     for (i = 0; i < paperSizes->getLength(); ++i) {
       size = (PSOutPaperSize *)paperSizes->get(i);
@@ -3557,7 +3553,7 @@ void PSOutputDev::startPage(int pageNum, GfxState *state, XRef *xrefA) {
   PSOutPaperSize *paperSize;
 
   xref = xrefA;
-  if (mode == psModePS || mode == psModePSOrigPageSizes) {
+  if (mode == psModePS) {
     GooString pageLabel;
     const GBool gotLabel = doc->getCatalog()->indexToLabel(pageNum -1, &pageLabel);
     if (gotLabel) {
@@ -3602,7 +3598,6 @@ void PSOutputDev::startPage(int pageNum, GfxState *state, XRef *xrefA) {
   xScale = yScale = 1;
   switch (mode) {
 
-  case psModePSOrigPageSizes:
   case psModePS:
     // rotate, translate, and scale page
     imgWidth = imgURX - imgLLX;
diff --git a/poppler/PSOutputDev.h b/poppler/PSOutputDev.h
index f14f03f..c654d2e 100644
--- a/poppler/PSOutputDev.h
+++ b/poppler/PSOutputDev.h
@@ -68,8 +68,7 @@ class PSOutputDev;
 enum PSOutMode {
   psModePS,
   psModeEPS,
-  psModeForm,
-  psModePSOrigPageSizes
+  psModeForm
 };
 
 enum PSFileType {
@@ -411,6 +410,7 @@ private:
       imgURX, imgURY;
   GBool preload;		// load all images into memory, and
 				//   predefine forms
+  GBool noCrop;
 
   PSOutputFunc outputFunc;
   void *outputStream;
diff --git a/utils/pdftops.1 b/utils/pdftops.1
index dd8c84b..ca26bcc 100644
--- a/utils/pdftops.1
+++ b/utils/pdftops.1
@@ -65,29 +65,18 @@ CID font embedding.
 Generate Level 3 separable PostScript.  The separation handling is the
 same as for \-level2sep.
 .TP
-.B \-origpagesizes
-Generate a PostScript file with variable page sizes and orientations,
-taking for each page the size of the original page in the PDF file. 
-The PostScript file contains "<</PageSize [WIDTH HEIGHT]>> setpagedevice"
-lines in each page header, so that the paper input tray gets correctly
-changed on the printer. This option should be used when pdftops is used
-as a print filter. Any specification of the page size via \-paper,
-\-paperw, or \-paperh will get overridden as long as each page of the
-PDF file has a defined paper size.  No more than one of the mode options
-(\-origpagesizes, \-eps, \-form) may be given.
-.TP
 .B \-eps
 Generate an Encapsulated PostScript (EPS) file.  An EPS file contains
 a single image, so if you use this option with a multi-page PDF file,
 you must use \-f and \-l to specify a single page.  No more than one of
-the mode options (\-origpagesizes, \-eps, \-form) may be given.
+the mode options (\-eps, \-form) may be given.
 .TP
 .B \-form
 Generate a PostScript form which can be imported by software that
 understands forms.  A form contains a single page, so if you use this
 option with a multi-page PDF file, you must use \-f and \-l to specify a
 single page.  The \-level1 option cannot be used with \-form.  No more
-than one of the mode options (\-origpagesizes, \-eps, \-form) may be
+than one of the mode options (\-eps, \-form) may be
 given.
 .TP
 .B \-opi
@@ -144,17 +133,18 @@ preload images and forms
 .TP
 .BI \-paper " size"
 Set the paper size to one of "letter", "legal", "A4", or "A3".  This
-can also be set to "match", which will set the paper size to match the
-size specified in the PDF file. \-origpagesizes overrides this setting
-if the PDF file has defined page sizes.
+can also be set to "match", which will set the paper size of each page to match the
+size specified in the PDF file. If none the \-paper, \-paperw, or \-paperh
+options are spoecified the default is to match the paper size.
 .TP
 .BI \-paperw " size"
-Set the paper width, in points. \-origpagesizes overrides this setting
-if the PDF file has defined page sizes.
+Set the paper width, in points.
 .TP
 .BI \-paperh " size"
-Set the paper height, in points. \-origpagesizes overrides this setting
-if the PDF file has defined page sizes.
+Set the paper height, in points.
+.TP
+.B \-origpagesizes
+This option is the same as "\-paper match".
 .TP
 .B \-nocrop
 By default, output is cropped to the CropBox specified in the PDF
diff --git a/utils/pdftops.cc b/utils/pdftops.cc
index b54fd42..e003baa 100644
--- a/utils/pdftops.cc
+++ b/utils/pdftops.cc
@@ -81,7 +81,7 @@ static GBool level2 = gFalse;
 static GBool level2Sep = gFalse;
 static GBool level3 = gFalse;
 static GBool level3Sep = gFalse;
-static GBool doOrigPageSizes = gFalse;
+static GBool origPageSizes = gFalse;
 static GBool doEPS = gFalse;
 static GBool doForm = gFalse;
 #if OPI_SUPPORT
@@ -129,7 +129,7 @@ static const ArgDesc argDesc[] = {
    "generate Level 3 PostScript"},
   {"-level3sep",  argFlag,     &level3Sep,      0,
    "generate Level 3 separable PostScript"},
-  {"-origpagesizes",argFlag,   &doOrigPageSizes,0,
+  {"-origpagesizes",argFlag,   &origPageSizes,0,
    "conserve original page sizes"},
   {"-eps",        argFlag,     &doEPS,          0,
    "generate Encapsulated PostScript (EPS)"},
@@ -231,10 +231,9 @@ int main(int argc, char *argv[]) {
     fprintf(stderr, "Error: use only one of the 'level' options.\n");
     exit(1);
   }
-  if ((doOrigPageSizes ? 1 : 0) +
-      (doEPS ? 1 : 0) +
+  if ((doEPS ? 1 : 0) +
       (doForm ? 1 : 0) > 1) {
-    fprintf(stderr, "Error: use only one of -origpagesizes, -eps, and -form\n");
+    fprintf(stderr, "Error: use only one of -eps, and -form\n");
     exit(1);
   }
   if (level1) {
@@ -254,15 +253,21 @@ int main(int argc, char *argv[]) {
     fprintf(stderr, "Error: forms are only available with Level 2 output.\n");
     exit(1);
   }
-  mode = doOrigPageSizes ? psModePSOrigPageSizes
-                         : doEPS ? psModeEPS
-                                 : doForm ? psModeForm
-                                          : psModePS;
+  mode = doEPS ? psModeEPS
+    : doForm ? psModeForm
+    : psModePS;
   fileName = new GooString(argv[1]);
 
   // read config file
   globalParams = new GlobalParams();
+  if (origPageSizes) {
+    paperWidth = paperHeight = -1;
+  }
   if (paperSize[0]) {
+    if (origPageSizes) {
+      fprintf(stderr, "Error: -origpagesizes and -paper may not be used together.\n");
+      exit(1);
+    }
     if (!setPSPaperSize(paperSize, paperWidth, paperHeight)) {
       fprintf(stderr, "Invalid paper size\n");
       delete fileName;
commit 31fc5181bc491ff2e4aee0ae05c0f611a36e585c
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Fri Dec 20 07:16:37 2013 +1030

    pdftops: Use crop box as page size
    
    unless -nocrop is used. The fontends use the crop box as the page size and
    acroread uses the cropbox as the page size for display and printing.
    
    Bug 72312

diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc
index 4120f70..9ebb5a0 100644
--- a/poppler/PSOutputDev.cc
+++ b/poppler/PSOutputDev.cc
@@ -3576,8 +3576,13 @@ void PSOutputDev::startPage(int pageNum, GfxState *state, XRef *xrefA) {
     if (paperMatch) {
       page = doc->getCatalog()->getPage(pageNum);
       imgLLX = imgLLY = 0;
-      imgURX = (int)ceil(page->getMediaWidth());
-      imgURY = (int)ceil(page->getMediaHeight());
+      if (noCrop) {
+        imgURX = (int)ceil(page->getMediaWidth());
+        imgURY = (int)ceil(page->getMediaHeight());
+      } else {
+        imgURX = (int)ceil(page->getCropWidth());
+        imgURY = (int)ceil(page->getCropHeight());
+      }
       if (state->getRotate() == 90 || state->getRotate() == 270) {
 	t = imgURX;
 	imgURX = imgURY;
@@ -3650,25 +3655,6 @@ void PSOutputDev::startPage(int pageNum, GfxState *state, XRef *xrefA) {
     writePS("%%BeginPageSetup\n");
     if (paperMatch) {
       writePSFmt("{0:d} {1:d} pdfSetupPaper\n", imgURX, imgURY);
-      if (mode == psModePSOrigPageSizes) {
-	// Set page size only when it actually changes, as otherwise Duplex
-	// printing does not work
-	if (rotate == 0 || rotate == 180) {
-	  if ((width != prevWidth) || (height != prevHeight)) {
-	    writePSFmt("<</PageSize [{0:d} {1:d}]>> setpagedevice\n",
-		       width, height);
-	    prevWidth = width;
-	    prevHeight = height;
-	  }
-	} else {
-	  if ((height != prevWidth) || (width != prevHeight)) {
-	    writePSFmt("<</PageSize [{0:d} {1:d}]>> setpagedevice\n",
-		       height, width);
-	    prevWidth = height;
-	    prevHeight = width;
-	  }
-	}
-      }
     }
     writePS("pdfStartPage\n");
     if (rotate == 0) {
commit bf2049b17ac4706f472c59e50266f4eaf0ffaa32
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Sun Dec 15 18:00:41 2013 +1030

    pdftps: fix DocumentMedia/Page/Media/PageBBox DSC comments
    
    Bug 72312

diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc
index 32be0a3..4120f70 100644
--- a/poppler/PSOutputDev.cc
+++ b/poppler/PSOutputDev.cc
@@ -944,7 +944,9 @@ struct PSOutImgClipRect {
 //------------------------------------------------------------------------
 
 struct PSOutPaperSize {
-  PSOutPaperSize(int wA, int hA) { w = wA; h = hA; }
+  PSOutPaperSize(GooString *nameA, int wA, int hA) { name = nameA; w = wA; h = hA; }
+  ~PSOutPaperSize() { delete name; }
+  GooString *name;
   int w, h;
 };
 
@@ -1052,7 +1054,8 @@ static void outputToFile(void *stream, const char *data, int len) {
 PSOutputDev::PSOutputDev(const char *fileName, PDFDoc *doc,
 			 char *psTitle,
 			 int firstPage, int lastPage, PSOutMode modeA,
-			 int paperWidthA, int paperHeightA, GBool duplexA,
+			 int paperWidthA, int paperHeightA,
+                         GBool noCropA, GBool duplexA,
 			 int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
 			 GBool forceRasterizeA,
 			 GBool manualCtrlA,
@@ -1114,14 +1117,15 @@ PSOutputDev::PSOutputDev(const char *fileName, PDFDoc *doc,
   init(outputToFile, f, fileTypeA, psTitle,
        doc, firstPage, lastPage, modeA,
        imgLLXA, imgLLYA, imgURXA, imgURYA, manualCtrlA,
-       paperWidthA, paperHeightA, duplexA);
+       paperWidthA, paperHeightA, noCropA, duplexA);
 }
 
 PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA,
 			 char *psTitle,
 			 PDFDoc *doc,
 			 int firstPage, int lastPage, PSOutMode modeA,
-			 int paperWidthA, int paperHeightA, GBool duplexA,
+			 int paperWidthA, int paperHeightA,
+                         GBool noCropA, GBool duplexA,
 			 int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
 			 GBool forceRasterizeA,
 			 GBool manualCtrlA,
@@ -1151,7 +1155,40 @@ PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA,
   init(outputFuncA, outputStreamA, psGeneric, psTitle,
        doc, firstPage, lastPage, modeA,
        imgLLXA, imgLLYA, imgURXA, imgURYA, manualCtrlA,
-       paperWidthA, paperHeightA, duplexA);
+       paperWidthA, paperHeightA, noCropA, duplexA);
+}
+
+struct StandardMedia {
+    const char *name;
+    int width;
+    int height;
+};
+
+static const StandardMedia standardMedia[] =
+{
+    { "A0",       2384, 3371 },
+    { "A1",       1685, 2384 },
+    { "A2",       1190, 1684 },
+    { "A3",        842, 1190 },
+    { "A4",        595,  842 },
+    { "A5",        420,  595 },
+    { "B4",        729, 1032 },
+    { "B5",        516,  729 },
+    { "Letter",    612,  792 },
+    { "Tabloid",   792, 1224 },
+    { "Ledger",   1224,  792 },
+    { "Legal",     612, 1008 },
+    { "Statement", 396,  612 },
+    { "Executive", 540,  720 },
+    { "Folio",     612,  936 },
+    { "Quarto",    610,  780 },
+    { "10x14",     720, 1008 },
+    { NULL,          0,    0 }
+};
+
+/* PLRM specifies a tolerance of 5 points when matching page sizes */
+static bool pageDimensionEqual(int a, int b) {
+  return (abs (a - b) < 5);
 }
 
 void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
@@ -1159,7 +1196,7 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
 		       int firstPage, int lastPage, PSOutMode modeA,
 		       int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
 		       GBool manualCtrlA, int paperWidthA, int paperHeightA,
-		       GBool duplexA) {
+		       GBool noCropA, GBool duplexA) {
   Catalog *catalog;
   PDFRectangle *box;
   PSOutPaperSize *size;
@@ -1184,39 +1221,61 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
   imgURX = imgURXA;
   imgURY = imgURYA;
   if (paperWidth < 0 || paperHeight < 0) {
-    Page *page;
     paperMatch = gTrue;
-    paperSizes = new GooList();
-    paperWidth = paperHeight = 1; // in case the document has zero pages
-    for (pg = (firstPage >= 1) ? firstPage : 1;
-	 pg <= lastPage && pg <= catalog->getNumPages();
-	 ++pg) {
-      page = catalog->getPage(pg);
-      if (page == NULL) {
-        paperMatch = gFalse;
-        break;
-      }
+  } else {
+    paperMatch = gFalse;
+  }
+  Page *page;
+  paperSizes = new GooList();
+  for (pg = (firstPage >= 1) ? firstPage : 1;
+       pg <= lastPage && pg <= catalog->getNumPages();
+       ++pg) {
+    page = catalog->getPage(pg);
+    if (page == NULL)
+      paperMatch = gFalse;
+    if (!paperMatch) {
+      w = paperWidth;
+      h = paperHeight;
+    } else if (noCropA) {
       w = (int)ceil(page->getMediaWidth());
       h = (int)ceil(page->getMediaHeight());
-      for (i = 0; i < paperSizes->getLength(); ++i) {
-	size = (PSOutPaperSize *)paperSizes->get(i);
-	if (size->w == w && size->h == h) {
-	  break;
-	}
-      }
-      if (i == paperSizes->getLength()) {
-	paperSizes->append(new PSOutPaperSize(w, h));
-      }
-      if (w > paperWidth) {
-	paperWidth = w;
-      }
-      if (h > paperHeight) {
-	paperHeight = h;
+    } else {
+      w = (int)ceil(page->getCropWidth());
+      h = (int)ceil(page->getCropHeight());
+    }
+    if (paperMatch) {
+      int rotate = page->getRotate();
+      if (rotate == 90 || rotate == 270)
+        std::swap(w, h);
+    }
+    if (w  > paperWidth)
+      paperWidth = w;
+    if (h  > paperHeight)
+      paperHeight = h;
+    for (i = 0; i < paperSizes->getLength(); ++i) {
+      size = (PSOutPaperSize *)paperSizes->get(i);
+      if (pageDimensionEqual(w, size->w) && pageDimensionEqual(h, size->h))
+        break;
+    }
+    if (i == paperSizes->getLength()) {
+      const StandardMedia *media = standardMedia;
+      GooString *name = NULL;
+      while (media->name) {
+        if (pageDimensionEqual(w, media->width) && pageDimensionEqual(h, media->height)) {
+          name = new GooString(media->name);
+          w = media->width;
+          h = media->height;
+          break;
+        }
+        media++;
       }
+      if (!name)
+        name = GooString::format("{0:d}x{1:d}mm", int(w*25.4/72), int(h*25.4/72));
+      paperSizes->append(new PSOutPaperSize(name, w, h));
     }
-    // NB: img{LLX,LLY,URX,URY} will be set by startPage()
-  } else {
-    paperMatch = gFalse;
+    pagePaperSize.insert(std::pair<int,int>(pg, i));
+    if (!paperMatch)
+      break; // we only need one entry when all pages are the same size
   }
   preload = globalParams->getPSPreload();
   if (imgLLX == 0 && imgURX == 0 && imgLLY == 0 && imgURY == 0) {
@@ -1224,11 +1283,6 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA,
     imgURX = paperWidth;
     imgURY = paperHeight;
   }
-  if (imgLLX == 0 && imgURX == 0 && imgLLY == 0 && imgURY == 0) {
-    imgLLX = imgLLY = 0;
-    imgURX = paperWidth;
-    imgURY = paperHeight;
-  }
   manualCtrl = manualCtrlA;
   if (mode == psModeForm) {
     lastPage = firstPage;
@@ -1436,22 +1490,18 @@ void PSOutputDev::writeHeader(int firstPage, int lastPage,
     prevWidth = 0;
     prevHeight = 0;
   case psModePS:
-    if (paperMatch) {      
-      for (i = 0; i < paperSizes->getLength(); ++i) {
-	size = (PSOutPaperSize *)paperSizes->get(i);
-	writePSFmt("%%{0:s} {1:d}x{2:d} {1:d} {2:d} 0 () ()\n",
-		   i==0 ? "DocumentMedia:" : "+", size->w, size->h);
-      }
-    } else {
-      writePSFmt("%%DocumentMedia: plain {0:d} {1:d} 0 () ()\n",
-		 paperWidth, paperHeight);
+    for (i = 0; i < paperSizes->getLength(); ++i) {
+      size = (PSOutPaperSize *)paperSizes->get(i);
+      writePSFmt("%%{0:s} {1:t} {2:d} {3:d} 0 () ()\n",
+                 i==0 ? "DocumentMedia:" : "+", size->name, size->w, size->h);
     }
     writePSFmt("%%BoundingBox: 0 0 {0:d} {1:d}\n", paperWidth, paperHeight);
     writePSFmt("%%Pages: {0:d}\n", lastPage - firstPage + 1);
     writePS("%%EndComments\n");
     if (!paperMatch) {
+      size = (PSOutPaperSize *)paperSizes->get(0);
       writePS("%%BeginDefaults\n");
-      writePS("%%PageMedia: plain\n");
+      writePSFmt("%%PageMedia: {0:t}\n", size->name);
       writePS("%%EndDefaults\n");
     }
     break;
@@ -3504,6 +3554,7 @@ void PSOutputDev::startPage(int pageNum, GfxState *state, XRef *xrefA) {
   int imgWidth, imgHeight, imgWidth2, imgHeight2;
   GBool landscape;
   GooString *s;
+  PSOutPaperSize *paperSize;
 
   xref = xrefA;
   if (mode == psModePS || mode == psModePSOrigPageSizes) {
@@ -3532,11 +3583,7 @@ void PSOutputDev::startPage(int pageNum, GfxState *state, XRef *xrefA) {
 	imgURX = imgURY;
 	imgURY = t;
       }
-      writePSFmt("%%PageMedia: {0:d}x{1:d}\n", imgURX, imgURY);
-      writePSFmt("%%PageBoundingBox: 0 0 {0:d} {1:d}\n", imgURX, imgURY);
     }
-    if (mode != psModePSOrigPageSizes)
-      writePS("%%BeginPageSetup\n");
   }
 
   // underlays
@@ -3589,8 +3636,18 @@ void PSOutputDev::startPage(int pageNum, GfxState *state, XRef *xrefA) {
 	}
       }
     }
+    if (paperMatch) {
+      paperSize = (PSOutPaperSize *)paperSizes->get(pagePaperSize[pageNum]);
+      writePSFmt("%%PageMedia: {0:t}\n", paperSize->name);
+    }
+    if (rotate == 0 || rotate == 180) {
+      writePSFmt("%%PageBoundingBox: 0 0 {0:d} {1:d}\n", width, height);
+    } else {
+      writePSFmt("%%PageBoundingBox: 0 0 {0:d} {1:d}\n", height, width);
+    }
     writePSFmt("%%PageOrientation: {0:s}\n",
 	       landscape ? "Landscape" : "Portrait");
+    writePS("%%BeginPageSetup\n");
     if (paperMatch) {
       writePSFmt("{0:d} {1:d} pdfSetupPaper\n", imgURX, imgURY);
       if (mode == psModePSOrigPageSizes) {
@@ -3729,9 +3786,7 @@ void PSOutputDev::startPage(int pageNum, GfxState *state, XRef *xrefA) {
     }
   }
 
-  if (mode == psModePS) {
-    writePS("%%EndPageSetup\n");
-  }
+  writePS("%%EndPageSetup\n");
 }
 
 void PSOutputDev::endPage() {
diff --git a/poppler/PSOutputDev.h b/poppler/PSOutputDev.h
index 92b007e..f14f03f 100644
--- a/poppler/PSOutputDev.h
+++ b/poppler/PSOutputDev.h
@@ -44,6 +44,7 @@
 #include "GlobalParams.h"
 #include "OutputDev.h"
 #include <set>
+#include <map>
 
 class GHooash;
 class PDFDoc;
@@ -97,6 +98,7 @@ public:
 	      char *psTitle,
 	      int firstPage, int lastPage, PSOutMode modeA,
 	      int paperWidthA = -1, int paperHeightA = -1,
+              GBool noCrop = gFalse,
 	      GBool duplexA = gTrue,
 	      int imgLLXA = 0, int imgLLYA = 0,
 	      int imgURXA = 0, int imgURYA = 0,
@@ -111,6 +113,7 @@ public:
 	      PDFDoc *docA,
 	      int firstPage, int lastPage, PSOutMode modeA,
 	      int paperWidthA = -1, int paperHeightA = -1,
+              GBool noCrop = gFalse,
 	      GBool duplexA = gTrue,
 	      int imgLLXA = 0, int imgLLYA = 0,
 	      int imgURXA = 0, int imgURYA = 0,
@@ -311,7 +314,7 @@ private:
 	    int firstPage, int lastPage, PSOutMode modeA,
 	    int imgLLXA, int imgLLYA, int imgURXA, int imgURYA,
 	    GBool manualCtrlA, int paperWidthA, int paperHeightA,
-            GBool duplexA);
+            GBool noCropA, GBool duplexA);
   void setupResources(Dict *resDict);
   void setupFonts(Dict *resDict);
   void setupFont(GfxFont *font, Dict *parentResDict);
@@ -452,6 +455,7 @@ private:
 
   GooList *paperSizes;		// list of used paper sizes, if paperMatch
 				//   is true [PSOutPaperSize]
+  std::map<int,int> pagePaperSize; // page num to paperSize entry mapping
   double tx0, ty0;		// global translation
   double xScale0, yScale0;	// global scaling
   int rotate0;			// rotation angle (0, 90, 180, 270)
diff --git a/qt4/src/poppler-ps-converter.cc b/qt4/src/poppler-ps-converter.cc
index ff8af65..1847eef 100644
--- a/qt4/src/poppler-ps-converter.cc
+++ b/qt4/src/poppler-ps-converter.cc
@@ -224,6 +224,7 @@ bool PSConverter::convert()
 	                                     d->paperWidth,
 	                                     d->paperHeight,
 	                                     gFalse,
+	                                     gFalse,
 	                                     d->marginLeft,
 	                                     d->marginBottom,
 	                                     d->paperWidth - d->marginRight,
diff --git a/qt5/src/poppler-ps-converter.cc b/qt5/src/poppler-ps-converter.cc
index 30f53fa..241d2a4 100644
--- a/qt5/src/poppler-ps-converter.cc
+++ b/qt5/src/poppler-ps-converter.cc
@@ -224,6 +224,7 @@ bool PSConverter::convert()
 	                                     d->paperWidth,
 	                                     d->paperHeight,
 	                                     gFalse,
+	                                     gFalse,
 	                                     d->marginLeft,
 	                                     d->marginBottom,
 	                                     d->paperWidth - d->marginRight,
diff --git a/utils/pdftops.cc b/utils/pdftops.cc
index cbe1d36..b54fd42 100644
--- a/utils/pdftops.cc
+++ b/utils/pdftops.cc
@@ -399,6 +399,7 @@ int main(int argc, char *argv[]) {
 			  NULL, firstPage, lastPage, mode,
 			  paperWidth,
 			  paperHeight,
+                          noCrop,
 			  duplex);
   if (psOut->isOk()) {
     doc->displayPages(psOut, firstPage, lastPage, 72, 72,
commit fe49033c9bd2103c13d4eb59983e06fdcdd33a8d
Author: Till Kamppeter <till.kamppeter at gmail.com>
Date:   Sat Dec 14 16:05:09 2013 +1030

    pdftops: ensure paper size takes into account rotation
    
    Bug 72312

diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc
index 623251f..32be0a3 100644
--- a/poppler/PSOutputDev.cc
+++ b/poppler/PSOutputDev.cc
@@ -1432,6 +1432,7 @@ void PSOutputDev::writeHeader(int firstPage, int lastPage,
 
   switch (mode) {
   case psModePSOrigPageSizes:
+    paperMatch = gTrue;
     prevWidth = 0;
     prevHeight = 0;
   case psModePS:
@@ -3550,34 +3551,6 @@ void PSOutputDev::startPage(int pageNum, GfxState *state, XRef *xrefA) {
   switch (mode) {
 
   case psModePSOrigPageSizes:
-    x1 = (int)floor(state->getX1());
-    y1 = (int)floor(state->getY1());
-    x2 = (int)ceil(state->getX2());
-    y2 = (int)ceil(state->getY2());
-    width = x2 - x1;
-    height = y2 - y1;
-    if (width > height) {
-      landscape = gTrue;
-    } else {
-      landscape = gFalse;
-    }
-    writePSFmt("%%PageBoundingBox: {0:d} {1:d} {2:d} {3:d}\n", x1, y1, x2 - x1, y2 - y1);
-    writePS("%%BeginPageSetup\n");
-    writePSFmt("%%PageOrientation: {0:s}\n",
-	       landscape ? "Landscape" : "Portrait");
-    if ((width != prevWidth) || (height != prevHeight)) {
-      // Set page size only when it actually changes, as otherwise Duplex
-      // printing does not work
-      writePSFmt("<</PageSize [{0:d} {1:d}]>> setpagedevice\n", width, height);
-      prevWidth = width;
-      prevHeight = height;
-    }
-    writePS("pdfStartPage\n");
-    writePSFmt("{0:d} {1:d} {2:d} {3:d} re W\n", x1, y1, x2 - x1, y2 - y1);
-    writePS("%%EndPageSetup\n");
-    ++seqPage;
-    break;
-
   case psModePS:
     // rotate, translate, and scale page
     imgWidth = imgURX - imgLLX;
@@ -3620,6 +3593,25 @@ void PSOutputDev::startPage(int pageNum, GfxState *state, XRef *xrefA) {
 	       landscape ? "Landscape" : "Portrait");
     if (paperMatch) {
       writePSFmt("{0:d} {1:d} pdfSetupPaper\n", imgURX, imgURY);
+      if (mode == psModePSOrigPageSizes) {
+	// Set page size only when it actually changes, as otherwise Duplex
+	// printing does not work
+	if (rotate == 0 || rotate == 180) {
+	  if ((width != prevWidth) || (height != prevHeight)) {
+	    writePSFmt("<</PageSize [{0:d} {1:d}]>> setpagedevice\n",
+		       width, height);
+	    prevWidth = width;
+	    prevHeight = height;
+	  }
+	} else {
+	  if ((height != prevWidth) || (width != prevHeight)) {
+	    writePSFmt("<</PageSize [{0:d} {1:d}]>> setpagedevice\n",
+		       height, width);
+	    prevWidth = height;
+	    prevHeight = width;
+	  }
+	}
+      }
     }
     writePS("pdfStartPage\n");
     if (rotate == 0) {


More information about the poppler mailing list