Subversion Repositories Scribus

Rev

Rev 10033 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4507 cbradney 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
7
/***************************************************************************
8
                          gsutil.cpp  -  description
9
                             -------------------
10
    begin                : Fri Sep 14 2001
11
    copyright            : (C) 2001 by Franz Schmid
12
    copyright            : (C) 2006- Scribus Team (code moved from util.cpp)
13
    email                : Franz.Schmid@altmuehlnet.de
14
 ***************************************************************************/
15
 
16
/***************************************************************************
17
 *                                                                         *
18
 *   This program is free software; you can redistribute it and/or modify  *
19
 *   it under the terms of the GNU General Public License as published by  *
20
 *   the Free Software Foundation; either version 2 of the License, or     *
21
 *   (at your option) any later version.                                   *
22
 *                                                                         *
23
 ***************************************************************************/
24
 
25
#include "gsutil.h"
26
 
27
#include <qdir.h>
28
#include <qfile.h>
29
#include <qfileinfo.h>
30
#include <qpainter.h>
31
#include <qprocess.h>
32
 
33
/* CB old includes from util.cpp.
34
#include <algorithm>
35
#include <cstdlib>
36
#include <cmath>
37
*/
38
#include "scconfig.h"
39
 
40
#ifdef HAVE_UNISTD_H
41
#include <unistd.h>
42
#endif
43
/*
44
#include <setjmp.h>
45
#include "pagestructs.h"
46
*/
47
#include "prefsfile.h"
48
/*
49
#include "prefscontext.h"
50
#include "prefstable.h"
51
*/
52
#include "prefsmanager.h"
53
#include "scpaths.h"
54
 
55
#include "scribus.h"
56
#include "util.h"
57
 
58
using namespace std;
59
 
60
 
61
int callGS(const QStringList& args_in, const QString device)
62
{
63
        QString cmd;
64
        QStringList args;
65
        PrefsManager* prefsManager = PrefsManager::instance();
66
        args.append( getShortPathName(prefsManager->ghostscriptExecutable()) );
67
        args.append( "-q" );
68
        args.append( "-dNOPAUSE" );
69
        args.append( "-dQUIET" );
70
        args.append( "-dPARANOIDSAFER" );
71
        args.append( "-dBATCH" );
72
        // Choose rendering device
73
        if (!device.isEmpty())
74
                args.append( QString("-sDEVICE=%1").arg(device) ); // user specified device
75
        else if (ScMW->HavePngAlpha != 0)
76
                args.append( "-sDEVICE=png16m" );
77
        else
78
                args.append( "-sDEVICE=pngalpha" );
79
        // and antialiasing
80
        if (prefsManager->appPrefs.gs_AntiAliasText)
81
                args.append( "-dTextAlphaBits=4" );
82
        if (prefsManager->appPrefs.gs_AntiAliasGraphics)
83
                args.append( "-dGraphicsAlphaBits=4" );
84
 
85
        // Add any extra font paths being used by Scribus to gs's font search path
86
        PrefsContext *pc = PrefsManager::instance()->prefsFile->getContext("Fonts");
87
        PrefsTable *extraFonts = pc->getTable("ExtraFontDirs");
88
        const char sep = ScPaths::envPathSeparator;
89
        if (extraFonts->getRowCount() >= 1)
5118 cbradney 90
                cmd = QString("-sFONTPATH=%1").arg(QDir::convertSeparators(extraFonts->get(0,0)));
4507 cbradney 91
        for (int i = 1; i < extraFonts->getRowCount(); ++i)
5118 cbradney 92
                cmd += QString("%1%2").arg(sep).arg(QDir::convertSeparators(extraFonts->get(i,0)));
4507 cbradney 93
        if( !cmd.isEmpty() )
94
                args.append( cmd );
95
 
96
        args += args_in;
97
        args.append("-c");
98
        args.append("showpage");
99
        return System( args );
100
}
101
 
