Subversion Repositories Scribus

Rev

Rev 13385 | 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
*/
2688 craig 7
 
10223 cbradney 8
#include <QCursor>
13085 jghali 9
#include <QDebug>
9764 jghali 10
#include <QDrag>
10292 cbradney 11
#include <QFile>
12
#include <QList>
9764 jghali 13
#include <QMimeData>
10638 jghali 14
#include <QPainterPath>
10292 cbradney 15
#include <QRegExp>
12795 fschmid 16
#include <QTemporaryFile>
68 Franz 17
#include <cmath>
10292 cbradney 18
#include "color.h"
3934 cbradney 19
#include "commonstrings.h"
10292 cbradney 20
#include "customfdialog.h"
21
#include "fonts/scfontmetrics.h"
3934 cbradney 22
#include "fpointarray.h"
10292 cbradney 23
#include "loadsaveplugin.h"
3934 cbradney 24
#include "menumanager.h"
10292 cbradney 25
#include "pageitem.h"
26
#include "prefsfile.h"
2834 cbradney 27
#include "prefsmanager.h"
10862 cbradney 28
#include "propertiespalette.h"
10292 cbradney 29
#include "sccolorengine.h"
30
#include "scconfig.h"
11962 jghali 31
#include "scgzfile.h"
12841 jghali 32
#include "scmimedata.h"
12785 fschmid 33
#include "scpaths.h"
12737 fschmid 34
#include "scpattern.h"
3934 cbradney 35
#include "scraction.h"
10292 cbradney 36
#include "scribus.h"
37
#include "scribusXml.h"
5781 cbradney 38
#include "scribuscore.h"
3207 craig 39
#include "scribusdoc.h"
3934 cbradney 40
#include "selection.h"
10292 cbradney 41
#include "svgplugin.h"
3934 cbradney 42
#include "undomanager.h"
43
#include "util.h"
10292 cbradney 44
#include "util_formats.h"
10200 cbradney 45
#include "util_icon.h"
10203 cbradney 46
#include "util_math.h"
68 Franz 47
 
10862 cbradney 48
 
504 cbradney 49
using namespace std;
50
 
3207 craig 51
int svgimplugin_getPluginAPIVersion()
68 Franz 52
{
3207 craig 53
        return PLUGIN_API_VERSION;
68 Franz 54
}
55
 
3207 craig 56
ScPlugin* svgimplugin_getPlugin()
68 Franz 57
{
3207 craig 58
        SVGImportPlugin* plug = new SVGImportPlugin();
59
        Q_CHECK_PTR(plug);
60
        return plug;
68 Franz 61
}
62
 
3207 craig 63
void svgimplugin_freePlugin(ScPlugin* plugin)
512 fschmid 64
{
3207 craig 65
        SVGImportPlugin* plug = dynamic_cast<SVGImportPlugin*>(plugin);
66
        Q_ASSERT(plug);
67
        delete plug;
512 fschmid 68
}
69
 
3696 craig 70
SVGImportPlugin::SVGImportPlugin() : LoadSavePlugin(),
9857 cbradney 71
        importAction(new ScrAction(ScrAction::DLL, QPixmap(), QPixmap(), "", QKeySequence(), this))
1208 cbradney 72
{
3207 craig 73
        // Set action info in languageChange, so we only have to do
3686 craig 74
        // it in one place. This includes registering file format
75
        // support.
3207 craig 76
        languageChange();
5243 cbradney 77
}
12110 fschmid 78
/*
5243 cbradney 79
void SVGImportPlugin::addToMainWindowMenu(ScribusMainWindow *mw)
80
{
3696 craig 81
        importAction->setEnabled(true);
10725 jghali 82
        connect( importAction, SIGNAL(triggered()), SLOT(import()) );
5243 cbradney 83
        mw->scrMenuMgr->addMenuItem(importAction, "FileImport");
1208 cbradney 84
}
12110 fschmid 85
*/
3686 craig 86
SVGImportPlugin::~SVGImportPlugin()
87
{
88
        unregisterAll();
89
};
3207 craig 90
 
91
void SVGImportPlugin::languageChange()
1208 cbradney 92
{
10427 cbradney 93
        importAction->setText( tr("Import &SVG..."));
3686 craig 94
        // (Re)register file format support.
95
        unregisterAll();
96
        registerFormats();
1208 cbradney 97
}
98
 
3207 craig 99
const QString SVGImportPlugin::fullTrName() const
1208 cbradney 100
{
3207 craig 101
        return QObject::tr("SVG Import");
1208 cbradney 102
}
103
 
3207 craig 104
const ScActionPlugin::AboutData* SVGImportPlugin::getAboutData() const
1208 cbradney 105
{
3241 craig 106
        AboutData* about = new AboutData;
3344 fschmid 107
        about->authors = "Franz Schmid <franz@scribus.info>";
3355 cbradney 108
        about->shortDescription = tr("Imports SVG Files");
3357 cbradney 109
        about->description = tr("Imports most SVG files into the current document,\nconverting their vector data into Scribus objects.");
3344 fschmid 110
        about->license = "GPL";
3241 craig 111
        Q_CHECK_PTR(about);
112
        return about;
1208 cbradney 113
}
114
 
3241 craig 115
void SVGImportPlugin::deleteAboutData(const AboutData* about) const
1208 cbradney 116
{
3241 craig 117
        Q_ASSERT(about);
118
        delete about;
1208 cbradney 119
}
120
 
3686 craig 121
void SVGImportPlugin::registerFormats()
3487 craig 122
{
4024 craig 123
        FileFormat fmt(this);
10292 cbradney 124
        fmt.trName = FormatsManager::instance()->nameOfFormat(FormatsManager::SVG);
4024 craig 125
        fmt.formatId = FORMATID_SVGIMPORT;
10292 cbradney 126
        fmt.filter = FormatsManager::instance()->extensionsForFormat(FormatsManager::SVG);
10600 fschmid 127
        fmt.nameMatch = QRegExp("\\."+FormatsManager::instance()->extensionListForFormat(FormatsManager::SVG, 1)+"$", Qt::CaseInsensitive);
3686 craig 128
        fmt.load = true;
129
        fmt.save = false;
10292 cbradney 130
        fmt.mimeTypes = FormatsManager::instance()->mimetypeOfFormat(FormatsManager::SVG);
3643 craig 131
        fmt.priority = 64;
3686 craig 132
        registerFormat(fmt);
3487 craig 133
}
134
 
5642 cbradney 135
bool SVGImportPlugin::fileSupported(QIODevice* /* file */, const QString & fileName) const
3487 craig 136
{
137
        // TODO: identify valid SVG
138
        return true;
139
}
140
 
5539 mrdocs 141
bool SVGImportPlugin::loadFile(const QString & fileName, const FileFormat & /* fmt */, int flags, int /*index*/)
4024 craig 142
{
143
        // For now, "load file" and import are the same thing for this plugin
5539 mrdocs 144
        return import(fileName, flags);
4024 craig 145
}
146
 
5539 mrdocs 147
bool SVGImportPlugin::import(QString filename, int flags)
68 Franz 148
{
5539 mrdocs 149
        if (!checkFlags(flags))
150
                return false;
5781 cbradney 151
        m_Doc=ScCore->primaryMainWindow()->doc;
152
        ScribusMainWindow* mw=(m_Doc==0) ? ScCore->primaryMainWindow() : m_Doc->scMW();
3207 craig 153
        if (filename.isEmpty())
506 fschmid 154
        {
5539 mrdocs 155
                flags |= lfInteractive;
2856 cbradney 156
                PrefsContext* prefs = PrefsManager::instance()->prefsFile->getPluginContext("SVGPlugin");
506 fschmid 157
                QString wdir = prefs->get("wdir", ".");
10292 cbradney 158
                CustomFDialog diaf(mw, wdir, QObject::tr("Open"), FormatsManager::instance()->fileDialogFormatList(FormatsManager::SVG));
506 fschmid 159
                if (diaf.exec())
160
                {
3207 craig 161
                        filename = diaf.selectedFile();
10427 cbradney 162
                        prefs->set("wdir", filename.left(filename.lastIndexOf("/")));
506 fschmid 163
                }
164
                else
3207 craig 165
                        return true;
415 Franz 166
        }
5781 cbradney 167
 
11576 avox 168
        UndoTransaction* activeTransaction = NULL;
169
        bool emptyDoc = (m_Doc == NULL);
13378 jghali 170
        bool hasCurrentPage = (m_Doc && m_Doc->currentPage());
13371 jghali 171
        TransactionSettings trSettings;
13378 jghali 172
        trSettings.targetName   = hasCurrentPage ? m_Doc->currentPage()->getUName() : "";
13371 jghali 173
        trSettings.targetPixmap = Um::IImageFrame;
174
        trSettings.actionName   = Um::ImportSVG;
175
        trSettings.description  = filename;
176
        trSettings.actionPixmap = Um::ISVG;
177
        if (emptyDoc || !(flags & lfInteractive) || !(flags & lfScripted))
1439 tsoots 178
                UndoManager::instance()->setUndoEnabled(false);
13371 jghali 179
        if (UndoManager::undoEnabled())
180
                activeTransaction = new UndoTransaction(UndoManager::instance()->beginTransaction(trSettings));
8043 jghali 181
        SVGPlug *dia = new SVGPlug(mw, flags);
3207 craig 182
        Q_CHECK_PTR(dia);
13371 jghali 183
        dia->import(filename, trSettings, flags);
11576 avox 184
        if (activeTransaction)
185
        {
186
                activeTransaction->commit();
187
                delete activeTransaction;
188
                activeTransaction = NULL;
189
        }
13371 jghali 190
        if (emptyDoc || !(flags & lfInteractive) || !(flags & lfScripted))
1439 tsoots 191
                UndoManager::instance()->setUndoEnabled(true);
7795 fschmid 192
        if (dia->importCanceled)
3800 subik 193
        {
7795 fschmid 194
                if (dia->importFailed)
195
                        QMessageBox::warning(mw, CommonStrings::trWarning, tr("The file could not be imported"), 1, 0, 0);
196
                else if (dia->unsupported)
197
                        QMessageBox::warning(mw, CommonStrings::trWarning, tr("SVG file contains some unsupported features"), 1, 0, 0);
3800 subik 198
        }
199
 
217 Franz 200
        delete dia;
3207 craig 201
        return true;
68 Franz 202
}
203
 
8043 jghali 204
SVGPlug::SVGPlug( ScribusMainWindow* mw, int flags ) :
5781 cbradney 205
        QObject(mw)
7564 cbradney 206
{      
7578 cbradney 207
        tmpSel=new Selection(this, false);
5781 cbradney 208
        m_Doc=mw->doc;
3800 subik 209
        unsupported = false;
7794 fschmid 210
        importFailed = false;
7795 fschmid 211
        importCanceled = true;
7991 fschmid 212
        importedColors.clear();
12737 fschmid 213
        importedPatterns.clear();
7866 fschmid 214
        docDesc = "";
215
        docTitle = "";
216
        groupLevel = 0;
5539 mrdocs 217
        interactive = (flags & LoadSavePlugin::lfInteractive);
9922 fschmid 218
//      m_gc.setAutoDelete( true );
8043 jghali 219
}
220
 
13371 jghali 221
bool SVGPlug::import(QString fname, const TransactionSettings& trSettings, int flags)
8043 jghali 222
{
223
        if (!loadData(fname))
224
                return false;
10398 cbradney 225
        QString CurDirP = QDir::currentPath();
8043 jghali 226
        QFileInfo efp(fname);
10600 fschmid 227
        QDir::setCurrent(efp.path());
13371 jghali 228
        convert(trSettings, flags);
8043 jghali 229
        QDir::setCurrent(CurDirP);
230
        return true;
231
}
232
 
