Subversion Repositories Scribus

Rev

Rev 3083 | Rev 3158 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
8 paul 1
/***************************************************************************
2
                          util.cpp  -  description
3
                             -------------------
4
    begin                : Fri Sep 14 2001
5
    copyright            : (C) 2001 by Franz Schmid
6
    email                : Franz.Schmid@altmuehlnet.de
7
 ***************************************************************************/
8
 
9
/***************************************************************************
10
 *                                                                         *
11
 *   This program is free software; you can redistribute it and/or modify  *
12
 *   it under the terms of the GNU General Public License as published by  *
13
 *   the Free Software Foundation; either version 2 of the License, or     *
14
 *   (at your option) any later version.                                   *
15
 *                                                                         *
16
 ***************************************************************************/
9 Franz 17
 
2529 craig 18
#include "util.h"
8 paul 19
#include <qbitmap.h>
20
#include <qpainter.h>
21
#include <qfile.h>
22
#include <qfileinfo.h>
23
#include <qtextstream.h>
1541 fschmid 24
#include <qdatastream.h>
2295 cbradney 25
#include <qregexp.h>
19 Franz 26
#include <qdir.h>
90 Franz 27
#include <qmessagebox.h>
2632 craig 28
#include <algorithm>
8 paul 29
#include <cstdlib>
30
#include <cmath>
2702 craig 31
 
32
#include "scconfig.h"
33
 
34
#ifdef HAVE_UNISTD_H
213 Franz 35
#include <unistd.h>
2702 craig 36
#endif
37
 
2730 cbradney 38
#if defined(_WIN32)
39
#if defined(_MSC_VER)
40
#define __STDC__ 1 // hack to get md5_buffer correctly identified
41
#endif
42
#include <windows.h>
43
#endif
44
 
8 paul 45
#include "md5.h"
2730 cbradney 46
 
201 Franz 47
#include <setjmp.h>
204 Franz 48
#include "qprocess.h"
1693 craig 49
#include "scpaths.h"
2517 craig 50
#include "prefsfile.h"
51
#include "prefscontext.h"
52
#include "prefstable.h"
2834 cbradney 53
#include "prefsmanager.h"
2952 cbradney 54
#include "commonstrings.h"
128 Franz 55
 
1555 fschmid 56
extern "C"
57
{
201 Franz 58
#define XMD_H           // shut JPEGlib up
59
#if defined(Q_OS_UNIXWARE)
60
#  define HAVE_BOOLEAN  // libjpeg under Unixware seems to need this
61
#endif
62
#include <jpeglib.h>
63
#include <jerror.h>
64
#undef HAVE_STDLIB_H
65
#ifdef const
66
#  undef const          // remove crazy C hackery in jconfig.h
67
#endif
68
}
69
 
214 Franz 70
#include "scribus.h"
68 Franz 71
#include <ft2build.h>
72
#include FT_FREETYPE_H
73
#include FT_OUTLINE_H
74
#include FT_GLYPH_H
8 paul 75
#ifdef HAVE_LIBZ
76
        #include <zlib.h>
77
#endif
78
#ifdef HAVE_TIFF
79
        #include <tiffio.h>
80
#endif
81
#ifdef HAVE_CMS
44 Franz 82
        #include CMS_INC
1555 fschmid 83
extern cmsHPROFILE CMSoutputProf;
84
extern cmsHPROFILE CMSprinterProf;
1781 fschmid 85
extern cmsHTRANSFORM stdTransG;
86
extern cmsHTRANSFORM stdProofG;
87
extern cmsHTRANSFORM stdTransImgG;
88
extern cmsHTRANSFORM stdProofImgG;
1555 fschmid 89
extern bool BlackPoint;
90
extern bool SoftProofing;
91
extern bool Gamut;
92
extern bool CMSuse;
93
extern int IntentMonitor;
94
extern int IntentPrinter;
8 paul 95
#endif
214 Franz 96
extern ScribusApp* ScApp;
8 paul 97
 
690 cbradney 98
using namespace std;
99
 
100
QImage ProofImage(QImage *Image)
8 paul 101
{
102
#ifdef HAVE_CMS
690 cbradney 103
        QImage out = Image->copy();
8 paul 104
        if ((CMSuse) && (SoftProofing))
167 Franz 105
        {
106
                for (int i=0; i < out.height(); ++i)
8 paul 107
                {
108
                        LPBYTE ptr = out.scanLine(i);
1781 fschmid 109
                        cmsDoTransform(stdProofImgG, ptr, ptr, out.width());
8 paul 110
                }
167 Franz 111
        }
8 paul 112
        else
167 Franz 113
        {
114
                if (CMSuse)
8 paul 115
                {
167 Franz 116
                        for (int i=0; i < out.height(); ++i)
8 paul 117
                        {
118
                                LPBYTE ptr = out.scanLine(i);
1781 fschmid 119
                                cmsDoTransform(stdTransImgG, ptr, ptr, out.width());
8 paul 120
                        }
121
                }
167 Franz 122
        }
8 paul 123
        return out;
124
#else
690 cbradney 125
        return Image->copy();
8 paul 126
#endif
127
}
128
 
204 Franz 129
/******************************************************************
130
 * Function System()
2907 subik 131
 *
204 Franz 132
 * Create a new process via QProcess and wait until finished.
133
 * return the process exit code.
134
 *
135
 ******************************************************************/
136
 
137
int System(const QStringList & args)
138
{
139
        QProcess *proc = new QProcess(NULL);
140
        proc->setArguments(args);
141
        if ( !proc->start() )
142
        {
214 Franz 143
                delete proc;
204 Franz 144
                return 1;
145
        }
146
        /* start was OK */
690 cbradney 147
        /* wait a little bit */
148
        while( proc->isRunning() )
2730 cbradney 149
#ifndef _WIN32
204 Franz 150
                usleep(5000);
2730 cbradney 151
#else
152
                Sleep(5);
153
#endif
690 cbradney 154
 
204 Franz 155
        int ex = proc->exitStatus();
156
        delete proc;
157
        return ex;
158
}
159
 
2529 craig 160
/**
161
 * @brief Return common gs args used across Scribus
162
 */
163
 
204 Franz 164
/******************************************************************
165
 * Function callGS()
166
 *   build the complete list of arguments for the call of our
167
 *   System() function.
168
 *
169
 *   The gs commands are all similar and consist of a few constant
170
 *   arguments, the variablke arguments and the end arguments which
2529 craig 171
 *   are also invariant. It will always use -q -dNOPAUSE and
172
 *   will always end with -c showpage -c quit. It also does automatic
173
 *   device selection unless overridden, and uses the user's antialiasing
174
 *   preferences and font search path.
204 Franz 175
 ******************************************************************/
1555 fschmid 176
 
2529 craig 177
int callGS(const QStringList& args_in, const QString device)
204 Franz 178
{
2529 craig 179
        return callGS(args_in.join(" "), device);
180
}
181
 
