Subversion Repositories Scribus

Rev

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

Rev Author Line No. Line
4430 cbradney 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
8 paul 7
/***************************************************************************
8
                          util.cpp  -  description
9
                             -------------------
10
    begin                : Fri Sep 14 2001
11
    copyright            : (C) 2001 by Franz Schmid
12
    email                : Franz.Schmid@altmuehlnet.de
13
 ***************************************************************************/
14
 
15
/***************************************************************************
16
 *                                                                         *
17
 *   This program is free software; you can redistribute it and/or modify  *
18
 *   it under the terms of the GNU General Public License as published by  *
19
 *   the Free Software Foundation; either version 2 of the License, or     *
20
 *   (at your option) any later version.                                   *
21
 *                                                                         *
22
 ***************************************************************************/
9 Franz 23
 
2529 craig 24
#include "util.h"
8 paul 25
#include <qbitmap.h>
26
#include <qpainter.h>
27
#include <qfile.h>
28
#include <qfileinfo.h>
29
#include <qtextstream.h>
1541 fschmid 30
#include <qdatastream.h>
2295 cbradney 31
#include <qregexp.h>
19 Franz 32
#include <qdir.h>
5557 subik 33
#include <qcheckbox.h>
2632 craig 34
#include <algorithm>
8 paul 35
#include <cstdlib>
36
#include <cmath>
2702 craig 37
 
38
#include "scconfig.h"
39
 
4506 cbradney 40
//#ifdef HAVE_UNISTD_H
41
//#include <unistd.h>
42
//#endif
2702 craig 43
 
2730 cbradney 44
#if defined(_WIN32)
45
#if defined(_MSC_VER)
46
#define __STDC__ 1 // hack to get md5_buffer correctly identified
47
#endif
3810 cbradney 48
#include <valarray>
2730 cbradney 49
#include <windows.h>
50
#endif
51
 
8 paul 52
#include "md5.h"
2730 cbradney 53
 
201 Franz 54
#include <setjmp.h>
3733 cbradney 55
#include "commonstrings.h"
3757 cbradney 56
#include "pagestructs.h"
2517 craig 57
#include "prefsfile.h"
58
#include "prefscontext.h"
59
#include "prefstable.h"
2834 cbradney 60
#include "prefsmanager.h"
3733 cbradney 61
#include "qprocess.h"
62
#include "scmessagebox.h"
5351 cbradney 63
#include "scpixmapcache.h"
3733 cbradney 64
#include "scpaths.h"
5184 avox 65
#include "text/nlsconfig.h"
128 Franz 66
 
1555 fschmid 67
extern "C"
68
{
201 Franz 69
#define XMD_H           // shut JPEGlib up
70
#if defined(Q_OS_UNIXWARE)
71
#  define HAVE_BOOLEAN  // libjpeg under Unixware seems to need this
72
#endif
73
#include <jpeglib.h>
74
#include <jerror.h>
75
#undef HAVE_STDLIB_H
76
#ifdef const
77
#  undef const          // remove crazy C hackery in jconfig.h
78
#endif
79
}
80
 
214 Franz 81
#include "scribus.h"
68 Franz 82
#include <ft2build.h>
83
#include FT_FREETYPE_H
84
#include FT_OUTLINE_H
85
#include FT_GLYPH_H
8 paul 86
#ifdef HAVE_LIBZ
87
        #include <zlib.h>
88
#endif
89
#ifdef HAVE_TIFF
90
        #include <tiffio.h>
91
#endif
92
#ifdef HAVE_CMS
44 Franz 93
        #include CMS_INC
8 paul 94
#endif
95
 
3205 craig 96
 
690 cbradney 97
using namespace std;
98
 
3240 fschmid 99
void sDebug(QString message)
100
{
101
        qDebug("%s", message.ascii());
102
}
103
 
5880 jghali 104
QImage ProofImage(QImage *Image, ScribusDoc* doc)
8 paul 105
{
106
#ifdef HAVE_CMS
690 cbradney 107
        QImage out = Image->copy();
5880 jghali 108
        bool cmsUse = doc ? doc->HasCMS : false;
109
        bool softProofing = doc ? doc->SoftProofing : false;
110
        if (cmsUse && softProofing)
167 Franz 111
        {
3200 cbradney 112
                int outheight=out.height();
113
                for (int i=0; i < outheight; ++i)
8 paul 114
                {
115
                        LPBYTE ptr = out.scanLine(i);
5880 jghali 116
                        cmsDoTransform(doc->stdProofImg, ptr, ptr, out.width());
8 paul 117
                }
167 Franz 118
        }
8 paul 119
        else
167 Franz 120
        {
5880 jghali 121
                if (cmsUse)
8 paul 122
                {
3200 cbradney 123
                        int outheight=out.height();
124
                        for (int i=0; i < outheight; ++i)
8 paul 125
                        {
126
                                LPBYTE ptr = out.scanLine(i);
5880 jghali 127
                                cmsDoTransform(doc->stdTransImg, ptr, ptr, out.width());
8 paul 128
                        }
129
                }
167 Franz 130
        }
8 paul 131
        return out;
132
#else
690 cbradney 133
        return Image->copy();
8 paul 134
#endif
135
}
136
 
4194 fschmid 137
int System(const QStringList & args, const QString fileStdErr, const QString fileStdOut)
204 Franz 138
{
4243 mrdocs 139
        QStringList stdErrData;
140
        QStringList stdOutData;
141
        QProcess proc(args);
4194 fschmid 142
        if ( !proc.start() )
204 Franz 143
                return 1;
144
        /* start was OK */
690 cbradney 145
        /* wait a little bit */
4243 mrdocs 146
        while( proc.isRunning() || proc.canReadLineStdout() || proc.canReadLineStderr() )
4194 fschmid 147
        {
4924 cbradney 148
                // Otherwise Scribus will sleep a *lot* when proc has huge std output
149
                if ( !proc.canReadLineStdout() && !proc.canReadLineStderr()) {
2730 cbradney 150
#ifndef _WIN32
5184 avox 151
                        usleep(5000);
2730 cbradney 152
#else
5184 avox 153
                        Sleep(5);
2730 cbradney 154
#endif
4924 cbradney 155
                }
4243 mrdocs 156
                // Some configurations needs stdout and stderr to be read
157
                // if needed before the created process can exit
158
                if ( proc.canReadLineStdout() )
159
                        stdOutData.append( proc.readLineStdout() );
160
                if ( proc.canReadLineStderr() )
161
                        stdErrData.append( proc.readLineStderr() );
4194 fschmid 162
        }
163
        // TODO: What about proc.normalExit() ?
164
        int ex = proc.exitStatus();
4505 cbradney 165
        QStringList::iterator pIterator;
166
        QStringList::iterator pEnd;
4194 fschmid 167
        if ( !fileStdErr.isEmpty() )
168
        {
169
                QFile ferr(fileStdErr);
170
                if ( ferr.open(IO_WriteOnly) )
171
                {
4243 mrdocs 172
                        pEnd = stdErrData.end();
173
                        QTextStream errStream(&ferr);
174
                        for ( pIterator = stdErrData.begin(); pIterator != pEnd; pIterator++ )
175
                                errStream << *pIterator << endl;
4194 fschmid 176
                        ferr.close();
177
                }
178
        }
179
 
180
        if ( !fileStdOut.isEmpty() )
181
        {
182
                QFile fout(fileStdOut);
183
                if ( fout.open(IO_WriteOnly) )
184
                {
4243 mrdocs 185
                        pEnd = stdOutData.end();
186
                        QTextStream outStream(&fout);
187
                        for ( pIterator = stdOutData.begin(); pIterator != pEnd; pIterator++ )
188
                                outStream << *pIterator << endl;
4194 fschmid 189
                        fout.close();
190
                }
191
        }
204 Franz 192
        return ex;
193
}
194
 
2885 fschmid 195
// On Windows, return short path name, else return longPath;
196
QString getShortPathName(QString longPath)
197
{
4505 cbradney 198
        QString shortPath(longPath);
2885 fschmid 199
#if defined _WIN32
200
        QFileInfo fInfo(longPath);
201
        if(fInfo.exists())
202
        {
203
                char shortName[MAX_PATH + 1];
204
                // An error should not be blocking as ERROR_INVALID_PARAMETER can simply mean
205
                // that volume does not support 8.3 filenames, so return longPath in this case
206
                int ret = GetShortPathName(QDir::convertSeparators(longPath).local8Bit(), shortName, sizeof(shortName));
207
                if( ret != ERROR_INVALID_PARAMETER && ret < sizeof(shortName))
208
                        shortPath = shortName;
209
        }
210
#endif
211
        return shortPath;
212
}
213
 
204 Franz 214
int copyFile(QString source, QString target)
215
{
4193 craig 216
        int bytesread;
204 Franz 217
        if ((source.isNull()) || (target.isNull()))
218
                return -1;
219
        if (source == target)
220
                return -1;
221
        QFile s(source);
222
        QFile t(target);
223
        if (!s.exists())
224
                return -1;
4193 craig 225
        QByteArray bb( 65536 );
204 Franz 226
        if (s.open(IO_ReadOnly))
227
        {
228
                if (t.open(IO_WriteOnly))
229
                {
4193 craig 230
                        bytesread = s.readBlock( bb.data(), bb.size() );
231
                        while( bytesread > 0 )
232
                        {
233
                                t.writeBlock( bb.data(), bytesread );
234
                                bytesread = s.readBlock( bb.data(), bb.size() );
235
                        }
204 Franz 236
                        t.close();
237
                }
4193 craig 238
                s.close();
204 Franz 239
        }
240
        return 0;
241
}
242
 