233
bool SVGPlug::loadData(QString fName)
234
{
235
        QString f("");
11962 jghali 236
        bool isCompressed = false, success = false;
10600 fschmid 237
        QByteArray bb(3, ' ');
8424 fschmid 238
        QFile fi(fName);
8501 cbradney 239
        if (fi.open(QIODevice::ReadOnly))
217 Franz 240
        {
10600 fschmid 241
                fi.read(bb.data(), 2);
8424 fschmid 242
                fi.close();
8625 subik 243
                // Qt4 bb[0]->QChar(bb[0])
244
                if ((QChar(bb[0]) == QChar(0x1F)) && (QChar(bb[1]) == QChar(0x8B)))
8424 fschmid 245
                        isCompressed = true;
246
        }
247
        if ((fName.right(2) == "gz") || (isCompressed))
248
        {
11962 jghali 249
                ScGzFile file(fName);
250
                if (!file.open(QIODevice::ReadOnly))
8043 jghali 251
                        return false;
11962 jghali 252
                success = inpdoc.setContent(&file);
253
                file.close();
217 Franz 254
        }
68 Franz 255
        else
11962 jghali 256
        {
257
                QFile file(fName);
258
                if (!file.open(QIODevice::ReadOnly))
259
                        return false;
260
                success = inpdoc.setContent(&file);
261
                file.close();
262
        }
263
        return success;
68 Franz 264
}
265
 
13371 jghali 266
void SVGPlug::convert(const TransactionSettings& trSettings, int flags)
68 Franz 267
{
268
        bool ret = false;
269
        SvgStyle *gc = new SvgStyle;
270
        QDomElement docElem = inpdoc.documentElement();
8252 jghali 271
        QSize wh = parseWidthHeight(docElem);
7573 jghali 272
        double width = wh.width();
273
        double height = wh.height();
5539 mrdocs 274
        if (!interactive || (flags & LoadSavePlugin::lfInsertPage))
217 Franz 275
        {
5781 cbradney 276
                m_Doc->setPage(width, height, 0, 0, 0, 0, 0, 0, false, false);
277
                m_Doc->addPage(0);
278
                m_Doc->view()->addPage(0);
217 Franz 279
        }
506 fschmid 280
        else
281
        {
5781 cbradney 282
                if (!m_Doc || (flags & LoadSavePlugin::lfCreateDoc))
506 fschmid 283
                {
5798 jghali 284
                        m_Doc=ScCore->primaryMainWindow()->doFileNew(width, height, 0, 0, 0, 0, 0, 0, false, false, 0, false, 0, 1, "Custom", true);
5781 cbradney 285
                        ScCore->primaryMainWindow()->HaveNewDoc();
506 fschmid 286
                        ret = true;
287
                }
288
        }
3207 craig 289
        if ((ret) || (!interactive))
550 fschmid 290
        {
291
                if (width > height)
5781 cbradney 292
                        m_Doc->PageOri = 1;
550 fschmid 293
                else
5781 cbradney 294
                        m_Doc->PageOri = 0;
5789 cbradney 295
                m_Doc->m_pageSize = "Custom";
550 fschmid 296
        }
5781 cbradney 297
        FPoint minSize = m_Doc->minCanvasCoordinate;
298
        FPoint maxSize = m_Doc->maxCanvasCoordinate;
10907 fschmid 299
        FPoint cOrigin = m_Doc->view()->canvasOrigin();
5781 cbradney 300
        m_Doc->view()->Deselect();
301
        m_Doc->setLoading(true);
302
        m_Doc->DoDrawing = false;
7452 fschmid 303
        m_Doc->view()->updatesOn(false);
5781 cbradney 304
        m_Doc->scMW()->ScriptRunning = true;
9380 fschmid 305
        qApp->changeOverrideCursor(QCursor(Qt::WaitCursor));
10638 jghali 306
        gc->FontFamily = m_Doc->toolSettings.defFont;
5781 cbradney 307
        if (!m_Doc->PageColors.contains("Black"))
308
                m_Doc->PageColors.insert("Black", ScColor(0, 0, 0, 255));
68 Franz 309
        m_gc.push( gc );
1013 fschmid 310
        viewTransformX = 0;
311
        viewTransformY = 0;
312
        viewScaleX = 1;
313
        viewScaleY = 1;
314
        if( !docElem.attribute( "viewBox" ).isEmpty() )
315
        {
316
                QString viewbox( docElem.attribute( "viewBox" ) );
10603 fschmid 317
                QStringList points = viewbox.replace( QRegExp(","), " ").simplified().split( ' ', QString::SkipEmptyParts );
11080 fschmid 318
                if (points.size() > 3)
319
                {
320
                        QMatrix matrix;
321
                        QSize wh2 = parseWidthHeight(docElem);
322
                        double w2 = wh2.width();
323
                        double h2 = wh2.height();
324
                        addGraphicContext();
325
                        viewTransformX = points[0].toDouble();
326
                        viewTransformY = points[1].toDouble();
327
                        viewScaleX = w2 / points[2].toDouble();
328
                        viewScaleY = h2 / points[3].toDouble();
12101 jghali 329
                        matrix.translate(-viewTransformX * viewScaleX, -viewTransformY * viewScaleY);
11080 fschmid 330
                        matrix.scale(viewScaleX, viewScaleY);
331
                        m_gc.top()->matrix = matrix;
332
                }
1013 fschmid 333
        }
9856 fschmid 334
        QList<PageItem*> Elements = parseGroup( docElem );
7866 fschmid 335
        if (flags & LoadSavePlugin::lfCreateDoc)
336
        {
337
                m_Doc->documentInfo.setTitle(docTitle);
338
                m_Doc->documentInfo.setComments(docDesc);
339
        }
7578 cbradney 340
        tmpSel->clear();
7794 fschmid 341
        if (Elements.count() == 0)
7991 fschmid 342
        {
7794 fschmid 343
                importFailed = true;
7991 fschmid 344
                if (importedColors.count() != 0)
345
                {
8625 subik 346
                        for (int cd = 0; cd < importedColors.count(); cd++)
7991 fschmid 347
                        {
348
                                m_Doc->PageColors.remove(importedColors[cd]);
349
                        }
350
                }
12737 fschmid 351
                if (importedPatterns.count() != 0)
352
                {
353
                        for (int cd = 0; cd < importedPatterns.count(); cd++)
354
                        {
355
                                m_Doc->docPatterns.remove(importedPatterns[cd]);
356
                        }
357
                }
7991 fschmid 358
        }
302 Franz 359
        if (Elements.count() > 1)
217 Franz 360
        {
7445 fschmid 361
                bool isGroup = true;
362
                int firstElem = -1;
363
                if (Elements.at(0)->Groups.count() != 0)
364
                        firstElem = Elements.at(0)->Groups.top();
9856 fschmid 365
                for (int bx = 0; bx < Elements.count(); ++bx)
217 Franz 366
                {
7445 fschmid 367
                        PageItem* bxi = Elements.at(bx);
368
                        if (bxi->Groups.count() != 0)
6605 fschmid 369
                        {
7445 fschmid 370
                                if (bxi->Groups.top() != firstElem)
371
                                        isGroup = false;
372
                        }
373
                        else
374
                                isGroup = false;
375
                }
376
                if (!isGroup)
377
                {
378
                        double minx = 99999.9;
379
                        double miny = 99999.9;
380
                        double maxx = -99999.9;
381
                        double maxy = -99999.9;
382
                        uint lowestItem = 999999;
383
                        uint highestItem = 0;
9856 fschmid 384
                        for (int a = 0; a < Elements.count(); ++a)
7445 fschmid 385
                        {
386
                                Elements.at(a)->Groups.push(m_Doc->GroupCounter);
387
                                PageItem* currItem = Elements.at(a);
8562 jghali 388
                                lowestItem = qMin(lowestItem, currItem->ItemNr);
389
                                highestItem = qMax(highestItem, currItem->ItemNr);
11889 fschmid 390
                                double x1, x2, y1, y2;
12751 fschmid 391
                                currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
11889 fschmid 392
                                minx = qMin(minx, x1);
393
                                miny = qMin(miny, y1);
394
                                maxx = qMax(maxx, x2);
395
                                maxy = qMax(maxy, y2);
6605 fschmid 396
                        }
7445 fschmid 397
                        double gx = minx;
398
                        double gy = miny;
399
                        double gw = maxx - minx;
400
                        double gh = maxy - miny;
401
                        PageItem *high = m_Doc->Items->at(highestItem);
402
                        int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, gx, gy, gw, gh, 0, m_Doc->toolSettings.dBrush, m_Doc->toolSettings.dPen, true);
9856 fschmid 403
                        PageItem *neu = m_Doc->Items->takeAt(z);
7445 fschmid 404
                        m_Doc->Items->insert(lowestItem, neu);
405
                        neu->Groups.push(m_Doc->GroupCounter);
406
                        neu->setItemName( tr("Group%1").arg(neu->Groups.top()));
11889 fschmid 407
                        neu->AutoName = false;
7445 fschmid 408
                        neu->isGroupControl = true;
409
                        neu->groupsLastItem = high;
9856 fschmid 410
                        for (int a = 0; a < m_Doc->Items->count(); ++a)
6605 fschmid 411
                        {
7445 fschmid 412
                                m_Doc->Items->at(a)->ItemNr = a;
6605 fschmid 413
                        }
7620 fschmid 414
                        neu->setRedrawBounding();
11705 fschmid 415
                        neu->setTextFlowMode(PageItem::TextFlowDisabled);
7445 fschmid 416
                        Elements.prepend(neu);
417
                        m_Doc->GroupCounter++;
217 Franz 418
                }
419
        }
5781 cbradney 420
        m_Doc->DoDrawing = true;
421
        m_Doc->scMW()->ScriptRunning = false;
3207 craig 422
        if (interactive)
5781 cbradney 423
                m_Doc->setLoading(false);
9380 fschmid 424
        qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
3207 craig 425
        if ((Elements.count() > 0) && (!ret) && (interactive))
217 Franz 426
        {
8262 fschmid 427
                if (flags & LoadSavePlugin::lfScripted)
217 Franz 428
                {
8262 fschmid 429
                        bool loadF = m_Doc->isLoading();
430
                        m_Doc->setLoading(false);
431
                        m_Doc->changed();
432
                        m_Doc->setLoading(loadF);
11835 fschmid 433
                        m_Doc->m_Selection->delaySignalsOn();
9856 fschmid 434
                        for (int dre=0; dre<Elements.count(); ++dre)
8262 fschmid 435
                        {
436
                                m_Doc->m_Selection->addItem(Elements.at(dre), true);
437
                        }
11835 fschmid 438
                        m_Doc->m_Selection->delaySignalsOff();
8262 fschmid 439
                        m_Doc->m_Selection->setGroupRect();
440
                        m_Doc->view()->updatesOn(true);
441
                        importCanceled = false;
217 Franz 442
                }
8262 fschmid 443
                else
444
                {
445
                        m_Doc->DragP = true;
446
                        m_Doc->DraggedElem = 0;
447
                        m_Doc->DragElements.clear();
11835 fschmid 448
                        m_Doc->m_Selection->delaySignalsOn();
9856 fschmid 449
                        for (int dre=0; dre<Elements.count(); ++dre)
8262 fschmid 450
                        {
451
                                m_Doc->DragElements.append(Elements.at(dre)->ItemNr);
452
                                tmpSel->addItem(Elements.at(dre), true);
453
                        }
454
                        ScriXmlDoc *ss = new ScriXmlDoc();
455
                        tmpSel->setGroupRect();
12841 jghali 456
                        ScElemMimeData* md = new ScElemMimeData();
457
                        md->setScribusElem(ss->WriteElem(m_Doc, m_Doc->view(), tmpSel));
12971 jghali 458
                        delete ss;
459
/*#ifndef Q_WS_MAC*/
4302 avox 460
// see #2526
8262 fschmid 461
                        m_Doc->itemSelection_DeleteItem(tmpSel);
12971 jghali 462
/*#endif*/
8262 fschmid 463
                        m_Doc->view()->updatesOn(true);
12737 fschmid 464
                        if (importedColors.count() != 0)
465
                        {
466
                                for (int cd = 0; cd < importedColors.count(); cd++)
467
                                {
468
                                        m_Doc->PageColors.remove(importedColors[cd]);
469
                                }
470
                        }
471
                        if (importedPatterns.count() != 0)
472
                        {
473
                                for (int cd = 0; cd < importedPatterns.count(); cd++)
474
                                {
475
                                        m_Doc->docPatterns.remove(importedPatterns[cd]);
476
                                }
477
                        }
11835 fschmid 478
                        m_Doc->m_Selection->delaySignalsOff();
13371 jghali 479
                        // We must copy the TransationSettings object as it is owned
480
                        // by handleObjectImport method afterwards
481
                        TransactionSettings* transacSettings = new TransactionSettings(trSettings);
482
                        m_Doc->view()->handleObjectImport(md, transacSettings);
8262 fschmid 483
                        m_Doc->DragP = false;
484
                        m_Doc->DraggedElem = 0;
485
                        m_Doc->DragElements.clear();
7991 fschmid 486
                }
217 Franz 487
        }