182
int callGS(const QString& args_in, const QString device)
183
{
2834 cbradney 184
        PrefsManager* prefsManager=PrefsManager::instance();
2885 fschmid 185
        QString cmd1 = getShortPathName(prefsManager->ghostscriptExecutable());
1186 fschmid 186
        cmd1 += " -q -dNOPAUSE";
2529 craig 187
        // Choose rendering device
2877 cbradney 188
        if (!device.isEmpty())
2529 craig 189
                // user specified device
190
                cmd1 += " -sDEVICE="+device;
191
        else if (ScApp->HavePngAlpha != 0)
1186 fschmid 192
                cmd1 += " -sDEVICE=png16m";
214 Franz 193
        else
1186 fschmid 194
                cmd1 += " -sDEVICE=pngalpha";
2529 craig 195
        // and antialiasing
2834 cbradney 196
        if (prefsManager->appPrefs.gs_AntiAliasText)
1186 fschmid 197
                cmd1 += " -dTextAlphaBits=4";
2834 cbradney 198
        if (prefsManager->appPrefs.gs_AntiAliasGraphics)
1186 fschmid 199
                cmd1 += " -dGraphicsAlphaBits=4";
2517 craig 200
 
201
        // Add any extra font paths being used by Scribus to gs's font search path
2856 cbradney 202
        PrefsContext *pc = PrefsManager::instance()->prefsFile->getContext("Fonts");
2517 craig 203
        PrefsTable *extraFonts = pc->getTable("ExtraFontDirs");
2843 fschmid 204
#ifndef _WIN32
2517 craig 205
        if (extraFonts->getRowCount() >= 1)
206
                cmd1 += QString(" -sFONTPATH='%1'").arg(extraFonts->get(0,0));
207
        for (int i = 1; i < extraFonts->getRowCount(); ++i)
208
                cmd1 += QString(":'%1'").arg(extraFonts->get(i,0));
2843 fschmid 209
#else
210
        if (extraFonts->getRowCount() >= 1)
211
                cmd1 += QString(" -sFONTPATH=\"%1\"").arg(extraFonts->get(0,0));
212
        for (int i = 1; i < extraFonts->getRowCount(); ++i)
213
                cmd1 += QString(";\"%1\"").arg(extraFonts->get(i,0));
214
#endif
2517 craig 215
 
216
        // then add any user specified args and run gs
2529 craig 217
        cmd1 += " " + args_in + " -c showpage -c quit";
2621 fschmid 218
//      qDebug("Calling gs as: %s", cmd1.ascii());
2642 craig 219
        return system(cmd1.local8Bit());
204 Franz 220
}
3083 fschmid 221
 
222
int  convertPS2PS(QString in, QString out, const QString& opts, int level)
223
{
224
        PrefsManager* prefsManager=PrefsManager::instance();
225
        QString cmd1 = getShortPathName(prefsManager->ghostscriptExecutable());
226
        cmd1 += " -q -dNOPAUSE -dSAFER -dBATCH";
227
        cmd1 += " -sDEVICE=pswrite";
228
        if(level <= 3)
229
                cmd1 += QString(" -dLanguageLevel=%1").arg(level);
230
        cmd1 += " " + opts + " ";
231
        cmd1 += " -sOutputFile=\"" + QDir::convertSeparators(out) + "\"";
232
        cmd1 += " \"" + QDir::convertSeparators(in) + "\"";
233
        int ret = system(cmd1.local8Bit());
234
        return ret;
235
}
204 Franz 236
 
2840 craig 237
// Return the GhostScript version string, or QString::null if it couldn't be retrived.
238
QString getGSVersion()
239
{
2885 fschmid 240
        QString gsVer;
241
        QStringList args;
242
        QString gsExe = getShortPathName(PrefsManager::instance()->ghostscriptExecutable());
243
        args.append(gsExe.local8Bit());
244
        args.append(QString("--version").local8Bit());
245
        QProcess* proc = new QProcess(args);
246
        proc->setCommunication(QProcess::Stdout);
247
        proc->start();
248
        while(proc->isRunning())
249
        {
250
#ifndef _WIN32
251
                usleep(5000);
252
#else
253
                Sleep(5);
254
#endif
255
                qApp->processEvents();
256
        }
257
        if(!proc->exitStatus())
258
                gsVer = proc->readLineStdout();
259
        delete proc;
260
        return gsVer;
2840 craig 261
}
262
 
263
// Return the GhostScript major and minor version numbers.
264
bool getNumericGSVersion(int & major, int & minor)
265
{
266
        QString gs_ver_string(getGSVersion());
267
        // gs's version string is of the form MAJOR.MINOR, so look for the .
268
        // then convert to numbers. 7.07 will become (7,7) for example.
269
        bool success = false;
270
        major = gs_ver_string.section('.', 0, 0).toInt(&success);
271
        if (!success)
272
                return false;
273
        minor = gs_ver_string.section('.', 1, 1).toInt(&success);
274
        if (!success)
275
                return false;
276
        return true;
277
}
278
 
