summaryrefslogtreecommitdiffstats
path: root/scribus/util_ghostscript.cpp
diff options
context:
space:
mode:
authorcraig <craig@11d20701-8431-0410-a711-e3c959e3b870>2012-01-01 11:40:09 +0000
committercraig <craig@11d20701-8431-0410-a711-e3c959e3b870>2012-01-01 11:40:09 +0000
commit7ed83b6c6666eb8b6b104c211ae7e52907350372 (patch)
tree4430b556abac0ad660a0aacf1887d77f85d8be02 /scribus/util_ghostscript.cpp
downloadscribus-7ed83b6c6666eb8b6b104c211ae7e52907350372.tar.gz
scribus-7ed83b6c6666eb8b6b104c211ae7e52907350372.tar.xz
scribus-7ed83b6c6666eb8b6b104c211ae7e52907350372.zip
Branch 1.3.5 tree to 1.4.x tree, goodbye 1.3.x
git-svn-id: svn://scribus.net/branches/Version14x/Scribus@17163 11d20701-8431-0410-a711-e3c959e3b870
Diffstat (limited to 'scribus/util_ghostscript.cpp')
-rw-r--r--scribus/util_ghostscript.cpp413
1 files changed, 413 insertions, 0 deletions
diff --git a/scribus/util_ghostscript.cpp b/scribus/util_ghostscript.cpp
new file mode 100644
index 0000000..4ed8222
--- /dev/null
+++ b/scribus/util_ghostscript.cpp
@@ -0,0 +1,413 @@
+/*
+For general Scribus (>=1.3.2) copyright and licensing information please refer
+to the COPYING file provided with the program. Following this notice may exist
+a copyright and/or license notice that predates the release of Scribus 1.3.2
+for which a new license (GPL+exception) is in place.
+*/
+/***************************************************************************
+ gsutil.cpp - description
+ -------------------
+ begin : Fri Sep 14 2001
+ copyright : (C) 2001 by Franz Schmid
+ copyright : (C) 2006- Scribus Team (code moved from util.cpp)
+ email : Franz.Schmid@altmuehlnet.de
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "util_ghostscript.h"
+
+#include <QDebug>
+#include <QDir>
+#include <QFile>
+#include <QFileInfo>
+#include <QPainter>
+#include <QPixmap>
+#include <QProcess>
+
+#include "scconfig.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if defined(_WIN32)
+#include <windows.h>
+#endif
+
+#include "prefsfile.h"
+#include "prefsmanager.h"
+#include "scpaths.h"
+#include "scribuscore.h"
+#include "scribus.h"
+#include "util.h"
+
+using namespace std;
+
+
+int callGS(const QStringList& args_in, const QString device)
+{
+ QString cmd;
+ QStringList args;
+ PrefsManager* prefsManager = PrefsManager::instance();
+ args.append( "-q" );
+ args.append( "-dNOPAUSE" );
+ args.append( "-dQUIET" );
+ args.append( "-dPARANOIDSAFER" );
+ args.append( "-dBATCH" );
+ // Choose rendering device
+ if (!device.isEmpty())
+ args.append( QString("-sDEVICE=%1").arg(device) ); // user specified device
+ else if (!ScCore->havePNGAlpha())
+ args.append( "-sDEVICE=png16m" );
+ else
+ args.append( "-sDEVICE=pngalpha" );
+ // and antialiasing
+ if (prefsManager->appPrefs.gs_AntiAliasText)
+ args.append( "-dTextAlphaBits=4" );
+ if (prefsManager->appPrefs.gs_AntiAliasGraphics)
+ args.append( "-dGraphicsAlphaBits=4" );
+
+ // Add any extra font paths being used by Scribus to gs's font search path
+ PrefsContext *pc = PrefsManager::instance()->prefsFile->getContext("Fonts");
+ PrefsTable *extraFonts = pc->getTable("ExtraFontDirs");
+ const char sep = ScPaths::envPathSeparator;
+ if (extraFonts->getRowCount() >= 1)
+ cmd = QString("-sFONTPATH=%1").arg(QDir::toNativeSeparators(extraFonts->get(0,0)));
+ for (int i = 1; i < extraFonts->getRowCount(); ++i)
+ cmd += QString("%1%2").arg(sep).arg(QDir::toNativeSeparators(extraFonts->get(i,0)));
+ if( !cmd.isEmpty() )
+ args.append( cmd );
+
+ args += args_in;
+ args.append("-c");
+ args.append("showpage");
+// qDebug(args.join(" ").toAscii());
+ return System( getShortPathName(prefsManager->ghostscriptExecutable()), args );
+}
+
+int callGS(const QString& args_in, const QString device)
+{
+ PrefsManager* prefsManager=PrefsManager::instance();
+ QString cmd1 = getShortPathName(prefsManager->ghostscriptExecutable());
+ cmd1 += " -q -dNOPAUSE -dQUIET -dPARANOIDSAFER -dBATCH";
+ // Choose rendering device
+ if (!device.isEmpty())
+ // user specified device
+ cmd1 += " -sDEVICE="+device;
+ else if (!ScCore->havePNGAlpha())
+ cmd1 += " -sDEVICE=png16m";
+ else
+ cmd1 += " -sDEVICE=pngalpha";
+ // and antialiasing
+ if (prefsManager->appPrefs.gs_AntiAliasText)
+ cmd1 += " -dTextAlphaBits=4";
+ if (prefsManager->appPrefs.gs_AntiAliasGraphics)
+ cmd1 += " -dGraphicsAlphaBits=4";
+
+ // Add any extra font paths being used by Scribus to gs's font search path
+ PrefsContext *pc = PrefsManager::instance()->prefsFile->getContext("Fonts");
+ PrefsTable *extraFonts = pc->getTable("ExtraFontDirs");
+#ifndef _WIN32
+ if (extraFonts->getRowCount() >= 1)
+ cmd1 += QString(" -sFONTPATH='%1'").arg(extraFonts->get(0,0));
+ for (int i = 1; i < extraFonts->getRowCount(); ++i)
+ cmd1 += QString(":'%1'").arg(extraFonts->get(i,0));
+#else
+ if (extraFonts->getRowCount() >= 1)
+ cmd1 += QString(" -sFONTPATH=\"%1\"").arg(extraFonts->get(0,0));
+ for (int i = 1; i < extraFonts->getRowCount(); ++i)
+ cmd1 += QString(";\"%1\"").arg(extraFonts->get(i,0));
+#endif
+
+ // then add any user specified args and run gs
+ cmd1 += " " + args_in + " -c showpage";
+// qDebug("Calling gs as: %s", cmd1.ascii());
+ return system(cmd1.toLocal8Bit().constData());
+}
+
+int convertPS2PS(QString in, QString out, const QStringList& opts, int level)
+{
+ PrefsManager* prefsManager=PrefsManager::instance();
+ QStringList args;
+ args.append( "-q" );
+ args.append( "-dQUIET" );
+ args.append( "-dNOPAUSE" );
+ args.append( "-dPARANOIDSAFER" );
+ args.append( "-dBATCH" );
+ if( level == 2 )
+ {
+ int major = 0, minor = 0;
+ // ps2write cannot be detected with testGSAvailability()
+ // so determine availability according to gs version.
+ getNumericGSVersion(major, minor);
+ if ((major >=8 && minor >= 53) || major > 8)
+ args.append( "-sDEVICE=ps2write" );
+ else
+ {
+ args.append( "-sDEVICE=pswrite" );
+ args.append( QString("-dLanguageLevel=%1").arg(level) );
+ }
+
+ }
+ else
+ {
+ args.append( "-sDEVICE=pswrite" );
+ if(level <= 3)
+ args.append( QString("-dLanguageLevel=%1").arg(level) );
+ }
+ args += opts;
+ args.append( QString("-sOutputFile=%1").arg(QDir::toNativeSeparators(out)) );
+ args.append( QDir::toNativeSeparators(in) );
+ int ret = System( getShortPathName(prefsManager->ghostscriptExecutable()), args );
+ return ret;
+}
+
+int convertPS2PDF(QString in, QString out, const QStringList& opts)
+{
+ PrefsManager* prefsManager=PrefsManager::instance();
+ QStringList args;
+ args.append( "-q" );
+ args.append( "-dQUIET" );
+ args.append( "-dNOPAUSE" );
+ args.append( "-dPARANOIDSAFER" );
+ args.append( "-dBATCH" );
+ args.append( "-sDEVICE=pdfwrite" );
+ args += opts;
+ args.append( QString("-sOutputFile=%1").arg(QDir::toNativeSeparators(out)) );
+ args.append( QDir::toNativeSeparators(in) );
+ int ret = System( getShortPathName(prefsManager->ghostscriptExecutable()), args );
+ return ret;
+}
+
+bool testGSAvailability( void )
+{
+ QStringList args;
+ PrefsManager* prefsManager = PrefsManager::instance();
+ return testGSAvailability(prefsManager->ghostscriptExecutable());
+}
+
+bool testGSAvailability( const QString& gsPath )
+{
+ QStringList args;
+ args.append( "-h" );
+ QProcess proc;
+ proc.start(getShortPathName(gsPath), args);
+ if (!proc.waitForStarted(5000))
+ return false;
+ proc.waitForFinished(5000);
+ return (proc.exitCode()==0);
+}
+
+bool testGSDeviceAvailability( const QString& device )
+{
+ QStringList args;
+ PrefsManager* prefsManager = PrefsManager::instance();
+ args.append( QString("-sDEVICE=%1").arg( device ) );
+ args.append( "-c" );
+ args.append( "quit" );
+ QProcess proc;
+ proc.start(getShortPathName(prefsManager->ghostscriptExecutable()), args);
+ if (!proc.waitForStarted(5000))
+ return false;
+ proc.waitForFinished(5000);
+ return (proc.exitCode()==0);
+}
+
+// Return the GhostScript version string, or QString::null if it couldn't be retrived.
+QString getGSVersion()
+{
+ QStringList args;
+ args.append(QString("--version").toLocal8Bit());
+ QString gsExe = getShortPathName(PrefsManager::instance()->ghostscriptExecutable());
+ QProcess proc;
+ proc.start(gsExe.toLocal8Bit(), args);
+ if (proc.waitForStarted(5000))
+ while (!proc.waitForFinished(5000))
+ qApp->processEvents();
+ QString gsVer;
+ if (proc.exitStatus()==QProcess::NormalExit)
+ gsVer = proc.readAllStandardOutput();
+ return gsVer;
+}
+
+// Return the GhostScript major and minor version numbers.
+bool getNumericGSVersion(int & major, int & minor)
+{
+ QString gs_ver_string(getGSVersion());
+ return getNumericGSVersion(gs_ver_string, major, minor);
+}
+
+bool getNumericGSVersion(const QString& ver, int& major, int& minor)
+{
+ // gs's version string is of the form MAJOR.MINOR, so look for the .
+ // then convert to numbers. 7.07 will become (7,7) for example.
+ bool success = false;
+ major = ver.section('.', 0, 0).toInt(&success);
+ if (!success)
+ return false;
+ minor = ver.section('.', 1, 1).toInt(&success);
+ if (!success)
+ return false;
+ return true;
+}
+
+QString getGSDefaultExeName(void)
+{
+ QString gsName("gs");
+#if defined _WIN32
+ // Set gsName to its default value
+ gsName = "gswin32c.exe";
+
+ QMap<int, QString> gplGS = getGSExePaths("SOFTWARE\\GPL Ghostscript");
+ QMap<int, QString> afplGS = getGSExePaths("SOFTWARE\\AFPL Ghostscript");
+ QMap<int, QString> gsVersions = gplGS.unite(afplGS);
+
+ if (gsVersions.isEmpty())
+ return gsName;
+
+ int currentVer = 0;
+ QString gsPath;
+ QMap<int, QString>::ConstIterator it, itEnd = gsVersions.constEnd();
+ for (it = gsVersions.constBegin(); it != itEnd; ++it)
+ {
+ int version = it.key();
+ if (version > currentVer)
+ {
+ gsPath = it.value();
+ QFileInfo fInfo(gsPath);
+ if (fInfo.exists())
+ {
+ gsName = gsPath;
+ currentVer = version;
+ }
+ }
+ }
+#endif
+#if defined Q_OS_MAC
+ QStringList gsPaths;
+ gsPaths << "/usr/bin/gs" << "/usr/local/bin/gs" << "/opt/local/bin/gs" << "/sw/bin/gs";
+ for (int i = 0; i < gsPaths.size(); ++i)
+ {
+ QFileInfo fInfo(gsPaths.at(i));
+ if (fInfo.exists())
+ {
+ gsName = gsPaths.at(i);
+ break;
+ }
+ }
+#endif
+ return gsName;
+}
+
+QMap<int, QString> SCRIBUS_API getGSExePaths(const QString& regKey)
+{
+ QMap<int, QString> gsVersions;
+#if defined _WIN32
+ // Try to locate GhostScript thanks to the registry
+ DWORD size;
+ HKEY hKey1, hKey2;
+ DWORD regType = REG_SZ;
+ WCHAR regVersion[MAX_PATH];
+ WCHAR regPath[MAX_PATH];
+ WCHAR gsPath[MAX_PATH];
+ QString gsVersion, gsName;
+
+ if( RegOpenKeyW(HKEY_LOCAL_MACHINE, (LPCWSTR) regKey.utf16(), &hKey1) == ERROR_SUCCESS )
+ {
+ size = sizeof(regVersion)/sizeof(WCHAR) - 1;
+ DWORD keyIndex = 0;
+ while ( RegEnumKeyExW(hKey1, keyIndex, regVersion, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS )
+ {
+ int gsNumericVer, gsMajor, gsMinor;
+ wcscpy(regPath, (const wchar_t*) regKey.utf16());
+ wcscat(regPath, L"\\");
+ wcscat(regPath, regVersion);
+ if (RegOpenKeyW(HKEY_LOCAL_MACHINE, regPath, &hKey2) == ERROR_SUCCESS)
+ {
+ size = sizeof(gsPath) - 1;
+ if (RegQueryValueExW(hKey2, L"GS_DLL", 0, &regType, (LPBYTE) gsPath, &size) == ERROR_SUCCESS)
+ {
+ // We now have GhostScript dll path, but we want gswin32c.exe
+ // Normally gswin32c.exe and gsdll.dll are in the same directory
+ if ( getNumericGSVersion(QString::fromUtf16((const ushort*) regVersion), gsMajor, gsMinor) )
+ {
+ gsNumericVer = gsMajor * 1000 + gsMinor;
+ gsName = QString::fromUtf16((const ushort*) gsPath);
+ size = gsName.lastIndexOf("\\");
+ if (size > 0)
+ {
+ gsName = gsName.left(size + 1);
+ gsName += "gswin32c.exe";
+ gsName.replace("\\", "/");
+ gsVersions.insert(gsNumericVer, gsName);
+ }
+ }
+ }
+ RegCloseKey(hKey2);
+ }
+ keyIndex++;
+ }
+ RegCloseKey(hKey1);
+ }
+#else
+ int gsNumericVer, gsMajor, gsMinor;
+ PrefsManager* prefsManager=PrefsManager::instance();
+ if (getNumericGSVersion(gsMajor, gsMinor))
+ {
+ gsNumericVer = gsMajor * 1000 + gsMinor;
+ gsVersions.insert(gsNumericVer, prefsManager->ghostscriptExecutable());
+ }
+#endif
+ return gsVersions;
+}
+
+QPixmap LoadPDF(QString fn, int Page, int Size, int *w, int *h)
+{
+ QString tmp, cmd1, cmd2;
+ QString pdfFile = QDir::toNativeSeparators(fn);
+ QString tmpFile = QDir::toNativeSeparators(ScPaths::getTempFileDir() + "sc.png");
+ QPixmap pm;
+ int ret = -1;
+ tmp.setNum(Page);
+ QStringList args;
+ args.append("-r72");
+// args.append("-sOutputFile=\""+tmpFile+"\"");
+ args.append("-sOutputFile="+tmpFile);
+ args.append("-dFirstPage="+tmp);
+ args.append("-dLastPage="+tmp);
+// args.append("\""+pdfFile+"\"");
+ args.append(pdfFile);
+ ret = callGS(args);
+ if (ret == 0)
+ {
+ QImage image;
+ image.load(tmpFile);
+ QFile::remove(tmpFile);
+ QImage im2;
+ *h = image.height();
+ *w = image.width();
+ double sx = image.width() / static_cast<double>(Size);
+ double sy = image.height() / static_cast<double>(Size);
+ double t = (sy < sx ? sx : sy);
+ im2 = image.scaled(static_cast<int>(image.width() / t), static_cast<int>(image.height() / t), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ pm=QPixmap::fromImage(im2);
+ QPainter p;
+ p.begin(&pm);
+ p.setBrush(Qt::NoBrush);
+ p.setPen(Qt::black);
+ p.drawRect(0, 0, pm.width(), pm.height());
+ p.end();
+ im2.detach();
+ }
+ return pm;
+}
+
+