68 Franz 488
        else
357 Franz 489
        {
7351 fschmid 490
                bool loadF = m_Doc->isLoading();
491
                m_Doc->setLoading(false);
5781 cbradney 492
                m_Doc->changed();
6556 fschmid 493
                m_Doc->reformPages();
7452 fschmid 494
                m_Doc->view()->updatesOn(true);
7351 fschmid 495
                m_Doc->setLoading(loadF);
357 Franz 496
        }
68 Franz 497
}
498
 
499
void SVGPlug::addGraphicContext()
500
{
501
        SvgStyle *gc = new SvgStyle;
9922 fschmid 502
        if ( m_gc.top() )
503
                *gc = *( m_gc.top() );
68 Franz 504
        m_gc.push( gc );
505
}
506
 
7612 jghali 507
void SVGPlug::setupNode( const QDomElement &e )
508
{
509
        addGraphicContext();
510
        setupTransform( e );
9922 fschmid 511
        parseStyle(m_gc.top(), e);
7612 jghali 512
}
513
 
68 Franz 514
void SVGPlug::setupTransform( const QDomElement &e )
515
{
9922 fschmid 516
        SvgStyle *gc = m_gc.top();
8501 cbradney 517
        QMatrix mat = parseTransform( e.attribute( "transform" ) );
68 Franz 518
        if (!e.attribute("transform").isEmpty())
519
                gc->matrix = mat * gc->matrix;
520
}
521
 
10785 jghali 522
void SVGPlug::finishNode( const QDomNode &e, PageItem* item)
7612 jghali 523
{
9922 fschmid 524
        SvgStyle *gc = m_gc.top();
8501 cbradney 525
        QMatrix gcm = gc->matrix;
7612 jghali 526
        double BaseX = m_Doc->currentPage()->xOffset();
527
        double BaseY = m_Doc->currentPage()->yOffset();
528
        double coeff1 = sqrt(gcm.m11() * gcm.m11() + gcm.m12() * gcm.m12());
529
        double coeff2 = sqrt(gcm.m21() * gcm.m21() + gcm.m22() * gcm.m22());
530
        switch (item->itemType())
531
        {
532
        case PageItem::ImageFrame:
533
                {
12785 fschmid 534
                        item->ClipEdited = true;
535
                        item->FrameType = 3;
8501 cbradney 536
                        QMatrix mm = gc->matrix;
12785 fschmid 537
                        item->PoLine.map(mm);
7612 jghali 538
                        item->setLineWidth(item->lineWidth() * (coeff1 + coeff2) / 2.0);
12785 fschmid 539
                        FPoint wh = getMaxClipF(&item->PoLine);
540
                        item->setWidthHeight(wh.x(), wh.y());
541
                        m_Doc->AdjustItemSize(item);
542
//                      item->moveBy(mm.dx(), mm.dy());
543
//                      item->setWidthHeight(item->width() * mm.m11(), item->height() * mm.m22());
544
//                      item->setLineWidth(item->lineWidth() * (coeff1 + coeff2) / 2.0);
13097 subik 545
                        if (item->PictureIsAvailable)
12785 fschmid 546
                        {
547
                                item->setImageXYOffset(0.0, 0.0);
548
                                item->setImageXYScale(item->width() / (item->pixm.width() * (item->pixm.imgInfo.xres / 72.0)),
549
                                                                          item->height() / (item->pixm.height() * (item->pixm.imgInfo.yres / 72.0)));
550
                                item->setImageScalingMode(false, false); // fit to frame
551
                        }
7612 jghali 552
                        break;
553
                }
554
        case PageItem::TextFrame:
555
                {
8501 cbradney 556
                        QMatrix mm = gc->matrix;
7612 jghali 557
                        item->setLineWidth(item->lineWidth() * (coeff1 + coeff2) / 2.0);
558
                }
559
                break;
560
        default:
561
                {
562
                        item->ClipEdited = true;
563
                        item->FrameType = 3;
8501 cbradney 564
                        QMatrix mm = gc->matrix;
7612 jghali 565
                        item->PoLine.map(mm);
566
                        /*if (haveViewBox)
567
                        {
10030 cbradney 568
                                QMatrix mv;
7612 jghali 569
                                mv.translate(viewTransformX, viewTransformY);
570
                                mv.scale(viewScaleX, viewScaleY);
571
                                ite->PoLine.map(mv);
572
                        }*/
573
                        item->setLineWidth(item->lineWidth() * (coeff1 + coeff2) / 2.0);
574
                        FPoint wh = getMaxClipF(&item->PoLine);
575
                        item->setWidthHeight(wh.x(), wh.y());
7672 fschmid 576
//                      if (item->asPolyLine())
8562 jghali 577
//                              item->setPolyClip(qRound(qMax(item->lineWidth() / 2.0, 1)));
7672 fschmid 578
//                      else
579
//                              item->Clip = FlattenPath(item->PoLine, item->Segments);
12745 fschmid 580
                        FPoint wx = getMinClipF(&item->PoLine);
581
                        inGroupXOrigin = qMin(inGroupXOrigin, wx.x());
582
                        inGroupYOrigin = qMin(inGroupYOrigin, wx.y());
7736 cbradney 583
                        m_Doc->AdjustItemSize(item);
7612 jghali 584
                        break;
585
                }
586
        }
7620 fschmid 587
        item->setRedrawBounding();
7612 jghali 588
        item->OwnPage = m_Doc->OnPage(item);
10785 jghali 589
        if (e.isElement())
590
        {
591
                QString nodeId = e.toElement().attribute("id");
592
                if( !nodeId.isEmpty() )
11889 fschmid 593
                {
10785 jghali 594
                        item->setItemName(" "+nodeId);
11889 fschmid 595
                        item->AutoName = false;
596
                }
10785 jghali 597
        }
7612 jghali 598
        item->setFillTransparency( 1 - gc->FillOpacity * gc->Opacity );
599
        item->setLineTransparency( 1 - gc->StrokeOpacity * gc->Opacity );
600
        item->PLineEnd = gc->PLineEnd;
601
        item->PLineJoin = gc->PLineJoin;
7865 fschmid 602
        if (item->fillColor() == CommonStrings::None)
603
                item->setTextFlowMode(PageItem::TextFlowDisabled);
604
        else
605
                item->setTextFlowMode(PageItem::TextFlowUsesFrameShape);
7678 fschmid 606
        item->DashOffset = gc->dashOffset;
607
        item->DashValues = gc->dashArray;
7612 jghali 608
        if (gc->Gradient != 0)
609
        {
12737 fschmid 610
                if (gc->Gradient == 8)
7612 jghali 611
                {
12737 fschmid 612
                        item->GrType = gc->Gradient;
12745 fschmid 613
                        item->setPattern(importedPattTrans[gc->GCol1]);
614
                        QMatrix mm = gc->matrixg;
12751 fschmid 615
                        double rot = getRotationFromMatrix(mm, 0.0) * 180 / M_PI;
616
                        mm.rotate(rot);
617
                        double patDx = (item->xPos() - BaseX) - mm.dx();
618
                        double patDy = (item->yPos() - BaseY) - mm.dy();
619
                        item->setPatternTransform(mm.m11() * 100.0, mm.m22() * 100.0, patDx, patDy, -rot);
12737 fschmid 620
                }
621
                else
622
                {
623
                        if (gc->GradCo.Stops() > 1)
7612 jghali 624
                        {
12737 fschmid 625
                                item->fill_gradient = gc->GradCo;
626
                                if (!gc->CSpace)
7612 jghali 627
                                {
12737 fschmid 628
                                        item->GrStartX = gc->GX1 * item->width();
629
                                        item->GrStartY = gc->GY1 * item->height();
630
                                        item->GrEndX = gc->GX2 * item->width();
631
                                        item->GrEndY = gc->GY2 * item->height();
632
                                        double angle1 = atan2(gc->GY2-gc->GY1,gc->GX2-gc->GX1)*(180.0/M_PI);
633
                                        double angle2 = atan2(item->GrEndY - item->GrStartX, item->GrEndX - item->GrStartX)*(180.0/M_PI);
634
                                        double dx = item->GrStartX + (item->GrEndX - item->GrStartX) / 2.0;
635
                                        double dy = item->GrStartY + (item->GrEndY - item->GrStartY) / 2.0;
636
                                        QMatrix mm, mm2;
637
                                        if ((gc->GY1 < gc->GY2) && (gc->GX1 < gc->GX2))
638
                                        {
639
                                                mm.rotate(-angle2);
640
                                                mm2.rotate(angle1);
641
                                        }
642
                                        FPointArray gra;
643
                                        gra.setPoints(2, item->GrStartX-dx, item->GrStartY-dy, item->GrEndX-dx, item->GrEndY-dy);
644
                                        gra.map(mm*mm2);
645
                                        gra.translate(dx, dy);
646
                                        item->GrStartX = gra.point(0).x();
647
                                        item->GrStartY = gra.point(0).y();
648
                                        item->GrEndX = gra.point(1).x();
649
                                        item->GrEndY = gra.point(1).y();
7612 jghali 650
                                }
12737 fschmid 651
                                else
652
                                {
653
                                        QMatrix mm = gc->matrix;
654
                                        mm = gc->matrixg * mm;
655
                                        FPointArray gra;
656
                                        gra.setPoints(2, gc->GX1, gc->GY1, gc->GX2, gc->GY2);
657
                                        gra.map(mm);
658
                                        gc->GX1 = gra.point(0).x();
659
                                        gc->GY1 = gra.point(0).y();
660
                                        gc->GX2 = gra.point(1).x();
661
                                        gc->GY2 = gra.point(1).y();
662
                                        item->GrStartX = gc->GX1 - item->xPos() + BaseX;
663
                                        item->GrStartY = gc->GY1 - item->yPos() + BaseY;
664
                                        item->GrEndX = gc->GX2 - item->xPos() + BaseX;
665
                                        item->GrEndY = gc->GY2 - item->yPos() + BaseY;
666
                                }
667
                                item->GrType = gc->Gradient;
7612 jghali 668
                        }
669
                        else
670
                        {
12737 fschmid 671
                                item->GrType = 0;
672
                                QList<VColorStop*> cstops = gc->GradCo.colorStops();
673
                                item->setFillColor(cstops.at(0)->name);
674
                                item->setFillShade(cstops.at(0)->shade);
7612 jghali 675
                        }
676
                }
677
        }
678
}
679
 
7605 jghali 680
bool SVGPlug::isIgnorableNode( const QDomElement &e )
681
{
682
        QString nodeName(e.tagName());
10021 jghali 683
        return isIgnorableNodeName(nodeName);
684
}
685
 
686
bool SVGPlug::isIgnorableNodeName( const QString &n )
687
{
688
        if (n.startsWith("sodipodi") || n.startsWith("inkscape") || n == "metadata")
7605 jghali 689
                return true;
690
        return false;
691
}
692
 