2910 fschmid 279
QString getGSDefaultExeName(void)
280
{
281
        QString gsName;
282
#if defined _WIN32
283
        // Try to locate GhostScript thanks to the registry
284
        DWORD size;
285
        HKEY hKey;
286
        LONG retValue;
287
        DWORD regType = REG_SZ;
288
        char regVersion[MAX_PATH];
289
        char regPath[MAX_PATH];
290
        char gsPath[MAX_PATH];
291
 
292
        // Set gsName to its default value
293
        gsName = "gswin32c.exe";
2954 subik 294
 
2910 fschmid 295
        // Search AFPL Ghostscript first as it has more chance to be up to date
296
        if( RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\AFPL Ghostscript", &hKey) == ERROR_SUCCESS )
297
                strcpy(regPath, "SOFTWARE\\AFPL Ghostscript");
2954 subik 298
        else if( RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\GPL Ghostscript", &hKey) == ERROR_SUCCESS )
2910 fschmid 299
                strcpy(regPath, "SOFTWARE\\GPL Ghostscript");
300
        else
301
                return gsName;
302
 
303
        // Search the first SubKey corresponding to the version key
304
        size = sizeof(regVersion) - 1;
305
        retValue = RegEnumKeyEx(hKey, 0, regVersion, &size, NULL, NULL, NULL, NULL);
306
        RegCloseKey(hKey);
307
        if( retValue != ERROR_SUCCESS )
308
                return gsName;
309
 
310
        strcat(regPath, "\\");
311
        strcat(regPath, regVersion);
312
 
313
        // Get the GS_DLL Value
314
        if (RegOpenKey(HKEY_LOCAL_MACHINE, regPath, &hKey) != ERROR_SUCCESS)
315
          return gsName;
316
        size = sizeof(gsPath) - 1;
317
        retValue = RegQueryValueEx(hKey, "GS_DLL", 0, &regType, (LPBYTE) gsPath, &size);
318
        RegCloseKey(hKey);
319
        if( retValue != ERROR_SUCCESS )
320
                return gsName;
2954 subik 321
 
2910 fschmid 322
        // We now have GhostScript dll path, but we want gswin32c.exe
323
        // Normally gswin32c.exe and gsdll.dll are in the same directory
324
        gsName = gsPath;
325
        size = gsName.findRev("\\");
326
        if(size <= 0)
327
                return QString("gswin32c.exe");
328
        gsName = gsName.left(size + 1);
329
        gsName += "gswin32c.exe";
330
 
331
        // Check GhostScript executable existence.
332
        QFileInfo fInfo(gsName);
333
        if( fInfo.exists() )
334
                gsName.replace("\\", "/"); // Return a qt-styled path
335
        else
336
                gsName = "gswin32c.exe";
337
 
338
#else
339
        gsName = "gs";
340
#endif
341
        return gsName;
342
}
343
 
2885 fschmid 344
// On Windows, return short path name, else return longPath;
345
QString getShortPathName(QString longPath)
346
{
347
        QString shortPath = longPath;
348
#if defined _WIN32
349
        QFileInfo fInfo(longPath);
350
        if(fInfo.exists())
351
        {
352
                char shortName[MAX_PATH + 1];
353
                // An error should not be blocking as ERROR_INVALID_PARAMETER can simply mean
354
                // that volume does not support 8.3 filenames, so return longPath in this case
355
                int ret = GetShortPathName(QDir::convertSeparators(longPath).local8Bit(), shortName, sizeof(shortName));
356
                if( ret != ERROR_INVALID_PARAMETER && ret < sizeof(shortName))
357
                        shortPath = shortName;
358
        }
359
#endif
360
        return shortPath;
361
}
362
 
204 Franz 363
int copyFile(QString source, QString target)
364
{
365
        if ((source.isNull()) || (target.isNull()))
366
                return -1;
367
        if (source == target)
368
                return -1;
369
        QFile s(source);
370
        QFile t(target);
371
        if (!s.exists())
372
                return -1;
373
        QByteArray bb(s.size());
374
        if (s.open(IO_ReadOnly))
375
        {
376
                s.readBlock(bb.data(), s.size());
377
                s.close();
378
                if (t.open(IO_WriteOnly))
379
                {
380
                        t.writeBlock(bb.data(), bb.size());
381
                        t.close();
382
                }
383
        }
384
        return 0;
385
}
386
 
387
int moveFile(QString source, QString target)
388
{
389
        if ((source.isNull()) || (target.isNull()))
390
                return -1;
391
        if (source == target)
392
                return -1;
393
        copyFile(source, target);
2921 fschmid 394
        QFile::remove(source);
204 Franz 395
        return 0;
396
}
397
 
690 cbradney 398
QPixmap LoadPDF(QString fn, int Page, int Size, int *w, int *h)
19 Franz 399
{
400
        QString tmp, cmd1, cmd2;
2843 fschmid 401
        QString pdfFile = QDir::convertSeparators(fn);
282 Franz 402
        QString tmpFile = QDir::convertSeparators(QDir::homeDirPath()+"/.scribus/sc.png");
19 Franz 403
        QPixmap pm;
404
        int ret = -1;
690 cbradney 405
        tmp.setNum(Page);
204 Franz 406
        QStringList args;
407
        args.append("-r72");
2843 fschmid 408
        args.append("-sOutputFile=\""+tmpFile+"\"");
204 Franz 409
        args.append("-dFirstPage="+tmp);
410
        args.append("-dLastPage="+tmp);
2843 fschmid 411
        args.append("\""+pdfFile+"\"");
204 Franz 412
        ret = callGS(args);
19 Franz 413
        if (ret == 0)
167 Franz 414
        {
19 Franz 415
                QImage image;
159 Franz 416
                image.load(tmpFile);
204 Franz 417
                unlink(tmpFile);
1555 fschmid 418
                QImage im2;
20 Franz 419
                *h = image.height();
420
                *w = image.width();
80 Franz 421
                double sx = image.width() / static_cast<double>(Size);
422
                double sy = image.height() / static_cast<double>(Size);
167 Franz 423
                double t = (sy < sx ? sx : sy);
424
                im2 = image.smoothScale(static_cast<int>(image.width() / t), static_cast<int>(image.height() / t));
19 Franz 425
                pm.convertFromImage(im2);
426
                QPainter p;
427
                p.begin(&pm);
428
                p.setBrush(Qt::NoBrush);
429
                p.setPen(Qt::black);
430
                p.drawRect(0, 0, pm.width(), pm.height());
431
                p.end();
432
                im2.detach();
167 Franz 433
        }
19 Franz 434
        return pm;
435
}
436
 
8 paul 437
QString GetAttr(QDomElement *el, QString at, QString def)
438
{
439
        return el->attribute(at, def);
440
}
441
 
442
int QStoInt(QString in)
443
{
2093 cbradney 444
        /* Dont need this, toInt returns 0 on failure, dont even need this function really.
8 paul 445
        bool ok = false;
446
        int c = in.toInt(&ok);
167 Franz 447
        return ok ? c : 0;
2093 cbradney 448
        */
449
        return in.toInt();
8 paul 450
}
451
 
80 Franz 452
double QStodouble(QString in)
8 paul 453
{
454
        bool ok = false;
80 Franz 455
        double c = in.toDouble(&ok);
167 Franz 456
        return ok ? c : 0.0;
8 paul 457
}
458
 
459
QPixmap loadIcon(QString nam)
460
{
1693 craig 461
        QString iconFilePath = QString("%1/%2").arg(ScPaths::instance().iconDir()).arg(nam);
8 paul 462
        QPixmap pm;
1672 craig 463
        if (!QFile::exists(iconFilePath))
464
                qWarning("Unable to load icon %s: File not found", iconFilePath.ascii());
465
        else
466
        {
467
                pm.load(iconFilePath);
468
                if (pm.isNull())
469
                        qWarning("Unable to load icon %s: Got null pixmap", iconFilePath.ascii());
470
        }
8 paul 471
        return pm;
472
}
473
 
1109 fschmid 474
uint getDouble(QString in, bool raw)
475
{
476
        QByteArray bb(4);
477
        if (raw)
478
        {
479
                bb[3] = static_cast<uchar>(QChar(in.at(0)));
480
                bb[2] = static_cast<uchar>(QChar(in.at(1)));
481
                bb[1] = static_cast<uchar>(QChar(in.at(2)));
482
                bb[0] = static_cast<uchar>(QChar(in.at(3)));
483
        }
484
        else
485
        {
486
                bb[0] = static_cast<uchar>(QChar(in.at(0)));
487
                bb[1] = static_cast<uchar>(QChar(in.at(1)));
488
                bb[2] = static_cast<uchar>(QChar(in.at(2)));
489
                bb[3] = static_cast<uchar>(QChar(in.at(3)));
490
        }
491
        uint ret;
492
        ret = bb[0] & 0xff;
493
        ret |= (bb[1] << 8) & 0xff00;
494
        ret |= (bb[2] << 16) & 0xff0000;
495
        ret |= (bb[3] << 24) & 0xff000000;
496
        return ret;
497
}
498
 
690 cbradney 499
bool loadText(QString filename, QString *Buffer)
8 paul 500
{
690 cbradney 501
        QFile f(filename);
8 paul 502
        QFileInfo fi(f);
503
        if (!fi.exists())
504
                return false;
167 Franz 505
        bool ret;
8 paul 506
        QByteArray bb(f.size());
507
        if (f.open(IO_ReadOnly))
167 Franz 508
        {
8 paul 509
                f.readBlock(bb.data(), f.size());
510
                f.close();
690 cbradney 511
                for (uint posi = 0; posi < bb.size(); ++posi)
3027 fschmid 512
                        *Buffer += QChar(bb[posi]);
8 paul 513
                ret = true;
167 Franz 514
        }
8 paul 515
        else
516
                ret = false;
517
        return ret;
518
}
519
 
80 Franz 520
QPointArray RegularPolygon(double w, double h, uint c, bool star, double factor, double rota)
8 paul 521
{
167 Franz 522
        uint cx = star ? c * 2 : c;
80 Franz 523
        double seg = 360.0 / cx;
524
        double sc = rota + 180.0;
525
        double di = factor;
8 paul 526
        int mx = 0;
527
        int my = 0;
528
        QPointArray pts = QPointArray();
529
        for (uint x = 0; x < cx; ++x)
167 Franz 530
        {
8 paul 531
                sc = seg * x + 180.0 + rota;
532
                if (star)
167 Franz 533
                {
534
                        double wf = x % 2 == 0 ? w / 2 : w / 2 * di;
535
                        double hf = x % 2 == 0 ? h / 2 : h / 2 * di;
536
                        mx = qRound(sin(sc / 180 * M_PI) * (wf) + (w/2));
537
                        my = qRound(cos(sc / 180 * M_PI) * (hf) + (h/2));
538
                }
8 paul 539
                else
167 Franz 540
                {
8 paul 541
                        mx = qRound(sin(sc / 180 * M_PI) * (w/2) + (w/2));
542
                        my = qRound(cos(sc / 180 * M_PI) * (h/2) + (h/2));
167 Franz 543
                }
8 paul 544
                pts.resize(x+1);
545
                pts.setPoint(x, mx, my);
167 Franz 546
        }
8 paul 547
        return pts;
548
}
549
 
80 Franz 550
FPointArray RegularPolygonF(double w, double h, uint c, bool star, double factor, double rota)
8 paul 551
{
167 Franz 552
        uint cx = star ? c * 2 : c;
80 Franz 553
        double seg = 360.0 / cx;
554
        double sc = rota + 180.0;
555
        double di = factor;
556
        double mx = 0;
557
        double my = 0;
1884 fschmid 558
        FPointArray pts;
8 paul 559
        for (uint x = 0; x < cx; ++x)
167 Franz 560
        {
8 paul 561
                sc = seg * x + 180.0 + rota;
562
                if (star)
167 Franz 563
                {
564
                        double wf = x % 2 == 0 ? w / 2 : w / 2 * di;
565
                        double hf = x % 2 == 0 ? h / 2 : h / 2 * di;
566
                        mx = qRound(sin(sc / 180 * M_PI) * (wf) + (w/2));
567
                        my = qRound(cos(sc / 180 * M_PI) * (hf) + (h/2));
568
                }
8 paul 569
                else
167 Franz 570
                {
8 paul 571
                        mx = sin(sc / 180 * M_PI) * (w/2) + (w/2);
572
                        my = cos(sc / 180 * M_PI) * (h/2) + (h/2);
167 Franz 573
                }
8 paul 574
                pts.resize(x+1);
575
                pts.setPoint(x, mx, my);
167 Franz 576
        }
8 paul 577
        return pts;
578
}
579
 
580
QPointArray FlattenPath(FPointArray ina, QValueList<uint> &Segs)
581
{
582
        QPointArray Bez(4);
583
        QPointArray outa, cli;
584
        Segs.clear();
585
        if (ina.size() > 3)
167 Franz 586
        {
587
                for (uint poi=0; poi<ina.size()-3; poi += 4)
8 paul 588
                {
167 Franz 589
                        if (ina.point(poi).x() > 900000)
8 paul 590
                        {
591
                                outa.resize(outa.size()+1);
592
                                outa.setPoint(outa.size()-1, cli.point(cli.size()-1));
80 Franz 593
                                Segs.append(outa.size());
8 paul 594
                                continue;
167 Franz 595
                        }
8 paul 596
                        BezierPoints(&Bez, ina.pointQ(poi), ina.pointQ(poi+1), ina.pointQ(poi+3), ina.pointQ(poi+2));
597
                        cli = Bez.cubicBezier();
598
                        outa.putPoints(outa.size(), cli.size()-1, cli);
167 Franz 599
                }
8 paul 600
                outa.resize(outa.size()+1);
601
                outa.setPoint(outa.size()-1, cli.point(cli.size()-1));
167 Franz 602
        }
8 paul 603
        return outa;
604
}
605
 
80 Franz 606
double xy2Deg(double x, double y)
8 paul 607
{
608
        return (atan2(y,x)*(180.0/M_PI));
609
}
610
 
611
void BezierPoints(QPointArray *ar, QPoint n1, QPoint n2, QPoint n3, QPoint n4)
612
{
613
        ar->setPoint(0, n1);
614
        ar->setPoint(1, n2);
615
        ar->setPoint(2, n3);
616
        ar->setPoint(3, n4);
617
        return;
618
}
619
 
690 cbradney 620
void Level2Layer(ScribusDoc *currentDoc, struct Layer *ll, int Level)
8 paul 621
{
2955 fschmid 622
        uint layerCount=currentDoc->layerCount();
2937 cbradney 623
        for (uint la2 = 0; la2 < layerCount; ++la2)
167 Franz 624
        {
690 cbradney 625
                if (currentDoc->Layers[la2].Level == Level)
8 paul 626
                {
1065 cbradney 627
                        ll->isViewable = currentDoc->Layers[la2].isViewable;
628
                        ll->isPrintable = currentDoc->Layers[la2].isPrintable;
690 cbradney 629
                        ll->LNr = currentDoc->Layers[la2].LNr;
1737 fschmid 630
                        ll->Name = currentDoc->Layers[la2].Name;
8 paul 631
                        break;
632
                }
167 Franz 633
        }
8 paul 634
}
635
 
2937 cbradney 636
/* CB Replaced by ScribusDoc::layerLevelFromNumber
2122 fschmid 637
int Layer2Level(ScribusDoc *currentDoc, int LayerNr)
638
{
2937 cbradney 639
        int retVal=currentDoc->layerLevelFromNumber(LayerNr);
640
        int layerCount=currentDoc->layerCount();
641
        for (uint la2 = 0; la2 < layerCount; ++la2)
2122 fschmid 642
        {
643
                if (currentDoc->Layers[la2].LNr == LayerNr)
644
                        return currentDoc->Layers[la2].Level;
645
        }
646
        return 0;
647
}
2937 cbradney 648
*/
8 paul 649
QString CompressStr(QString *in)
650
{
651
        QString out = "";
652
#ifdef HAVE_LIBZ
653
        QByteArray bb(in->length());
654
        for (uint ax = 0; ax < in->length(); ++ax)
655
                bb[ax] = uchar(QChar(in->at(ax)));
656
        uLong exlen = uint(bb.size() * 0.001 + 16) + bb.size();
657
        QByteArray bc(exlen);
2295 cbradney 658
        int errcode = compress2((Byte *)bc.data(), &exlen, (Byte *)bb.data(), uLong(bb.size()), 9);
659
        if (errcode != Z_OK) {
660
                qDebug(QString("compress2 failed with code %1").arg(errcode));
661
                out = *in;
662
        }
663
        else {
664
                for (uint cl = 0; cl < exlen; ++cl)
2884 fschmid 665
                        out += QChar(bc[cl]);
2295 cbradney 666
        }
8 paul 667
#else
668
        out = *in;
669
#endif
670
        return out;
671
}
672
 
673
char *toHex( uchar u )
674
{
1555 fschmid 675
        static char hexVal[3];
676
        int i = 1;
677
        while ( i >= 0 )
167 Franz 678
        {
679
                ushort hex = (u & 0x000f);
680
                if ( hex < 0x0a )
1555 fschmid 681
                        hexVal[i] = '0'+hex;
167 Franz 682
                else
1555 fschmid 683
                        hexVal[i] = 'A'+(hex-0x0a);
167 Franz 684
                u = u >> 4;
1555 fschmid 685
                i--;
686
        }
687
        hexVal[2] = '\0';
688
        return hexVal;
8 paul 689
}
690
 
691
QString String2Hex(QString *in, bool lang)
692
{
693
        int i = 0;
694
        QString out = "";
695
        for( uint xi = 0; xi < in->length(); ++xi )
167 Franz 696
        {
8 paul 697
                out += toHex(uchar(QChar(in->at(xi))));
698
                ++i;
699
                if ((i>40) && (lang))
167 Franz 700
                {
8 paul 701
                        out += '\n';
702
                        i=0;
703
                }
167 Franz 704
        }
8 paul 705
        return out;
706
}
707
 
708
QByteArray ComputeMD5Sum(QByteArray *in)
709
{
710
        QByteArray MDsum(16);
49 paul 711
        md5_buffer (in->data(), in->size(), reinterpret_cast<void*>(MDsum.data()));
8 paul 712
        return MDsum;
713
}
714
 
19 Franz 715
QString Path2Relative(QString Path)
716
{
717
        QString Ndir = "";
3089 fschmid 718
        QStringList Pdir;
19 Franz 719
        QFileInfo Bfi = QFileInfo(Path);
3089 fschmid 720
        QStringList Bdir;
690 cbradney 721
        bool end = true;
19 Franz 722
        uint dcoun = 0;
723
        uint dcoun2 = 0;
3089 fschmid 724
 
725
#ifndef _WIN32
726
        Pdir = QStringList::split("/", QDir::currentDirPath());
727
        Bdir = QStringList::split("/", Bfi.dirPath(true));
728
#else
729
        // On win32, file systems are case insensitive
730
        Pdir = QStringList::split("/", QDir::currentDirPath().lower());
731
        Bdir = QStringList::split("/", Bfi.dirPath(true).lower());
732
        // We must check that both path are located on same drive
733
        if( Pdir.size() > 0 && Bdir.size() > 0 )
734
        {
735
                QString drive = Bdir.front();
736
                QString currentDrive = Pdir.front();
737
                if( drive != currentDrive )
738
                        return Path;
739
        }
740
#endif
741
 
690 cbradney 742
        while (end)
167 Franz 743
        {
19 Franz 744
                if (Pdir[dcoun] == Bdir[dcoun])
745
                        dcoun++;
746
                else
747
                        break;
748
                if (dcoun > Pdir.count())
749
                        break;
167 Franz 750
        }
19 Franz 751
        dcoun2 = dcoun;
3089 fschmid 752
 
753
#ifdef _WIN32
754
        Bdir = QStringList::split("/", Bfi.dirPath(true));
755
#endif
756
 
19 Franz 757
        for (uint ddx2 = dcoun; ddx2 < Pdir.count(); ddx2++)
758
                Ndir += "../";
759
        for (uint ddx = dcoun2; ddx < Bdir.count(); ddx++)
760
                Ndir += Bdir[ddx]+"/";
761
        Ndir += Bfi.fileName();
762
        return Ndir;
763
}
764
 
90 Franz 765
/***************************************************************************
766
    begin                : Wed Oct 29 2003
767
    copyright            : (C) 2003 The Scribus Team
768
    email                : paul@all-the-johnsons.co.uk
769
 ***************************************************************************/
770
// check if the file exists, if it does, ask if they're sure
771
// return true if they're sure, else return false;
772
 
773
bool overwrite(QWidget *parent, QString filename)
774
{
167 Franz 775
        bool retval = true;
776
        QFileInfo fi(filename);
777
        if (fi.exists())
1555 fschmid 778
        {
779
                int t = QMessageBox::warning(parent, QObject::tr("File exists"),
780
                                             QObject::tr("A file named '%1' already exists.\nDo you want to replace it with the file you are saving?").arg(filename),
2952 cbradney 781
                                             CommonStrings::tr_Cancel, QObject::tr("&Replace"), "", 1, 0);
1555 fschmid 782
                if (t == 0)
90 Franz 783
                        retval = false;
1555 fschmid 784
        }
785
        return retval;
90 Franz 786
}
124 Franz 787
 
1957 cbradney 788
void WordAndPara(PageItem* currItem, int *w, int *p, int *c, int *wN, int *pN, int *cN)
125 Franz 789
{
790
        QChar Dat = QChar(32);
791
        int para = 0;
792
        int ww = 0;
793
        int cc = 0;
794
        int paraN = 0;
795
        int wwN = 0;
796
        int ccN = 0;
797
        bool first = true;
1957 cbradney 798
        PageItem *nextItem = currItem;
799
        PageItem *nbl = currItem;
800
        while (nextItem != 0)
167 Franz 801
        {
1957 cbradney 802
                if (nextItem->BackBox != 0)
803
                        nextItem = nextItem->BackBox;
125 Franz 804
                else
805
                        break;
167 Franz 806
        }
1957 cbradney 807
        while (nextItem != 0)
167 Franz 808
        {
1957 cbradney 809
                for (uint a = 0; a < nextItem->itemText.count(); ++a)
1555 fschmid 810
                {
1957 cbradney 811
                        QChar b = nextItem->itemText.at(a)->ch[0];
125 Franz 812
                        if (b == QChar(13))
167 Franz 813
                        {
1957 cbradney 814
                                if (a >= nextItem->MaxChars)
125 Franz 815
                                        paraN++;
816
                                else
817
                                        para++;
167 Franz 818
                        }
125 Franz 819
                        if ((!b.isLetterOrNumber()) && (Dat.isLetterOrNumber()) && (!first))
167 Franz 820
                        {
1957 cbradney 821
                                if (a >= nextItem->MaxChars)
125 Franz 822
                                        wwN++;
823
                                else
824
                                        ww++;
167 Franz 825
                        }
1957 cbradney 826
                        if (a >= nextItem->MaxChars)
125 Franz 827
                                ccN++;
828
                        else
829
                                cc++;
1555 fschmid 830
                        Dat = b;
125 Franz 831
                        first = false;
1555 fschmid 832
                }
1957 cbradney 833
                nbl = nextItem;
834
                nextItem = nextItem->NextBox;
167 Franz 835
        }
1065 cbradney 836
        if (nbl->MaxChars < nbl->itemText.count())
125 Franz 837
                paraN++;
838
        else
839
                para++;
840
        if (Dat.isLetterOrNumber())
167 Franz 841
        {
1065 cbradney 842
                if (nbl->MaxChars < nbl->itemText.count())
125 Franz 843
                        wwN++;
844
                else
845
                        ww++;
167 Franz 846
        }
125 Franz 847
        *w = ww;
848
        *p = para;
849
        *c = cc;
850
        *wN = wwN;
851
        *pN = paraN;
852
        *cN = ccN;
853
}
203 Franz 854
 
690 cbradney 855
void ReOrderText(ScribusDoc *currentDoc, ScribusView *view)
203 Franz 856
{
2380 cbradney 857
        double savScale = view->getScale();
858
        view->setScale(1.0);
690 cbradney 859
        currentDoc->RePos = true;
203 Franz 860
        QPixmap pgPix(10, 10);
861
        QRect rd = QRect(0,0,9,9);
862
        ScPainter *painter = new ScPainter(&pgPix, pgPix.width(), pgPix.height());
690 cbradney 863
        for (uint azz=0; azz<currentDoc->MasterItems.count(); ++azz)
203 Franz 864
        {
1957 cbradney 865
                PageItem *currItem = currentDoc->MasterItems.at(azz);
866
                if (currItem->itemType() == PageItem::PathText)
867
                        currItem->DrawObj(painter, rd);
203 Franz 868
        }
690 cbradney 869
        for (uint azz=0; azz<currentDoc->Items.count(); ++azz)
203 Franz 870
        {
1957 cbradney 871
                PageItem *currItem = currentDoc->Items.at(azz);
872
                if ((currItem->itemType() == PageItem::TextFrame) || (currItem->itemType() == PageItem::PathText))
873
                        currItem->DrawObj(painter, rd);
203 Franz 874
        }
690 cbradney 875
        currentDoc->RePos = false;
2380 cbradney 876
        view->setScale(savScale);
203 Franz 877
        delete painter;
878
}
447 cbradney 879
 
880
/*! 10/06/2004 - pv
881
\param QString s1 first string
882
\param QString s2 second string
883
\retval bool t/f related s1>s2
884
 */
885
bool compareQStrings(QString s1, QString s2)
886
{
887
        if (QString::localeAwareCompare(s1, s2) >= 0)
2680 cbradney 888
                return false;
889
        return true;
447 cbradney 890
}
891
 
892
/*! 10/06/2004 - pv
893
Returns a sorted list of QStrings - sorted by locale specific
894
rules! Uses compareQStrings() as rule. There is STL used!
895
TODO: Maybe we can implement one cass for various sorting...
896
\param QStringList aList unsorted string list
897
\retval QStringList sorted string list
898
*/
899
QStringList sortQStringList(QStringList aList)
900
{
901
        std::vector<QString> sortList;
902
        QStringList retList;
903
        QStringList::Iterator it;
904
        for (it = aList.begin(); it != aList.end(); ++it)
905
                sortList.push_back(*it);
906
        std::sort(sortList.begin(), sortList.end(), compareQStrings);
456 fschmid 907
        for(uint i = 0; i < sortList.size(); i++)
447 cbradney 908
                retList.append(sortList[i]);
909
        return retList;
910
}
517 fschmid 911
 
1065 cbradney 912
void GetItemProps(bool newVersion, QDomElement *obj, struct CopyPasteBuffer *OB)
517 fschmid 913
{
914
        QString tmp;
915
        int x, y;
2282 fschmid 916
        double xf, yf, xf2;
1460 cbradney 917
        OB->PType = static_cast<PageItem::ItemType>(QStoInt(obj->attribute("PTYPE")));
517 fschmid 918
        OB->Width=QStodouble(obj->attribute("WIDTH"));
919
        OB->Height=QStodouble(obj->attribute("HEIGHT"));
920
        OB->RadRect = QStodouble(obj->attribute("RADRECT","0"));
921
        OB->ClipEdited = QStoInt(obj->attribute("CLIPEDIT", "0"));
922
        OB->FrameType = QStoInt(obj->attribute("FRTYPE", "0"));
923
        OB->Pwidth=QStodouble(obj->attribute("PWIDTH"));
1394 cbradney 924
        OB->Pcolor = obj->attribute("PCOLOR");
517 fschmid 925
        if ((!newVersion) && (OB->PType == 4))
926
        {
927
                OB->TxtFill = obj->attribute("PCOLOR2");
928
                OB->Pcolor2 = "None";
929
        }
930
        else
931
        {
932
                OB->Pcolor2 = obj->attribute("PCOLOR2");
933
                OB->TxtFill = obj->attribute("TXTFILL", "Black");
934
        }
1394 cbradney 935
        OB->Shade = QStoInt(obj->attribute("SHADE"));
936
        OB->Shade2 = QStoInt(obj->attribute("SHADE2"));
517 fschmid 937
        OB->TxtStroke=obj->attribute("TXTSTROKE", "None");
938
        OB->ShTxtFill=QStoInt(obj->attribute("TXTFILLSH", "100"));
939
        OB->ShTxtStroke=QStoInt(obj->attribute("TXTSTRSH", "100"));
2242 fschmid 940
        OB->TxtScale=qRound(QStodouble(obj->attribute("TXTSCALE", "100")) * 10);
941
        OB->TxtScaleV=qRound(QStodouble(obj->attribute("TXTSCALEV", "100")) * 10);
942
        OB->TxTBase=qRound(QStodouble(obj->attribute("TXTBASE", "0")) * 10);
517 fschmid 943
        OB->TxTStyle=QStoInt(obj->attribute("TXTSTYLE", "0"));
2247 fschmid 944
        OB->TxtShadowX=qRound(QStodouble(obj->attribute("TXTSHX", "5")) * 10);
945
        OB->TxtShadowY=qRound(QStodouble(obj->attribute("TXTSHY", "-5")) * 10);
2257 fschmid 946
        OB->TxtOutline=qRound(QStodouble(obj->attribute("TXTOUT", "1")) * 10);
2262 fschmid 947
        OB->TxtUnderPos=qRound(QStodouble(obj->attribute("TXTULP", "-0.1")) * 10);
948
        OB->TxtUnderWidth=qRound(QStodouble(obj->attribute("TXTULW", "-0.1")) * 10);
2272 fschmid 949
        OB->TxtStrikePos=qRound(QStodouble(obj->attribute("TXTSTP", "-0.1")) * 10);
950
        OB->TxtStrikeWidth=qRound(QStodouble(obj->attribute("TXTSTW", "-0.1")) * 10);
517 fschmid 951
        OB->Cols = QStoInt(obj->attribute("COLUMNS","1"));
952
        OB->ColGap = QStodouble(obj->attribute("COLGAP","0.0"));
953
        OB->GrType = QStoInt(obj->attribute("GRTYP","0"));
954
        OB->fill_gradient.clearStops();
955
        if (OB->GrType != 0)
956
        {
957
                OB->GrStartX = QStodouble(obj->attribute("GRSTARTX","0.0"));
958
                OB->GrStartY = QStodouble(obj->attribute("GRSTARTY","0.0"));
959
                OB->GrEndX = QStodouble(obj->attribute("GRENDX","0.0"));
960
                OB->GrEndY = QStodouble(obj->attribute("GRENDY","0.0"));
961
                OB->GrColor = obj->attribute("GRCOLOR","");
2877 cbradney 962
                if (OB->GrColor.isEmpty())
2179 fschmid 963
                        OB->GrColor = "Black";
964
                OB->GrColor2 = obj->attribute("GRCOLOR2","Black");
2877 cbradney 965
                if (OB->GrColor2.isEmpty())
2179 fschmid 966
                        OB->GrColor2 = "Black";
967
                OB->GrShade = QStoInt(obj->attribute("GRSHADE","100"));
968
                OB->GrShade2 = QStoInt(obj->attribute("GRSHADE2","100"));
517 fschmid 969
        }
970
        OB->Rot=QStodouble(obj->attribute("ROT"));
971
        OB->PLineArt=Qt::PenStyle(QStoInt(obj->attribute("PLINEART")));
972
        OB->PLineEnd=Qt::PenCapStyle(QStoInt(obj->attribute("PLINEEND","0")));
973
        OB->PLineJoin=Qt::PenJoinStyle(QStoInt(obj->attribute("PLINEJOIN","0")));
974
        OB->LineSp=QStodouble(obj->attribute("LINESP"));
2309 fschmid 975
        OB->LineSpMode = QStoInt(obj->attribute("LINESPMode","0"));
517 fschmid 976
        OB->LocalScX=QStodouble(obj->attribute("LOCALSCX"));
977
        OB->LocalScY=QStodouble(obj->attribute("LOCALSCY"));
978
        OB->LocalX=QStodouble(obj->attribute("LOCALX"));
979
        OB->LocalY=QStodouble(obj->attribute("LOCALY"));
980
        OB->PicArt=QStoInt(obj->attribute("PICART"));
2258 fschmid 981
        OB->flippedH = QStoInt(obj->attribute("FLIPPEDH")) % 2;
982
        OB->flippedV = QStoInt(obj->attribute("FLIPPEDV")) % 2;
517 fschmid 983
        OB->BBoxX=QStodouble(obj->attribute("BBOXX"));
984
        OB->BBoxH=QStodouble(obj->attribute("BBOXH"));
985
        OB->ScaleType = QStoInt(obj->attribute("SCALETYPE","1"));
986
        OB->AspectRatio = QStoInt(obj->attribute("RATIO","0"));
987
        OB->isPrintable=QStoInt(obj->attribute("PRINTABLE"));
988
        OB->isAnnotation=QStoInt(obj->attribute("ANNOTATION","0"));
989
        OB->AnType = QStoInt(obj->attribute("ANTYPE","0"));
990
        OB->AnAction = obj->attribute("ANACTION","");
991
        OB->An_E_act = obj->attribute("ANEACT","");
992
        OB->An_X_act = obj->attribute("ANXACT","");
993
        OB->An_D_act = obj->attribute("ANDACT","");
994
        OB->An_Fo_act = obj->attribute("ANFOACT","");
995
        OB->An_Bl_act = obj->attribute("ANBLACT","");
996
        OB->An_K_act = obj->attribute("ANKACT","");
997
        OB->An_F_act = obj->attribute("ANFACT","");
998
        OB->An_V_act = obj->attribute("ANVACT","");
999
        OB->An_C_act = obj->attribute("ANCACT","");
1000
        OB->AnActType = QStoInt(obj->attribute("ANACTYP","0"));
1001
        OB->An_Extern = obj->attribute("ANEXTERN","");
2877 cbradney 1002
        if ((!OB->An_Extern.isEmpty()) && (OB->AnActType != 8))
517 fschmid 1003
        {
1004
                QFileInfo efp(OB->An_Extern);
1005
                OB->An_Extern = efp.absFilePath();
1006
        }
1007
        OB->AnZiel = QStoInt(obj->attribute("ANZIEL","0"));
1008
        OB->AnName = obj->attribute("ANNAME","");
1009
        OB->AnToolTip = obj->attribute("ANTOOLTIP","");
1010
        OB->AnRollOver = obj->attribute("ANROLL","");
1011
        OB->AnDown = obj->attribute("ANDOWN","");
1012
        OB->AnBwid = QStoInt(obj->attribute("ANBWID","1"));
1013
        OB->AnBsty = QStoInt(obj->attribute("ANBSTY","0"));
1014
        OB->AnFeed = QStoInt(obj->attribute("ANFEED","1"));
1015
        OB->AnFlag = QStoInt(obj->attribute("ANFLAG","0"));
1016
        OB->AnFont = QStoInt(obj->attribute("ANFONT","4"));
1017
        OB->AnFormat = QStoInt(obj->attribute("ANFORMAT","0"));
1018
        OB->AnVis = QStoInt(obj->attribute("ANVIS","0"));
1019
        OB->AnIsChk = static_cast<bool>(QStoInt(obj->attribute("ANCHK","0")));
1020
        OB->AnAAact = static_cast<bool>(QStoInt(obj->attribute("ANAA","0")));
1021
        OB->AnHTML = static_cast<bool>(QStoInt(obj->attribute("ANHTML","0")));
1022
        OB->AnUseIcons = static_cast<bool>(QStoInt(obj->attribute("ANICON","0")));
1023
        OB->AnChkStil = QStoInt(obj->attribute("ANCHKS","0"));
1024
        OB->AnMaxChar = QStoInt(obj->attribute("ANMC","-1"));
1025
        OB->AnBColor = obj->attribute("ANBCOL","None");
1026
        OB->AnIPlace = QStoInt(obj->attribute("ANPLACE","1"));
1027
        OB->AnScaleW = QStoInt(obj->attribute("ANSCALE","0"));
1028
        if (QStoInt(obj->attribute("TRANSPARENT","0")) == 1)
1029
                OB->Pcolor = "None";
1030
        OB->Textflow=QStoInt(obj->attribute("TEXTFLOW"));
1031
        OB->Textflow2 =QStoInt(obj->attribute("TEXTFLOW2","0"));
1032
        OB->UseContour = QStoInt(obj->attribute("TEXTFLOW3","0"));
1033
        OB->Extra=QStodouble(obj->attribute("EXTRA"));
1034
        OB->TExtra=QStodouble(obj->attribute("TEXTRA", "1"));
1035
        OB->BExtra=QStodouble(obj->attribute("BEXTRA", "1"));
1036
        OB->RExtra=QStodouble(obj->attribute("REXTRA", "1"));
1525 cbradney 1037
        OB->PoShow = QStoInt(obj->attribute("PLTSHOW","0"));
517 fschmid 1038
        OB->BaseOffs = QStodouble(obj->attribute("BASEOF","0"));
1039
        OB->ISize = qRound(QStodouble(obj->attribute("ISIZE","12")) * 10);
2382 fschmid 1040
        if (obj->hasAttribute("EXTRAV"))
1041
                OB->ExtraV = qRound(QStodouble(obj->attribute("EXTRAV","0")) / QStodouble(obj->attribute("ISIZE","12")) * 1000.0);
1042
        else
1043
                OB->ExtraV = QStoInt(obj->attribute("TXTKERN"));
517 fschmid 1044
        OB->Pfile=obj->attribute("PFILE");
1045
        OB->Pfile2=obj->attribute("PFILE2","");
1046
        OB->Pfile3=obj->attribute("PFILE3","");
1047
        OB->IProfile=obj->attribute("PRFILE","");
1048
        OB->EmProfile=obj->attribute("EPROF","");
1049
        OB->IRender = QStoInt(obj->attribute("IRENDER","1"));
1050
        OB->UseEmbedded = QStoInt(obj->attribute("EMBEDDED","1"));
1051
        OB->Locked = static_cast<bool>(QStoInt(obj->attribute("LOCK","0")));
1052
        OB->LockRes = static_cast<bool>(QStoInt(obj->attribute("LOCKR","0")));
1053
        OB->Reverse = static_cast<bool>(QStoInt(obj->attribute("REVERS","0")));
1054
        OB->isTableItem = static_cast<bool>(QStoInt(obj->attribute("isTableItem","0")));
1055
        OB->TopLine = static_cast<bool>(QStoInt(obj->attribute("TopLine","0")));
1056
        OB->LeftLine = static_cast<bool>(QStoInt(obj->attribute("LeftLine","0")));
1057
        OB->RightLine = static_cast<bool>(QStoInt(obj->attribute("RightLine","0")));
1058
        OB->BottomLine = static_cast<bool>(QStoInt(obj->attribute("BottomLine","0")));
1059
        OB->TopLinkID =  QStoInt(obj->attribute("TopLINK","-1"));
1060
        OB->LeftLinkID =  QStoInt(obj->attribute("LeftLINK","-1"));
1061
        OB->RightLinkID =  QStoInt(obj->attribute("RightLINK","-1"));
1062
        OB->BottomLinkID =  QStoInt(obj->attribute("BottomLINK","-1"));
1063
        OB->Transparency = QStodouble(obj->attribute("TransValue","0.0"));
1064
        if (obj->hasAttribute("TransValueS"))
1065
                OB->TranspStroke = QStodouble(obj->attribute("TransValueS","0.0"));
1066
        else
1067
                OB->TranspStroke = OB->Transparency;
1068
        tmp = "";
1069
        if (obj->hasAttribute("NUMCLIP"))
1070
        {
1071
                OB->Clip.resize(obj->attribute("NUMCLIP").toUInt());
1072
                tmp = obj->attribute("CLIPCOOR");
1073
                QTextStream fc(&tmp, IO_ReadOnly);
1074
                for (uint c=0; c<obj->attribute("NUMCLIP").toUInt(); ++c)
1075
                {
1076
                        fc >> x;
1077
                        fc >> y;
1078
                        OB->Clip.setPoint(c, x, y);
1079
                }
1080
        }
1081
        else
1082
                OB->Clip.resize(0);
1083
        tmp = "";
1084
        if (obj->hasAttribute("NUMPO"))
1085
        {
1086
                OB->PoLine.resize(obj->attribute("NUMPO").toUInt());
1087
                tmp = obj->attribute("POCOOR");
1088
                QTextStream fp(&tmp, IO_ReadOnly);
1089
                for (uint cx=0; cx<obj->attribute("NUMPO").toUInt(); ++cx)
1090
                {
1091
                        fp >> xf;
1092
                        fp >> yf;
1093
                        OB->PoLine.setPoint(cx, xf, yf);
1094
                }
1095
        }
1096
        else
1097
                OB->PoLine.resize(0);
1098
        tmp = "";
1099
        if (obj->hasAttribute("NUMCO"))
1100
        {
1101
                OB->ContourLine.resize(obj->attribute("NUMCO").toUInt());
1102
                tmp = obj->attribute("COCOOR");
1103
                QTextStream fp(&tmp, IO_ReadOnly);
1104
                for (uint cx=0; cx<obj->attribute("NUMCO").toUInt(); ++cx)
1105
                {
1106
                        fp >> xf;
1107
                        fp >> yf;
1108
                        OB->ContourLine.setPoint(cx, xf, yf);
1109
                }
1110
        }
1111
        else
1112
                OB->ContourLine.resize(0);
1113
        tmp = "";
1114
        if ((obj->hasAttribute("NUMTAB")) && (QStoInt(obj->attribute("NUMTAB","0")) != 0))
1115
        {
2282 fschmid 1116
                struct PageItem::TabRecord tb;
517 fschmid 1117
                tmp = obj->attribute("TABS");
1118
                QTextStream tgv(&tmp, IO_ReadOnly);
1119
                OB->TabValues.clear();
2282 fschmid 1120
                for (int cxv = 0; cxv < QStoInt(obj->attribute("NUMTAB","0")); cxv += 2)
517 fschmid 1121
                {
1122
                        tgv >> xf;
2282 fschmid 1123
                        tgv >> xf2;
1124
                        tb.tabPosition = xf2;
1125
                        tb.tabType = static_cast<int>(xf);
1126
                        tb.tabFillChar = QChar();
1127
                        OB->TabValues.append(tb);
517 fschmid 1128
                }
1129
                tmp = "";
1130
        }
1131
        else
1132
                OB->TabValues.clear();
1133
        if ((obj->hasAttribute("NUMDASH")) && (QStoInt(obj->attribute("NUMDASH","0")) != 0))
1134
        {
1135
                tmp = obj->attribute("DASHS");
1136
                QTextStream dgv(&tmp, IO_ReadOnly);
1137
                OB->DashValues.clear();
1138
                for (int cxv = 0; cxv < QStoInt(obj->attribute("NUMDASH","0")); ++cxv)
1139
                {
1140
                        dgv >> xf;
1141
                        OB->DashValues.append(xf);
1142
                }
1143
                tmp = "";
1144
        }
1145
        else
1146
                OB->DashValues.clear();
1147
        OB->DashOffset = QStodouble(obj->attribute("DASHOFF","0.0"));
1148
}
1149
 
690 cbradney 1150
QColor SetColor(ScribusDoc *currentDoc, QString color, int shad)
517 fschmid 1151
{
1488 fschmid 1152
        return currentDoc->PageColors[color].getShadeColorProof(shad);
517 fschmid 1153
}
2529 craig 1154
 
2636 cbradney 1155
 
1156
/**
1157
 * QPixmaps are really slow with Qt/Mac 3.3.4. Really, *really*, slow.
1158
 * So we better cache them.
1159
 */
2907 subik 1160
QPixmap * getSmallPixmap(QColor rgb)
2636 cbradney 1161
{
1162
        static QMap<QRgb, QPixmap*> pxCache;
1163
 
1164
        QPixmap * pm = pxCache[rgb.rgb()];
3079 fschmid 1165
        if (!pm)
1166
        {
2636 cbradney 1167
                pm = new QPixmap(15, 15);
1168
                pm->fill(rgb);
3079 fschmid 1169
                QPainter p;
1170
                p.begin(pm);
1171
                p.setBrush(Qt::NoBrush);
1172
                QPen b(Qt::black, 1);
1173
                p.setPen(b);
1174
                p.drawRect(0, 0, 15, 15);
1175
                p.end();
2636 cbradney 1176
                pxCache[rgb.rgb()] = pm;
1177
        }
1178
        return pm;
1179
}
1180
 
2907 subik 1181
QPixmap * getWidePixmap(QColor rgb)
2636 cbradney 1182
{
1183
        static QMap<QRgb, QPixmap*> pxCache;
2907 subik 1184
 
2636 cbradney 1185
        QPixmap * pm = pxCache[rgb.rgb()];
1186
        if (!pm) {
1187
                pm = new QPixmap(30, 15);
1188
                pm->fill(rgb);
1189
                pxCache[rgb.rgb()] = pm;
1190
        }
1191
        return pm;
1192
}
1193
 
3046 fschmid 1194
void paintAlert(QPixmap &toPaint, QPixmap &target, int x, int y)
3041 fschmid 1195
{
1196
        QPainter p;
1197
        p.begin(&target);
3046 fschmid 1198
        p.drawPixmap(x, y, toPaint);
3041 fschmid 1199
        p.end();
1200
}
1201
 
2529 craig 1202
FPoint getMaxClipF(FPointArray* Clip)
1203
{
1204
        FPoint np, rp;
1205
        double mx = 0;
1206
        double my = 0;
1207
        for (uint c = 0; c < Clip->size(); ++c)
1208
        {
1209
                np = Clip->point(c);
1210
                if (np.x() > 900000)
1211
                        continue;
1212
                if (np.x() > mx)
1213
                        mx = np.x();
1214
                if (np.y() > my)
1215
                        my = np.y();
1216
        }
1217
        rp.setXY(mx, my);
1218
        return rp;
1219
}
1220
 
1221
FPoint getMinClipF(FPointArray* Clip)
1222
{
1223
        FPoint np, rp;
1224
        double mx = 99999;
1225
        double my = 99999;
1226
        for (uint c = 0; c < Clip->size(); ++c)
1227
        {
1228
                np = Clip->point(c);
1229
                if (np.x() > 900000)
1230
                        continue;
1231
                if (np.x() < mx)
1232
                        mx = np.x();
1233
                if (np.y() < my)
1234
                        my = np.y();
1235
        }
1236
        rp.setXY(mx, my);
1237
        return rp;
1238
}
1239
 
2834 cbradney 1240
/*!
1241
 \fn QString checkFileExtension(const QString &currName, const QString &extension)
1242
 \author Craig Bradney
1243
 \brief A quick function to make sure a filename has the correct extension and add it if not
1244
 \param currName Current filename
1245
 \param extension File extension to ensure exists
1246
 */
1247
QString checkFileExtension(const QString &currName, const QString &extension)
1248
{
1249
        QString newName(currName);
1250
        //If filename ends with a period, just add the extension
1251
        if (newName.right(1)==".")
1252
        {
1253
                newName+=extension.lower();
1254
                return newName;
1255
        }
1256
        //If filename doesnt end with the period+extension, add it on
1257
        QString dotExt("." + extension.lower());
1258
        if (!newName.endsWith(dotExt,false))
1259
                newName+=dotExt;
1260
        return newName;
1261
}
2907 subik 1262
 
1263
/*! Creates a common name for page exports (SVG, bitmap, EPS).
1264
Output format is: documentname-page01.extension
1265
\param pageNo number of the exported page (begins from 1)
1266
\param extension "svg" or e.g. "png" etc.
1267
\retval QString standardized filename
1268
\author Petr Vanek
1269
*/
1270
QString getFileNameByPage(uint pageNo, QString extension)
1271
{
1272
        QString number;
1273
        number = number.setNum(pageNo + ScApp->doc->FirstPnum);
1274
        QString defaultName = ScApp->doc->DocName;
1275
        if (defaultName.isNull())
1276
                defaultName = "export";
1277
        else
1278
        {
1279
                QFileInfo fi(defaultName);
1280
                defaultName = fi.baseName(true);
1281
        }
2954 subik 1282
        return QString("%1-%2%3.%4").arg(defaultName).arg(QObject::tr("page", "page export")).arg(number).arg(extension);
2907 subik 1283
}