102
int callGS(const QString& args_in, const QString device)
103
{
104
        PrefsManager* prefsManager=PrefsManager::instance();
105
        QString cmd1 = getShortPathName(prefsManager->ghostscriptExecutable());
106
        cmd1 += " -q -dNOPAUSE -dQUIET -dPARANOIDSAFER -dBATCH";
107
        // Choose rendering device
108
        if (!device.isEmpty())
109
                // user specified device
110
                cmd1 += " -sDEVICE="+device;
111
        else if (ScMW->HavePngAlpha != 0)
112
                cmd1 += " -sDEVICE=png16m";
113
        else
114
                cmd1 += " -sDEVICE=pngalpha";
115
        // and antialiasing
116
        if (prefsManager->appPrefs.gs_AntiAliasText)
117
                cmd1 += " -dTextAlphaBits=4";
118
        if (prefsManager->appPrefs.gs_AntiAliasGraphics)
119
                cmd1 += " -dGraphicsAlphaBits=4";
120
 
121
        // Add any extra font paths being used by Scribus to gs's font search path
122
        PrefsContext *pc = PrefsManager::instance()->prefsFile->getContext("Fonts");
123
        PrefsTable *extraFonts = pc->getTable("ExtraFontDirs");
124
#ifndef _WIN32
125
        if (extraFonts->getRowCount() >= 1)
126
                cmd1 += QString(" -sFONTPATH='%1'").arg(extraFonts->get(0,0));
127
        for (int i = 1; i < extraFonts->getRowCount(); ++i)
128
                cmd1 += QString(":'%1'").arg(extraFonts->get(i,0));
129
#else
130
        if (extraFonts->getRowCount() >= 1)
131
                cmd1 += QString(" -sFONTPATH=\"%1\"").arg(extraFonts->get(0,0));
132
        for (int i = 1; i < extraFonts->getRowCount(); ++i)
133
                cmd1 += QString(";\"%1\"").arg(extraFonts->get(i,0));
134
#endif
135
 
136
        // then add any user specified args and run gs
137
        cmd1 += " " + args_in + " -c showpage";
138
//      qDebug("Calling gs as: %s", cmd1.ascii());
139
        return system(cmd1.local8Bit());
140
}
141
 
142
int  convertPS2PS(QString in, QString out, const QStringList& opts, int level)
143
{
144
        PrefsManager* prefsManager=PrefsManager::instance();
145
        QStringList args;
146
        args.append( getShortPathName(prefsManager->ghostscriptExecutable()) );
147
        args.append( "-q" );
148
        args.append( "-dQUIET" );
149
        args.append( "-dNOPAUSE" );
150
        args.append( "-dPARANOIDSAFER" );
151
        args.append( "-dBATCH" );
5626 jghali 152
        if( level == 2 )
153
        {
154
                int major = 0, minor = 0;
155
                // ps2write cannot be detected with testGSAvailability()
156
                // so determine availability according to gs version.
157
                getNumericGSVersion(major, minor);
158
                if ((major >=8 && minor >= 53) || major > 8)
159
                        args.append( "-sDEVICE=ps2write" );
160
                else
161
                {
162
                        args.append( "-sDEVICE=pswrite" );
163
                        args.append( QString("-dLanguageLevel=%1").arg(level) );
164
                }
165
 
166
        }
167
        else
168
        {
169
                args.append( "-sDEVICE=pswrite" );
170
                if(level <= 3)
171
                        args.append( QString("-dLanguageLevel=%1").arg(level) );
172
        }
4507 cbradney 173
        args += opts;
174
        args.append( QString("-sOutputFile=%1").arg(QDir::convertSeparators(out)) );
175
        args.append( QDir::convertSeparators(in) );
176
        int ret = System( args );
177
        return ret;
178
}
179
 
180
int  testGSAvailability( void )
181
{
182
        QStringList args;
183
        PrefsManager* prefsManager = PrefsManager::instance();
5772 jghali 184
        int ret = testGSAvailability(prefsManager->ghostscriptExecutable());
185
        return ret;
186
}
187
 
188
int testGSAvailability( QString gsPath )
189
{
190
        QStringList args;
191
        args.append( getShortPathName(gsPath) );
4507 cbradney 192
        args.append( "-h" );
193
        int ret = System( args );
194
        return ret;
195
}
196
 
197
int  testGSDeviceAvailability( QString device )
198
{
199
        QStringList args;
200
        PrefsManager* prefsManager = PrefsManager::instance();
201
        args.append( getShortPathName(prefsManager->ghostscriptExecutable()) );
202
        args.append( QString("-sDEVICE=%1").arg( device ) );
203
        args.append( "-c" );
204
        args.append( "quit" );
205
        int ret = System( args );
206
        return ret;
207
}
208
 