12725 jghali 693
FPoint SVGPlug::parseTextPosition(const QDomElement &e, const FPoint* pos)
8230 jghali 694
{
12725 jghali 695
        // FIXME According to spec, we should in fact return a point list
696
        double  x = pos ? pos->x() : 0.0;
697
        double  y = pos ? pos->y() : 0.0;
698
 
699
        if (e.hasAttribute( "x" ))
8230 jghali 700
        {
12725 jghali 701
                QString xatt =  e.attribute( "x" , "0" );
702
                if ( xatt.contains(',') || xatt.contains(' ') )
703
                {
704
                        xatt.replace(QChar(','), QChar(' '));
705
                        QStringList xl(xatt.split(QChar(' '), QString::SkipEmptyParts));
706
                        xatt = xl.first();
707
                }
708
                x = parseUnit( xatt );
8230 jghali 709
        }
12725 jghali 710
 
711
        if (e.hasAttribute( "y" ))
8230 jghali 712
        {
12725 jghali 713
                QString yatt =  e.attribute( "y" , "0" );
714
                if ( yatt.contains(',') || yatt.contains(' ') )
715
                {
716
                        yatt.replace(QChar(','), QChar(' '));
717
                        QStringList yl(yatt.split(QChar(' '), QString::SkipEmptyParts));
718
                        yatt = yl.first();
719
                }
720
                y = parseUnit( yatt );
8230 jghali 721
        }
12725 jghali 722
 
723
        if (e.hasAttribute( "dx" ))
724
        {
725
                QString dxatt =  e.attribute( "dx" , "0" );
726
                if ( dxatt.contains(',') || dxatt.contains(' ') )
727
                {
728
                        dxatt.replace(QChar(','), QChar(' '));
729
                        QStringList xl(dxatt.split(QChar(' '), QString::SkipEmptyParts));
730
                        dxatt = xl.first();
731
                }
732
                x += parseUnit( dxatt );
733
        }
734
 
735
        if (e.hasAttribute( "dy" ))
736
        {
737
                QString dyatt =  e.attribute( "dy" , "0" );
738
                if ( dyatt.contains(',') || dyatt.contains(' ') )
739
                {
740
                        dyatt.replace(QChar(','), QChar(' '));
741
                        QStringList xl(dyatt.split(QChar(' '), QString::SkipEmptyParts));
742
                        dyatt = xl.first();
743
                }
744
                y += parseUnit( dyatt );
745
        }
746
 
8230 jghali 747
        return FPoint(x, y);
748
}
749
 
8252 jghali 750
QSize SVGPlug::parseWidthHeight(const QDomElement &e)
7573 jghali 751
{
752
        QSize size(550, 841);
753
        QString sw = e.attribute("width", "100%");
754
        QString sh = e.attribute("height", "100%");
755
        double w =  550, h = 841;
756
        if (!sw.isEmpty())
757
                w = sw.endsWith("%") ? fromPercentage(sw) : parseUnit(sw);
758
        if (!sh.isEmpty())
759
                h = sh.endsWith("%") ? fromPercentage(sh) : parseUnit(sh);
760
        if (!e.attribute("viewBox").isEmpty())
761
        {
762
                QRect viewBox = parseViewBox(e);
763
                double scw = (viewBox.width() > 0 && viewBox.height() > 0) ? viewBox.width()  : size.width();
764
                double sch = (viewBox.width() > 0 && viewBox.height() > 0) ? viewBox.height() : size.height();
765
                w *= (sw.endsWith("%") ? scw : 1.0);
766
                h *= (sh.endsWith("%") ? sch : 1.0);
767
        }
768
        else
769
        {
770
                w *= (sw.endsWith("%") ? size.width() : 1.0);
771
                h *= (sh.endsWith("%") ? size.height() : 1.0);
772
        }
8230 jghali 773
        // OpenOffice files may not have width and height attributes, so avoid unnecessary large dimensions
774
        if (w > 10000 || h > 10000)
775
        {
776
                double m = max(w, h);
777
                w = w / m * 842;
778
                h = h / m * 842;
779
        }
7794 fschmid 780
        size.setWidth(qRound(w));
781
        size.setHeight(qRound(h));
7573 jghali 782
        return size;
783
}
784
 
785
QRect SVGPlug::parseViewBox(const QDomElement &e)
786
{
787
        QRect box(0, 0, 0, 0);
788
        if ( !e.attribute( "viewBox" ).isEmpty() )
789
        {
790
                QString viewbox( e.attribute( "viewBox" ) );
10603 fschmid 791
                QStringList points = viewbox.replace( QRegExp(","), " ").simplified().split( ' ', QString::SkipEmptyParts );
11080 fschmid 792
                if (points.size() > 3)
793
                {
794
                        double left = points[0].toDouble();
795
                        double bottom  = points[1].toDouble();
796
                        double width = points[2].toDouble();
797
                        double height = points[3].toDouble();
798
                        box.setCoords((int) left, (int) bottom, (int) (left + width), (int) (bottom + height));
799
                }
7573 jghali 800
        }
801
        return box;
802
}
803
 
7556 jghali 804
void SVGPlug::parseDefs(const QDomElement &e)
805
{
806
        for ( QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling() )
807
        {
808
                QDomElement b = n.toElement();
7612 jghali 809
                if ( b.isNull() )
7556 jghali 810
                        continue;
811
                SvgStyle svgStyle;
812
                parseStyle( &svgStyle, b );
7605 jghali 813
                if ( !svgStyle.Display)
7556 jghali 814
                        continue;
815
                QString STag2 = b.tagName();
8507 jghali 816
                if ( STag2 == "g" )
10854 jghali 817
                {
818
                        QString id = b.attribute("id", "");
819
                        if (!id.isEmpty())
820
                                m_nodeMap.insert(id, b);
8507 jghali 821
                        parseDefs(b);
10854 jghali 822
                }
8507 jghali 823
                else if ( STag2 == "linearGradient" || STag2 == "radialGradient" )
7556 jghali 824
                        parseGradient( b );
7607 fschmid 825
                else if (STag2 == "clipPath")
826
                        parseClipPath(b);
12737 fschmid 827
                else if (STag2 == "pattern")
828
                        parsePattern(b);
7556 jghali 829
                else if ( b.hasAttribute("id") )
830
                {
831
                        QString id = b.attribute("id");
832
                        if (!id.isEmpty())
833
                                m_nodeMap.insert(id, b);
834
                }
835
        }
836
}
837
 
7605 jghali 838
void SVGPlug::parseClipPath(const QDomElement &e)
839
{
840
        QString id(e.attribute("id"));
841
        if (!id.isEmpty())
842
        {
843
                FPointArray clip;
844
                QDomNode n2 = e.firstChild();
845
                QDomElement b2 = n2.toElement();
846
                while (b2.nodeName() == "use")
8604 jghali 847
                        b2 = getReferencedNode(b2);
7607 fschmid 848
                if (b2.nodeName() == "path")
849
                        parseSVG( b2.attribute( "d" ), &clip );
850
                else if (b2.nodeName() == "rect")
851
                {
12101 jghali 852
                        double x = parseUnit( b2.attribute( "x", "0.0" ));
853
                        double y = parseUnit( b2.attribute( "y", "0.0" ));
854
                        double width  = parseUnit( b2.attribute( "width" ));
7607 fschmid 855
                        double height = parseUnit( b2.attribute( "height" ) );
12101 jghali 856
                        clip.addQuadPoint(x, y, x, y, width+x, y, width+x, y);
857
                        clip.addQuadPoint(width+x, y, width+x, y, width+x, height+y, width+x, height+y);
858
                        clip.addQuadPoint(width+x, height+y, width+x, height+y, x, height+y, x, height+y);
859
                        clip.addQuadPoint(x, height+y, x, height+y, x, y, x, y);
7607 fschmid 860
                }
7605 jghali 861
                if (clip.size() >= 2)
862
                        m_clipPaths.insert(id, clip);
863
        }
864
}
865
 
866
void SVGPlug::parseClipPathAttr(const QDomElement &e, FPointArray& clipPath)
867
{
868
        clipPath.resize(0);
12802 fschmid 869
/*      if (e.hasAttribute("style"))
12785 fschmid 870
        {
871
                QString style = e.attribute( "style" ).simplified();
872
                QStringList substyles = style.split(';', QString::SkipEmptyParts);
873
                for( QStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it )
874
                {
875
                        QStringList substyle = (*it).split(':', QString::SkipEmptyParts);
876
                        QString command(substyle[0].trimmed());
877
                        QString params(substyle[1].trimmed());
878
                        if (command == "clip-path")
879
                        {
880
                                if (params.startsWith( "url("))
881
                                {
882
                                        unsigned int start = params.indexOf("#") + 1;
883
                                        unsigned int end = params.lastIndexOf(")");
884
                                        QString key = params.mid(start, end - start);
885
                                        QMap<QString, FPointArray>::iterator it = m_clipPaths.find(key);
886
                                        if (it != m_clipPaths.end())
887
                                                clipPath = it.value().copy();
888
                                }
889
                        }
890
                }
12802 fschmid 891
        } */
7605 jghali 892
        if (e.hasAttribute("clip-path"))
893
        {
894
                QString attr = e.attribute("clip-path");
895
                if (attr.startsWith( "url("))
896
                {
10517 cbradney 897
                        unsigned int start = attr.indexOf("#") + 1;
10427 cbradney 898
                        unsigned int end = attr.lastIndexOf(")");
7605 jghali 899
                        QString key = attr.mid(start, end - start);
900
                        QMap<QString, FPointArray>::iterator it = m_clipPaths.find(key);
901
                        if (it != m_clipPaths.end())
10516 cbradney 902
                                clipPath = it.value().copy();
7605 jghali 903
                }
904
        }
905
}
906
 
9856 fschmid 907
QList<PageItem*> SVGPlug::parseGroup(const QDomElement &e)
68 Franz 908
{
7612 jghali 909
        FPointArray clipPath;
9856 fschmid 910
        QList<PageItem*> GElements, gElements;
7612 jghali 911
        double BaseX = m_Doc->currentPage()->xOffset();
912
        double BaseY = m_Doc->currentPage()->yOffset();
7866 fschmid 913
        groupLevel++;
7612 jghali 914
        setupNode(e);
915
        parseClipPathAttr(e, clipPath);
7640 fschmid 916
        int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, BaseX, BaseY, 1, 1, 0, CommonStrings::None, CommonStrings::None, true);
7612 jghali 917
        PageItem *neu = m_Doc->Items->at(z);
7315 jghali 918
        for ( QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling() )
217 Franz 919
        {
68 Franz 920
                QDomElement b = n.toElement();
7612 jghali 921
                if( b.isNull() || isIgnorableNode(b) )
68 Franz 922
                        continue;
6356 jghali 923
                SvgStyle svgStyle;
12785 fschmid 924
                parseStyle( &svgStyle, b);
6356 jghali 925
                if (!svgStyle.Display)
7612 jghali 926
                        continue;
9856 fschmid 927
                QList<PageItem*> el = parseElement(b);
928
                for (int ec = 0; ec < el.count(); ++ec)
7612 jghali 929
                        gElements.append(el.at(ec));
7315 jghali 930
        }
7866 fschmid 931
        groupLevel--;
9922 fschmid 932
        SvgStyle *gc = m_gc.top();
12802 fschmid 933
        if (clipPath.size() == 0)
934
        {
935
                if (gc->clipPath.size() != 0)
936
                        clipPath = gc->clipPath.copy();
937
        }
10854 jghali 938
        if (gElements.count() == 0 || (gElements.count() < 2 && (clipPath.size() == 0) && (gc->Opacity == 1.0)))
7612 jghali 939
        {
13356 jghali 940
                // Unfortunately we have to take the long route here, or we risk crash on undo/redo
941
                // FIXME : create group object after parsing grouped objects
942
                /*m_Doc->Items->takeAt(z);
943
                delete neu;*/
944
                Selection tmpSelection(m_Doc, false);
945
                tmpSelection.addItem(neu);
946
                m_Doc->itemSelection_DeleteItem(&tmpSelection);
9856 fschmid 947
                for (int a = 0; a < m_Doc->Items->count(); ++a)
7640 fschmid 948
                {
949
                        m_Doc->Items->at(a)->ItemNr = a;
950
                }
9856 fschmid 951
                for (int gr = 0; gr < gElements.count(); ++gr)
7640 fschmid 952
                {
953
                        GElements.append(gElements.at(gr));
954
                }
7612 jghali 955
        }
956
        else
