Subversion Repositories Scribus

Rev

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