243
int moveFile(QString source, QString target)
244
{
245
        if ((source.isNull()) || (target.isNull()))
246
                return -1;
247
        if (source == target)
248
                return -1;
249
        copyFile(source, target);
2921 fschmid 250
        QFile::remove(source);
204 Franz 251
        return 0;
252
}
253
 
8 paul 254
QString GetAttr(QDomElement *el, QString at, QString def)
255
{
256
        return el->attribute(at, def);
257
}
258
 
259
QPixmap loadIcon(QString nam)
260
{
1693 craig 261
        QString iconFilePath = QString("%1/%2").arg(ScPaths::instance().iconDir()).arg(nam);
8 paul 262
        QPixmap pm;
1672 craig 263
        if (!QFile::exists(iconFilePath))
264
                qWarning("Unable to load icon %s: File not found", iconFilePath.ascii());
265
        else
266
        {
267
                pm.load(iconFilePath);
268
                if (pm.isNull())
269
                        qWarning("Unable to load icon %s: Got null pixmap", iconFilePath.ascii());
270
        }
8 paul 271
        return pm;
272
}
273
 
1109 fschmid 274
uint getDouble(QString in, bool raw)
275
{
276
        QByteArray bb(4);
277
        if (raw)
278
        {
279
                bb[3] = static_cast<uchar>(QChar(in.at(0)));
280
                bb[2] = static_cast<uchar>(QChar(in.at(1)));
281
                bb[1] = static_cast<uchar>(QChar(in.at(2)));
282
                bb[0] = static_cast<uchar>(QChar(in.at(3)));
283
        }
284
        else
285
        {
286
                bb[0] = static_cast<uchar>(QChar(in.at(0)));
287
                bb[1] = static_cast<uchar>(QChar(in.at(1)));
288
                bb[2] = static_cast<uchar>(QChar(in.at(2)));
289
                bb[3] = static_cast<uchar>(QChar(in.at(3)));
290
        }
291
        uint ret;
292
        ret = bb[0] & 0xff;
293
        ret |= (bb[1] << 8) & 0xff00;
294
        ret |= (bb[2] << 16) & 0xff0000;
295
        ret |= (bb[3] << 24) & 0xff000000;
296
        return ret;
297
}
298
 
3158 craig 299
// Legacy implementation of LoadText with incorrect
300
// handling of unicode data. This should be retired.
301
// Use loadRawText instead.
302
// FIXME XXX
303
//
690 cbradney 304
bool loadText(QString filename, QString *Buffer)
8 paul 305
{
690 cbradney 306
        QFile f(filename);
8 paul 307
        QFileInfo fi(f);
308
        if (!fi.exists())
309
                return false;
167 Franz 310
        bool ret;
8 paul 311
        QByteArray bb(f.size());
312
        if (f.open(IO_ReadOnly))
167 Franz 313
        {
8 paul 314
                f.readBlock(bb.data(), f.size());
315
                f.close();
690 cbradney 316
                for (uint posi = 0; posi < bb.size(); ++posi)
3027 fschmid 317
                        *Buffer += QChar(bb[posi]);
3497 avox 318
                /*
319
                int len = bb.size();
320
                int oldLen = Buffer->length();
321
                Buffer->setLength( oldLen + len + 1);
322
                // digged into Qt 3.3 sources to find that. Might break in Qt 4 -- AV
323
                unsigned short * ucsString = const_cast<unsigned short *>(Buffer->ucs2()) + oldLen;
324
                char * data = bb.data();
325
                for (uint posi = 0; posi < len; ++posi)
326
                        *ucsString++ = *data++;
327
                *ucsString = 0;
328
                 */
8 paul 329
                ret = true;
167 Franz 330
        }
8 paul 331
        else
332
                ret = false;
333
        return ret;
334
}
335
 
3646 craig 336
bool loadRawText(const QString & filename, QCString & buf)
3158 craig 337
{
338
        bool ret = false;
339
        QFile f(filename);
340
        QFileInfo fi(f);
341
        if (fi.exists())
342
        {
3646 craig 343
                QCString tempBuf(f.size() + 1);
3158 craig 344
                if (f.open(IO_ReadOnly))
345
                {
4193 craig 346
                        unsigned int bytesRead = f.readBlock(tempBuf.data(), f.size());
3646 craig 347
                        tempBuf[bytesRead] = '\0';
3158 craig 348
                        ret = bytesRead == f.size();
349
                        if (ret)
350
                                buf = tempBuf; // sharing makes this efficient
351
                }
352
        }
353
        if (f.isOpen())
354
                f.close();
355
        return ret;
356
}
357
 
5234 fschmid 358
bool loadRawBytes(const QString & filename, QByteArray & buf)
359
{
360
        bool ret = false;
361
        QFile f(filename);
362
        QFileInfo fi(f);
363
        if (fi.exists())
364
        {
365
                QByteArray tempBuf(f.size());
366
                if (f.open(IO_ReadOnly))
367
                {
368
                        unsigned int bytesRead = f.readBlock(tempBuf.data(), f.size());
369
                        ret = bytesRead == f.size();
370
                        if (ret)
371
                                buf = tempBuf; // sharing makes this efficient
372
                }
373
        }
374
        if (f.isOpen())
375
                f.close();
376
        return ret;
377
}
378
 
80 Franz 379
QPointArray RegularPolygon(double w, double h, uint c, bool star, double factor, double rota)
8 paul 380
{
167 Franz 381
        uint cx = star ? c * 2 : c;
80 Franz 382
        double seg = 360.0 / cx;
383
        double sc = rota + 180.0;
384
        double di = factor;
8 paul 385
        int mx = 0;
386
        int my = 0;
4505 cbradney 387
        //QPointArray pts = QPointArray();
388
        QPointArray pts(cx);
8 paul 389
        for (uint x = 0; x < cx; ++x)
167 Franz 390
        {
8 paul 391
                sc = seg * x + 180.0 + rota;
392
                if (star)
167 Franz 393
                {
394
                        double wf = x % 2 == 0 ? w / 2 : w / 2 * di;
395
                        double hf = x % 2 == 0 ? h / 2 : h / 2 * di;
396
                        mx = qRound(sin(sc / 180 * M_PI) * (wf) + (w/2));
397
                        my = qRound(cos(sc / 180 * M_PI) * (hf) + (h/2));
398
                }
8 paul 399
                else
167 Franz 400
                {
8 paul 401
                        mx = qRound(sin(sc / 180 * M_PI) * (w/2) + (w/2));
402
                        my = qRound(cos(sc / 180 * M_PI) * (h/2) + (h/2));
167 Franz 403
                }
4505 cbradney 404
                //pts.resize(x+1);
8 paul 405
                pts.setPoint(x, mx, my);
167 Franz 406
        }
8 paul 407
        return pts;
408
}
409
 
80 Franz 410
FPointArray RegularPolygonF(double w, double h, uint c, bool star, double factor, double rota)
8 paul 411
{
167 Franz 412
        uint cx = star ? c * 2 : c;
80 Franz 413
        double seg = 360.0 / cx;
414
        double sc = rota + 180.0;
415
        double di = factor;
416
        double mx = 0;
417
        double my = 0;
4505 cbradney 418
        //FPointArray pts;
419
        FPointArray pts(cx);
8 paul 420
        for (uint x = 0; x < cx; ++x)
167 Franz 421
        {
8 paul 422
                sc = seg * x + 180.0 + rota;
423
                if (star)
167 Franz 424
                {
425
                        double wf = x % 2 == 0 ? w / 2 : w / 2 * di;
426
                        double hf = x % 2 == 0 ? h / 2 : h / 2 * di;
427
                        mx = qRound(sin(sc / 180 * M_PI) * (wf) + (w/2));
428
                        my = qRound(cos(sc / 180 * M_PI) * (hf) + (h/2));
429
                }
8 paul 430
                else
167 Franz 431
                {
8 paul 432
                        mx = sin(sc / 180 * M_PI) * (w/2) + (w/2);
433
                        my = cos(sc / 180 * M_PI) * (h/2) + (h/2);
167 Franz 434
                }
4505 cbradney 435
                //pts.resize(x+1);
8 paul 436
                pts.setPoint(x, mx, my);
167 Franz 437
        }
8 paul 438
        return pts;
439
}
440
 
441
QPointArray FlattenPath(FPointArray ina, QValueList<uint> &Segs)
442
{
443
        QPointArray Bez(4);
444
        QPointArray outa, cli;
445
        Segs.clear();
446
        if (ina.size() > 3)
167 Franz 447
        {
448
                for (uint poi=0; poi<ina.size()-3; poi += 4)
8 paul 449
                {
5234 fschmid 450
                        if (ina.point(poi).x() > 900000 && cli.size() > 0)
8 paul 451
                        {
452
                                outa.resize(outa.size()+1);
453
                                outa.setPoint(outa.size()-1, cli.point(cli.size()-1));
80 Franz 454
                                Segs.append(outa.size());
8 paul 455
                                continue;
167 Franz 456
                        }
8 paul 457
                        BezierPoints(&Bez, ina.pointQ(poi), ina.pointQ(poi+1), ina.pointQ(poi+3), ina.pointQ(poi+2));
458
                        cli = Bez.cubicBezier();
459
                        outa.putPoints(outa.size(), cli.size()-1, cli);
167 Franz 460
                }
8 paul 461
                outa.resize(outa.size()+1);
462
                outa.setPoint(outa.size()-1, cli.point(cli.size()-1));
167 Franz 463
        }
8 paul 464
        return outa;
465
}
466
 
80 Franz 467
double xy2Deg(double x, double y)
8 paul 468
{
469
        return (atan2(y,x)*(180.0/M_PI));
470
}
471
 