957
        {
958
                double minx = 99999.9;
959
                double miny = 99999.9;
960
                double maxx = -99999.9;
961
                double maxy = -99999.9;
962
                GElements.append(neu);
9856 fschmid 963
                for (int gr = 0; gr < gElements.count(); ++gr)
7612 jghali 964
                {
965
                        PageItem* currItem = gElements.at(gr);
11889 fschmid 966
                        double x1, x2, y1, y2;
12751 fschmid 967
                        currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
11889 fschmid 968
                        minx = qMin(minx, x1);
969
                        miny = qMin(miny, y1);
970
                        maxx = qMax(maxx, x2);
971
                        maxy = qMax(maxy, y2);
7612 jghali 972
                }
973
                double gx = minx;
974
                double gy = miny;
975
                double gw = maxx - minx;
976
                double gh = maxy - miny;
977
                neu->setXYPos(gx, gy);
978
                neu->setWidthHeight(gw, gh);
979
                if (clipPath.size() != 0)
980
                {
10396 jghali 981
                        QMatrix mm = gc->matrix;
7612 jghali 982
                        neu->PoLine = clipPath.copy();
983
                        neu->PoLine.map(mm);
12101 jghali 984
                        neu->PoLine.translate(-gx + BaseX, -gy + BaseY);
7612 jghali 985
                        clipPath.resize(0);
13356 jghali 986
 
7612 jghali 987
                }
988
                else
989
                        neu->SetRectFrame();
990
                neu->Clip = FlattenPath(neu->PoLine, neu->Segments);
991
                neu->Groups.push(m_Doc->GroupCounter);
992
                neu->isGroupControl = true;
993
                neu->groupsLastItem = gElements.at(gElements.count()-1);
994
                if( !e.attribute("id").isEmpty() )
995
                        neu->setItemName(e.attribute("id"));
996
                else
997
                        neu->setItemName( tr("Group%1").arg(neu->Groups.top()));
11889 fschmid 998
                neu->AutoName = false;
7612 jghali 999
                neu->setFillTransparency(1 - gc->Opacity);
12745 fschmid 1000
                neu->gXpos = neu->xPos() - gx;
1001
                neu->gYpos = neu->yPos() - gy;
1002
                neu->gWidth = gw;
1003
                neu->gHeight = gh;
9856 fschmid 1004
                for (int gr = 0; gr < gElements.count(); ++gr)
7612 jghali 1005
                {
1006
                        gElements.at(gr)->Groups.push(m_Doc->GroupCounter);
12745 fschmid 1007
                        gElements.at(gr)->gXpos = gElements.at(gr)->xPos() - gx;
1008
                        gElements.at(gr)->gYpos = gElements.at(gr)->yPos() - gy;
1009
                        gElements.at(gr)->gWidth = gw;
1010
                        gElements.at(gr)->gHeight = gh;
7612 jghali 1011
                        GElements.append(gElements.at(gr));
1012
                }
7620 fschmid 1013
                neu->setRedrawBounding();
11705 fschmid 1014
                neu->setTextFlowMode(PageItem::TextFlowDisabled);
7640 fschmid 1015
                m_Doc->GroupCounter++;
7612 jghali 1016
        }
7597 jghali 1017
        delete( m_gc.pop() );
7315 jghali 1018
        return GElements;
1019
}
1020
 
9856 fschmid 1021
QList<PageItem*> SVGPlug::parseElement(const QDomElement &e)
7315 jghali 1022
{
9856 fschmid 1023
        QList<PageItem*> GElements;
7556 jghali 1024
        if (e.hasAttribute("id"))
1025
                m_nodeMap.insert(e.attribute("id"), e);
7315 jghali 1026
        QString STag = e.tagName();
1027
        if( STag == "g" )
1028
        {
7612 jghali 1029
                GElements = parseGroup( e );
7315 jghali 1030
                return GElements;
1031
        }
8507 jghali 1032
        if( STag == "defs" )
7556 jghali 1033
                parseDefs(e);
8507 jghali 1034
        else if( STag == "switch" )
7315 jghali 1035
                GElements = parseSwitch(e);
8507 jghali 1036
        else if( STag == "symbol" )
1037
                GElements = parseSymbol(e);
1038
        else if( STag == "use" )
7556 jghali 1039
                GElements = parseUse(e);
7315 jghali 1040
        else if( STag == "linearGradient" || STag == "radialGradient" )
1041
                parseGradient( e );
1042
        else if( STag == "rect" )
7612 jghali 1043
                GElements = parseRect(e);
7315 jghali 1044
        else if( STag == "ellipse" )
7612 jghali 1045
                GElements = parseEllipse(e);
7315 jghali 1046
        else if( STag == "circle" )
7612 jghali 1047
                GElements = parseCircle(e);
7315 jghali 1048
        else if( STag == "line" )
7612 jghali 1049
                GElements = parseLine(e);
7315 jghali 1050
        else if( STag == "path" )
7612 jghali 1051
                GElements = parsePath(e);
7315 jghali 1052
        else if( STag == "polyline" || e.tagName() == "polygon" )
7612 jghali 1053
                GElements = parsePolyline(e);
7315 jghali 1054
        else if( STag == "text" )
7612 jghali 1055
                GElements = parseText(e);
7605 jghali 1056
        else if( STag == "clipPath" )
1057
                parseClipPath(e);
7866 fschmid 1058
        else if( STag == "desc" )
1059
        {
1060
                if (groupLevel == 1)
1061
                        docDesc = e.text();
1062
        }
1063
        else if( STag == "title" )
1064
        {
1065
                if (groupLevel == 1)
1066
                        docTitle = e.text();
1067
        }
12785 fschmid 1068
        else if( STag == "image" )
1069
                GElements = parseImage(e);
10493 fschmid 1070
/*      else if( STag == "i:pgf" )
1071
        {
1072
                QByteArray cdat;
1073
                QByteArray ddat;
1074
                cdat = e.text().simplified();
1075
                QList<QByteArray> cdlist = cdat.split(' ');
1076
                for (int cd = 0; cd < cdlist.count(); cd++)
1077
                {
1078
                        ddat += QByteArray::fromBase64(cdlist[cd]);
1079
                }
1080
                QFile outf("/home/franz/testdata.txt");
1081
                outf.open(QIODevice::WriteOnly);
1082
                outf.write(ddat);
1083
                outf.close();
1084
                QString f2 = "/home/franz/testdata_decom.ai";
1085
                FILE *source = fopen("/home/franz/testdata.txt", "rb");
1086
                FILE *dest = fopen(f2, "wb");
1087
                int ret;
1088
                unsigned have;
1089
                z_stream strm;
1090
                char in[4096];
1091
                char out[4096];
1092
                strm.zalloc = Z_NULL;
1093
                strm.zfree = Z_NULL;
1094
                strm.opaque = Z_NULL;
1095
                strm.avail_in = 0;
1096
                strm.next_in = Z_NULL;
1097
                ret = inflateInit(&strm);
1098
                if (ret != Z_OK)
1099
                        return GElements;
1100
                do
1101
                {
1102
                        strm.avail_in = fread(in, 1, 4096, source);
1103
                        if (ferror(source))
1104
                        {
1105
                                (void)inflateEnd(&strm);
1106
                                return GElements;
1107
                        }
1108
                        if (strm.avail_in == 0)
1109
                                break;
1110
                        strm.next_in = (Bytef*)in;
1111
                        do
1112
                        {
1113
                                strm.avail_out = 4096;
1114
                                strm.next_out = (Bytef*)out;
1115
                                ret = inflate(&strm, Z_NO_FLUSH);
1116
                                assert(ret != Z_STREAM_ERROR);
1117
                                switch (ret)
1118
                                {
1119
                                        case Z_NEED_DICT:
1120
                                                ret = Z_DATA_ERROR;
1121
                                        case Z_DATA_ERROR:
1122
                                        case Z_MEM_ERROR:
1123
                                                (void)inflateEnd(&strm);
1124
                                                return GElements;
1125
                                }
1126
                                have = 4096 - strm.avail_out;
1127
                                if (fwrite(out, 1, have, dest) != have || ferror(dest))
1128
                                {
1129
                                        (void)inflateEnd(&strm);
1130
                                        return GElements;
1131
                                }
1132
                        }
1133
                        while (strm.avail_out == 0);
1134
                }
1135
                while (ret != Z_STREAM_END);
1136
                (void)inflateEnd(&strm);
1137
                fclose(source);
1138
                fclose(dest);
1139
        } */
7605 jghali 1140
/*      else if( STag == "image" )
7612 jghali 1141
                GElements = parseImage(e);
7504 fschmid 1142
        } */
10021 jghali 1143
        else if(!isIgnorableNodeName(STag) )
7315 jghali 1144
        {
1145
                // warn if unsupported SVG feature are encountered
13385 jghali 1146
                if (!m_unsupportedFeatures.contains(STag))
1147
                {
1148
                        m_unsupportedFeatures.insert(STag, STag);
1149
                        qDebug() << QString("unsupported SVG feature: %1").arg(STag);
1150
                        unsupported = true;
1151
                }
7315 jghali 1152
        }
7612 jghali 1153
        return GElements;
1154
}
1155
 
9856 fschmid 1156
QList<PageItem*> SVGPlug::parseCircle(const QDomElement &e)
7612 jghali 1157
{
9856 fschmid 1158
        QList<PageItem*> CElements;
7612 jghali 1159
        double BaseX = m_Doc->currentPage()->xOffset();
1160
        double BaseY = m_Doc->currentPage()->yOffset();
1161
        double r = parseUnit( e.attribute( "r" ) );
1162
        double x = parseUnit( e.attribute( "cx" ) ) - r;
1163
        double y = parseUnit( e.attribute( "cy" ) ) - r;
1164
        setupNode(e);
9922 fschmid 1165
        SvgStyle *gc = m_gc.top();
7612 jghali 1166
        int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Ellipse, BaseX, BaseY, r * 2.0, r * 2.0, gc->LWidth, gc->FillCol, gc->StrokeCol, true);
1167
        PageItem* ite = m_Doc->Items->at(z);
8501 cbradney 1168
        QMatrix mm = QMatrix();
7612 jghali 1169
        mm.translate(x, y);
1170
        ite->PoLine.map(mm);
1171
        FPoint wh = getMaxClipF(&ite->PoLine);
1172
        ite->setWidthHeight(wh.x(), wh.y());
1173
        finishNode(e, ite);
1174
        CElements.append(ite);
1175
        delete( m_gc.pop() );
1176
        return CElements;
1177
}
1178
 
9856 fschmid 1179
QList<PageItem*> SVGPlug::parseEllipse(const QDomElement &e)
7612 jghali 1180
{
9856 fschmid 1181
        QList<PageItem*> EElements;
7612 jghali 1182
        double BaseX = m_Doc->currentPage()->xOffset();
1183
        double BaseY = m_Doc->currentPage()->yOffset();
1184
        double rx = parseUnit( e.attribute( "rx" ) );
1185
        double ry = parseUnit( e.attribute( "ry" ) );
1186
        double x = parseUnit( e.attribute( "cx" ) ) - rx;
1187
        double y = parseUnit( e.attribute( "cy" ) ) - ry;
1188
        setupNode(e);
9922 fschmid 1189
        SvgStyle *gc = m_gc.top();
7612 jghali 1190
        int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Ellipse, BaseX, BaseY, rx * 2.0, ry * 2.0, gc->LWidth, gc->FillCol, gc->StrokeCol, true);
1191
        PageItem* ite = m_Doc->Items->at(z);
8501 cbradney 1192
        QMatrix mm = QMatrix();
7612 jghali 1193
        mm.translate(x, y);
1194
        ite->PoLine.map(mm);
1195
        FPoint wh = getMaxClipF(&ite->PoLine);
1196
        ite->setWidthHeight(wh.x(), wh.y());
1197
        finishNode(e, ite);
1198
        EElements.append(ite);
1199
        delete( m_gc.pop() );
1200
        return EElements;
1201
}
1202
 
9856 fschmid 1203
QList<PageItem*> SVGPlug::parseImage(const QDomElement &e)
7612 jghali 1204
{
1205
        FPointArray clipPath;
9856 fschmid 1206
        QList<PageItem*> IElements;
7612 jghali 1207
        QString fname = e.attribute("xlink:href");
1208
        double BaseX = m_Doc->currentPage()->xOffset();
1209
        double BaseY = m_Doc->currentPage()->yOffset();
1210
        double x = e.attribute( "x" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "x" ) );
1211
        double y = e.attribute( "y" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "y" ) );
1212
        double w = e.attribute( "width" ).isEmpty() ? 1.0 : parseUnit( e.attribute( "width" ) );
1213
        double h = e.attribute( "height" ).isEmpty() ? 1.0 : parseUnit( e.attribute( "height" ) );
1214
        setupNode(e);
1215
        parseClipPathAttr(e, clipPath);
1216
        int z = m_Doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, x+BaseX, y+BaseY, w, h, 1, m_Doc->toolSettings.dBrushPict, CommonStrings::None, true);
