diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc index 623251f..09c39f0 100644 --- a/poppler/PSOutputDev.cc +++ b/poppler/PSOutputDev.cc @@ -1154,6 +1154,43 @@ PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA, paperWidthA, paperHeightA, duplexA); } +PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA, + char *psTitle, + PDFDoc *doc, + int *pageList, const int pageListSize, PSOutMode modeA, + int paperWidthA, int paperHeightA, GBool duplexA, + int imgLLXA, int imgLLYA, int imgURXA, int imgURYA, + GBool forceRasterizeA, + GBool manualCtrlA, + PSOutCustomCodeCbk customCodeCbkA, + void *customCodeCbkDataA) { + underlayCbk = NULL; + underlayCbkData = NULL; + overlayCbk = NULL; + overlayCbkData = NULL; + customCodeCbk = customCodeCbkA; + customCodeCbkData = customCodeCbkDataA; + + fontIDs = NULL; + fontNames = new GooHash(gTrue); + t1FontNames = NULL; + font8Info = NULL; + font16Enc = NULL; + imgIDs = NULL; + formIDs = NULL; + paperSizes = NULL; + embFontList = NULL; + customColors = NULL; + haveTextClip = gFalse; + t3String = NULL; + forceRasterize = forceRasterizeA; + + init2(outputFuncA, outputStreamA, psGeneric, psTitle, + doc, pageList, pageListSize, modeA, + imgLLXA, imgLLYA, imgURXA, imgURYA, manualCtrlA, + paperWidthA, paperHeightA, duplexA); +} + void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA, PSFileType fileTypeA, char *pstitle, PDFDoc *docA, int firstPage, int lastPage, PSOutMode modeA, @@ -1314,6 +1351,161 @@ void PSOutputDev::init(PSOutputFunc outputFuncA, void *outputStreamA, seqPage = 1; } +void PSOutputDev::init2(PSOutputFunc outputFuncA, void *outputStreamA, + PSFileType fileTypeA, char *pstitle, PDFDoc *docA, + int *pageList, const int pageListSize, PSOutMode modeA, + int imgLLXA, int imgLLYA, int imgURXA, int imgURYA, + GBool manualCtrlA, int paperWidthA, int paperHeightA, + GBool duplexA) { + Catalog *catalog; + PDFRectangle *box; + PSOutPaperSize *size; + GooList *names; + int pg, w, h, i; + + // initialize + displayText = gTrue; + ok = gTrue; + outputFunc = outputFuncA; + outputStream = outputStreamA; + fileType = fileTypeA; + doc = docA; + xref = doc->getXRef(); + catalog = doc->getCatalog(); + level = globalParams->getPSLevel(); + mode = modeA; + paperWidth = paperWidthA; + paperHeight = paperHeightA; + imgLLX = imgLLXA; + imgLLY = imgLLYA; + 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 = 0; pg < pageListSize; ++pg) { + page = catalog->getPage(pageList[pg]); + if (page == NULL) { + paperMatch = gFalse; + break; + } + 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; + } + } + // NB: img{LLX,LLY,URX,URY} will be set by startPage() + } else { + paperMatch = gFalse; + } + preload = globalParams->getPSPreload(); + if (imgLLX == 0 && imgURX == 0 && imgLLY == 0 && imgURY == 0) { + imgLLX = imgLLY = 0; + imgURX = paperWidth; + imgURY = paperHeight; + } + if (imgLLX == 0 && imgURX == 0 && imgLLY == 0 && imgURY == 0) { + imgLLX = imgLLY = 0; + imgURX = paperWidth; + imgURY = paperHeight; + } + manualCtrl = manualCtrlA; + processColors = 0; + inType3Char = gFalse; + inUncoloredPattern = gFalse; + t3FillColorOnly = gFalse; + +#if OPI_SUPPORT + // initialize OPI nesting levels + opi13Nest = 0; + opi20Nest = 0; +#endif + + tx0 = ty0 = -1; + xScale0 = yScale0 = 0; + rotate0 = -1; + clipLLX0 = clipLLY0 = 0; + clipURX0 = clipURY0 = -1; + + // initialize fontIDs, fontFileIDs, and fontFileNames lists + fontIDSize = 64; + fontIDLen = 0; + fontIDs = (Ref *)gmallocn(fontIDSize, sizeof(Ref)); + for (i = 0; i < 14; ++i) { + fontNames->add(new GooString(psBase14SubstFonts[i].psName), 1); + } + names = globalParams->getPSResidentFonts(); + for (i = 0; i < names->getLength(); ++i) { + fontNames->add((GooString *)names->get(i), 1); + } + delete names; + t1FontNameSize = 64; + t1FontNameLen = 0; + t1FontNames = (PST1FontName *)gmallocn(t1FontNameSize, sizeof(PST1FontName)); + font8InfoLen = 0; + font8InfoSize = 0; + font16EncLen = 0; + font16EncSize = 0; + imgIDLen = 0; + imgIDSize = 0; + formIDLen = 0; + formIDSize = 0; + + numSaves = 0; + numTilingPatterns = 0; + nextFunc = 0; + + // initialize embedded font resource comment list + embFontList = new GooString(); + + if (!manualCtrl) { + Page *page; + // this check is needed in case the document has zero pages + if ((pageListSize > 0) && ((page = doc->getPage(pageList[0])))) { + writeHeader(pageListSize, + page->getMediaBox(), + page->getCropBox(), + page->getRotate(), + pstitle); + } else { + error(errSyntaxError, -1, "Invalid page {0:d}", (pageListSize > 0)?pageList[0]:0); + box = new PDFRectangle(0, 0, 1, 1); + writeHeader(pageListSize, box, box, 0, pstitle); + delete box; + } + if (mode != psModeForm) { + writePS("%%BeginProlog\n"); + } + writeXpdfProcset(); + if (mode != psModeForm) { + writePS("%%EndProlog\n"); + writePS("%%BeginSetup\n"); + } + writeDocSetup(doc, catalog, pageList, pageListSize, duplexA); + if (mode != psModeForm) { + writePS("%%EndSetup\n"); + } + } + + // initialize sequential page number + seqPage = 1; +} + PSOutputDev::~PSOutputDev() { PSOutCustomColor *cc; int i; @@ -1489,6 +1681,115 @@ void PSOutputDev::writeHeader(int firstPage, int lastPage, } } +void PSOutputDev::writeHeader(const int pageCount, + PDFRectangle *mediaBox, PDFRectangle *cropBox, + int pageRotate, char *psTitle) { + Object info, obj1; + PSOutPaperSize *size; + double x1, y1, x2, y2; + int i; + + switch (mode) { + case psModePSOrigPageSizes: + case psModePS: + writePS("%!PS-Adobe-3.0\n"); + break; + case psModeEPS: + writePS("%!PS-Adobe-3.0 EPSF-3.0\n"); + break; + case psModeForm: + writePS("%!PS-Adobe-3.0 Resource-Form\n"); + break; + } + writePSFmt("%Produced by poppler pdftops version: {0:s} (http://poppler.freedesktop.org)\n", PACKAGE_VERSION); + xref->getDocInfo(&info); + if (info.isDict() && info.dictLookup("Creator", &obj1)->isString()) { + writePS("%%Creator: "); + writePSTextLine(obj1.getString()); + } + obj1.free(); + info.free(); + if(psTitle) { + char *sanitizedTile = strdup(psTitle); + for (Guint i = 0; i < strlen(sanitizedTile); ++i) { + if (sanitizedTile[i] == '\n' || sanitizedTile[i] == '\r') { + sanitizedTile[i] = ' '; + } + } + writePSFmt("%%Title: {0:s}\n", sanitizedTile); + free(sanitizedTile); + } + writePSFmt("%%LanguageLevel: {0:d}\n", + (level == psLevel1 || level == psLevel1Sep) ? 1 : + (level == psLevel2 || level == psLevel2Sep) ? 2 : 3); + if (level == psLevel1Sep || level == psLevel2Sep || level == psLevel3Sep) { + writePS("%%DocumentProcessColors: (atend)\n"); + writePS("%%DocumentCustomColors: (atend)\n"); + } + writePS("%%DocumentSuppliedResources: (atend)\n"); + if ((level == psLevel1 || level == psLevel1Sep) && globalParams->getPSBinary()) { + writePS("%%DocumentData: Binary\n"); + } + + switch (mode) { + case psModePSOrigPageSizes: + 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); + } + writePSFmt("%%BoundingBox: 0 0 {0:d} {1:d}\n", paperWidth, paperHeight); + writePSFmt("%%Pages: {0:d}\n", pageCount); + writePS("%%EndComments\n"); + if (!paperMatch) { + writePS("%%BeginDefaults\n"); + writePS("%%PageMedia: plain\n"); + writePS("%%EndDefaults\n"); + } + break; + case psModeEPS: + epsX1 = cropBox->x1; + epsY1 = cropBox->y1; + epsX2 = cropBox->x2; + epsY2 = cropBox->y2; + if (pageRotate == 0 || pageRotate == 180) { + x1 = epsX1; + y1 = epsY1; + x2 = epsX2; + y2 = epsY2; + } else { // pageRotate == 90 || pageRotate == 270 + x1 = 0; + y1 = 0; + x2 = epsY2 - epsY1; + y2 = epsX2 - epsX1; + } + writePSFmt("%%BoundingBox: {0:d} {1:d} {2:d} {3:d}\n", + (int)floor(x1), (int)floor(y1), (int)ceil(x2), (int)ceil(y2)); + writePSFmt("%%HiResBoundingBox: {0:.6g} {1:.6g} {2:.6g} {3:.6g}\n", + x1, y1, x2, y2); + writePS("%%DocumentSuppliedResources: (atend)\n"); + writePS("%%EndComments\n"); + break; + case psModeForm: + writePS("%%EndComments\n"); + writePS("32 dict dup begin\n"); + writePSFmt("/BBox [{0:d} {1:d} {2:d} {3:d}] def\n", + (int)floor(mediaBox->x1), (int)floor(mediaBox->y1), + (int)ceil(mediaBox->x2), (int)ceil(mediaBox->y2)); + writePS("/FormType 1 def\n"); + writePS("/Matrix [1 0 0 1 0 0] def\n"); + break; + } +} + void PSOutputDev::writeXpdfProcset() { GBool lev1, lev2, lev3, sep, nonSep; const char **p; @@ -1602,6 +1903,81 @@ void PSOutputDev::writeDocSetup(PDFDoc *doc, Catalog *catalog, } } +void PSOutputDev::writeDocSetup(PDFDoc *doc, Catalog *catalog, + int* pageList, const int pageListSize, + GBool duplexA) { + Page *page; + Dict *resDict; + Annots *annots; + Object *acroForm; + Object obj1, obj2, obj3; + GooString *s; + int pg, i; + + if (mode == psModeForm) { + // swap the form and xpdf dicts + writePS("xpdf end begin dup begin\n"); + } else { + writePS("xpdf begin\n"); + } + for (pg = 0; pg < pageListSize; ++pg) { + page = doc->getPage(pageList[pg]); + if (!page) { + error(errSyntaxError, -1, "Failed writing resources for page {0:d}", pg); + continue; + } + if ((resDict = page->getResourceDict())) { + setupResources(resDict); + } + annots = page->getAnnots(); + for (i = 0; i < annots->getNumAnnots(); ++i) { + if (annots->getAnnot(i)->getAppearanceResDict(&obj1)->isDict()) { + setupResources(obj1.getDict()); + } + obj1.free(); + } + } + if ((acroForm = catalog->getAcroForm()) && acroForm->isDict()) { + if (acroForm->dictLookup("DR", &obj1)->isDict()) { + setupResources(obj1.getDict()); + } + obj1.free(); + if (acroForm->dictLookup("Fields", &obj1)->isArray()) { + for (i = 0; i < obj1.arrayGetLength(); ++i) { + if (obj1.arrayGet(i, &obj2)->isDict()) { + if (obj2.dictLookup("DR", &obj3)->isDict()) { + setupResources(obj3.getDict()); + } + obj3.free(); + } + obj2.free(); + } + } + obj1.free(); + } + if (mode != psModeForm) { + if (mode != psModeEPS && !manualCtrl) { + writePSFmt("{0:s} pdfSetup\n", + duplexA ? "true" : "false"); + if (!paperMatch) { + writePSFmt("{0:d} {1:d} pdfSetupPaper\n", paperWidth, paperHeight); + } + } +#if OPI_SUPPORT + if (globalParams->getPSOPI()) { + writePS("/opiMatrix matrix currentmatrix def\n"); + } +#endif + } + if (customCodeCbk) { + if ((s = (*customCodeCbk)(this, psOutCustomDocSetup, 0, + customCodeCbkData))) { + writePS(s->getCString()); + delete s; + } + } +} + void PSOutputDev::writePageTrailer() { if (mode != psModeForm) { writePS("pdfEndPage\n"); diff --git a/poppler/PSOutputDev.h b/poppler/PSOutputDev.h index 92b007e..7b18fa8 100644 --- a/poppler/PSOutputDev.h +++ b/poppler/PSOutputDev.h @@ -119,6 +119,19 @@ public: PSOutCustomCodeCbk customCodeCbkA = NULL, void *customCodeCbkDataA = NULL); + PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA, + char *psTitle, + PDFDoc *docA, + int *pageList, int pageListSize, PSOutMode modeA, + int paperWidthA = -1, int paperHeightA = -1, + GBool duplexA = gTrue, + int imgLLXA = 0, int imgLLYA = 0, + int imgURXA = 0, int imgURYA = 0, + GBool forceRasterizeA = gFalse, + GBool manualCtrlA = gFalse, + PSOutCustomCodeCbk customCodeCbkA = NULL, + void *customCodeCbkDataA = NULL); + // Destructor -- writes the trailer and closes the file. virtual ~PSOutputDev(); @@ -161,6 +174,9 @@ public: void writeHeader(int firstPage, int lastPage, PDFRectangle *mediaBox, PDFRectangle *cropBox, int pageRotate, char *pstitle); + void writeHeader(const int pageCount, + PDFRectangle *mediaBox, PDFRectangle *cropBox, + int pageRotate, char *pstitle); // Write the Xpdf procset. void writeXpdfProcset(); @@ -312,6 +328,12 @@ private: int imgLLXA, int imgLLYA, int imgURXA, int imgURYA, GBool manualCtrlA, int paperWidthA, int paperHeightA, GBool duplexA); + void init2(PSOutputFunc outputFuncA, void *outputStreamA, + PSFileType fileTypeA, char *pstitle, PDFDoc *doc, + int *pageList, const int pageListSize, PSOutMode modeA, + int imgLLXA, int imgLLYA, int imgURXA, int imgURYA, + GBool manualCtrlA, int paperWidthA, int paperHeightA, + GBool duplexA); void setupResources(Dict *resDict); void setupFonts(Dict *resDict); void setupFont(GfxFont *font, Dict *parentResDict); @@ -385,6 +407,7 @@ private: // Write the document-level setup. void writeDocSetup(PDFDoc *doc, Catalog *catalog, int firstPage, int lastPage, GBool duplexA); + void writeDocSetup(PDFDoc *doc, Catalog *catalog, int* pageList, const int pageListSize, GBool duplexA); void writePSChar(char c); void writePS(const char *s); diff --git a/qt4/src/poppler-ps-converter.cc b/qt4/src/poppler-ps-converter.cc index ff8af65..ba38b9d 100644 --- a/qt4/src/poppler-ps-converter.cc +++ b/qt4/src/poppler-ps-converter.cc @@ -214,12 +214,20 @@ bool PSConverter::convert() char* pstitlechar; if (!d->title.isEmpty()) pstitlechar = pstitle8Bit.data(); else pstitlechar = 0; + + const int pageListSize = d->pageList.size(); + int *pageList = new int[pageListSize]; + + for (int i = 0; i < pageListSize; ++i) + { + pageList[i] = d->pageList[i]; + } PSOutputDev *psOut = new PSOutputDev(outputToQIODevice, dev, pstitlechar, d->document->doc, - 1, - d->document->doc->getNumPages(), + pageList, + pageListSize, (d->opts & PrintToEPS) ? psModeEPS : psModePS, d->paperWidth, d->paperHeight, @@ -230,6 +238,8 @@ bool PSConverter::convert() d->paperHeight - d->marginTop, (d->opts & ForceRasterization)); + delete pageList; + if (d->opts & StrictMargins) { double xScale = ((double)d->paperWidth - (double)d->marginLeft - (double)d->marginRight) / (double)d->paperWidth;