472
void BezierPoints(QPointArray *ar, QPoint n1, QPoint n2, QPoint n3, QPoint n4)
473
{
474
        ar->setPoint(0, n1);
475
        ar->setPoint(1, n2);
476
        ar->setPoint(2, n3);
477
        ar->setPoint(3, n4);
478
        return;
479
}
480
 
690 cbradney 481
void Level2Layer(ScribusDoc *currentDoc, struct Layer *ll, int Level)
8 paul 482
{
2955 fschmid 483
        uint layerCount=currentDoc->layerCount();
2937 cbradney 484
        for (uint la2 = 0; la2 < layerCount; ++la2)
167 Franz 485
        {
690 cbradney 486
                if (currentDoc->Layers[la2].Level == Level)
8 paul 487
                {
1065 cbradney 488
                        ll->isViewable = currentDoc->Layers[la2].isViewable;
489
                        ll->isPrintable = currentDoc->Layers[la2].isPrintable;
690 cbradney 490
                        ll->LNr = currentDoc->Layers[la2].LNr;
1737 fschmid 491
                        ll->Name = currentDoc->Layers[la2].Name;
5373 fschmid 492
                        ll->flowControl = currentDoc->Layers[la2].flowControl;
493
                        ll->transparency = currentDoc->Layers[la2].transparency;
5375 fschmid 494
                        ll->blendMode = currentDoc->Layers[la2].blendMode;
8 paul 495
                        break;
496
                }
167 Franz 497
        }
8 paul 498
}
499
 
2937 cbradney 500
/* CB Replaced by ScribusDoc::layerLevelFromNumber
2122 fschmid 501
int Layer2Level(ScribusDoc *currentDoc, int LayerNr)
502
{
2937 cbradney 503
        int retVal=currentDoc->layerLevelFromNumber(LayerNr);
504
        int layerCount=currentDoc->layerCount();
505
        for (uint la2 = 0; la2 < layerCount; ++la2)
2122 fschmid 506
        {
507
                if (currentDoc->Layers[la2].LNr == LayerNr)
508
                        return currentDoc->Layers[la2].Level;
509
        }
510
        return 0;
511
}
2937 cbradney 512
*/
8 paul 513
QString CompressStr(QString *in)
514
{
515
        QString out = "";
516
#ifdef HAVE_LIBZ
517
        QByteArray bb(in->length());
518
        for (uint ax = 0; ax < in->length(); ++ax)
519
                bb[ax] = uchar(QChar(in->at(ax)));
520
        uLong exlen = uint(bb.size() * 0.001 + 16) + bb.size();
521
        QByteArray bc(exlen);
2295 cbradney 522
        int errcode = compress2((Byte *)bc.data(), &exlen, (Byte *)bb.data(), uLong(bb.size()), 9);
3158 craig 523
        if (errcode != Z_OK)
524
        {
525
                qDebug("compress2 failed with code %i", errcode);
2295 cbradney 526
                out = *in;
527
        }
528
        else {
529
                for (uint cl = 0; cl < exlen; ++cl)
2884 fschmid 530
                        out += QChar(bc[cl]);
2295 cbradney 531
        }
8 paul 532
#else
533
        out = *in;
534
#endif
535
        return out;
536
}
537
 
5234 fschmid 538
QByteArray CompressArray(QByteArray *in)
539
{
540
        QByteArray out;
541
#ifdef HAVE_LIBZ
542
        uLong exlen = uint(in->size() * 0.001 + 16) + in->size();
543
        QByteArray temp(exlen);
544
        int errcode = compress2((Byte *)temp.data(), &exlen, (Byte *)in->data(), uLong(in->size()), 9);
545
        if (errcode != Z_OK)
546
        {
547
                qDebug("compress2 failed with code %i", errcode);
548
                out = *in;
549
        }
550
        else {
551
                temp.resize(exlen);
552
                out = temp;
553
        }
554
#else
555
        out = *in;
556
#endif
557
        return out;
558
}
559
 
8 paul 560
char *toHex( uchar u )
561
{
1555 fschmid 562
        static char hexVal[3];
563
        int i = 1;
564
        while ( i >= 0 )
167 Franz 565
        {
566
                ushort hex = (u & 0x000f);
567
                if ( hex < 0x0a )
1555 fschmid 568
                        hexVal[i] = '0'+hex;
167 Franz 569
                else
1555 fschmid 570
                        hexVal[i] = 'A'+(hex-0x0a);
167 Franz 571
                u = u >> 4;
1555 fschmid 572
                i--;
573
        }
574
        hexVal[2] = '\0';
575
        return hexVal;
8 paul 576
}
577
 
578
QString String2Hex(QString *in, bool lang)
579
{
580
        int i = 0;
581
        QString out = "";
582
        for( uint xi = 0; xi < in->length(); ++xi )
167 Franz 583
        {
8 paul 584
                out += toHex(uchar(QChar(in->at(xi))));
585
                ++i;
586
                if ((i>40) && (lang))
167 Franz 587
                {
8 paul 588
                        out += '\n';
589
                        i=0;
590
                }
167 Franz 591
        }
8 paul 592
        return out;
593
}
594
 
595
QByteArray ComputeMD5Sum(QByteArray *in)
596
{
597
        QByteArray MDsum(16);
49 paul 598
        md5_buffer (in->data(), in->size(), reinterpret_cast<void*>(MDsum.data()));
8 paul 599
        return MDsum;
600
}
601
 
19 Franz 602
QString Path2Relative(QString Path)
603
{
604
        QString Ndir = "";
3089 fschmid 605
        QStringList Pdir;
19 Franz 606
        QFileInfo Bfi = QFileInfo(Path);
3089 fschmid 607
        QStringList Bdir;
690 cbradney 608
        bool end = true;
19 Franz 609
        uint dcoun = 0;
610
        uint dcoun2 = 0;
3089 fschmid 611
 
612
#ifndef _WIN32
613
        Pdir = QStringList::split("/", QDir::currentDirPath());
614
        Bdir = QStringList::split("/", Bfi.dirPath(true));
615
#else
616
        // On win32, file systems are case insensitive
617
        Pdir = QStringList::split("/", QDir::currentDirPath().lower());
618
        Bdir = QStringList::split("/", Bfi.dirPath(true).lower());
619
        // We must check that both path are located on same drive
620
        if( Pdir.size() > 0 && Bdir.size() > 0 )
621
        {
622
                QString drive = Bdir.front();
623
                QString currentDrive = Pdir.front();
4546 subik 624
                if( drive != currentDrive )
3089 fschmid 625
                        return Path;
626
        }
627
#endif
628
 
690 cbradney 629
        while (end)
167 Franz 630
        {
19 Franz 631
                if (Pdir[dcoun] == Bdir[dcoun])
632
                        dcoun++;
633
                else
634
                        break;
635
                if (dcoun > Pdir.count())
636
                        break;
167 Franz 637
        }
19 Franz 638
        dcoun2 = dcoun;
3089 fschmid 639
 
640
#ifdef _WIN32
641
        Bdir = QStringList::split("/", Bfi.dirPath(true));
642
#endif
643
 
19 Franz 644
        for (uint ddx2 = dcoun; ddx2 < Pdir.count(); ddx2++)
645
                Ndir += "../";
646
        for (uint ddx = dcoun2; ddx < Bdir.count(); ddx++)
647
                Ndir += Bdir[ddx]+"/";
648
        Ndir += Bfi.fileName();
649
        return Ndir;
650
}
651
 
90 Franz 652
/***************************************************************************
653
    begin                : Wed Oct 29 2003
654
    copyright            : (C) 2003 The Scribus Team
655
    email                : paul@all-the-johnsons.co.uk
656
 ***************************************************************************/
657
// check if the file exists, if it does, ask if they're sure
658
// return true if they're sure, else return false;
659
 
660
bool overwrite(QWidget *parent, QString filename)
661
{
167 Franz 662
        bool retval = true;
663
        QFileInfo fi(filename);
664
        if (fi.exists())
1555 fschmid 665
        {
4546 subik 666
                int t = ScMessageBox::warning(parent, QObject::tr("File exists"),
3733 cbradney 667
                                                                        "<qt>"+ QObject::tr("A file named '%1' already exists.<br/>Do you want to replace it with the file you are saving?").arg(filename) +"</qt>",
668
                                                                        QObject::tr("&Replace"), CommonStrings::tr_Cancel, "", 1, 1);
669
                if (t == 1)
90 Franz 670
                        retval = false;
1555 fschmid 671
        }
672
        return retval;
90 Franz 673
}
124 Franz 674
 