12795 fschmid 1217
        PageItem* ite = m_Doc->Items->at(z);
7612 jghali 1218
        if (!fname.isEmpty())
12785 fschmid 1219
        {
1220
                if (!fname.startsWith("data:"))
1221
                        m_Doc->LoadPict(fname, z);
1222
                else
1223
                {
1224
                        int startData = fname.indexOf(",");
1225
                        QString dataType = fname.left(startData);
1226
                        fname.remove(0, startData+1);
1227
                        QByteArray ba;
1228
                        ba.append(fname);
1229
                        if (dataType.contains("base64"))
1230
                                ba = QByteArray::fromBase64(ba);
12795 fschmid 1231
                        ite->tempImageFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_svg_XXXXXX.png");
1232
                        ite->tempImageFile->open();
1233
                        QString fileName = getLongPathName(ite->tempImageFile->fileName());
1234
                        ite->tempImageFile->close();
1235
                        ite->isInlineImage = true;
12785 fschmid 1236
                        QImage img;
1237
                        img.loadFromData(ba);
12795 fschmid 1238
                        img.save(fileName, "PNG");
1239
                        m_Doc->LoadPict(fileName, z);
12785 fschmid 1240
                }
1241
        }
7612 jghali 1242
        if (clipPath.size() != 0)
1243
                ite->PoLine = clipPath.copy();
1244
        clipPath.resize(0);
1245
        ite->Clip = FlattenPath(ite->PoLine, ite->Segments);
1246
        finishNode(e, ite);
1247
        IElements.append(ite);
1248
        delete( m_gc.pop() );
1249
        return IElements;
1250
}
1251
 
9856 fschmid 1252
QList<PageItem*> SVGPlug::parseLine(const QDomElement &e)
7612 jghali 1253
{
9856 fschmid 1254
        QList<PageItem*> LElements;
7612 jghali 1255
        double BaseX = m_Doc->currentPage()->xOffset();
1256
        double BaseY = m_Doc->currentPage()->yOffset();
1257
        double x1 = e.attribute( "x1" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "x1" ) );
1258
        double y1 = e.attribute( "y1" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "y1" ) );
1259
        double x2 = e.attribute( "x2" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "x2" ) );
1260
        double y2 = e.attribute( "y2" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "y2" ) );
1261
        setupNode(e);
9922 fschmid 1262
        SvgStyle *gc = m_gc.top();
11263 jghali 1263
        int z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol, true);
7612 jghali 1264
        PageItem* ite = m_Doc->Items->at(z);
1265
        ite->PoLine.resize(4);
1266
        ite->PoLine.setPoint(0, FPoint(x1, y1));
1267
        ite->PoLine.setPoint(1, FPoint(x1, y1));
1268
        ite->PoLine.setPoint(2, FPoint(x2, y2));
1269
        ite->PoLine.setPoint(3, FPoint(x2, y2));
1270
        finishNode(e, ite);
1271
        LElements.append(ite);
1272
        delete( m_gc.pop() );
1273
        return LElements;
1274
}
1275
 
9856 fschmid 1276
QList<PageItem*> SVGPlug::parsePath(const QDomElement &e)
7612 jghali 1277
{
1278
        FPointArray pArray;
9856 fschmid 1279
        QList<PageItem*> PElements;
7612 jghali 1280
        double BaseX = m_Doc->currentPage()->xOffset();
1281
        double BaseY = m_Doc->currentPage()->yOffset();
1282
        setupNode(e);
9922 fschmid 1283
        SvgStyle *gc = m_gc.top();
7612 jghali 1284
        PageItem::ItemType itype = parseSVG(e.attribute("d"), &pArray) ? PageItem::PolyLine : PageItem::Polygon;
1285
        int z = m_Doc->itemAdd(itype, PageItem::Unspecified, BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol, true);
1286
        PageItem* ite = m_Doc->Items->at(z);
7678 fschmid 1287
        ite->fillRule = (gc->fillRule != "nonzero");
7612 jghali 1288
        ite->PoLine = pArray;
1289
        if (ite->PoLine.size() < 4)
7315 jghali 1290
        {
7612 jghali 1291
//                      m_Doc->m_Selection->addItem(ite);
1292
                tmpSel->addItem(ite);
1293
//                      m_Doc->itemSelection_DeleteItem();
1294
                m_Doc->itemSelection_DeleteItem(tmpSel);
1295
//                      m_Doc->m_Selection->clear();
1296
        }
1297
        else
1298
        {
1299
                finishNode(e, ite);
1300
                PElements.append(ite);
1301
        }
1302
        delete( m_gc.pop() );
1303
        return PElements;
1304
}
1305
 
9856 fschmid 1306
QList<PageItem*> SVGPlug::parsePolyline(const QDomElement &e)
7612 jghali 1307
{
1308
        int z;
9856 fschmid 1309
        QList<PageItem*> PElements;
7612 jghali 1310
        double BaseX = m_Doc->currentPage()->xOffset();
1311
        double BaseY = m_Doc->currentPage()->yOffset();
1312
        setupNode(e);
9922 fschmid 1313
        SvgStyle *gc = m_gc.top();
7612 jghali 1314
        QString points = e.attribute( "points" );
1315
        if (!points.isEmpty())
1316
        {
1317
                QString STag = e.tagName();
10394 cbradney 1318
                points = points.simplified().replace(',', " ");
10603 fschmid 1319
                QStringList pointList = points.split( ' ', QString::SkipEmptyParts );
7612 jghali 1320
                if (( e.tagName() == "polygon" ) && (pointList.count() > 4))
1321
                        z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol, true);
1322
                else
1323
                        z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol, true);
7315 jghali 1324
                PageItem* ite = m_Doc->Items->at(z);
7612 jghali 1325
                ite->fillRule = (gc->fillRule != "nonzero");
1326
                ite->PoLine.resize(0);
8237 avox 1327
                ite->PoLine.svgInit();
7612 jghali 1328
                bool bFirst = true;
1329
                double x = 0.0;
1330
                double y = 0.0;
1331
                for( QStringList::Iterator it = pointList.begin(); it != pointList.end(); it++ )
217 Franz 1332
                {
7612 jghali 1333
                        if( bFirst )
217 Franz 1334
                        {
7612 jghali 1335
                                x = (*(it++)).toDouble();
1336
                                y = (*it).toDouble();
8252 jghali 1337
                                ite->PoLine.svgMoveTo(x, y);
7612 jghali 1338
                                bFirst = false;
68 Franz 1339
                        }
1340
                        else
7315 jghali 1341
                        {
7612 jghali 1342
                                x = (*(it++)).toDouble();
1343
                                y = (*it).toDouble();
8252 jghali 1344
                                ite->PoLine.svgLineTo(x, y);
7315 jghali 1345
                        }
217 Franz 1346
                }
7612 jghali 1347
                if (( STag == "polygon" ) && (pointList.count() > 4))
8237 avox 1348
                        ite->PoLine.svgClosePath();
7612 jghali 1349
                else
1350
                        ite->convertTo(PageItem::PolyLine);
1351
                finishNode(e, ite);
1352
                PElements.append(ite);
7315 jghali 1353
        }
1354
        delete( m_gc.pop() );
7612 jghali 1355
        return PElements;
7315 jghali 1356
}
1357
 
9856 fschmid 1358
QList<PageItem*> SVGPlug::parseRect(const QDomElement &e)
7612 jghali 1359
{
9856 fschmid 1360
        QList<PageItem*> RElements;
7612 jghali 1361
        double BaseX = m_Doc->currentPage()->xOffset();
1362
        double BaseY = m_Doc->currentPage()->yOffset();
1363
        double x = parseUnit( e.attribute( "x" ) );
1364
        double y = parseUnit( e.attribute( "y" ) );
1365
        double width = parseUnit( e.attribute( "width" ));
1366
        double height = parseUnit( e.attribute( "height" ) );
1367
        double rx = e.attribute( "rx" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "rx" ) );
1368
        double ry = e.attribute( "ry" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "ry" ) );
1369
        setupNode(e);
9922 fschmid 1370
        SvgStyle *gc = m_gc.top();
7612 jghali 1371
        int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, BaseX, BaseY, width, height, gc->LWidth, gc->FillCol, gc->StrokeCol, true);
1372
        PageItem* ite = m_Doc->Items->at(z);
1373
        if ((rx != 0) || (ry != 0))
1374
        {
8562 jghali 1375
                ite->setCornerRadius(qMax(rx, ry));
7612 jghali 1376
                ite->SetFrameRound();
1377
                m_Doc->setRedrawBounding(ite);
1378
        }
8501 cbradney 1379
        QMatrix mm = QMatrix();
7612 jghali 1380
        mm.translate(x, y);
1381
        ite->PoLine.map(mm);
1382
        FPoint wh = getMaxClipF(&ite->PoLine);
1383
        ite->setWidthHeight(wh.x(), wh.y());
1384
        finishNode(e, ite);
1385
        RElements.append(ite);
1386
        delete( m_gc.pop() );
1387
        return RElements;
1388
}
1389
 
9856 fschmid 1390
QList<PageItem*> SVGPlug::parseText(const QDomElement &e)
7315 jghali 1391
{
9856 fschmid 1392
        QList<PageItem*> GElements;
7612 jghali 1393
        setupNode(e);
12725 jghali 1394
        double chunkWidth = 0;
10785 jghali 1395
        FPoint currentPos = parseTextPosition(e);
12725 jghali 1396
        SvgStyle *gc      = m_gc.top();
1397
        if (gc->textAnchor != "start")
1398
                getTextChunkWidth(e, chunkWidth);
12719 fschmid 1399
        for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling())
7315 jghali 1400
        {
10785 jghali 1401
                if (n.isElement() && (n.toElement().tagName() == "tspan"))
217 Franz 1402
                {
12725 jghali 1403
                        QList<PageItem*> el = parseTextSpan(n.toElement(), currentPos, chunkWidth);
9856 fschmid 1404
                        for (int ec = 0; ec < el.count(); ++ec)
215 Franz 1405
                                GElements.append(el.at(ec));
217 Franz 1406
                }
10785 jghali 1407
                if (n.isText())
1408
                {
12725 jghali 1409
                        QList<PageItem*> el = parseTextNode(n.toText(), currentPos, chunkWidth);
10785 jghali 1410
                        for (int ec = 0; ec < el.count(); ++ec)
1411
                                GElements.append(el.at(ec));
1412
                }
12719 fschmid 1413
        }
7612 jghali 1414
        delete( m_gc.pop() );
7315 jghali 1415
        return GElements;
1416
}
12725 jghali 1417
 
1418
QList<PageItem*> SVGPlug::parseTextSpan(const QDomElement& e, FPoint& currentPos, double chunkW)
7315 jghali 1419
{
9856 fschmid 1420
        QList<PageItem*> GElements;
12725 jghali 1421
        setupNode(e);
1422
        currentPos   = parseTextPosition(e, &currentPos);
1423
        SvgStyle *gc = m_gc.top();
1424
        if ((e.hasAttribute("x") || e.hasAttribute("y")) && (gc->textAnchor != "start"))
12718 fschmid 1425
        {
12725 jghali 1426
                chunkW = 0;
1427
                getTextChunkWidth(e, chunkW);
12718 fschmid 1428
        }
12725 jghali 1429
        for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling())
12718 fschmid 1430
        {
12725 jghali 1431
                if (n.isElement() && (n.toElement().tagName() == "tspan"))
12718 fschmid 1432
                {
12725 jghali 1433
                        QList<PageItem*> el = parseTextSpan(n.toElement(), currentPos, chunkW);
1434
                        for (int ec = 0; ec < el.count(); ++ec)
1435
                                GElements.append(el.at(ec));
12718 fschmid 1436
                }
12725 jghali 1437
                if (n.isText())
12718 fschmid 1438
                {
12725 jghali 1439
                        QList<PageItem*> el = parseTextNode(n.toText(), currentPos, chunkW);
1440
                        for (int ec = 0; ec < el.count(); ++ec)
1441
                                GElements.append(el.at(ec));
12718 fschmid 1442
                }
1443
        }
12725 jghali 1444
        delete( m_gc.pop() );
12718 fschmid 1445
        return GElements;
1446
}
12725 jghali 1447
 
