From f6c244ff7967162da92c83243f7e02a00c442859 Mon Sep 17 00:00:00 2001 From: Adrian Johnson Date: Mon, 11 Nov 2013 22:10:51 +1030 Subject: [PATCH 9/9] Incorporate review comments for PDFWriter --- poppler/PDFWriter.cc | 116 ++++++++++++++++++++++++++++++--------------------- poppler/PDFWriter.h | 22 +++++++--- poppler/Stream.cc | 6 +-- 3 files changed, 87 insertions(+), 57 deletions(-) diff --git a/poppler/PDFWriter.cc b/poppler/PDFWriter.cc index 4f1f49b..2472222 100644 --- a/poppler/PDFWriter.cc +++ b/poppler/PDFWriter.cc @@ -23,11 +23,12 @@ PDFWriter::PDFWriter(PDFDoc *docA) reverse = gFalse; pageSet = ALL; numberUp = 1; - numberUpOrder = LR_TB; + numberUpLayout = LEFT_TO_RIGHT_TOP_TO_BOTTOM; pageScale = 1.0; resize = NONE; orientation = PORTRAIT; autoRotate = gTrue; + embedFonts = gFalse; nextObject = 0; } @@ -302,36 +303,36 @@ void PDFWriter::getNupCTM(int nupPage, PDFRectangle *mediaSize, PDFRectangle *ma if (orientation == LANDSCAPE) std::swap(rows, cols); - switch (numberUpOrder) { - case LR_TB: + switch (numberUpLayout) { + case LEFT_TO_RIGHT_TOP_TO_BOTTOM: x = nupPage % cols; y = (numberUp - nupPage - 1) / cols; break; - case LR_BT: + case LEFT_TO_RIGHT_BOTTOM_TO_TOP: x = nupPage % cols; y = nupPage / cols; break; - case RL_TB: + case RIGHT_TO_LEFT_TOP_TO_BOTTOM: x = (numberUp - nupPage - 1) % cols; y = (numberUp - nupPage - 1) / cols; break; - case RL_BT: + case RIGHT_TO_LEFT_BOTTOM_TO_TOP: x = (numberUp - nupPage - 1) % cols; y = nupPage / cols; break; - case TB_LR: + case TOP_TO_BOTTOM_LEFT_TO_RIGHT: x = nupPage /cols; y = (numberUp - nupPage - 1) % cols; break; - case TB_RL: + case TOP_TO_BOTTOM_RIGHT_TO_LEFT: x = (numberUp - nupPage - 1) /cols; y = (numberUp - nupPage - 1) % cols; break; - case BT_LR: + case BOTTOM_TO_TOP_LEFT_TO_RIGHT: x = nupPage /cols; y = nupPage % cols; break; - case BT_RL: + case BOTTOM_TO_TOP_RIGHT_TO_LEFT: x = (numberUp - nupPage - 1) /cols; y = nupPage % cols; break; @@ -369,6 +370,30 @@ void PDFWriter::beginIndirectObject(Ref *ref) outputStr->printf("%d %d obj\n", ref->num, ref->gen); } +static const char *pageKeysToExclude[] = { + "Type", + "Parent", + "MediaBox", + "CropBox", + "ArtBox", + "BleedBox", + "TrimBox", + "Contents", + NULL +}; + +// Check if Page dict key is to be excluded from the Page dict written. +static GBool excludePageEntry(const char *key) +{ + const char **s = pageKeysToExclude; + while (*s) { + if (strcmp(*s, key) == 0) + return gTrue; + s++; + } + return gFalse; +} + // Write page object (for the n-up == 1 case). A stream containing the // new CTM (if required) is prepended to the Contents and an updated // MediaBox and Parent is written. The other *Box keys are removed as @@ -378,19 +403,7 @@ void PDFWriter::writePageObject(int pageNum, int copy, PDFRectangle *mediaSize) { PDFRectangle margins; Matrix ctm; - Object ctmObj; Ref ctmRef; - static const char *pageKeysToExclude[] = { - "Type", - "Parent", - "MediaBox", - "CropBox", - "ArtBox", - "BleedBox", - "TrimBox", - "Contents", - NULL - }; Page *page = doc->getCatalog()->getPage(pageNum); getPaperSize(page, mediaSize, &margins); @@ -435,26 +448,18 @@ void PDFWriter::writePageObject(int pageNum, int copy, PDFRectangle *mediaSize) } else { writeObject(&contentsObj); } + contentsObj.free(); outputStr->printf(" ]\n"); for (int i = 0; i < pageDict->getLength(); i++) { - GooString keyName(pageDict->getKey(i)); - GBool outputKey = gTrue; - const char **excludeKey = pageKeysToExclude; - while (*excludeKey) { - if (keyName.cmp(*excludeKey) == 0) { - outputKey = gFalse; - break; - } - excludeKey++; - } - if (outputKey) { - outputStr->printf("/%s ", keyName.getCString()); - Object obj1; - writeObject(pageDict->getValNF(i, &obj1)); - outputStr->printf("\n"); - obj1.free(); - } + const char *key = pageDict->getKey(i); + if (excludePageEntry(key)) + continue; + outputStr->printf("/%s ", key); + Object obj1; + writeObject(pageDict->getValNF(i, &obj1)); + outputStr->printf("\n"); + obj1.free(); } outputStr->printf(">>\n"); outputStr->printf("endobj\n"); @@ -496,19 +501,20 @@ void PDFWriter::writeXObject(int pageNum) pageDict->lookup("MediaBox", &obj); outputStr->printf("/BBox "); writeObject(&obj); + obj.free(); outputStr->printf("\n"); - pageDict->lookup("Resources", &obj); - if (!obj.isNull()) { + if (!pageDict->lookup("Resources", &obj)->isNull()) { outputStr->printf("/Resources "); writeObject(&obj); + obj.free(); outputStr->printf("\n"); } - pageDict->lookup("Group", &obj); - if (!obj.isNull()) { + if (!pageDict->lookup("Group", &obj)->isNull()) { outputStr->printf("/Group "); writeObject(&obj); + obj.free(); outputStr->printf("\n"); } @@ -560,6 +566,7 @@ void PDFWriter::writeXObject(int pageNum) } else { error(errSyntaxError, -1, "Weird page contents"); } + obj.free(); deflateStr.close(); Goffset length = outputStr->getPos() - streamStart; outputStr->printf("\nendstream\n"); @@ -664,17 +671,30 @@ void PDFWriter::writePageTree() outputStr->printf("endobj\n"); } -void PDFWriter::writeFile(FILE *f) +GBool PDFWriter::writeFile(GooString *name) +{ + FILE *f = fopen(name->getCString(), "wb"); + OutStream *outStr = new FileOutStream(f, 0); + writeStream(outStr); + outStr->close(); + if (ferror(f)) { + error(errIO, -1, "Couldn't write file '{0:t}'", name); + return gFalse; + } + return gTrue; +} + +void PDFWriter::writeStream(OutStream *outStr) { PDFRectangle mediaSize; int outputPageNum; int nupPageNum; // 0..numberUp-1 int pageNum; - Object pageObj; + + outputStr = outStr; // header objectsCount = 0; - outputStr = new FileOutStream(f,0); yRef = new XRef(); countRef = new XRef(); yRef->add(0, 65535, 0, gFalse); @@ -693,8 +713,8 @@ void PDFWriter::writeFile(FILE *f) Object pageObj; Ref *refPage = doc->getCatalog()->getPageRef(pageNum); doc->getXRef()->fetch(refPage->num, refPage->gen, &pageObj); - Dict *pageDict = pageObj.getDict(); - doc->markPageObjects(pageDict, yRef, countRef, 0, numberUp > 1 ? gFalse : gTrue); + doc->markPageObjects(pageObj.getDict(), yRef, countRef, 0, numberUp > 1 ? gFalse : gTrue); + pageObj.free(); } nupPageNum++; if (nupPageNum == numberUp) { diff --git a/poppler/PDFWriter.h b/poppler/PDFWriter.h index 200c955..a5d6e7c 100644 --- a/poppler/PDFWriter.h +++ b/poppler/PDFWriter.h @@ -26,9 +26,17 @@ public: enum PageSet { ALL, ODD, EVEN }; // order to layout multiple pages on a sheet. - // LR_TB = Left to Right then Top to Bottom - // LR_BT = Left to Right then Bottom to Top etc - enum NumberUpOrder { LR_TB, LR_BT, RL_TB, RL_BT, TB_LR, TB_RL, BT_LR, BT_RL }; + enum NumberUpLayout { + LEFT_TO_RIGHT_TOP_TO_BOTTOM, + LEFT_TO_RIGHT_BOTTOM_TO_TOP, + RIGHT_TO_LEFT_TOP_TO_BOTTOM, + RIGHT_TO_LEFT_BOTTOM_TO_TOP, + TOP_TO_BOTTOM_LEFT_TO_RIGHT, + TOP_TO_BOTTOM_RIGHT_TO_LEFT, + BOTTOM_TO_TOP_LEFT_TO_RIGHT, + BOTTOM_TO_TOP_RIGHT_TO_LEFT + }; + enum Orientation { PORTRAIT, LANDSCAPE, REVERSE_PORTRAIT, REVERSE_LANDSCAPE }; enum Resize { NONE, SHRINK, FIT }; @@ -57,7 +65,7 @@ public: void setNumberUp(int numberUpA) { numberUp = numberUpA; } // Order to layout pages on sheet when printing multiple pages per sheet; - void setNumberUpOrdering(NumberUpOrder order) { numberUpOrder = order; } + void setNumberUpLayout(NumberUpLayout layout) { numberUpLayout = layout; } // Add paper size (including margins of printable area). // If one paper size is added, all pages will be printed to this @@ -84,7 +92,9 @@ public: void addPage(int page); - void writeFile(FILE *f); + void writeStream(OutStream *outputStr); + + GBool writeFile(GooString *name); private: int getNextPage(); @@ -135,7 +145,7 @@ private: std::vector paperSizes; PageSet pageSet; int numberUp; - NumberUpOrder numberUpOrder; + NumberUpLayout numberUpLayout; double pageScale; Resize resize; Orientation orientation; diff --git a/poppler/Stream.cc b/poppler/Stream.cc index 9b7b2e8..72cbf1a 100644 --- a/poppler/Stream.cc +++ b/poppler/Stream.cc @@ -396,9 +396,9 @@ void OutStream::format(const char *format, ...) { va_list argptr; va_start (argptr, format); - GooString *s = GooString::formatv(format, argptr); - write((Guchar*)s->getCString(), s->getLength()); - delete s; + GooString s; + s.appendfv(format, argptr); + write((Guchar*)s.getCString(), s.getLength()); va_end (argptr); } -- 1.8.3.2