From 4ee0efd2cf05a8fae7f6771eaf5c0255ac790b2f Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Sun, 15 Dec 2013 18:00:41 +1030 Subject: [PATCH 2/5] pdftps: fix DocumentMedia/Page/Media/PageBBox DSC comments Bug 72312 --- poppler/PSOutputDev.cc | 168 ++++++++++++++++++++++++++-------------- poppler/PSOutputDev.h | 6 +- qt4/src/poppler-ps-converter.cc | 1 + qt5/src/poppler-ps-converter.cc | 1 + utils/pdftops.cc | 1 + 5 files changed, 119 insertions(+), 58 deletions(-) diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc index 32be0a3..4fe07bf 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,60 @@ 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; + } 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 = page->getMediaWidth(); + h = page->getMediaHeight(); + } else { + w = page->getCropWidth(); + h = page->getCropHeight(); + } + 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++; } - 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; - } + 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(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 +1282,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 +1489,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 +3553,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 +3582,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 +3635,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 +3785,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 +#include 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 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, -- 1.8.3.2