1448
QList<PageItem*> SVGPlug::parseTextNode(const QDomText& e, FPoint& currentPos, double chunkW)
12718 fschmid 1449
{
1450
        QList<PageItem*> GElements;
1451
        double BaseX  = m_Doc->currentPage()->xOffset();
1452
        double BaseY  = m_Doc->currentPage()->yOffset();
1453
        double StartX = currentPos.x(), StartY = currentPos.y();
12725 jghali 1454
 
1455
        QString textString = e.data().simplified();
10785 jghali 1456
        if ( textString.isEmpty() )
1457
                return GElements;
1458
 
10638 jghali 1459
        SvgStyle *gc   = m_gc.top();
1460
        QFont textFont = getFontFromStyle(*gc);
1461
        QFontMetrics fm(textFont);
1462
    double width   = fm.width(textString);
1463
 
1464
        if( gc->textAnchor == "middle" )
12725 jghali 1465
                StartX -= chunkW / 2.0;
10638 jghali 1466
        else if( gc->textAnchor == "end")
12725 jghali 1467
                StartX -= chunkW;
10638 jghali 1468
 
1469
        FPointArray textPath;
1470
        QString textFillColor   = gc->FillCol;
1471
        QString textStrokeColor = gc->StrokeCol;
1472
        QPainterPath painterPath;
1473
        painterPath.addText( StartX, StartY, textFont, textString );
1474
        textPath.fromQPainterPath(painterPath);
1475
        if (textPath.size() > 0)
1476
        {
12725 jghali 1477
//              double  lineWidth = 0.0;
10638 jghali 1478
                int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, BaseX, BaseY, 10, 10, gc->LWidth, textFillColor, textStrokeColor, true);
1479
                PageItem* ite = m_Doc->Items->at(z);
1480
                ite->PoLine = textPath;
1481
                finishNode(e, ite);
1482
                GElements.append(ite);
1483
        }
10785 jghali 1484
        currentPos.setX( currentPos.x() + width );
10638 jghali 1485
        return GElements;
7315 jghali 1486
}
12725 jghali 1487
 
9856 fschmid 1488
QList<PageItem*> SVGPlug::parseSwitch(const QDomElement &e)
7315 jghali 1489
{
1490
        QString href;
1491
        QStringList hrefs;
9856 fschmid 1492
        QList<PageItem*> SElements;
7315 jghali 1493
        for (QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling())
1494
        {
1495
                QDomElement de = n.toElement();
1496
                QString STag = de.tagName();
1497
                if (STag == "foreignObject")
217 Franz 1498
                {
7315 jghali 1499
                        if (de.hasAttribute("xlink:href"))
217 Franz 1500
                        {
7315 jghali 1501
                                href = de.attribute("xlink:href").mid(1);
1502
                                if (!href.isEmpty())
1503
                                        hrefs.append(href);
217 Franz 1504
                        }
7315 jghali 1505
                        for (QDomNode n1 = de.firstChild(); !n1.isNull(); n1 = n1.nextSibling())
217 Franz 1506
                        {
7315 jghali 1507
                                QDomElement de1 = n1.toElement();
1508
                                if (de1.hasAttribute("xlink:href"))
296 Franz 1509
                                {
7315 jghali 1510
                                        href = de1.attribute("xlink:href").mid(1);
1511
                                        if (!href.isEmpty())
1512
                                                hrefs.append(href);
298 Franz 1513
                                }
217 Franz 1514
                        }
1515
                }
7315 jghali 1516
                else
1517
                {
1518
                        if (de.hasAttribute("requiredExtensions") || de.hasAttribute("requiredFeatures"))
1519
                                continue;
1520
                        else if (de.hasAttribute("id") && hrefs.contains(de.attribute("id")))
1521
                                continue;
1522
                        else
1523
                        {
1524
                                SElements = parseElement(de);
1525
                                if (SElements.count() > 0)
1526
                                        break;
1527
                        }
1528
                }
217 Franz 1529
        }
7315 jghali 1530
        return SElements;
68 Franz 1531
}
1532
 
9856 fschmid 1533
QList<PageItem*> SVGPlug::parseSymbol(const QDomElement &e)
8507 jghali 1534
{
9856 fschmid 1535
        QList<PageItem*> SElements;
12266 jghali 1536
        QString id = e.attribute("id");
8507 jghali 1537
        if( !id.isEmpty() )
1538
                m_nodeMap.insert(id, e);
1539
        return SElements;
1540
}
1541
 
9856 fschmid 1542
QList<PageItem*> SVGPlug::parseUse(const QDomElement &e)
7556 jghali 1543
{
9856 fschmid 1544
        QList<PageItem*> UElements;
12266 jghali 1545
        setupNode(e);
1546
        if( e.hasAttribute("x") || e.hasAttribute("y") )
1547
        {
1548
                QMatrix matrix;
1549
                double  xAtt = e.attribute("x", "0.0").toDouble();
1550
                double  yAtt = e.attribute("y", "0.0").toDouble();
1551
                SvgStyle *gc = m_gc.top();
1552
                gc->matrix   = QMatrix(1.0, 0.0, 0.0, 1.0, xAtt, yAtt) * gc->matrix;
1553
        }
1554
        QString href = e.attribute("xlink:href").mid(1);
1555
        QMap<QString, QDomElement>::Iterator it = m_nodeMap.find(href);
1556
        if (it != m_nodeMap.end())
1557
        {
1558
                QDomElement elem = it.value().toElement();
1559
                if( elem.tagName() == "symbol" )
1560
                        UElements = parseGroup(elem);
1561
                else
1562
                        UElements = parseElement(elem);
1563
        }
1564
        delete (m_gc.pop());
7556 jghali 1565
        return UElements;
1566
}
1567
 
10638 jghali 1568
QFont SVGPlug::getFontFromStyle(SvgStyle& style)
1569
{
1570
        QFont font(QApplication::font());
1571
        font.setStyleStrategy( QFont::PreferOutline );
1572
 
1573
        if (!style.FontFamily.isEmpty())
1574
                font.setFamily(style.FontFamily);
1575
 
1576
        if (!style.FontStyle.isEmpty())
1577
        {
1578
                if (style.FontStyle == "normal")
1579
                        font.setStyle(QFont::StyleNormal);
1580
                else if (style.FontStyle == "italic")
1581
                        font.setStyle(QFont::StyleItalic);
1582
                else if (style.FontStyle == "oblique")
1583
                        font.setStyle(QFont::StyleOblique);
1584
        }
1585
 
1586
        if (!style.FontWeight.isEmpty())
1587
        {
1588
                if (style.FontWeight == "normal")
1589
                        font.setWeight(QFont::Normal);
1590
                else if (style.FontWeight == "bold")
1591
                        font.setWeight(QFont::Bold);
1592
                else if (style.FontWeight == "bolder")
1593
                        font.setWeight(QFont::DemiBold);
1594
                else if (style.FontWeight == "lighter")
1595
                        font.setWeight(QFont::Light);
1596
                else
1597
                {
1598
                        bool weightIsNum = false;
1599
                        int  fontWeight  = style.FontWeight.toInt(&weightIsNum);
1600
                        if (weightIsNum)
1601
                        {
1602
                                if (fontWeight == 100 || fontWeight == 200)
1603
                                        font.setWeight(QFont::Light);
1604
                                else if (fontWeight == 300 || fontWeight == 400)
1605
                                        font.setWeight(QFont::Normal);
1606
                                else if (fontWeight == 500 || fontWeight == 600)
1607
                                        font.setWeight(QFont::DemiBold);
1608
                                else if (fontWeight == 700 || fontWeight == 800)
1609
                                        font.setWeight(QFont::Bold);
1610
                                else if (fontWeight == 900)
1611
                                        font.setWeight(QFont::Black);
1612
                        }
1613
                }
1614
        }
1615
 
1616
        if (!style.FontStretch.isEmpty())
1617
        {
1618
                if (style.FontStretch == "normal")
1619
                        font.setStretch(QFont::Unstretched);
1620
                else if (style.FontStretch == "ultra-condensed")
1621
                        font.setStretch(QFont::UltraCondensed);
1622
                else if (style.FontStretch == "extra-condensed")
1623
                        font.setStretch(QFont::ExtraCondensed);
1624
                else if (style.FontStretch == "condensed")
1625
                        font.setStretch(QFont::Condensed);
1626
                else if (style.FontStretch == "semi-condensed")
1627
                        font.setStretch(QFont::SemiCondensed);
1628
                else if (style.FontStretch == "semi-expanded")
1629
                        font.setStretch(QFont::SemiExpanded);
1630
                else if (style.FontStretch == "expanded")
1631
                        font.setStretch(QFont::Expanded);
1632
                else if (style.FontStretch == "extra-expanded")
1633
                        font.setStretch(QFont::ExtraExpanded);
1634
                else if (style.FontStretch == "ultra-expanded")
1635
                        font.setStretch(QFont::UltraExpanded);
1636
                else if (style.FontStretch == "narrower")
1637
                        font.setStretch(QFont::SemiCondensed);
1638
                else if (style.FontStretch == "wider")
1639
                        font.setStretch(QFont::SemiExpanded);
1640
        }
12887 jghali 1641
        if (!style.textDecoration.isEmpty())
1642
        {
1643
                bool underline = false, overline  = false;
1644
                bool strikeOut = false;
1645
                if (style.textDecoration == "underline")
1646
                        underline = true;
1647
                else if (style.textDecoration == "overline")
1648
                        overline = true;
1649
                else if (style.textDecoration == "line-through")
1650
                        strikeOut = true;
1651
                font.setUnderline(underline);
1652
                font.setOverline(overline);
1653
                font.setStrikeOut(strikeOut);
1654
        }
10638 jghali 1655
        font.setPointSize(style.FontSize / 10);
1656
        return font;
1657
}
1658
 
8604 jghali 1659
QDomElement SVGPlug::getReferencedNode(const QDomElement &e)
1660
{
1661
        QDomElement ret;
1662
        QMap<QString, QDomElement>::Iterator it;
1663
        QString href = e.attribute("xlink:href").mid(1);
1664
        it = m_nodeMap.find(href);
1665
        if (it != m_nodeMap.end())
12287 jghali 1666
                ret = it.value().toElement();
8604 jghali 1667
        return ret;
1668
}
1669
 
12725 jghali 1670
bool SVGPlug::getTextChunkWidth(const QDomElement &e, double& width)
1671
{
1672
        bool doBreak = false;
1673
        setupNode(e);
1674
        QDomNode c = e.firstChild();
1675
        for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling())
1676
        {
1677
                if (n.isElement() && (n.toElement().tagName() == "tspan"))
1678
                {
1679
                        QDomElement elem = n.toElement();
1680
                        if (elem.hasAttribute("x") || elem.hasAttribute("y"))
1681
                        {
1682
                                doBreak = true;
1683
                                break;
1684
                        }
1685
                        doBreak = getTextChunkWidth(n.toElement(), width);
1686
                        if (doBreak) break;
1687
                }
1688
                if (n.isText())
1689
                {
1690
                        QDomText text = n.toText();
1691
                        QString  textString = text.data().simplified();
1692
                        if (textString.length() > 0)
1693
                        {
1694
                                SvgStyle *gc   = m_gc.top();
1695
                                QFont textFont = getFontFromStyle(*gc);
1696
                                QFontMetrics fm(textFont);
1697
                                width += fm.width(textString);
1698
                        }
1699
                }
1700
        }
1701
        delete (m_gc.pop());
1702
        return doBreak;
1703
}
1704
 
68 Franz 1705
double SVGPlug::fromPercentage( const QString &s )
1706
{
10668 jghali 1707
        QString s1 = s;
1708
        if (s1.endsWith( ";" ))
1709
                s1 = s1.left(s1.length() - 1);
1710
        if (s1.endsWith( "%" ))
7556 jghali 1711
        {
10668 jghali 1712
                s1 = s1.left(s1.length() - 1);
7556 jghali 1713
                return s1.toDouble() / 100.0;
1714
        }
68 Franz 1715
        else
10668 jghali 1716
                return s1.toDouble();
68 Franz 1717
}
1718
 
