| /* poppler-ps-converter.cc: qt interface to poppler | 
 |  * Copyright (C) 2007, 2009, 2010, 2015, Albert Astals Cid <aacid@kde.org> | 
 |  * Copyright (C) 2008, Pino Toscano <pino@kde.org> | 
 |  * Copyright (C) 2010 Hib Eris <hib@hiberis.nl> | 
 |  * Copyright (C) 2011 Glad Deschrijver <glad.deschrijver@gmail.com> | 
 |  * Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it> | 
 |  * Copyright (C) 2013 Thomas Freitag <Thomas.Freitag@alfa.de> | 
 |  * Copyright (C) 2014 Adrian Johnson <ajohnson@redneon.com> | 
 |  * | 
 |  * This program is free software; you can redistribute it and/or modify | 
 |  * it under the terms of the GNU General Public License as published by | 
 |  * the Free Software Foundation; either version 2, or (at your option) | 
 |  * any later version. | 
 |  * | 
 |  * This program is distributed in the hope that it will be useful, | 
 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 |  * GNU General Public License for more details. | 
 |  * | 
 |  * You should have received a copy of the GNU General Public License | 
 |  * along with this program; if not, write to the Free Software | 
 |  * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. | 
 |  */ | 
 |  | 
 | #include "poppler-qt5.h" | 
 |  | 
 | #include "poppler-private.h" | 
 | #include "poppler-converter-private.h" | 
 |  | 
 | #include "PSOutputDev.h" | 
 |  | 
 | static void outputToQIODevice(void *stream, const char *data, int len) | 
 | { | 
 | 	static_cast<QIODevice*>(stream)->write(data, len); | 
 | } | 
 |  | 
 | namespace Poppler { | 
 |  | 
 | class PSConverterPrivate : public BaseConverterPrivate | 
 | { | 
 | 	public: | 
 | 		PSConverterPrivate(); | 
 |  | 
 | 		QList<int> pageList; | 
 | 		QString title; | 
 | 		double hDPI; | 
 | 		double vDPI; | 
 | 		int rotate; | 
 | 		int paperWidth; | 
 | 		int paperHeight; | 
 | 		int marginRight; | 
 | 		int marginBottom; | 
 | 		int marginLeft; | 
 | 		int marginTop; | 
 | 		PSConverter::PSOptions opts; | 
 | 		void (* pageConvertedCallback)(int page, void *payload); | 
 | 		void *pageConvertedPayload; | 
 | }; | 
 |  | 
 | PSConverterPrivate::PSConverterPrivate() | 
 | 	: BaseConverterPrivate(), | 
 | 	hDPI(72), vDPI(72), rotate(0), paperWidth(-1), paperHeight(-1), | 
 | 	marginRight(0), marginBottom(0), marginLeft(0), marginTop(0), | 
 | 	opts(PSConverter::Printing), pageConvertedCallback(nullptr), | 
 | 	pageConvertedPayload(nullptr) | 
 | { | 
 | } | 
 |  | 
 |  | 
 | PSConverter::PSConverter(DocumentData *document) | 
 | 	: BaseConverter(*new PSConverterPrivate()) | 
 | { | 
 | 	Q_D(PSConverter); | 
 | 	d->document = document; | 
 | } | 
 |  | 
 | PSConverter::~PSConverter() | 
 | { | 
 | } | 
 |  | 
 | void PSConverter::setPageList(const QList<int> &pageList) | 
 | { | 
 | 	Q_D(PSConverter); | 
 | 	d->pageList = pageList; | 
 | } | 
 |  | 
 | void PSConverter::setTitle(const QString &title) | 
 | { | 
 | 	Q_D(PSConverter); | 
 | 	d->title = title; | 
 | } | 
 |  | 
 | void PSConverter::setHDPI(double hDPI) | 
 | { | 
 | 	Q_D(PSConverter); | 
 | 	d->hDPI = hDPI; | 
 | } | 
 |  | 
 | void PSConverter::setVDPI(double vDPI) | 
 | { | 
 | 	Q_D(PSConverter); | 
 | 	d->vDPI = vDPI; | 
 | } | 
 |  | 
 | void PSConverter::setRotate(int rotate) | 
 | { | 
 | 	Q_D(PSConverter); | 
 | 	d->rotate = rotate; | 
 | } | 
 |  | 
 | void PSConverter::setPaperWidth(int paperWidth) | 
 | { | 
 | 	Q_D(PSConverter); | 
 | 	d->paperWidth = paperWidth; | 
 | } | 
 |  | 
 | void PSConverter::setPaperHeight(int paperHeight) | 
 | { | 
 | 	Q_D(PSConverter); | 
 | 	d->paperHeight = paperHeight; | 
 | } | 
 |  | 
 | void PSConverter::setRightMargin(int marginRight) | 
 | { | 
 | 	Q_D(PSConverter); | 
 | 	d->marginRight = marginRight; | 
 | } | 
 |  | 
 | void PSConverter::setBottomMargin(int marginBottom) | 
 | { | 
 | 	Q_D(PSConverter); | 
 | 	d->marginBottom = marginBottom; | 
 | } | 
 |  | 
 | void PSConverter::setLeftMargin(int marginLeft) | 
 | { | 
 | 	Q_D(PSConverter); | 
 | 	d->marginLeft = marginLeft; | 
 | } | 
 |  | 
 | void PSConverter::setTopMargin(int marginTop) | 
 | { | 
 | 	Q_D(PSConverter); | 
 | 	d->marginTop = marginTop; | 
 | } | 
 |  | 
 | void PSConverter::setStrictMargins(bool strictMargins) | 
 | { | 
 | 	Q_D(PSConverter); | 
 | 	if (strictMargins) | 
 | 		d->opts |= StrictMargins; | 
 | 	else | 
 | 		d->opts &= ~StrictMargins; | 
 | } | 
 |  | 
 | void PSConverter::setForceRasterize(bool forceRasterize) | 
 | { | 
 | 	Q_D(PSConverter); | 
 | 	if (forceRasterize) | 
 | 		d->opts |= ForceRasterization; | 
 | 	else | 
 | 		d->opts &= ~ForceRasterization; | 
 | } | 
 |  | 
 | void PSConverter::setPSOptions(PSConverter::PSOptions options) | 
 | { | 
 | 	Q_D(PSConverter); | 
 | 	d->opts = options; | 
 | } | 
 |  | 
 | PSConverter::PSOptions PSConverter::psOptions() const | 
 | { | 
 | 	Q_D(const PSConverter); | 
 | 	return d->opts; | 
 | } | 
 |  | 
 | void PSConverter::setPageConvertedCallback(void (* callback)(int page, void *payload), void *payload) | 
 | { | 
 | 	Q_D(PSConverter); | 
 | 	d->pageConvertedCallback = callback; | 
 | 	d->pageConvertedPayload = payload; | 
 | } | 
 |  | 
 | static bool annotDisplayDecideCbk(Annot *annot, void *user_data) | 
 | { | 
 | 	if (annot->getType() == Annot::typeWidget) | 
 | 		return true; // Never hide forms | 
 | 	else | 
 | 		return *(bool*)user_data; | 
 | } | 
 |  | 
 | bool PSConverter::convert() | 
 | { | 
 | 	Q_D(PSConverter); | 
 | 	d->lastError = NoError; | 
 |  | 
 | 	Q_ASSERT(!d->pageList.isEmpty()); | 
 | 	Q_ASSERT(d->paperWidth != -1); | 
 | 	Q_ASSERT(d->paperHeight != -1); | 
 | 	 | 
 | 	if (d->document->locked) | 
 | 	{ | 
 | 		d->lastError = FileLockedError; | 
 | 		return false; | 
 | 	} | 
 | 	 | 
 | 	QIODevice *dev = d->openDevice(); | 
 | 	if (!dev) | 
 | 	{ | 
 | 		d->lastError = OpenOutputError; | 
 | 		return false; | 
 | 	} | 
 |  | 
 | 	QByteArray pstitle8Bit = d->title.toLocal8Bit(); | 
 | 	char* pstitlechar; | 
 | 	if (!d->title.isEmpty()) pstitlechar = pstitle8Bit.data(); | 
 | 	else pstitlechar = nullptr; | 
 | 	 | 
 | 	std::vector<int> pages; | 
 | 	foreach(int page, d->pageList) | 
 | 	{ | 
 | 		pages.push_back(page); | 
 | 	} | 
 |  | 
 | 	PSOutputDev *psOut = new PSOutputDev(outputToQIODevice, dev, | 
 | 	                                     pstitlechar, | 
 | 	                                     d->document->doc, | 
 | 	                                     pages, | 
 | 	                                     (d->opts & PrintToEPS) ? psModeEPS : psModePS, | 
 | 	                                     d->paperWidth, | 
 | 	                                     d->paperHeight, | 
 | 	                                     false, | 
 | 	                                     false, | 
 | 	                                     d->marginLeft, | 
 | 	                                     d->marginBottom, | 
 | 	                                     d->paperWidth - d->marginRight, | 
 | 	                                     d->paperHeight - d->marginTop, | 
 | 	                                     (d->opts & ForceRasterization)); | 
 | 	 | 
 | 	if (d->opts & StrictMargins) | 
 | 	{ | 
 | 		double xScale = ((double)d->paperWidth - (double)d->marginLeft - (double)d->marginRight) / (double)d->paperWidth; | 
 | 		double yScale = ((double)d->paperHeight - (double)d->marginBottom - (double)d->marginTop) / (double)d->paperHeight; | 
 | 		psOut->setScale(xScale, yScale); | 
 | 	} | 
 | 	 | 
 | 	if (psOut->isOk()) | 
 | 	{ | 
 | 		bool isPrinting = (d->opts & Printing) ? true : false; | 
 | 		bool showAnnotations = (d->opts & HideAnnotations) ? false : true; | 
 | 		foreach(int page, d->pageList) | 
 | 		{ | 
 | 			d->document->doc->displayPage(psOut, | 
 | 			                              page, | 
 | 			                              d->hDPI, | 
 | 			                              d->vDPI, | 
 | 			                              d->rotate, | 
 | 			                              false, | 
 | 			                              true, | 
 | 			                              isPrinting, | 
 | 			                              nullptr, | 
 | 			                              nullptr, | 
 | 			                              annotDisplayDecideCbk, | 
 | 			                              &showAnnotations, true); | 
 | 			if (d->pageConvertedCallback) | 
 | 				(*d->pageConvertedCallback)(page, d->pageConvertedPayload); | 
 | 		} | 
 | 		delete psOut; | 
 | 		d->closeDevice(); | 
 | 		return true; | 
 | 	} | 
 | 	else | 
 | 	{ | 
 | 		delete psOut; | 
 | 		d->closeDevice(); | 
 | 		return false; | 
 | 	} | 
 | } | 
 |  | 
 | } |