209
// Return the GhostScript version string, or QString::null if it couldn't be retrived.
210
QString getGSVersion()
211
{
212
        QString gsVer;
213
        QStringList args;
214
        QString gsExe = getShortPathName(PrefsManager::instance()->ghostscriptExecutable());
215
        args.append(gsExe.local8Bit());
216
        args.append(QString("--version").local8Bit());
217
        QProcess proc(args);
218
        proc.setCommunication(QProcess::Stdout);
219
        proc.start();
220
        while(proc.isRunning())
221
        {
222
#ifndef _WIN32
223
                usleep(5000);
224
#else
225
                Sleep(5);
226
#endif
227
                qApp->processEvents();
228
        }
229
        if(!proc.exitStatus())
230
                gsVer = proc.readLineStdout();
231
        return gsVer;
232
}
233
 
234
// Return the GhostScript major and minor version numbers.
235
bool getNumericGSVersion(int & major, int & minor)
236
{
237
        QString gs_ver_string(getGSVersion());
10033 jghali 238
        return getNumericGSVersion(gs_ver_string, major, minor);
239
}
240
 
241
bool getNumericGSVersion(const QString& ver, int& major, int& minor)
242
{
4507 cbradney 243
        // gs's version string is of the form MAJOR.MINOR, so look for the .
244
        // then convert to numbers. 7.07 will become (7,7) for example.
245
        bool success = false;
10033 jghali 246
        major = ver.section('.', 0, 0).toInt(&success);
4507 cbradney 247
        if (!success)
248
                return false;
10033 jghali 249
        minor = ver.section('.', 1, 1).toInt(&success);
4507 cbradney 250
        if (!success)
251
                return false;
252
        return true;
253
}
254
 
255
QString getGSDefaultExeName(void)
256
{
257
        QString gsName;
258
#if defined _WIN32
259
        // Set gsName to its default value
260
        gsName = "gswin32c.exe";
261
 
10033 jghali 262
        QMap<int, QString> gplGS  = getGSExePaths("SOFTWARE\\GPL Ghostscript");
263
        QMap<int, QString> afplGS = getGSExePaths("SOFTWARE\\AFPL Ghostscript");
4507 cbradney 264
 
10033 jghali 265
        QMap<int, QString> gsVersions;
266
        QMap<int, QString>::ConstIterator it, itEnd;
267
        for (it = afplGS.constBegin(); it != afplGS.constEnd(); ++it)
268
                gsVersions.insert(it.key(), it.data());
269
        for (it = gplGS.constBegin(); it != gplGS.constEnd(); ++it)
270
                gsVersions.insert(it.key(), it.data());
4507 cbradney 271
 
10033 jghali 272
        if (gsVersions.isEmpty())
4507 cbradney 273
                return gsName;
274
 
10033 jghali 275
        int currentVer = 0;
276
        QString gsPath;
277
        for (it = gsVersions.constBegin(); it != gsVersions.constEnd(); ++it)
278
        {
279
                int version = it.key();
280
                if (version > currentVer)
281
                {
282
                        gsPath = it.data();
283
                        QFileInfo fInfo(gsPath);
284
                        if (fInfo.exists())
285
                        {
286
                                gsName = gsPath;
287
                                currentVer = version;
288
                        }
289
                }
290
        }
4507 cbradney 291
 
8168 avox 292
#elif defined(Q_OS_MAC)
293
        QFileInfo bundleExe("/Library/Frameworks/Ghostscript/bin/gsc");
294
        if (bundleExe.exists())
295
                gsName = bundleExe.absFilePath();
296
        else
297
                gsName = "gs";
4507 cbradney 298
#else
299
        gsName = "gs";
300
#endif
301
        return gsName;
302
}
303
 