10638 jghali 1719
double SVGPlug::parseFontSize(const QString& fsize)
1720
{
1721
        bool noUnit  = true;
1722
        QString unit = fsize.right(2);
1723
        if (unit == "pt" || unit == "cm" || unit == "mm" ||
1724
                unit == "in" || unit == "px")
1725
        {
1726
                noUnit = false;
1727
        }
1728
        double value = parseUnit(fsize);
1729
        if (noUnit)
1730
                value *= 0.8;
1731
        return value;
1732
}
1733
 
68 Franz 1734
double SVGPlug::parseUnit(const QString &unit)
1735
{
693 fschmid 1736
        bool noUnit = false;
270 Franz 1737
        QString unitval=unit;
1738
        if( unit.right( 2 ) == "pt" )
1739
                unitval.replace( "pt", "" );
1740
        else if( unit.right( 2 ) == "cm" )
1741
                unitval.replace( "cm", "" );
1742
        else if( unit.right( 2 ) == "mm" )
1743
                unitval.replace( "mm" , "" );
1744
        else if( unit.right( 2 ) == "in" )
1745
                unitval.replace( "in", "" );
1746
        else if( unit.right( 2 ) == "px" )
1747
                unitval.replace( "px", "" );
693 fschmid 1748
        if (unitval == unit)
1749
                noUnit = true;
270 Franz 1750
        double value = unitval.toDouble();
1751
        if( unit.right( 2 ) == "pt" )
1752
                value = value;
1753
        else if( unit.right( 2 ) == "cm" )
1754
                value = ( value / 2.54 ) * 72;
1755
        else if( unit.right( 2 ) == "mm" )
1756
                value = ( value / 25.4 ) * 72;
1757
        else if( unit.right( 2 ) == "in" )
1758
                value = value * 72;
1759
        else if( unit.right( 2 ) == "px" )
865 fschmid 1760
                value = value * 0.8;
693 fschmid 1761
        else if(noUnit)
8252 jghali 1762
                value = value;
68 Franz 1763
        return value;
1764
}
1765
 
8501 cbradney 1766
QMatrix SVGPlug::parseTransform( const QString &transform )
68 Franz 1767
{
8501 cbradney 1768
        QMatrix ret;
12124 jghali 1769
        // Workaround for QString::split() bug when string ends with space
1770
        QString trans = transform.simplified();
68 Franz 1771
        // Split string for handling 1 transform statement at a time
12124 jghali 1772
        QStringList subtransforms = trans.split(')', QString::SkipEmptyParts);
68 Franz 1773
        QStringList::ConstIterator it = subtransforms.begin();
1774
        QStringList::ConstIterator end = subtransforms.end();
1775
        for(; it != end; ++it)
1776
        {
8501 cbradney 1777
                QMatrix result;
12124 jghali 1778
                QStringList subtransform = it->split('(', QString::SkipEmptyParts);
10398 cbradney 1779
                subtransform[0] = subtransform[0].trimmed().toLower();
10394 cbradney 1780
                subtransform[1] = subtransform[1].simplified();
68 Franz 1781
                QRegExp reg("[,( ]");
10603 fschmid 1782
                QStringList params = subtransform[1].split(reg, QString::SkipEmptyParts);
68 Franz 1783
                if(subtransform[0].startsWith(";") || subtransform[0].startsWith(","))
1784
                        subtransform[0] = subtransform[0].right(subtransform[0].length() - 1);
1785
                if(subtransform[0] == "rotate")
1786
                {
1787
                        if(params.count() == 3)
1788
                        {
8252 jghali 1789
                                double x = params[1].toDouble();
1790
                                double y = params[2].toDouble();
68 Franz 1791
                                result.translate(x, y);
1792
                                result.rotate(params[0].toDouble());
1793
                                result.translate(-x, -y);
1794
                        }
1795
                        else
1796
                                result.rotate(params[0].toDouble());
1797
                }
1798
                else if(subtransform[0] == "translate")
1799
                {
1800
                        if(params.count() == 2)
8252 jghali 1801
                                result.translate(params[0].toDouble(), params[1].toDouble());
68 Franz 1802
                        else    // Spec : if only one param given, assume 2nd param to be 0
8252 jghali 1803
                                result.translate(params[0].toDouble(), 0);
68 Franz 1804
                }
1805
                else if(subtransform[0] == "scale")
1806
                {
1807
                        if(params.count() == 2)
1808
                                result.scale(params[0].toDouble(), params[1].toDouble());
1809
                        else    // Spec : if only one param given, assume uniform scaling
1810
                                result.scale(params[0].toDouble(), params[0].toDouble());
1811
                }
1812
                else if(subtransform[0] == "skewx")
1813
                        result.shear(tan(params[0].toDouble() * 0.01745329251994329576), 0.0F);
1814
                else if(subtransform[0] == "skewy")
1815
                        result.shear(0.0F, tan(params[0].toDouble() * 0.01745329251994329576));
1816
                else if(subtransform[0] == "matrix")
1817
                {
1818
                        if(params.count() >= 6)
332 Franz 1819
                        {
1820
                                double sx = params[0].toDouble();
1821
                                double sy = params[3].toDouble();
8252 jghali 1822
                                result.setMatrix(sx, params[1].toDouble(), params[2].toDouble(), sy, params[4].toDouble(), params[5].toDouble());
332 Franz 1823
                        }
68 Franz 1824
                }
6611 jghali 1825
                ret = result * ret;
68 Franz 1826
        }
2597 fschmid 1827
        return ret;
68 Franz 1828
}
1829
 
1830
const char * SVGPlug::getCoord( const char *ptr, double &number )
1831
{
1832
        int integer, exponent;
1833
        double decimal, frac;
1834
        int sign, expsign;
1835
 
1836
        exponent = 0;
1837
        integer = 0;
1838
        frac = 1.0;
1839
        decimal = 0;
1840
        sign = 1;
1841
        expsign = 1;
1842
 
1843
        // read the sign
1844
        if(*ptr == '+')
1845
                ptr++;
1846
        else if(*ptr == '-')
1847
        {
1848
                ptr++;
1849
                sign = -1;
1850
        }
1851
 
1852
        // read the integer part
1853
        while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
1854
                integer = (integer * 10) + *(ptr++) - '0';
1855
        if(*ptr == '.') // read the decimals
217 Franz 1856
        {
68 Franz 1857
                ptr++;
1858
                while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
1859
                        decimal += (*(ptr++) - '0') * (frac *= 0.1);
217 Franz 1860
        }
68 Franz 1861
 
1862
        if(*ptr == 'e' || *ptr == 'E') // read the exponent part
1863
        {
1864
                ptr++;
1865
 
1866
                // read the sign of the exponent
1867
                if(*ptr == '+')
1868
                        ptr++;
1869
                else if(*ptr == '-')
1870
                {
1871
                        ptr++;
1872
                        expsign = -1;
1873
                }
1874
 
1875
                exponent = 0;
1876
                while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
1877
                {
1878
                        exponent *= 10;
1879
                        exponent += *ptr - '0';
1880
                        ptr++;
1881
                }
217 Franz 1882
        }
68 Franz 1883
        number = integer + decimal;
80 Franz 1884
        number *= sign * pow( static_cast<double>(10), static_cast<double>( expsign * exponent ) );
68 Franz 1885
        // skip the following space
1886
        if(*ptr == ' ')
1887
                ptr++;
1888
 
1889
        return ptr;
1890
}
1891
 
1892
bool SVGPlug::parseSVG( const QString &s, FPointArray *ite )
1893
{
8253 jghali 1894
        return ite->parseSVG(s);
68 Franz 1895
}
1896
 
1897
 
1898
QColor SVGPlug::parseColorN( const QString &rgbColor )
1899
{
1900
        int r, g, b;
10398 cbradney 1901
        keywordToRGB( rgbColor.toLower(), r, g, b );
68 Franz 1902
        return QColor( r, g, b );
1903
}
1904
 
4645 subik 1905
 
68 Franz 1906
QString SVGPlug::parseColor( const QString &s )
1907
{
1908
        QColor c;
6286 jghali 1909
        QString ret = CommonStrings::None;
13391 jghali 1910
        if (s.length() > 11) // icc-color()
217 Franz 1911
        {
13391 jghali 1912
                int iccColorIndex  = s.indexOf("icc-color");
1913
                if (iccColorIndex >= 0)
1914
                {
1915
                        QString iccColorName = parseIccColor(s);
1916
                        if (iccColorName.length() > 0)
1917
                                return iccColorName;
1918
                }
1919
        }
1920
        if (s.startsWith( "rgb(" ) )
1921
        {
10394 cbradney 1922
                QString parse = s.trimmed();
10603 fschmid 1923
                QStringList colors = parse.split(',', QString::SkipEmptyParts);
68 Franz 1924
                QString r = colors[0].right( ( colors[0].length() - 4 ) );
1925
                QString g = colors[1];
1926
                QString b = colors[2].left( ( colors[2].length() - 1 ) );
13391 jghali 1927
                if (r.contains( "%" ))
217 Franz 1928
                {
68 Franz 1929
                        r = r.left( r.length() - 1 );
80 Franz 1930
                        r = QString::number( static_cast<int>( ( static_cast<double>( 255 * r.toDouble() ) / 100.0 ) ) );
217 Franz 1931
                }
13391 jghali 1932
                if (g.contains( "%" ))
217 Franz 1933
                {
68 Franz 1934
                        g = g.left( g.length() - 1 );
80 Franz 1935
                        g = QString::number( static_cast<int>( ( static_cast<double>( 255 * g.toDouble() ) / 100.0 ) ) );
217 Franz 1936
                }
13391 jghali 1937
                if (b.contains( "%" ))
217 Franz 1938
                {
68 Franz 1939
                        b = b.left( b.length() - 1 );
80 Franz 1940
                        b = QString::number( static_cast<int>( ( static_cast<double>( 255 * b.toDouble() ) / 100.0 ) ) );
217 Franz 1941
                }
68 Franz 1942
                c = QColor(r.toInt(), g.toInt(), b.toInt());
217 Franz 1943
        }
68 Franz 1944
        else
217 Franz 1945
        {
10394 cbradney 1946
                QString rgbColor = s.trimmed();
13391 jghali 1947
                if (rgbColor.startsWith( "#" ))
11030 jghali 1948
                {
1949
                        rgbColor = rgbColor.left(7);
68 Franz 1950
                        c.setNamedColor( rgbColor );
11030 jghali 1951
                }
68 Franz 1952
                else
1953
                        c = parseColorN( rgbColor );
217 Franz 1954
        }
1065 cbradney 1955
        ColorList::Iterator it;
68 Franz 1956
        bool found = false;
1488 fschmid 1957
        int r, g, b;
1958
        QColor tmpR;
5781 cbradney 1959
        for (it = m_Doc->PageColors.begin(); it != m_Doc->PageColors.end(); ++it)
217 Franz 1960
        {
10469 cbradney 1961
                if (it.value().getColorModel() == colorModelRGB)
68 Franz 1962
                {
10469 cbradney 1963
                        it.value().getRGB(&r, &g, &b);
7554 jghali 1964
                        tmpR.setRgb(r, g, b);
1965
                        if (c == tmpR)
1966
                        {
1967
                                ret = it.key();
1968
                                found = true;
12051 jghali 1969
                                break;
7554 jghali 1970
                        }
68 Franz 1971
                }
217 Franz 1972
        }
68 Franz 1973
        if (!found)
217 Franz 1974
        {
2886 fschmid 1975
                ScColor tmp;
68 Franz 1976
                tmp.fromQColor(c);
7491 fschmid 1977
                tmp.setSpotColor(false);
1978
                tmp.setRegistrationColor(false);
13391 jghali 1979
                QString newColorName = "FromSVG"+c.name();
1980
                m_Doc->PageColors.insert(newColorName, tmp);
1981
                importedColors.append(newColorName);
1982
                ret = newColorName;
217 Franz 1983
        }
68 Franz 1984
        return ret;
1985
}
1986
 
13391 jghali 1987
QString SVGPlug::parseIccColor( const QString &s )
1988
{
1989
        QColor color, tmpR;
1990
        QString ret;
1991
        bool iccColorFound = false, found = false;
1992
        int iccColorIndex  = s.indexOf("icc-color");
1993
        if (iccColorIndex < 0)
1994
                return ret;
1995
        int iccFirst = s.indexOf("(", iccColorIndex);
1996
        int iccLast  = s.indexOf(")", iccColorIndex);
1997
        if (iccFirst >= 0 && iccLast >=