Scribus Developer Documentation - API
logo-pen

Scribus Developer Documentation - API

util_ghostscript.cpp

Go to the documentation of this file.
00001 /*
00002 For general Scribus (>=1.3.2) copyright and licensing information please refer
00003 to the COPYING file provided with the program. Following this notice may exist
00004 a copyright and/or license notice that predates the release of Scribus 1.3.2
00005 for which a new license (GPL+exception) is in place.
00006 */
00007 /***************************************************************************
00008                           gsutil.cpp  -  description
00009                              -------------------
00010     begin                : Fri Sep 14 2001
00011     copyright            : (C) 2001 by Franz Schmid
00012     copyright            : (C) 2006- Scribus Team (code moved from util.cpp)
00013     email                : Franz.Schmid@altmuehlnet.de
00014  ***************************************************************************/
00015 
00016 /***************************************************************************
00017  *                                                                         *
00018  *   This program is free software; you can redistribute it and/or modify  *
00019  *   it under the terms of the GNU General Public License as published by  *
00020  *   the Free Software Foundation; either version 2 of the License, or     *
00021  *   (at your option) any later version.                                   *
00022  *                                                                         *
00023  ***************************************************************************/
00024 
00025 #include "util_ghostscript.h"
00026 
00027 #include <QDebug>
00028 #include <QDir>
00029 #include <QFile>
00030 #include <QFileInfo>
00031 #include <QPainter>
00032 #include <QPixmap>
00033 #include <QProcess>
00034 
00035 #include "scconfig.h"
00036 
00037 #ifdef HAVE_UNISTD_H
00038 #include <unistd.h>
00039 #endif
00040 
00041 #include "prefsfile.h"
00042 #include "prefsmanager.h"
00043 #include "scpaths.h"
00044 #include "scribuscore.h"
00045 #include "scribus.h"
00046 #include "util.h"
00047 
00048 using namespace std;
00049 
00050 
00051 int callGS(const QStringList& args_in, const QString device)
00052 {
00053     QString cmd;
00054     QStringList args;
00055     PrefsManager* prefsManager = PrefsManager::instance();
00056     args.append( "-q" );
00057     args.append( "-dNOPAUSE" );
00058     args.append( "-dQUIET" );
00059     args.append( "-dPARANOIDSAFER" );
00060     args.append( "-dBATCH" );
00061     // Choose rendering device
00062     if (!device.isEmpty())
00063         args.append( QString("-sDEVICE=%1").arg(device) ); // user specified device
00064     else if (!ScCore->havePNGAlpha())
00065         args.append( "-sDEVICE=png16m" );
00066     else
00067         args.append( "-sDEVICE=pngalpha" );
00068     // and antialiasing
00069     if (prefsManager->appPrefs.gs_AntiAliasText)
00070         args.append( "-dTextAlphaBits=4" );
00071     if (prefsManager->appPrefs.gs_AntiAliasGraphics)
00072         args.append( "-dGraphicsAlphaBits=4" );
00073 
00074     // Add any extra font paths being used by Scribus to gs's font search path
00075     PrefsContext *pc = PrefsManager::instance()->prefsFile->getContext("Fonts");
00076     PrefsTable *extraFonts = pc->getTable("ExtraFontDirs");
00077     const char sep = ScPaths::envPathSeparator;
00078     if (extraFonts->getRowCount() >= 1)
00079         cmd = QString("-sFONTPATH=%1").arg(QDir::convertSeparators(extraFonts->get(0,0)));
00080     for (int i = 1; i < extraFonts->getRowCount(); ++i)
00081         cmd += QString("%1%2").arg(sep).arg(QDir::convertSeparators(extraFonts->get(i,0)));
00082     if( !cmd.isEmpty() )
00083         args.append( cmd );
00084 
00085     args += args_in;
00086     args.append("-c");
00087     args.append("showpage");
00088 //  qDebug(args.join(" ").toAscii());
00089     return System( getShortPathName(prefsManager->ghostscriptExecutable()), args );
00090 }
00091 
00092 int callGS(const QString& args_in, const QString device)
00093 {
00094     PrefsManager* prefsManager=PrefsManager::instance();
00095     QString cmd1 = getShortPathName(prefsManager->ghostscriptExecutable());
00096     cmd1 += " -q -dNOPAUSE -dQUIET -dPARANOIDSAFER -dBATCH";
00097     // Choose rendering device
00098     if (!device.isEmpty())
00099         // user specified device
00100         cmd1 += " -sDEVICE="+device;
00101     else if (!ScCore->havePNGAlpha())
00102         cmd1 += " -sDEVICE=png16m";
00103     else
00104         cmd1 += " -sDEVICE=pngalpha";
00105     // and antialiasing
00106     if (prefsManager->appPrefs.gs_AntiAliasText)
00107         cmd1 += " -dTextAlphaBits=4";
00108     if (prefsManager->appPrefs.gs_AntiAliasGraphics)
00109         cmd1 += " -dGraphicsAlphaBits=4";
00110 
00111     // Add any extra font paths being used by Scribus to gs's font search path
00112     PrefsContext *pc = PrefsManager::instance()->prefsFile->getContext("Fonts");
00113     PrefsTable *extraFonts = pc->getTable("ExtraFontDirs");
00114 #ifndef _WIN32
00115     if (extraFonts->getRowCount() >= 1)
00116         cmd1 += QString(" -sFONTPATH='%1'").arg(extraFonts->get(0,0));
00117     for (int i = 1; i < extraFonts->getRowCount(); ++i)
00118         cmd1 += QString(":'%1'").arg(extraFonts->get(i,0));
00119 #else
00120     if (extraFonts->getRowCount() >= 1)
00121         cmd1 += QString(" -sFONTPATH=\"%1\"").arg(extraFonts->get(0,0));
00122     for (int i = 1; i < extraFonts->getRowCount(); ++i)
00123         cmd1 += QString(";\"%1\"").arg(extraFonts->get(i,0));
00124 #endif
00125 
00126     // then add any user specified args and run gs
00127     cmd1 += " " + args_in + " -c showpage";
00128 //  qDebug("Calling gs as: %s", cmd1.ascii());
00129     return system(cmd1.toLocal8Bit().constData());
00130 }
00131 
00132 int convertPS2PS(QString in, QString out, const QStringList& opts, int level)
00133 {
00134     PrefsManager* prefsManager=PrefsManager::instance();
00135     QStringList args;
00136     args.append( "-q" );
00137     args.append( "-dQUIET" );
00138     args.append( "-dNOPAUSE" );
00139     args.append( "-dPARANOIDSAFER" );
00140     args.append( "-dBATCH" );
00141     if( level == 2 )
00142     {
00143         int major = 0, minor = 0;
00144         // ps2write cannot be detected with testGSAvailability()
00145         // so determine availability according to gs version.
00146         getNumericGSVersion(major, minor);
00147         if ((major >=8 && minor >= 53) || major > 8)
00148             args.append( "-sDEVICE=ps2write" );
00149         else
00150         {
00151             args.append( "-sDEVICE=pswrite" );
00152             args.append( QString("-dLanguageLevel=%1").arg(level) );
00153         }
00154             
00155     }
00156     else
00157     {
00158         args.append( "-sDEVICE=pswrite" );
00159         if(level <= 3)
00160             args.append( QString("-dLanguageLevel=%1").arg(level) );
00161     }
00162     args += opts;
00163     args.append( QString("-sOutputFile=%1").arg(QDir::convertSeparators(out)) );
00164     args.append( QDir::convertSeparators(in) );
00165     int ret = System( getShortPathName(prefsManager->ghostscriptExecutable()), args );
00166     return ret;
00167 }
00168 
00169 bool testGSAvailability( void )
00170 {
00171     QStringList args;
00172     PrefsManager* prefsManager = PrefsManager::instance();
00173     return testGSAvailability(prefsManager->ghostscriptExecutable());
00174 }
00175 
00176 bool testGSAvailability( const QString& gsPath )
00177 {
00178     QStringList args;
00179     args.append( "-h" );
00180     QProcess proc;
00181     proc.start(getShortPathName(gsPath), args);
00182     if (!proc.waitForStarted(5000))
00183         return false;
00184     proc.waitForFinished(5000);
00185     return (proc.exitCode()==0);
00186 }
00187 
00188 bool testGSDeviceAvailability( const QString& device )
00189 {
00190     QStringList args;
00191     PrefsManager* prefsManager = PrefsManager::instance();
00192     args.append( QString("-sDEVICE=%1").arg( device ) );
00193     args.append( "-c" );
00194     args.append( "quit" );
00195     QProcess proc;
00196     proc.start(getShortPathName(prefsManager->ghostscriptExecutable()), args);
00197     if (!proc.waitForStarted(5000))
00198         return false;
00199     proc.waitForFinished(5000);
00200     return (proc.exitCode()==0);
00201 }
00202 
00203 // Return the GhostScript version string, or QString::null if it couldn't be retrived.
00204 QString getGSVersion()
00205 {
00206     QStringList args;
00207     args.append(QString("--version").toLocal8Bit());
00208     QString gsExe = getShortPathName(PrefsManager::instance()->ghostscriptExecutable());
00209     QProcess proc;
00210     proc.start(gsExe.toLocal8Bit(), args);
00211     if (proc.waitForStarted(5000))
00212         while (!proc.waitForFinished(5000))
00213             qApp->processEvents();
00214     QString gsVer;
00215     if (proc.exitStatus()==QProcess::NormalExit)
00216         gsVer = proc.readAllStandardOutput();
00217     return gsVer;
00218 }
00219 
00220 // Return the GhostScript major and minor version numbers.
00221 bool getNumericGSVersion(int & major, int & minor)
00222 {
00223     QString gs_ver_string(getGSVersion());
00224     return getNumericGSVersion(gs_ver_string, major, minor);
00225 }
00226 
00227 bool getNumericGSVersion(const QString& ver, int& major, int& minor)
00228 {
00229     // gs's version string is of the form MAJOR.MINOR, so look for the .
00230     // then convert to numbers. 7.07 will become (7,7) for example.
00231     bool success = false;
00232     major = ver.section('.', 0, 0).toInt(&success);
00233     if (!success)
00234         return false;
00235     minor = ver.section('.', 1, 1).toInt(&success);
00236     if (!success)
00237         return false;
00238     return true;
00239 }
00240 
00241 QString getGSDefaultExeName(void)
00242 {
00243     QString gsName;
00244 #if defined _WIN32
00245     // Set gsName to its default value
00246     gsName = "gswin32c.exe";
00247 
00248     QMap<int, QString> gplGS  = getGSExePaths("SOFTWARE\\GPL Ghostscript");
00249     QMap<int, QString> afplGS = getGSExePaths("SOFTWARE\\AFPL Ghostscript");
00250     QMap<int, QString> gsVersions = gplGS.unite(afplGS);
00251 
00252     if (gsVersions.isEmpty())
00253         return gsName;
00254 
00255     int currentVer = 0;
00256     QString gsPath;
00257     QMap<int, QString>::ConstIterator it, itEnd = gsVersions.constEnd();
00258     for (it = gsVersions.constBegin(); it != itEnd; ++it)
00259     {
00260         int version = it.key();
00261         if (version > currentVer)
00262         {
00263             gsPath = it.value();
00264             QFileInfo fInfo(gsPath);
00265             if (fInfo.exists())
00266             {
00267                 gsName = gsPath;
00268                 currentVer = version;
00269             }
00270         }
00271     }
00272 #else
00273     gsName = "gs";
00274 #endif
00275     return gsName;
00276 }
00277 
00278 QMap<int, QString> SCRIBUS_API getGSExePaths(const QString& regKey)
00279 {
00280     QMap<int, QString> gsVersions;
00281 #if defined _WIN32
00282     // Try to locate GhostScript thanks to the registry
00283     DWORD size;
00284     HKEY hKey1, hKey2;
00285     DWORD regType = REG_SZ;
00286     WCHAR regVersion[MAX_PATH];
00287     WCHAR regPath[MAX_PATH];
00288     WCHAR gsPath[MAX_PATH];
00289     QString gsVersion, gsName;
00290 
00291     if( RegOpenKeyW(HKEY_LOCAL_MACHINE, (LPCWSTR) regKey.utf16(), &hKey1) == ERROR_SUCCESS )
00292     {
00293         size = sizeof(regVersion)/sizeof(WCHAR) - 1;
00294         DWORD keyIndex = 0;
00295         while ( RegEnumKeyExW(hKey1, keyIndex, regVersion, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS )
00296         {
00297             int gsNumericVer, gsMajor, gsMinor;
00298             wcscpy(regPath, (const wchar_t*) regKey.utf16());
00299             wcscat(regPath, L"\\");
00300             wcscat(regPath, regVersion);
00301             if (RegOpenKeyW(HKEY_LOCAL_MACHINE, regPath, &hKey2) == ERROR_SUCCESS)
00302             {
00303                 size = sizeof(gsPath) - 1;
00304                 if (RegQueryValueExW(hKey2, L"GS_DLL", 0, &regType, (LPBYTE) gsPath, &size) == ERROR_SUCCESS)
00305                 {
00306                     // We now have GhostScript dll path, but we want gswin32c.exe
00307                     // Normally gswin32c.exe and gsdll.dll are in the same directory
00308                     if ( getNumericGSVersion(QString::fromUtf16((const ushort*) regVersion), gsMajor, gsMinor) )
00309                     {
00310                         gsNumericVer = gsMajor * 1000 + gsMinor;
00311                         gsName = QString::fromUtf16((const ushort*) gsPath);
00312                         size   = gsName.lastIndexOf("\\");
00313                         if (size > 0)
00314                         {
00315                             gsName  = gsName.left(size + 1);
00316                             gsName += "gswin32c.exe";
00317                             gsName.replace("\\", "/");
00318                             gsVersions.insert(gsNumericVer, gsName);
00319                         }   
00320                     }   
00321                 }
00322                 RegCloseKey(hKey2);
00323             }
00324             keyIndex++;
00325         }
00326         RegCloseKey(hKey1);
00327     }
00328 #else
00329     int gsNumericVer, gsMajor, gsMinor;
00330     PrefsManager* prefsManager=PrefsManager::instance();
00331     if (getNumericGSVersion(gsMajor, gsMinor))
00332     {
00333         gsNumericVer = gsMajor * 1000 + gsMinor;
00334         gsVersions.insert(gsNumericVer, prefsManager->ghostscriptExecutable());
00335     }
00336 #endif
00337     return gsVersions;
00338 }
00339 
00340 QPixmap LoadPDF(QString fn, int Page, int Size, int *w, int *h)
00341 {
00342     QString tmp, cmd1, cmd2;
00343     QString pdfFile = QDir::convertSeparators(fn);
00344     QString tmpFile = QDir::convertSeparators(ScPaths::getTempFileDir() + "sc.png");
00345     QPixmap pm;
00346     int ret = -1;
00347     tmp.setNum(Page);
00348     QStringList args;
00349     args.append("-r72");
00350 //  args.append("-sOutputFile=\""+tmpFile+"\"");
00351     args.append("-sOutputFile="+tmpFile);
00352     args.append("-dFirstPage="+tmp);
00353     args.append("-dLastPage="+tmp);
00354 //  args.append("\""+pdfFile+"\"");
00355     args.append(pdfFile);
00356     ret = callGS(args);
00357     if (ret == 0)
00358     {
00359         QImage image;
00360         image.load(tmpFile);
00361         QFile::remove(tmpFile);
00362         QImage im2;
00363         *h = image.height();
00364         *w = image.width();
00365         double sx = image.width() / static_cast<double>(Size);
00366         double sy = image.height() / static_cast<double>(Size);
00367         double t = (sy < sx ? sx : sy);
00368         im2 = image.scaled(static_cast<int>(image.width() / t), static_cast<int>(image.height() / t), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
00369         pm=QPixmap::fromImage(im2);
00370         QPainter p;
00371         p.begin(&pm);
00372         p.setBrush(Qt::NoBrush);
00373         p.setPen(Qt::black);
00374         p.drawRect(0, 0, pm.width(), pm.height());
00375         p.end();
00376         im2.detach();
00377     }
00378     return pm;
00379 }
00380 
00381 
Created with personalized Doxygen. This is documentation for GPL software Scribus - Open Source Desktop Publishing.