10033 jghali 304
QMap<int, QString> SCRIBUS_API getGSExePaths(const char* regKey)
305
{
306
        QMap<int, QString> gsVersions;
307
#if defined _WIN32
308
        // Try to locate GhostScript thanks to the registry
309
        DWORD size;
310
        HKEY hKey1, hKey2;
311
        DWORD regType = REG_SZ;
312
        char regVersion[MAX_PATH];
313
        char regPath[MAX_PATH];
314
        char gsPath[MAX_PATH];
315
        QString gsVersion, gsName;
316
 
317
        if( RegOpenKey(HKEY_LOCAL_MACHINE, regKey, &hKey1) == ERROR_SUCCESS )
318
        {
319
                size = sizeof(regVersion) - 1;
320
                DWORD keyIndex = 0;
321
                while ( RegEnumKeyEx(hKey1, keyIndex, regVersion, &size, NULL, NULL, NULL, NULL) == ERROR_SUCCESS )
322
                {
323
                        int gsNumericVer, gsMajor, gsMinor;
324
                        strcpy(regPath, regKey);
325
                        strcat(regPath, "\\");
326
                        strcat(regPath, regVersion);
327
                        if (RegOpenKey(HKEY_LOCAL_MACHINE, regPath, &hKey2) == ERROR_SUCCESS)
328
                        {
329
                                size = sizeof(gsPath) - 1;
330
                                if (RegQueryValueEx(hKey2, "GS_DLL", 0, &regType, (LPBYTE) gsPath, &size) == ERROR_SUCCESS)
331
                                {
332
                                        // We now have GhostScript dll path, but we want gswin32c.exe
333
                                        // Normally gswin32c.exe and gsdll.dll are in the same directory
334
                                        if ( getNumericGSVersion(QString(regVersion), gsMajor, gsMinor) )
335
                                        {
336
                                                gsNumericVer = gsMajor * 1000 + gsMinor;
337
                                                gsName = gsPath;
338
                                                size   = gsName.findRev("\\");
339
                                                if (size > 0)
340
                                                {
341
                                                        gsName  = gsName.left(size + 1);
342
                                                        gsName += "gswin32c.exe";
343
                                                        gsName.replace("\\", "/");
344
                                                        gsVersions.insert(gsNumericVer, gsName);
345
                                                }      
346
                                        }      
347
                                }
348
                                RegCloseKey(hKey2);
349
                        }
350
                        keyIndex++;
351
                }
352
                RegCloseKey(hKey1);
353
        }
354
#else
355
        int gsNumericVer, gsMajor, gsMinor;
356
        PrefsManager* prefsManager=PrefsManager::instance();
357
        if (getNumericGSVersion(gsMajor, gsMinor))
358
        {
359
                gsNumericVer = gsMajor * 1000 + gsMinor;
360
                gsVersions.insert(gsNumericVer, prefsManager->ghostscriptExecutable());
361
        }
362
#endif
363
        return gsVersions;
364
}
365
 
4507 cbradney 366
QPixmap LoadPDF(QString fn, int Page, int Size, int *w, int *h)
367
{
368
        QString tmp, cmd1, cmd2;
369
        QString pdfFile = QDir::convertSeparators(fn);
370
        QString tmpFile = QDir::convertSeparators(QDir::homeDirPath()+"/.scribus/sc.png");
371
        QPixmap pm;
372
        int ret = -1;
373
        tmp.setNum(Page);
374
        QStringList args;
375
        args.append("-r72");
11819 jghali 376
        args.append("-sOutputFile="+tmpFile);
4507 cbradney 377
        args.append("-dFirstPage="+tmp);
378
        args.append("-dLastPage="+tmp);
11819 jghali 379
        args.append(pdfFile);
4507 cbradney 380
        ret = callGS(args);
381
        if (ret == 0)
382
        {
383
                QImage image;
384
                image.load(tmpFile);
385
                unlink(tmpFile);
386
                QImage im2;
387
                *h = image.height();
388
                *w = image.width();
389
                double sx = image.width() / static_cast<double>(Size);
390
                double sy = image.height() / static_cast<double>(Size);
391
                double t = (sy < sx ? sx : sy);
392
                im2 = image.smoothScale(static_cast<int>(image.width() / t), static_cast<int>(image.height() / t));
393
                pm.convertFromImage(im2);
394
                QPainter p;
395
                p.begin(&pm);
396
                p.setBrush(Qt::NoBrush);
397
                p.setPen(Qt::black);
398
                p.drawRect(0, 0, pm.width(), pm.height());
399
                p.end();
400
                im2.detach();
401
        }
402
        return pm;
403
}
404