diff --git a/glib/poppler-document.cc b/glib/poppler-document.cc index 3c0e6d7..6949d2b 100644 --- a/glib/poppler-document.cc +++ b/glib/poppler-document.cc @@ -2749,7 +2749,7 @@ poppler_pdf_file_finalize (GObject *object) PopplerPDFFile *pdf_file = POPPLER_PDF_FILE (object); delete pdf_file->writer; - g_object_unref (pdf_file->document); + g_list_free_full (pdf_file->documents, g_object_unref); G_OBJECT_CLASS (poppler_pdf_file_parent_class)->finalize (object); } @@ -2763,15 +2763,12 @@ poppler_pdf_file_finalize (GObject *object) * Return value: a PopplerPDFFile **/ PopplerPDFFile * -poppler_pdf_file_new (PopplerDocument *document) +poppler_pdf_file_new () { PopplerPDFFile *pdf_file; - g_return_val_if_fail (POPPLER_IS_DOCUMENT (document), NULL); - pdf_file = (PopplerPDFFile *) g_object_new (POPPLER_TYPE_PDF_FILE, NULL); - pdf_file->document = (PopplerDocument *) g_object_ref (document); - pdf_file->writer = new PDFWriter(document->doc); + pdf_file->writer = new PDFWriter (); return pdf_file; } @@ -3091,9 +3088,32 @@ poppler_pdf_file_set_center (PopplerPDFFile *pdf_file, **/ void poppler_pdf_file_add_page (PopplerPDFFile *pdf_file, - gint page) + PopplerPage *page) { - pdf_file->writer->addPage(page); + pdf_file->documents = g_list_append (pdf_file->documents, g_object_ref (page->document)); + pdf_file->writer->addPage (page->page); +} + +/** + * poppler_pdf_file_add_document: + * @pdf_file: a PopplerPDFFile which was not yet been written + * @document: the document to print + * + * Include pages of the specified document in the list of pages to be printed. + * + **/ +void +poppler_pdf_file_add_document (PopplerPDFFile *pdf_file, + PopplerDocument *document) +{ + int i, count; + + g_return_if_fail (POPPLER_IS_DOCUMENT (document)); + + count = poppler_document_get_n_pages (document); + for (i = 1; i <= count; i++) + poppler_pdf_file_add_page (pdf_file, + poppler_document_get_page (document, i)); } /** diff --git a/glib/poppler-document.h b/glib/poppler-document.h index 42e38b5..501755c 100644 --- a/glib/poppler-document.h +++ b/glib/poppler-document.h @@ -297,7 +297,7 @@ void poppler_ps_file_free (PopplerPSFile *ps_file); #define POPPLER_PDF_FILE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), POPPLER_TYPE_PDF_FILE, PopplerPDFFile)) #define POPPLER_IS_PDF_FILE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), POPPLER_TYPE_PDF_FILE)) GType poppler_pdf_file_get_type (void) G_GNUC_CONST; -PopplerPDFFile *poppler_pdf_file_new (PopplerDocument *document); +PopplerPDFFile *poppler_pdf_file_new (); void poppler_pdf_file_set_num_copies (PopplerPDFFile *pdf_file, gint copies); void poppler_pdf_file_set_collate (PopplerPDFFile *pdf_file, @@ -330,7 +330,9 @@ void poppler_pdf_file_set_auto_rotate (PopplerPDFFile *pdf_file, void poppler_pdf_file_set_center (PopplerPDFFile *pdf_file, gboolean center); void poppler_pdf_file_add_page (PopplerPDFFile *pdf_file, - gint page); + PopplerPage *page); +void poppler_pdf_file_add_document (PopplerPDFFile *pdf_file, + PopplerDocument *document); gboolean poppler_pdf_file_write (PopplerPDFFile *pdf_file, const char *uri); void poppler_pdf_file_free (PopplerPDFFile *ps_file); diff --git a/glib/poppler-private.h b/glib/poppler-private.h index 46dd18e..6be9594 100644 --- a/glib/poppler-private.h +++ b/glib/poppler-private.h @@ -51,7 +51,7 @@ struct _PopplerPDFFile /*< private >*/ GObject parent_instance; - PopplerDocument *document; + GList *documents; PDFWriter *writer; }; diff --git a/poppler/PDFWriter.cc b/poppler/PDFWriter.cc index ce65f07..db69381 100644 --- a/poppler/PDFWriter.cc +++ b/poppler/PDFWriter.cc @@ -20,9 +20,8 @@ #include #include -PDFWriter::PDFWriter(PDFDoc *docA) +PDFWriter::PDFWriter() { - doc = docA; copies = 1; collate = gTrue; reverse = gFalse; @@ -35,14 +34,16 @@ PDFWriter::PDFWriter(PDFDoc *docA) autoRotate = gTrue; embedFonts = gFalse; nextObject = 0; - fontInfoScanner = new FontInfoScanner(doc); fontInfo = new GooList(); } PDFWriter::~PDFWriter() { + std::map::iterator it; + delete fontInfo; - delete fontInfoScanner; + for (it = docs.begin(); it != docs.end(); ++it) + delete it->second; } void PDFWriter::addPaperSize(double width, double height, @@ -68,11 +69,44 @@ void PDFWriter::addPaperSize(double width, double height, paperSizes.push_back(paperSize); } -void PDFWriter::addPage(int page) + +FontInfoScanner *PDFWriter::getFontInfoScanner(PDFDoc *doc) { + std::map::iterator it; + FontInfoScanner *fontInfoScanner; + + it = docs.find(doc); + if (it == docs.end()) { + fontInfoScanner = new FontInfoScanner(doc); + docs[doc] = fontInfoScanner; + } else { + fontInfoScanner = it->second; + } + + return fontInfoScanner; +} + +void PDFWriter::addPage(Page *page) +{ + PDFDoc *doc = page->getDoc(); + pages.push_back(page); + // scan fonts - fontInfoScanner->scanPage(fontInfo, page, doc->getXRef()); + getFontInfoScanner(doc)->scanPage(fontInfo, page->getNum(), doc->getXRef()); +} + +void PDFWriter::addDoc(PDFDoc *doc) +{ + FontInfoScanner *fontInfoScanner = getFontInfoScanner(doc); + int i; + + for (i = 1; i <= doc->getNumPages(); i++) { + pages.push_back(doc->getPage(i)); + + // scan fonts + fontInfoScanner->scanPage(fontInfo, i, doc->getXRef()); + } } struct PageScale { @@ -413,7 +447,8 @@ void PDFWriter::writePageObject(int pageNum, int copy, PDFRectangle *mediaSize) Matrix ctm; Ref ctmRef; - Page *page = doc->getCatalog()->getPage(pageNum); + Page *page = pages[pageNum]; + PDFDoc *doc = page->getDoc(); getPaperSize(page, mediaSize, &margins); getPageCTM(page, mediaSize, &margins, &ctm); GBool ctmRequired = !ctm.isIdentity(); @@ -492,8 +527,9 @@ static void copyStream(Stream *inStr, OutStream *outStr) // concatenated together into a single XObject stream. void PDFWriter::writeXObject(int pageNum) { - Page *page = doc->getCatalog()->getPage(pageNum); - Ref *refPage = doc->getCatalog()->getPageRef(pageNum); + Page *page = pages[pageNum]; + PDFDoc *doc = page->getDoc(); + Ref *refPage = doc->getCatalog()->getPageRef(page->getNum()); Object pageObj; doc->getXRef()->fetch(refPage->num, refPage->gen, &pageObj); Dict *pageDict = pageObj.getDict(); @@ -681,6 +717,11 @@ void PDFWriter::writePageTree() GBool PDFWriter::writeFile(GooString *name) { + if (pages.size() == 0) { + error(errIO, -1, "There are no pages to write"); + return gFalse; + } + FILE *f = fopen(name->getCString(), "wb"); OutStream *outStr = new FileOutStream(f, 0); writeStream(outStr); @@ -702,7 +743,7 @@ void PDFWriter::updateObject (Object* obj, Ref ref) // new ref. // dict - a page/xobject/pattern dict // obj,ref - object containing the dict. -void PDFWriter::replaceNonEmbeddedFonts(Dict *dict, Object *obj, Ref ref) +void PDFWriter::replaceNonEmbeddedFonts(PDFDoc *doc, Dict *dict, Object *obj, Ref ref) { Object *curObj = obj; Ref curRef = ref; @@ -777,12 +818,14 @@ void PDFWriter::replaceNonEmbeddedFonts(Dict *dict, Object *obj, Ref ref) font.gfxFont = gfxFont; fontDict->incRef(); font.fontDict = fontDict; + font.doc = doc; } else { font.isEmbedded = gTrue; font.newRef.num = 0; font.newRef.gen = 0; font.gfxFont = NULL; font.fontDict = NULL; + font.doc = NULL; } // if non-embedded replace with substitute font ref if (!font.isEmbedded) { @@ -811,7 +854,7 @@ void PDFWriter::replaceNonEmbeddedFonts(Dict *dict, Object *obj, Ref ref) obj4.fetch(doc->getXRef(), &obj5); Dict *dict2 = obj5.streamGetDict(); if (dict2) - replaceNonEmbeddedFonts(dict2, &obj5, obj4.getRef()); + replaceNonEmbeddedFonts(doc, dict2, &obj5, obj4.getRef()); obj4.free(); obj5.free(); } @@ -819,7 +862,7 @@ void PDFWriter::replaceNonEmbeddedFonts(Dict *dict, Object *obj, Ref ref) } } -void PDFWriter::markPageObjects(Dict *pageDict, GBool markContent) +void PDFWriter::markPageObjects(PDFDoc *doc, Dict *pageDict, GBool markContent) { for (int i = 0; i < pageDict->getLength(); i++) { Object obj; @@ -877,14 +920,14 @@ void PDFWriter::writeType1Font(Font *font, GooString *filename) font->fontDict->lookup("FontDescriptor", &fdObj); if (!fdObj.isDict()) { fdObj.free(); - fdObj.initDict(doc->getXRef()); + fdObj.initDict(font->doc->getXRef()); Object obj4; obj4.initName("FontDescriptor"); fdObj.dictSet("Type", &obj4); } FoFiType1 *type1Font = FoFiType1::load(filename->getCString()); - obj.initDict(font->fontDict->copy(doc->getXRef())); + obj.initDict(font->fontDict->copy(font->doc->getXRef())); obj2.initName(type1Font->getName()); obj.dictSet("BaseFont", &obj2); obj3.initRef(fontDescriptorRef.num - numOffset, fontDescriptorRef.gen); @@ -1001,7 +1044,7 @@ void PDFWriter::writeSubstituteFonts() { for (std::multimap::iterator it = fonts.begin(); it != fonts.end(); ++it) { if (!it->second.isEmbedded) { - GfxFontLoc *fontLoc = it->second.gfxFont->locateFont(doc->getXRef(), gFalse); + GfxFontLoc *fontLoc = it->second.gfxFont->locateFont(it->second.doc->getXRef(), gFalse); if (fontLoc->locType != gfxFontLocEmbedded) { switch (fontLoc->fontType) { case fontType1: @@ -1032,9 +1075,18 @@ void PDFWriter::writeSubstituteFonts() void PDFWriter::writeStream(OutStream *outStr) { PDFRectangle mediaSize; + PDFDoc *doc; int outputPageNum; int nupPageNum; // 0..numberUp-1 int pageNum; + int majorVersion = 0; + int minorVersion = 0; + int i; + + if (pages.size() == 0) { + error(errIO, -1, "There are no pages to write"); + return; + } outputStr = outStr; @@ -1061,15 +1113,24 @@ void PDFWriter::writeStream(OutStream *outStr) } } - int major = doc->getPDFMajorVersion(); - int minor = doc->getPDFMinorVersion(); + for (i = 0; i < pages.size(); i++) { + doc = pages[i]->getDoc(); + if (doc->getPDFMajorVersion() > majorVersion) { + majorVersion = doc->getPDFMajorVersion(); + minorVersion = doc->getPDFMinorVersion(); + } else if (doc->getPDFMajorVersion() == majorVersion) { + if (doc->getPDFMinorVersion() > minorVersion) + minorVersion = doc->getPDFMinorVersion(); + } + } + if (fontEmbedRequired) { // If we are embedding substitute fonts ensure version is at least // 1.3 to support all of Type1, TrueType and CFF fonts. - if (major == 1 && minor < 3) - minor = 3; + if (majorVersion == 1 && minorVersion < 3) + minorVersion = 3; } - PDFDoc::writeHeader(outputStr, major, minor); + PDFDoc::writeHeader(outputStr, majorVersion, minorVersion); // Mark all page objects. when printing n-up the content streams // are not marked as they will be included in the XObjects created for @@ -1077,16 +1138,17 @@ void PDFWriter::writeStream(OutStream *outStr) outputPageNum = 1; nupPageNum = 0; for (int i = 0; i < (int)pages.size(); i++) { - pageNum = pages[i]; + pageNum = pages[i]->getNum(); + doc = pages[i]->getDoc(); if (pageSet == ALL || (pageSet == ODD && outputPageNum % 2 == 1) || (pageSet == EVEN && outputPageNum % 2 == 0)) { Object pageObj; Ref *refPage = doc->getCatalog()->getPageRef(pageNum); doc->getXRef()->fetch(refPage->num, refPage->gen, &pageObj); - markPageObjects(pageObj.getDict(), numberUp > 1 ? gFalse : gTrue); + markPageObjects(doc, pageObj.getDict(), numberUp > 1 ? gFalse : gTrue); if (fontEmbedRequired) - replaceNonEmbeddedFonts(pageObj.getDict(), &pageObj, *refPage); + replaceNonEmbeddedFonts(doc, pageObj.getDict(), &pageObj, *refPage); pageObj.free(); } nupPageNum++; @@ -1118,15 +1180,14 @@ void PDFWriter::writeStream(OutStream *outStr) outputPageNum = 1; nupPageNum = 0; for (int i = 0; i < (int)pages.size(); i++) { - pageNum = pages[i]; if (pageSet == ALL || (pageSet == ODD && outputPageNum % 2 == 1) || (pageSet == EVEN && outputPageNum % 2 == 0)) { if (numberUp == 1) { for (int cp = 0; cp < copies; cp++) - writePageObject(pageNum, cp, &mediaSize); + writePageObject(i, cp, &mediaSize); } else { - writeXObject(pageNum); + writeXObject(i); if (nupPageNum == numberUp - 1 || i == (int)pages.size() - 1) { for (int cp = 0; cp < copies; cp++) writeSheetPageObject(cp, &mediaSize); diff --git a/poppler/PDFWriter.h b/poppler/PDFWriter.h index ab7e362..496f1a3 100644 --- a/poppler/PDFWriter.h +++ b/poppler/PDFWriter.h @@ -41,7 +41,7 @@ public: enum Orientation { PORTRAIT, LANDSCAPE, REVERSE_PORTRAIT, REVERSE_LANDSCAPE }; enum Resize { NONE, SHRINK, FIT }; - PDFWriter(PDFDoc *docA); + PDFWriter(); ~PDFWriter(); // print options @@ -94,7 +94,9 @@ public: // If true non-embedded fonts will be replaced with an embedded substitute font void setEmbedFonts(GBool embed) {embedFonts = embed; } - void addPage(int page); + void addPage(Page *page); + + void addDoc(PDFDoc *doc); void writeStream(OutStream *outputStr); @@ -115,6 +117,7 @@ private: Ref newRef; // only set if not embedded GfxFont *gfxFont; // only set if not embedded Dict *fontDict; // only set if not embedded + PDFDoc *doc; // only set if not embedded }; int getNextPage(); @@ -132,14 +135,16 @@ private: void writeXObject(int pageNum); void writeSheetPageObject(int copy, PDFRectangle *mediaSize); void writeBlankPage(int copy, PDFRectangle *mediaSize); - void replaceNonEmbeddedFonts(Dict *dict, Object *obj, Ref ref); - void markPageObjects(Dict *pageDict, GBool markContent); + void replaceNonEmbeddedFonts(PDFDoc *doc, Dict *dict, Object *obj, Ref ref); + void markPageObjects(PDFDoc *doc, Dict *pageDict, GBool markContent); void updateObject (Object* obj, Ref ref); void writeType1Font(Font *font, GooString *filename); void writeSubstituteFonts(); void writePageTree(); - PDFDoc *doc; + FontInfoScanner *getFontInfoScanner(PDFDoc *doc); + + std::map docs; Guint numOffset; int nextObject; int maxObject; @@ -151,7 +156,6 @@ private: std::vector xobjectRefs; std::vector ctmObjects; std::vector ctmStrings; - FontInfoScanner *fontInfoScanner; GooList *fontInfo; std::multimap fonts; GBool fontEmbedRequired; @@ -163,7 +167,7 @@ private: GBool collate; GBool reverse; GBool duplex; - std::vector pages; + std::vector pages; std::vector paperSizes; PageSet pageSet; int numberUp; diff --git a/test/pdftopdf.cc b/test/pdftopdf.cc index f2a311a..62b2879 100644 --- a/test/pdftopdf.cc +++ b/test/pdftopdf.cc @@ -452,7 +452,7 @@ int main (int argc, char *argv[]) goto done; } - writer = new PDFWriter(doc); + writer = new PDFWriter(); // set output options setPaperSizes(writer); @@ -493,7 +493,7 @@ int main (int argc, char *argv[]) if (last == -1) last = doc->getNumPages(); for (int i = first; i <= last; i++) { - writer->addPage(i); + writer->addPage(doc->getPage(i)); } } writer->writeFile(outputName);