1957 cbradney 675
void WordAndPara(PageItem* currItem, int *w, int *p, int *c, int *wN, int *pN, int *cN)
125 Franz 676
{
677
        QChar Dat = QChar(32);
678
        int para = 0;
679
        int ww = 0;
680
        int cc = 0;
681
        int paraN = 0;
682
        int wwN = 0;
683
        int ccN = 0;
684
        bool first = true;
1957 cbradney 685
        PageItem *nextItem = currItem;
686
        PageItem *nbl = currItem;
687
        while (nextItem != 0)
167 Franz 688
        {
1957 cbradney 689
                if (nextItem->BackBox != 0)
690
                        nextItem = nextItem->BackBox;
125 Franz 691
                else
692
                        break;
167 Franz 693
        }
1957 cbradney 694
        while (nextItem != 0)
167 Franz 695
        {
5732 avox 696
                for (int a = nextItem->firstInFrame(); a <= nextItem->lastInFrame(); ++a)
1555 fschmid 697
                {
5184 avox 698
                        QChar b = nextItem->itemText.text(a);
5732 avox 699
                        if (b == SpecialChars::PARSEP)
167 Franz 700
                        {
5732 avox 701
                                para++;
167 Franz 702
                        }
125 Franz 703
                        if ((!b.isLetterOrNumber()) && (Dat.isLetterOrNumber()) && (!first))
167 Franz 704
                        {
5732 avox 705
                                ww++;
167 Franz 706
                        }
5732 avox 707
                        cc++;
1555 fschmid 708
                        Dat = b;
125 Franz 709
                        first = false;
1555 fschmid 710
                }
1957 cbradney 711
                nbl = nextItem;
712
                nextItem = nextItem->NextBox;
167 Franz 713
        }
5732 avox 714
        if (nbl->frameOverflows()) {
125 Franz 715
                paraN++;
5736 avox 716
                for (int a = nbl->lastInFrame()+1; a < nbl->itemText.length(); ++a)
5732 avox 717
                {
5736 avox 718
                        QChar b = nbl->itemText.text(a);
5732 avox 719
                        if (b == SpecialChars::PARSEP)
720
                        {
721
                                paraN++;
722
                        }
723
                        if ((!b.isLetterOrNumber()) && (Dat.isLetterOrNumber()) && (!first))
724
                        {
725
                                wwN++;
726
                        }
727
                        ccN++;
728
                        Dat = b;
729
                        first = false;
730
                }
731
        }              
732
        else {
125 Franz 733
                para++;
5732 avox 734
        }
125 Franz 735
        if (Dat.isLetterOrNumber())
167 Franz 736
        {
5559 avox 737
                if (nbl->frameOverflows())
125 Franz 738
                        wwN++;
739
                else
740
                        ww++;
167 Franz 741
        }
125 Franz 742
        *w = ww;
743
        *p = para;
744
        *c = cc;
745
        *wN = wwN;
746
        *pN = paraN;
747
        *cN = ccN;
748
}
203 Franz 749
 
690 cbradney 750
void ReOrderText(ScribusDoc *currentDoc, ScribusView *view)
203 Franz 751
{
4593 cbradney 752
        double savScale = view->scale();
2380 cbradney 753
        view->setScale(1.0);
690 cbradney 754
        currentDoc->RePos = true;
203 Franz 755
        QPixmap pgPix(10, 10);
756
        QRect rd = QRect(0,0,9,9);
757
        ScPainter *painter = new ScPainter(&pgPix, pgPix.width(), pgPix.height());
690 cbradney 758
        for (uint azz=0; azz<currentDoc->MasterItems.count(); ++azz)
203 Franz 759
        {
1957 cbradney 760
                PageItem *currItem = currentDoc->MasterItems.at(azz);
761
                if (currItem->itemType() == PageItem::PathText)
762
                        currItem->DrawObj(painter, rd);
203 Franz 763
        }
3727 cbradney 764
        for (uint azz=0; azz<currentDoc->Items->count(); ++azz)
203 Franz 765
        {
3727 cbradney 766
                PageItem *currItem = currentDoc->Items->at(azz);
1957 cbradney 767
                if ((currItem->itemType() == PageItem::TextFrame) || (currItem->itemType() == PageItem::PathText))
768
                        currItem->DrawObj(painter, rd);
203 Franz 769
        }
690 cbradney 770
        currentDoc->RePos = false;
2380 cbradney 771
        view->setScale(savScale);
203 Franz 772
        delete painter;
773
}
447 cbradney 774
 
4449 subik 775
/*! \brief Helper function for sorting in sortQStringList.
776
\author 10/06/2004 - pv
4645 subik 777
\param s1 first string
778
\param s2 second string
447 cbradney 779
\retval bool t/f related s1>s2
780
 */
781
bool compareQStrings(QString s1, QString s2)
782
{
783
        if (QString::localeAwareCompare(s1, s2) >= 0)
2680 cbradney 784
                return false;
785
        return true;
447 cbradney 786
}
787
 
788
QStringList sortQStringList(QStringList aList)
789
{
790
        std::vector<QString> sortList;
791
        QStringList retList;
792
        QStringList::Iterator it;
793
        for (it = aList.begin(); it != aList.end(); ++it)
794
                sortList.push_back(*it);
795
        std::sort(sortList.begin(), sortList.end(), compareQStrings);
456 fschmid 796
        for(uint i = 0; i < sortList.size(); i++)
447 cbradney 797
                retList.append(sortList[i]);
798
        return retList;
799
}
517 fschmid 800
 
