Back to index

scribus-ng  1.3.4.dfsg+svn20071115
gsutil.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 "gsutil.h"
00026 
00027 #include <qdir.h>
00028 #include <qfile.h>
00029 #include <qfileinfo.h>
00030 #include <qpainter.h>
00031 #include <qprocess.h>
00032 
00033 #include "scconfig.h"
00034 
00035 #ifdef HAVE_UNISTD_H
00036 #include <unistd.h>
00037 #endif
00038 #include "prefsfile.h"
00039 #include "prefsmanager.h"
00040 #include "scpaths.h"
00041 #include "scribuscore.h"
00042 
00043 #include "scribus.h"
00044 
00045 #include "util.h"
00046 
00047 using namespace std;
00048 
00049 
00050 int callGS(const QStringList& args_in, const QString device)
00051 {
00052        QString cmd;
00053        QStringList args;
00054        PrefsManager* prefsManager = PrefsManager::instance();
00055        args.append( getShortPathName(prefsManager->ghostscriptExecutable()) );
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() != 0)
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(" "));
00089        return System( 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() != 0)
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.local8Bit());
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( getShortPathName(prefsManager->ghostscriptExecutable()) );
00137        args.append( "-q" );
00138        args.append( "-dQUIET" );
00139        args.append( "-dNOPAUSE" );
00140        args.append( "-dPARANOIDSAFER" );
00141        args.append( "-dBATCH" );
00142        if( level == 2 )
00143        {
00144               int major = 0, minor = 0;
00145               // ps2write cannot be detected with testGSAvailability()
00146               // so determine availability according to gs version.
00147               getNumericGSVersion(major, minor);
00148               if ((major >=8 && minor >= 53) || major > 8)
00149                      args.append( "-sDEVICE=ps2write" );
00150               else
00151               {
00152                      args.append( "-sDEVICE=pswrite" );
00153                      args.append( QString("-dLanguageLevel=%1").arg(level) );
00154               }
00155                      
00156        }
00157        else
00158        {
00159               args.append( "-sDEVICE=pswrite" );
00160               if(level <= 3)
00161                      args.append( QString("-dLanguageLevel=%1").arg(level) );
00162        }
00163        args += opts;
00164        args.append( QString("-sOutputFile=%1").arg(QDir::convertSeparators(out)) );
00165        args.append( QDir::convertSeparators(in) );
00166        int ret = System( args );
00167        return ret;
00168 }
00169 
00170 int testGSAvailability( void )
00171 {
00172        QStringList args;
00173        PrefsManager* prefsManager = PrefsManager::instance();
00174        int ret = testGSAvailability(prefsManager->ghostscriptExecutable());
00175        return ret;
00176 }
00177 
00178 int testGSAvailability( QString gsPath )
00179 {
00180        QStringList args;
00181        args.append( getShortPathName(gsPath) );
00182        args.append( "-h" );
00183        int ret = System( args );
00184        return ret;
00185 }
00186 
00187 int testGSDeviceAvailability( QString device )
00188 {
00189        QStringList args;
00190        PrefsManager* prefsManager = PrefsManager::instance();
00191        args.append( getShortPathName(prefsManager->ghostscriptExecutable()) );
00192        args.append( QString("-sDEVICE=%1").arg( device ) );
00193        args.append( "-c" );
00194        args.append( "quit" );
00195        int ret = System( args );
00196        return ret;
00197 }
00198 
00199 // Return the GhostScript version string, or QString::null if it couldn't be retrived.
00200 QString getGSVersion()
00201 {
00202        QString gsVer;
00203        QStringList args;
00204        QString gsExe = getShortPathName(PrefsManager::instance()->ghostscriptExecutable());
00205        args.append(gsExe.local8Bit());
00206        args.append(QString("--version").local8Bit());
00207        QProcess proc(args);
00208        proc.setCommunication(QProcess::Stdout);
00209        proc.start();
00210        while(proc.isRunning())
00211        {
00212 #ifndef _WIN32
00213               usleep(5000);
00214 #else
00215               Sleep(5);
00216 #endif
00217               qApp->processEvents();
00218        }
00219        if(!proc.exitStatus())
00220               gsVer = proc.readLineStdout();
00221        return gsVer;
00222 }
00223 
00224 // Return the GhostScript major and minor version numbers.
00225 bool getNumericGSVersion(int & major, int & minor)
00226 {
00227        QString gs_ver_string(getGSVersion());
00228        // gs's version string is of the form MAJOR.MINOR, so look for the .
00229        // then convert to numbers. 7.07 will become (7,7) for example.
00230        bool success = false;
00231        major = gs_ver_string.section('.', 0, 0).toInt(&success);
00232        if (!success)
00233               return false;
00234        minor = gs_ver_string.section('.', 1, 1).toInt(&success);
00235        if (!success)
00236               return false;
00237        return true;
00238 }
00239 
00240 QString getGSDefaultExeName(void)
00241 {
00242        QString gsName;
00243 #if defined _WIN32
00244        // Try to locate GhostScript thanks to the registry
00245        DWORD size;
00246        HKEY hKey;
00247        LONG retValue;
00248        DWORD regType = REG_SZ;
00249        char regVersion[MAX_PATH];
00250        char regPath[MAX_PATH];
00251        char gsPath[MAX_PATH];
00252 
00253        // Set gsName to its default value
00254        gsName = "gswin32c.exe";
00255 
00256        // Search AFPL Ghostscript first as it has more chance to be up to date
00257        if( RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\AFPL Ghostscript", &hKey) == ERROR_SUCCESS )
00258               strcpy(regPath, "SOFTWARE\\AFPL Ghostscript");
00259        else if( RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\GPL Ghostscript", &hKey) == ERROR_SUCCESS )
00260               strcpy(regPath, "SOFTWARE\\GPL Ghostscript");
00261        else
00262               return gsName;
00263 
00264        // Search the first SubKey corresponding to the version key
00265        size = sizeof(regVersion) - 1;
00266        retValue = RegEnumKeyEx(hKey, 0, regVersion, &size, NULL, NULL, NULL, NULL);
00267        RegCloseKey(hKey);
00268        if( retValue != ERROR_SUCCESS )
00269               return gsName;
00270 
00271        strcat(regPath, "\\");
00272        strcat(regPath, regVersion);
00273 
00274        // Get the GS_DLL Value
00275        if (RegOpenKey(HKEY_LOCAL_MACHINE, regPath, &hKey) != ERROR_SUCCESS)
00276           return gsName;
00277        size = sizeof(gsPath) - 1;
00278        retValue = RegQueryValueEx(hKey, "GS_DLL", 0, &regType, (LPBYTE) gsPath, &size);
00279        RegCloseKey(hKey);
00280        if( retValue != ERROR_SUCCESS )
00281               return gsName;
00282 
00283        // We now have GhostScript dll path, but we want gswin32c.exe
00284        // Normally gswin32c.exe and gsdll.dll are in the same directory
00285        gsName = gsPath;
00286        size = gsName.findRev("\\");
00287        if(size <= 0)
00288               return QString("gswin32c.exe");
00289        gsName = gsName.left(size + 1);
00290        gsName += "gswin32c.exe";
00291 
00292        // Check GhostScript executable existence.
00293        QFileInfo fInfo(gsName);
00294        if( fInfo.exists() )
00295               gsName.replace("\\", "/"); // Return a qt-styled path
00296        else
00297               gsName = "gswin32c.exe";
00298 
00299 #else
00300        gsName = "gs";
00301 #endif
00302        return gsName;
00303 }
00304 
00305 QPixmap LoadPDF(QString fn, int Page, int Size, int *w, int *h)
00306 {
00307        QString tmp, cmd1, cmd2;
00308        QString pdfFile = QDir::convertSeparators(fn);
00309        QString tmpFile = QDir::convertSeparators(ScPaths::getTempFileDir() + "sc.png");
00310        QPixmap pm;
00311        int ret = -1;
00312        tmp.setNum(Page);
00313        QStringList args;
00314        args.append("-r72");
00315 //     args.append("-sOutputFile=\""+tmpFile+"\"");
00316        args.append("-sOutputFile="+tmpFile);
00317        args.append("-dFirstPage="+tmp);
00318        args.append("-dLastPage="+tmp);
00319 //     args.append("\""+pdfFile+"\"");
00320        args.append(pdfFile);
00321        ret = callGS(args);
00322        if (ret == 0)
00323        {
00324               QImage image;
00325               image.load(tmpFile);
00326               unlink(tmpFile);
00327               QImage im2;
00328               *h = image.height();
00329               *w = image.width();
00330               double sx = image.width() / static_cast<double>(Size);
00331               double sy = image.height() / static_cast<double>(Size);
00332               double t = (sy < sx ? sx : sy);
00333               im2 = image.smoothScale(static_cast<int>(image.width() / t), static_cast<int>(image.height() / t));
00334               pm.convertFromImage(im2);
00335               QPainter p;
00336               p.begin(&pm);
00337               p.setBrush(Qt::NoBrush);
00338               p.setPen(Qt::black);
00339               p.drawRect(0, 0, pm.width(), pm.height());
00340               p.end();
00341               im2.detach();
00342        }
00343        return pm;
00344 }
00345