1065 cbradney 801
void GetItemProps(bool newVersion, QDomElement *obj, struct CopyPasteBuffer *OB)
517 fschmid 802
{
803
        QString tmp;
804
        int x, y;
2282 fschmid 805
        double xf, yf, xf2;
4026 craig 806
        OB->PType = static_cast<PageItem::ItemType>(obj->attribute("PTYPE").toInt());
807
        OB->Width=obj->attribute("WIDTH").toDouble();
808
        OB->Height=obj->attribute("HEIGHT").toDouble();
809
        OB->RadRect = obj->attribute("RADRECT", "0").toDouble();
810
        OB->ClipEdited = obj->attribute("CLIPEDIT", "0").toInt();
811
        OB->FrameType = obj->attribute("FRTYPE", "0").toInt();
812
        OB->Pwidth=obj->attribute("PWIDTH").toDouble();
1394 cbradney 813
        OB->Pcolor = obj->attribute("PCOLOR");
517 fschmid 814
        if ((!newVersion) && (OB->PType == 4))
815
        {
816
                OB->TxtFill = obj->attribute("PCOLOR2");
4546 subik 817
                OB->Pcolor2 = CommonStrings::None;
517 fschmid 818
        }
819
        else
820
        {
821
                OB->Pcolor2 = obj->attribute("PCOLOR2");
822
                OB->TxtFill = obj->attribute("TXTFILL", "Black");
823
        }
4026 craig 824
        OB->Shade = obj->attribute("SHADE").toInt();
825
        OB->Shade2 = obj->attribute("SHADE2").toInt();
4546 subik 826
        OB->TxtStroke=obj->attribute("TXTSTROKE", CommonStrings::None);
4026 craig 827
        OB->ShTxtFill=obj->attribute("TXTFILLSH", "100").toInt();
828
        OB->ShTxtStroke=obj->attribute("TXTSTRSH", "100").toInt();
829
        OB->TxtScale=qRound(obj->attribute("TXTSCALE", "100").toDouble() * 10);
830
        OB->TxtScaleV=qRound(obj->attribute("TXTSCALEV", "100").toDouble() * 10);
831
        OB->TxTBase=qRound(obj->attribute("TXTBASE", "0").toDouble() * 10);
832
        OB->TxTStyle=obj->attribute("TXTSTYLE", "0").toInt();
833
        OB->TxtShadowX=qRound(obj->attribute("TXTSHX", "5").toDouble() * 10);
834
        OB->TxtShadowY=qRound(obj->attribute("TXTSHY", "-5").toDouble() * 10);
835
        OB->TxtOutline=qRound(obj->attribute("TXTOUT", "1").toDouble() * 10);
836
        OB->TxtUnderPos=qRound(obj->attribute("TXTULP", "-0.1").toDouble() * 10);
837
        OB->TxtUnderWidth=qRound(obj->attribute("TXTULW", "-0.1").toDouble() * 10);
838
        OB->TxtStrikePos=qRound(obj->attribute("TXTSTP", "-0.1").toDouble() * 10);
839
        OB->TxtStrikeWidth=qRound(obj->attribute("TXTSTW", "-0.1").toDouble() * 10);
840
        OB->Cols = obj->attribute("COLUMNS", "1").toInt();
841
        OB->ColGap = obj->attribute("COLGAP", "0.0").toDouble();
842
        OB->GrType = obj->attribute("GRTYP", "0").toInt();
517 fschmid 843
        OB->fill_gradient.clearStops();
844
        if (OB->GrType != 0)
845
        {
4026 craig 846
                OB->GrStartX = obj->attribute("GRSTARTX", "0.0").toDouble();
847
                OB->GrStartY = obj->attribute("GRSTARTY", "0.0").toDouble();
848
                OB->GrEndX = obj->attribute("GRENDX", "0.0").toDouble();
849
                OB->GrEndY = obj->attribute("GRENDY", "0.0").toDouble();
517 fschmid 850
                OB->GrColor = obj->attribute("GRCOLOR","");
2877 cbradney 851
                if (OB->GrColor.isEmpty())
2179 fschmid 852
                        OB->GrColor = "Black";
853
                OB->GrColor2 = obj->attribute("GRCOLOR2","Black");
2877 cbradney 854
                if (OB->GrColor2.isEmpty())
2179 fschmid 855
                        OB->GrColor2 = "Black";
4026 craig 856
                OB->GrShade = obj->attribute("GRSHADE", "100").toInt();
857
                OB->GrShade2 = obj->attribute("GRSHADE2", "100").toInt();
517 fschmid 858
        }
4026 craig 859
        OB->Rot=obj->attribute("ROT").toDouble();
860
        OB->PLineArt=Qt::PenStyle(obj->attribute("PLINEART").toInt());
861
        OB->PLineEnd=Qt::PenCapStyle(obj->attribute("PLINEEND", "0").toInt());
862
        OB->PLineJoin=Qt::PenJoinStyle(obj->attribute("PLINEJOIN", "0").toInt());
863
        OB->LineSp=obj->attribute("LINESP").toDouble();
864
        OB->LineSpMode = obj->attribute("LINESPMode", "0").toInt();
865
        OB->LocalScX=obj->attribute("LOCALSCX").toDouble();
866
        OB->LocalScY=obj->attribute("LOCALSCY").toDouble();
867
        OB->LocalX=obj->attribute("LOCALX").toDouble();
868
        OB->LocalY=obj->attribute("LOCALY").toDouble();
869
        OB->PicArt=obj->attribute("PICART").toInt();
870
        OB->flippedH = obj->attribute("FLIPPEDH").toInt() % 2;
871
        OB->flippedV = obj->attribute("FLIPPEDV").toInt() % 2;
4335 fschmid 872
/*      OB->BBoxX=obj->attribute("BBOXX").toDouble();
873
        OB->BBoxH=obj->attribute("BBOXH").toDouble(); */
4026 craig 874
        OB->ScaleType = obj->attribute("SCALETYPE", "1").toInt();
875
        OB->AspectRatio = obj->attribute("RATIO", "0").toInt();
876
        OB->isPrintable=obj->attribute("PRINTABLE").toInt();
4084 cbradney 877
        OB->m_isAnnotation=obj->attribute("ANNOTATION", "0").toInt();
878
        OB->m_annotation.setType(obj->attribute("ANTYPE", "0").toInt());
879
        OB->m_annotation.setAction(obj->attribute("ANACTION",""));
880
        OB->m_annotation.setE_act(obj->attribute("ANEACT",""));
881
        OB->m_annotation.setX_act(obj->attribute("ANXACT",""));
882
        OB->m_annotation.setD_act(obj->attribute("ANDACT",""));
883
        OB->m_annotation.setFo_act(obj->attribute("ANFOACT",""));
884
        OB->m_annotation.setBl_act(obj->attribute("ANBLACT",""));
885
        OB->m_annotation.setK_act(obj->attribute("ANKACT",""));
886
        OB->m_annotation.setF_act(obj->attribute("ANFACT",""));
887
        OB->m_annotation.setV_act(obj->attribute("ANVACT",""));
888
        OB->m_annotation.setC_act(obj->attribute("ANCACT",""));
889
        OB->m_annotation.setActionType(obj->attribute("ANACTYP", "0").toInt());
890
        OB->m_annotation.setExtern(obj->attribute("ANEXTERN",""));
891
        if ((!OB->m_annotation.Extern().isEmpty()) && (OB->m_annotation.ActionType() != 8))
517 fschmid 892
        {
4084 cbradney 893
                QFileInfo efp(OB->m_annotation.Extern());
894
                OB->m_annotation.setExtern(efp.absFilePath());
517 fschmid 895
        }
4084 cbradney 896
        OB->m_annotation.setZiel(obj->attribute("ANZIEL", "0").toInt());
897
        OB->AnName=obj->attribute("ANNAME","");
898
        OB->m_annotation.setToolTip(obj->attribute("ANTOOLTIP",""));
899
        OB->m_annotation.setRollOver(obj->attribute("ANROLL",""));
900
        OB->m_annotation.setDown(obj->attribute("ANDOWN",""));
901
        OB->m_annotation.setBwid(obj->attribute("ANBWID", "1").toInt());
902
        OB->m_annotation.setBsty(obj->attribute("ANBSTY", "0").toInt());
903
        OB->m_annotation.setFeed(obj->attribute("ANFEED", "1").toInt());
904
        OB->m_annotation.setFlag(obj->attribute("ANFLAG", "0").toInt());
905
        OB->m_annotation.setFont(obj->attribute("ANFONT", "4").toInt());
906
        OB->m_annotation.setFormat(obj->attribute("ANFORMAT", "0").toInt());
907
        OB->m_annotation.setVis(obj->attribute("ANVIS", "0").toInt());
908
        OB->m_annotation.setIsChk(static_cast<bool>(obj->attribute("ANCHK", "0").toInt()));
909
        OB->m_annotation.setAAact(static_cast<bool>(obj->attribute("ANAA", "0").toInt()));
910
        OB->m_annotation.setHTML(static_cast<bool>(obj->attribute("ANHTML", "0").toInt()));
911
        OB->m_annotation.setUseIcons(static_cast<bool>(obj->attribute("ANICON", "0").toInt()));
912
        OB->m_annotation.setChkStil(obj->attribute("ANCHKS", "0").toInt());
913
        OB->m_annotation.setMaxChar(obj->attribute("ANMC", "-1").toInt());
4546 subik 914
        OB->m_annotation.setBorderColor(obj->attribute("ANBCOL",CommonStrings::None));
4084 cbradney 915
        OB->m_annotation.setIPlace(obj->attribute("ANPLACE", "1").toInt());
916
        OB->m_annotation.setScaleW(obj->attribute("ANSCALE", "0").toInt());
4026 craig 917
        if (obj->attribute("TRANSPARENT", "0").toInt() == 1)
4546 subik 918
                OB->Pcolor = CommonStrings::None;
5620 jghali 919
        if ( obj->hasAttribute("TEXTFLOWMODE") )
920
                OB->TextflowMode = (PageItem::TextFlowMode) obj->attribute("TEXTFLOWMODE", "0").toInt();
921
        else if ( obj->attribute("TEXTFLOW").toInt() )
922
        {
923
                if (obj->attribute("TEXTFLOW2", "0").toInt())
924
                        OB->TextflowMode = PageItem::TextFlowUsesBoundingBox;
925
                else if (obj->attribute("TEXTFLOW3", "0").toInt())
926
                        OB->TextflowMode = PageItem::TextFlowUsesContourLine;
927
                else
928
                        OB->TextflowMode = PageItem::TextFlowUsesFrameShape;   
929
        }
930
        else
931
                OB->TextflowMode = PageItem::TextFlowDisabled;
4026 craig 932
        OB->Extra=obj->attribute("EXTRA").toDouble();
933
        OB->TExtra=obj->attribute("TEXTRA", "1").toDouble();
934
        OB->BExtra=obj->attribute("BEXTRA", "1").toDouble();
935
        OB->RExtra=obj->attribute("REXTRA", "1").toDouble();
936
        OB->PoShow = obj->attribute("PLTSHOW", "0").toInt();
937
        OB->BaseOffs = obj->attribute("BASEOF", "0").toDouble();
938
        OB->ISize = qRound(obj->attribute("ISIZE", "12").toDouble() * 10);
2382 fschmid 939
        if (obj->hasAttribute("EXTRAV"))
4026 craig 940
                OB->ExtraV = qRound(obj->attribute("EXTRAV", "0").toDouble() / obj->attribute("ISIZE", "12").toDouble() * 1000.0);
2382 fschmid 941
        else
4026 craig 942
                OB->ExtraV = obj->attribute("TXTKERN").toInt();
517 fschmid 943
        OB->Pfile=obj->attribute("PFILE");
944
        OB->Pfile2=obj->attribute("PFILE2","");
945
        OB->Pfile3=obj->attribute("PFILE3","");
946
        OB->IProfile=obj->attribute("PRFILE","");
947
        OB->EmProfile=obj->attribute("EPROF","");
4026 craig 948
        OB->IRender = obj->attribute("IRENDER", "1").toInt();
949
        OB->UseEmbedded = obj->attribute("EMBEDDED", "1").toInt();
950
        OB->Locked = static_cast<bool>(obj->attribute("LOCK", "0").toInt());
951
        OB->LockRes = static_cast<bool>(obj->attribute("LOCKR", "0").toInt());
952
        OB->Reverse = static_cast<bool>(obj->attribute("REVERS", "0").toInt());
953
        OB->isTableItem = static_cast<bool>(obj->attribute("isTableItem", "0").toInt());
954
        OB->TopLine = static_cast<bool>(obj->attribute("TopLine", "0").toInt());
955
        OB->LeftLine = static_cast<bool>(obj->attribute("LeftLine", "0").toInt());
956
        OB->RightLine = static_cast<bool>(obj->attribute("RightLine", "0").toInt());
957
        OB->BottomLine = static_cast<bool>(obj->attribute("BottomLine", "0").toInt());
958
        OB->TopLinkID =  obj->attribute("TopLINK", "-1").toInt();
959
        OB->LeftLinkID =  obj->attribute("LeftLINK", "-1").toInt();
960
        OB->RightLinkID =  obj->attribute("RightLINK", "-1").toInt();
961
        OB->BottomLinkID =  obj->attribute("BottomLINK", "-1").toInt();
962
        OB->Transparency = obj->attribute("TransValue", "0.0").toDouble();
517 fschmid 963
        if (obj->hasAttribute("TransValueS"))
4026 craig 964
                OB->TranspStroke = obj->attribute("TransValueS", "0.0").toDouble();
517 fschmid 965
        else
966
                OB->TranspStroke = OB->Transparency;
5746 fschmid 967
        OB->TransBlend = obj->attribute("TransBlend", "0").toInt();
968
        OB->TransBlendS = obj->attribute("TransBlendS", "0").toInt();
517 fschmid 969
        tmp = "";
970
        if (obj->hasAttribute("NUMCLIP"))
971
        {
972
                OB->Clip.resize(obj->attribute("NUMCLIP").toUInt());
973
                tmp = obj->attribute("CLIPCOOR");
974
                QTextStream fc(&tmp, IO_ReadOnly);
975
                for (uint c=0; c<obj->attribute("NUMCLIP").toUInt(); ++c)
976
                {
977
                        fc >> x;
978
                        fc >> y;
979
                        OB->Clip.setPoint(c, x, y);
980
                }
981
        }
982
        else
983
                OB->Clip.resize(0);
984
        tmp = "";
985
        if (obj->hasAttribute("NUMPO"))
986
        {
987
                OB->PoLine.resize(obj->attribute("NUMPO").toUInt());
988
                tmp = obj->attribute("POCOOR");
989
                QTextStream fp(&tmp, IO_ReadOnly);
990
                for (uint cx=0; cx<obj->attribute("NUMPO").toUInt(); ++cx)
991
                {
992
                        fp >> xf;
993
                        fp >> yf;
994
                        OB->PoLine.setPoint(cx, xf, yf);
995
                }
996
        }
997
        else
998
                OB->PoLine.resize(0);
999
        tmp = "";
1000
        if (obj->hasAttribute("NUMCO"))
1001
        {
1002
                OB->ContourLine.resize(obj->attribute("NUMCO").toUInt());
1003
                tmp = obj->attribute("COCOOR");
1004
                QTextStream fp(&tmp, IO_ReadOnly);
1005
                for (uint cx=0; cx<obj->attribute("NUMCO").toUInt(); ++cx)
1006
                {
1007
                        fp >> xf;
1008
                        fp >> yf;
1009
                        OB->ContourLine.setPoint(cx, xf, yf);
1010
                }
1011
        }
1012
        else
1013
                OB->ContourLine.resize(0);
1014
        tmp = "";
4026 craig 1015
        if ((obj->hasAttribute("NUMTAB")) && (obj->attribute("NUMTAB", "0").toInt() != 0))
517 fschmid 1016
        {
5184 avox 1017
                ParagraphStyle::TabRecord tb;
517 fschmid 1018
                tmp = obj->attribute("TABS");
1019
                QTextStream tgv(&tmp, IO_ReadOnly);
1020
                OB->TabValues.clear();
4026 craig 1021
                for (int cxv = 0; cxv < obj->attribute("NUMTAB", "0").toInt(); cxv += 2)
517 fschmid 1022
                {
1023
                        tgv >> xf;
2282 fschmid 1024
                        tgv >> xf2;
1025
                        tb.tabPosition = xf2;
1026
                        tb.tabType = static_cast<int>(xf);
1027
                        tb.tabFillChar = QChar();
1028
                        OB->TabValues.append(tb);
517 fschmid 1029
                }
1030
                tmp = "";
1031
        }
1032
        else
1033
                OB->TabValues.clear();
4026 craig 1034
        if ((obj->hasAttribute("NUMDASH")) && (obj->attribute("NUMDASH", "0").toInt() != 0))
517 fschmid 1035
        {
1036
                tmp = obj->attribute("DASHS");
1037
                QTextStream dgv(&tmp, IO_ReadOnly);
1038
                OB->DashValues.clear();
4026 craig 1039
                for (int cxv = 0; cxv < obj->attribute("NUMDASH", "0").toInt(); ++cxv)
517 fschmid 1040
                {
1041
                        dgv >> xf;
1042
                        OB->DashValues.append(xf);
1043
                }
1044
                tmp = "";
1045
        }
1046
        else
1047
                OB->DashValues.clear();
4026 craig 1048
        OB->DashOffset = obj->attribute("DASHOFF", "0.0").toDouble();
517 fschmid 1049
}
1050
 
690 cbradney 1051
QColor SetColor(ScribusDoc *currentDoc, QString color, int shad)
517 fschmid 1052
{
1488 fschmid 1053
        return currentDoc->PageColors[color].getShadeColorProof(shad);
517 fschmid 1054
}
2529 craig 1055
 
2636 cbradney 1056
 
1057
/**
1058
 * QPixmaps are really slow with Qt/Mac 3.3.4. Really, *really*, slow.
1059
 * So we better cache them.
1060
 */
2907 subik 1061
QPixmap * getSmallPixmap(QColor rgb)
2636 cbradney 1062
{
5351 cbradney 1063
        static ScPixmapCache<QRgb> pxCache;
2636 cbradney 1064
 
3719 cbradney 1065
        QRgb index=rgb.rgb();
1066
        if (pxCache.contains(index))
1067
                return pxCache[index];
1068
 
1069
        QPixmap *pm = new QPixmap(15, 15);
1070
        pm->fill(rgb);
1071
        QPainter p;
1072
        p.begin(pm);
1073
        p.setBrush(Qt::NoBrush);
1074
        QPen b(Qt::black, 1);
1075
        p.setPen(b);
1076
        p.drawRect(0, 0, 15, 15);
1077
        p.end();
1078
        pxCache.insert(index, pm);
2636 cbradney 1079
        return pm;
1080
}
1081
 
2907 subik 1082
QPixmap * getWidePixmap(QColor rgb)
2636 cbradney 1083
{
5351 cbradney 1084
        static ScPixmapCache<QRgb> pxCache;
2907 subik 1085
 
3719 cbradney 1086
        QRgb index=rgb.rgb();
1087
        if (pxCache.contains(index))
1088
                return pxCache[index];
1089
 
1090
        QPixmap *pm = new QPixmap(30, 15);
1091
        pm->fill(rgb);
1092
        pxCache.insert(index, pm);
2636 cbradney 1093
        return pm;
1094
}
1095
 
3497 avox 1096
static Q_UINT64 code64(ScColor & col) {
1097
        int C, M, Y, K, R, G, B;
4505 cbradney 1098
        Q_UINT64 result=0;
3497 avox 1099
        col.getRGB( &R, &G, &B );
1100
        col.getCMYK( &C, &M, &Y, &K );
1101
        result |= col.getColorModel() == colorModelRGB ? 1 : 0;
1102
        result |= col.isOutOfGamut() ? 64 : 0;
1103
        result |= col.isSpotColor() ? 32 : 0;
1104
        result |= col.isRegistrationColor() ? 16 : 0;
1105
        result <<= 8;
1106
        result |= C;
1107
        result <<= 8;
1108
        result |= M;
1109
        result <<= 8;
1110
        result |= Y;
1111
        result <<= 8;
1112
        result |= K;
1113
        result <<= 8;
1114
        result |= R;
1115
        result <<= 8;
1116
        result |= G;
1117
        result <<= 8;
1118
        result |= B;
1119
        return result;
1120
}
1121
 
1122
QPixmap * getFancyPixmap(ScColor col) {
5351 cbradney 1123
        static ScPixmapCache<Q_UINT64> pxCache;
4546 subik 1124
 
3497 avox 1125
        static QPixmap alertIcon;
1126
        static QPixmap cmykIcon;
1127
        static QPixmap rgbIcon;
1128
        static QPixmap spotIcon;
1129
        static QPixmap regIcon;
1130
        static bool iconsInitialized = false;
4546 subik 1131
 
3497 avox 1132
        if ( !iconsInitialized ) {
1133
                alertIcon = loadIcon("alert.png");
1134
                cmykIcon = loadIcon("cmyk.png");
1135
                rgbIcon = loadIcon("rgb.png");
1136
                spotIcon = loadIcon("spot.png");
1137
                regIcon = loadIcon("register.png");
1138
                iconsInitialized = true;
1139
        }
4546 subik 1140
 
3717 cbradney 1141
        Q_UINT64 res=code64(col);
1142
        if (pxCache.contains(res))
1143
                return pxCache[res];
4546 subik 1144
 
3717 cbradney 1145
        QPixmap *pa=new QPixmap(60, 15);
1146
        QPixmap *pm=getSmallPixmap(col.getRawRGBColor());
1147
        pa->fill(Qt::white);
1148
        paintAlert(*pm, *pa, 0, 0);
1149
        col.checkGamut();
1150
        if (col.isOutOfGamut())
1151
                paintAlert(alertIcon, *pa, 15, 0);
1152
        if ((col.getColorModel() == colorModelCMYK) || (col.isSpotColor()))
1153
                paintAlert(cmykIcon, *pa, 30, 0);
1154
        else
1155
                paintAlert(rgbIcon, *pa, 30, 0);
1156
        if (col.isSpotColor())
1157
                paintAlert(spotIcon, *pa, 46, 2);
1158
        if (col.isRegistrationColor())
1159
                paintAlert(regIcon, *pa, 45, 0);
1160
        pxCache.insert(res, pa);
3497 avox 1161
        return pa;
1162
}
1163
 
1164
 
5361 cbradney 1165
void paintAlert(QPixmap &toPaint, QPixmap &target, int x, int y, bool useMask)
3041 fschmid 1166
{
4449 subik 1167
        // there is no alpha mask in the beginning
5413 fschmid 1168
        if (useMask)
1169
        {
1170
                if (target.mask()==0)
1171
                        target.setMask(QBitmap(target.width(), target.height(), useMask));
1172
        }
3041 fschmid 1173
        QPainter p;
1174
        p.begin(&target);
3046 fschmid 1175
        p.drawPixmap(x, y, toPaint);
5413 fschmid 1176
        if (useMask)
1177
        {
1178
                QPainter alpha; // transparency handling
1179
                alpha.begin(target.mask());
1180
                alpha.setBrush(Qt::color1);
1181
                alpha.setPen(Qt::color1);
1182
                alpha.drawRect(x, y, 15, 15);
1183
                alpha.end();
1184
        }
3041 fschmid 1185
        p.end();
1186
}
1187
 
2529 craig 1188
FPoint getMaxClipF(FPointArray* Clip)
1189
{
1190
        FPoint np, rp;
1191
        double mx = 0;
1192
        double my = 0;
3719 cbradney 1193
        uint clipSize=Clip->size();
1194
        for (uint c = 0; c < clipSize; ++c)
2529 craig 1195
        {
1196
                np = Clip->point(c);
1197
                if (np.x() > 900000)
1198
                        continue;
1199
                if (np.x() > mx)
1200
                        mx = np.x();
1201
                if (np.y() > my)
1202
                        my = np.y();
1203
        }
1204
        rp.setXY(mx, my);
1205
        return rp;
1206
}
1207
 
1208
FPoint getMinClipF(FPointArray* Clip)
1209
{
1210
        FPoint np, rp;
1211
        double mx = 99999;
1212
        double my = 99999;
3719 cbradney 1213
        uint clipSize=Clip->size();
1214
        for (uint c = 0; c < clipSize; ++c)
2529 craig 1215
        {
1216
                np = Clip->point(c);
1217
                if (np.x() > 900000)
1218
                        continue;
1219
                if (np.x() < mx)
1220
                        mx = np.x();
1221
                if (np.y() < my)
1222
                        my = np.y();
1223
        }
1224
        rp.setXY(mx, my);
1225
        return rp;
1226
}
1227
 
2834 cbradney 1228
QString checkFileExtension(const QString &currName, const QString &extension)
1229
{
1230
        QString newName(currName);
1231
        //If filename ends with a period, just add the extension
1232
        if (newName.right(1)==".")
1233
        {
1234
                newName+=extension.lower();
1235
                return newName;
1236
        }
1237
        //If filename doesnt end with the period+extension, add it on
1238
        QString dotExt("." + extension.lower());
1239
        if (!newName.endsWith(dotExt,false))
1240
                newName+=dotExt;
1241
        return newName;
1242
}
2907 subik 1243
 
5781 cbradney 1244
QString getFileNameByPage(ScribusDoc* currDoc, uint pageNo, QString extension)
2907 subik 1245
{
1246
        QString number;
5781 cbradney 1247
        number = number.setNum(pageNo + currDoc->FirstPnum);
1248
        QString defaultName = currDoc->DocName;
2907 subik 1249
        if (defaultName.isNull())
1250
                defaultName = "export";
1251
        else
1252
        {
1253
                QFileInfo fi(defaultName);
1254
                defaultName = fi.baseName(true);
1255
        }
2954 subik 1256
        return QString("%1-%2%3.%4").arg(defaultName).arg(QObject::tr("page", "page export")).arg(number).arg(extension);
2907 subik 1257
}
3689 cbradney 1258
 
1259
inline double square(double x)
1260
{
1261
        return x*x;
1262
}
1263
 
1264
inline double distance(double x, double y)
1265
{
1266
        return sqrt(x*x+y*y);
1267
}
1268
 
4754 cbradney 1269
double constrainAngle(double angle)
1270
{
1271
        double newAngle=angle;
1272
        double constrainTo=15.0;
1273
        if (newAngle<0.0)
1274
                newAngle+=360.0;
1275
        newAngle=qRound(angle/constrainTo)*constrainTo;
1276
        if (newAngle==360.0)
1277
                newAngle=0.0;
1278
        return newAngle;
1279
}
1280
 
3757 cbradney 1281
const QString getStringFromSequence(DocumentSectionType type, uint position)
1282
{
1283
        QString retVal("");
1284
        switch( type )
1285
        {
3778 cbradney 1286
                case Type_1_2_3:
1287
                        retVal=QString::number(position);
1288
                        break;
3757 cbradney 1289
                case Type_A_B_C:
3778 cbradney 1290
                        retVal=numberToLetterSequence(position).upper();
1291
                        break;
3757 cbradney 1292
                case Type_a_b_c:
3778 cbradney 1293
                        retVal=numberToLetterSequence(position);
3757 cbradney 1294
                        break;
1295
                case Type_I_II_III:
1296
                        retVal=arabicToRoman(position);
1297
                        break;
1298
                case Type_i_ii_iii:
1299
                        //well, for lower case people will want that, even if its "wrong"
1300
                        //ie, X=10, x=10000
1301
                        retVal=arabicToRoman(position).lower();
1302
                        break;
1303
                default:
1304
                        break;
1305
        }
1306
        return retVal;
1307
}
1308
 
1309
const QString numberToLetterSequence(uint i)
1310
{
1311
        QString retVal("");
1312
        unsigned digits = 1;
1313
        unsigned offset = 0;
1314
        uint column=i;
1315
        --column;
1316
 
1317
        if( column > 4058115285U ) return  QString("@");
1318
 
1319
        for( unsigned limit = 26; column >= limit+offset; limit *= 26, digits++ )
1320
                offset += limit;
1321
 
1322
        for( unsigned c = column - offset; digits; --digits, c/=26 )
1323
                retVal.prepend( QChar( 'a' + (c%26) ) );
1324
        return retVal;
1325
}
1326
 
1327
const QString arabicToRoman(uint i)
1328
{
1329
        QString roman("");
1330
        int arabic = i;
1331
        while (arabic - 1000000 >= 0){
1332
        roman += "m";
1333
        arabic -= 1000000;
1334
        }
1335
        while (arabic - 900000 >= 0){
1336
        roman += "cm";
1337
        arabic -= 900000;
1338
        }
1339
        while (arabic - 500000 >= 0){
1340
        roman += "d";
1341
        arabic -= 500000;
1342
        }
1343
        while (arabic - 400000 >= 0){
1344
        roman += "cd";
1345
        arabic -= 400000;
1346
        }
1347
        while (arabic - 100000 >= 0){
1348
        roman += "c";
1349
        arabic -= 100000;
1350
        }
1351
        while (arabic - 90000 >= 0){
1352
        roman += "xc";
1353
        arabic -= 90000;
1354
        }
1355
        while (arabic - 50000 >= 0){
1356
        roman += "l";
1357
        arabic -= 50000;
1358
        }
1359
        while (arabic - 40000 >= 0){
1360
        roman += "xl";
1361
        arabic -= 40000;
1362
        }
1363
        while (arabic - 10000 >= 0){
1364
        roman += "x";
1365
        arabic -= 10000;
1366
        }
1367
        while (arabic - 9000 >= 0){
1368
        roman += "Mx";
1369
        arabic -= 9000;
1370
        }
1371
        while (arabic - 5000 >= 0){
1372
        roman += "v";
1373
        arabic -= 5000;
1374
        }
1375
        while (arabic - 4000 >= 0){
1376
        roman += "Mv";
1377
        arabic -= 4000;
1378
        }
1379
        while (arabic - 1000 >= 0){
1380
        roman += "M";
1381
        arabic -= 1000;
1382
        }
1383
        while (arabic - 900 >= 0){
1384
        roman += "CM";
1385
        arabic -= 900;
1386
        }
1387
        while (arabic - 500 >= 0){
1388
        roman += "D";
1389
        arabic -= 500;
1390
        }
1391
        while (arabic - 400 >= 0){
1392
        roman += "CD";
1393
        arabic -= 400;
1394
        }
1395
        while (arabic - 100 >= 0){
1396
        roman += "C";
1397
        arabic -= 100;
1398
        }
1399
        while (arabic - 90 >= 0){
1400
        roman += "XC";
1401
        arabic -= 90;
1402
        }
1403
        while (arabic - 50 >= 0){
1404
        roman += "L";
1405
        arabic -= 50;
1406
        }
1407
        while (arabic - 40 >= 0){
1408
        roman += "XL";
1409
        arabic -= 40;
1410
        }
1411
        while (arabic - 10 >= 0){
1412
        roman += "X";
1413
        arabic -= 10;
1414
        }
1415
        while (arabic - 9 >= 0){
1416
        roman += "IX";
1417
        arabic -= 9;
1418
        }
1419
        while (arabic - 5 >= 0){
1420
        roman += "V";
1421
        arabic -= 5;
1422
        }
1423
        while (arabic - 4 >= 0){
1424
        roman += "IV";
1425
        arabic -= 4;
1426
        }
1427
        while (arabic - 1 >= 0){
1428
        roman += "I";
1429
        arabic -= 1;
1430
        }
1431
        return roman;
3776 cbradney 1432
}
3784 cbradney 1433
 
1434
//CB Moved from scribus.cpp
1435
void parsePagesString(QString pages, std::vector<int>* pageNs, int sourcePageCount)
1436
{
1437
        QString tmp(pages);
1438
        QString token;
1439
        int from, to, pageNr;
1440
        do
1441
        {
1442
                if (tmp.find(",") == -1)
1443
                {
1444
                        token = tmp;
1445
                        tmp = "";
1446
                }
1447
                else
1448
                {
1449
                        token = tmp.left(tmp.find(","));
1450
                        tmp = tmp.right(tmp.length() - tmp.find(",") - 1);
1451
                }
1452
 
1453
                token = token.stripWhiteSpace();
1454
                if (token == "*") // Import all source doc pages
1455
                {
1456
                        for (int i = 1; i <= sourcePageCount; ++i)
1457
                                pageNs->push_back(i);
1458
                }
1459
                else if (token.find("-") != -1) // import a range of source doc pages
1460
                {
1461
                        from = QString(token.left(token.find("-"))).toInt();
1462
                        to = QString(token.right(token.length() - token.find("-") - 1)).toInt();
1463
                        if ((from != 0) && (to != 0))
1464
                        {
1465
                                if (from > sourcePageCount)
1466
                                        from = sourcePageCount;
1467
                                if (to > sourcePageCount)
1468
                                        to = sourcePageCount;
1469
                                if (from == to)
1470
                                        pageNs->push_back(to);
1471
                                else if (from < to)
1472
                                {
1473
                                        for (int i = from; i <= to; ++i)
1474
                                                pageNs->push_back(i);
1475
                                }
1476
                                else
1477
                                {
1478
                                        for (int i = from; i >= to; --i)
1479
                                                pageNs->push_back(i);
1480
                                }
1481
                        }
1482
                }
1483
                else // import single source doc page
1484
                {
1485
                        pageNr = token.toInt();
1486
                        if ((pageNr > 0) && (pageNr <= sourcePageCount))
1487
                                pageNs->push_back(pageNr);
1488
                }
1489
        } while (!tmp.isEmpty());
3793 cbradney 1490
}
5184 avox 1491
 
1492
 
1493
int findParagraphStyle(ScribusDoc* doc, const ParagraphStyle& parStyle)
1494
{
1495
        bool named = !parStyle.name().isEmpty();
1496
//qDebug(QString("looking up %1/ %2").arg(parStyle.name()).arg(parStyle.alignment())); 
1497
        if (named) {
1498
                for (uint i=0; i < doc->docParagraphStyles.size(); ++i)
1499
                {
1500
//qDebug(QString("%1 %2").arg(i).arg(doc->docParagraphStyles[i].name()));
1501
                        if (parStyle.name() == doc->docParagraphStyles[i].name()) {
1502
                                return i;
1503
                        }
1504
                }
1505
                assert(false);
1506
                return -1;
1507
        }
1508
        else {
1509
                return parStyle.alignment();
1510
        }
1511
}
5557 subik 1512
 
1513
QPixmap getQCheckBoxPixmap(const bool checked, const QColor background)
1514
{
1515
        QCheckBox *tmpItem = new QCheckBox("", 0, "tmpItem");
1516
        tmpItem->setMaximumSize(QSize(30, 30));
1517
        tmpItem->setMinimumSize(QSize(30, 30));
1518
        tmpItem->setPaletteBackgroundColor(background);
1519
        tmpItem->setChecked(checked);
1520
        QPixmap pm = QPixmap::grabWidget(tmpItem);
1521
        pm.setMask(pm.createHeuristicMask());
1522
        delete tmpItem;
1523
        return pm;
1524
}
5712 fschmid 1525
 
1526
unsigned char INT_MULT ( unsigned char a, unsigned char b )
1527
{
1528
        int c = a * b + 0x80;
1529
        return (unsigned char)(( ( c >> 8 ) + c ) >> 8);
1530
}
1531
 
1532
/*!
1533
 * Convert a color in RGB space to HSV space (Hue, Saturation, Value).
1534
 * \param red the red component (modified in place).
1535
 * \param green the green component (modified in place).
1536
 * \param blue the blue component (modified in place).
1537
 */
1538
void RGBTOHSV ( uchar& red, uchar& green, uchar& blue )
1539
{
1540
        int r, g, b;
1541
        double h, s, v;
1542
        int min, max;
1543
        h = 0.;
1544
        r = red;
1545
        g = green;
1546
        b = blue;
1547
        if ( r > g )
1548
        {
1549
                max = QMAX( r, b );
1550
                min = QMIN( g, b );
1551
        }
1552
        else
1553
        {
1554
                max = QMAX( g, b );
1555
                min = QMIN( r, b );
1556
        }
1557
        v = max;
1558
        if ( max != 0 )
1559
                s = ( ( max - min ) * 255 ) / (double)max;
1560
        else
1561
                s = 0;
1562
        if ( s == 0 )
1563
                h = 0;
1564
        else
1565
        {
1566
                int delta = max - min;
1567
                if ( r == max )
1568
                        h = ( g - b ) / (double)delta;
1569
                else if ( g == max )
1570
                        h = 2 + ( b - r ) / (double)delta;
1571
                else if ( b == max )
1572
                        h = 4 + ( r - g ) / (double)delta;
1573
                h *= 42.5;
1574
                if ( h < 0 )
1575
                        h += 255;
1576
                if ( h > 255 )
1577
                        h -= 255;
1578
        }
1579
        red   = (uchar)h;
1580
        green = (uchar)s;
1581
        blue  = (uchar)v;
1582
}
1583
 
1584
/*!
1585
 * Convert a color in HSV space to RGB space.
1586
 * \param hue the hue component (modified in place).
1587
 * \param saturation the saturation component (modified in place).
1588
 * \param value the value component (modified in place).
1589
 */
1590
void HSVTORGB ( uchar& hue, uchar& saturation, uchar& value )
1591
{
1592
        if ( saturation == 0 )
1593
        {
1594
                hue        = value;
1595
                saturation = value;
1596
                value      = value;
1597
        }
1598
        else
1599
        {
1600
                double h = hue * 6. / 255.;
1601
                double s = saturation / 255.;
1602
                double v = value / 255.;
1603
 
1604
                double f = h - (int)h;
1605
                double p = v * ( 1. - s );
1606
                double q = v * ( 1. - ( s * f ) );
1607
                double t = v * ( 1. - ( s * ( 1. - f ) ) );
1608
                // Worth a note here that gcc 2.96 will generate different results
1609
                // depending on optimization mode on i386.
1610
                switch ((int)h)
1611
                {
1612
                case 0:
1613
                        hue        = (uchar)( v * 255 );
1614
                        saturation = (uchar)( t * 255 );
1615
                        value      = (uchar)( p * 255 );
1616
                        break;
1617
                case 1:
1618
                        hue        = (uchar)( q * 255 );
1619
                        saturation = (uchar)( v * 255 );
1620
                        value      = (uchar)( p * 255 );
1621
                        break;
1622
                case 2:
1623
                        hue        = (uchar)( p * 255 );
1624
                        saturation = (uchar)( v * 255 );
1625
                        value      = (uchar)( t * 255 );
1626
                        break;
1627
                case 3:
1628
                        hue        = (uchar)( p * 255 );
1629
                        saturation = (uchar)( q * 255 );
1630
                        value      = (uchar)( v * 255 );
1631
                        break;
1632
                case 4:
1633
                        hue        = (uchar)( t * 255 );
1634
                        saturation = (uchar)( p * 255 );
1635
                        value      = (uchar)( v * 255 );
1636
                        break;
1637
                case 5:
1638
                        hue        = (uchar)( v * 255 );
1639
                        saturation = (uchar)( p * 255 );
1640
                        value      = (uchar)( q * 255 );
1641
                }
1642
        }
1643
}
1644
 
1645
/*!
1646
 * Convert a color in RGB space to HLS space (Hue, Lightness, Saturation).
1647
 * \param red the red component (modified in place).
1648
 * \param green the green component (modified in place).
1649
 * \param blue the blue component (modified in place).
1650
 */
1651
void RGBTOHLS ( uchar& red, uchar& green, uchar& blue )
1652
{
1653
        int r = red;
1654
        int g = green;
1655
        int b = blue;
1656
        int min, max;
1657
        if ( r > g )
1658
        {
1659
                max = QMAX( r, b );
1660
                min = QMIN( g, b );
1661
        }
1662
        else
1663
        {
1664
                max = QMAX( g, b );
1665
                min = QMIN( r, b );
1666
        }
1667
        double h;
1668
        double l = ( max + min ) / 2.;
1669
        double s;
1670
        if ( max == min )
1671
        {
1672
                s = 0.;
1673
                h = 0.;
1674
        }
1675
        else
1676
        {
1677
                int delta = max - min;
1678
                if ( l < 128 )
1679
                        s = 255 * (double)delta / (double)( max + min );
1680
                else
1681
                        s = 255 * (double)delta / (double)( 511 - max - min );
1682
                if ( r == max )
1683
                        h = ( g - b ) / (double)delta;
1684
                else if ( g == max )
1685
                        h = 2 + ( b - r ) / (double)delta;
1686
                else
1687
                        h = 4 + ( r - g ) / (double)delta;
1688
                h *= 42.5;
1689
                if ( h < 0 )
1690
                        h += 255;
1691
                else if ( h > 255 )
1692
                        h -= 255;
1693
        }
1694
        red   = (uchar)h;
1695
        green = (uchar)l;
1696
        blue  = (uchar)s;
1697
}
1698
 
1699
/*!
1700
 * Implement the HLS "double hex-cone".
1701
 * \param n1 lightness fraction (?)
1702
 * \param n2 saturation fraction (?)
1703
 * \param hue hue "angle".
1704
 * \return HLS value.
1705
 */
1706
int HLSVALUE ( double n1, double n2, double hue )
1707
{
1708
        double value;
1709
        if ( hue > 255 )
1710
                hue -= 255;
1711
        else if ( hue < 0 )
1712
                hue += 255;
1713
        if ( hue < 42.5 )
1714
                value = n1 + ( n2 - n1 ) * ( hue / 42.5 );
1715
        else if ( hue < 127.5 )
1716
                value = n2;
1717
        else if ( hue < 170 )
1718
                value = n1 + ( n2 - n1 ) * ( ( 170 - hue ) / 42.5 );
1719
        else
1720
                value = n1;
1721
        return (int)( value * 255 );
1722
}
1723
 
1724
/*!
1725
 * Convert a color in HLS space to RGB space.
1726
 * \param hue the hue component (modified in place).
1727
 * \param lightness the lightness component (modified in place).
1728
 * \param saturation the saturation component (modified in place).
1729
 */
1730
void HLSTORGB ( uchar& hue, uchar& lightness, uchar& saturation )
1731
{
1732
        double h = hue;
1733
        double l = lightness;
1734
        double s = saturation;
1735
        if ( s == 0 )
1736
        {
1737
                hue        = (uchar)l;
1738
                lightness  = (uchar)l;
1739
                saturation = (uchar)l;
1740
        }
1741
        else
1742
        {
1743
                double m1, m2;
1744
                if ( l < 128 )
1745
                        m2 = ( l * ( 255 + s ) ) / 65025.;
1746
                else
1747
                        m2 = ( l + s - ( l * s ) / 255. ) / 255.;
1748
                m1 = ( l / 127.5 ) - m2;
1749
                hue        = HLSVALUE( m1, m2, h + 85 );
1750
                lightness  = HLSVALUE( m1, m2, h );
1751
                saturation = HLSVALUE( m1, m2, h - 85 );
1752
        }
1753
}