~ubuntu-branches/ubuntu/maverick/scribus-ng/maverick-backports

« back to all changes in this revision

Viewing changes to scribus/plugins/import/svg/svgplugin.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Oleksandr Moskalenko
  • Date: 2010-07-15 12:43:00 UTC
  • mfrom: (0.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20100715124300-2u304r2rvy55vpkv
Tags: 1.3.7.dfsg~svn20100715-1
* Upstream svn. update.
* debian/scribus-ng.lintian: Updated overrides.
* debian/control: Updated standards version to 3.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
 
3
to the COPYING file provided with the program. Following this notice may exist
 
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
 
5
for which a new license (GPL+exception) is in place.
 
6
*/
 
7
 
 
8
#include <QCursor>
 
9
#include <QDebug>
 
10
#include <QDrag>
 
11
#include <QFile>
 
12
#include <QList>
 
13
#include <QMimeData>
 
14
#include <QPainterPath>
 
15
#include <QRegExp>
 
16
#include <QTemporaryFile>
 
17
#include <cmath>
 
18
#include "color.h"
 
19
#include "commonstrings.h"
 
20
#include "customfdialog.h"
 
21
#include "fonts/scfontmetrics.h"
 
22
#include "fpointarray.h"
 
23
#include "loadsaveplugin.h"
 
24
#include "menumanager.h"
 
25
#include "pageitem.h"
 
26
#include "prefsfile.h"
 
27
#include "prefsmanager.h"
 
28
#include "propertiespalette.h"
 
29
#include "sccolorengine.h"
 
30
#include "scclocale.h"
 
31
#include "scconfig.h"
 
32
#include "scgzfile.h"
 
33
#include "scmimedata.h"
 
34
#include "scpaths.h"
 
35
#include "scpattern.h"
 
36
#include "scraction.h"
 
37
#include "scribus.h"
 
38
#include "scribusXml.h"
 
39
#include "scribuscore.h"
 
40
#include "scribusdoc.h"
 
41
#include "selection.h"
 
42
#include "svgplugin.h"
 
43
#include "undomanager.h"
 
44
#include "util.h"
 
45
#include "util_formats.h"
 
46
#include "util_icon.h"
 
47
#include "util_math.h"
 
48
 
 
49
 
 
50
using namespace std;
 
51
 
 
52
int svgimplugin_getPluginAPIVersion()
 
53
{
 
54
        return PLUGIN_API_VERSION;
 
55
}
 
56
 
 
57
ScPlugin* svgimplugin_getPlugin()
 
58
{
 
59
        SVGImportPlugin* plug = new SVGImportPlugin();
 
60
        Q_CHECK_PTR(plug);
 
61
        return plug;
 
62
}
 
63
 
 
64
void svgimplugin_freePlugin(ScPlugin* plugin)
 
65
{
 
66
        SVGImportPlugin* plug = dynamic_cast<SVGImportPlugin*>(plugin);
 
67
        Q_ASSERT(plug);
 
68
        delete plug;
 
69
}
 
70
 
 
71
SVGImportPlugin::SVGImportPlugin() : LoadSavePlugin(),
 
72
        importAction(new ScrAction(ScrAction::DLL, QPixmap(), QPixmap(), "", QKeySequence(), this))
 
73
{
 
74
        // Set action info in languageChange, so we only have to do
 
75
        // it in one place. This includes registering file format
 
76
        // support.
 
77
        languageChange();
 
78
}
 
79
/*
 
80
void SVGImportPlugin::addToMainWindowMenu(ScribusMainWindow *mw)
 
81
{
 
82
        importAction->setEnabled(true);
 
83
        connect( importAction, SIGNAL(triggered()), SLOT(import()) );
 
84
        mw->scrMenuMgr->addMenuItem(importAction, "FileImport");
 
85
}
 
86
*/
 
87
SVGImportPlugin::~SVGImportPlugin()
 
88
{
 
89
        unregisterAll();
 
90
};
 
91
 
 
92
void SVGImportPlugin::languageChange()
 
93
{
 
94
        importAction->setText( tr("Import &SVG..."));
 
95
        // (Re)register file format support.
 
96
        unregisterAll();
 
97
        registerFormats();
 
98
}
 
99
 
 
100
const QString SVGImportPlugin::fullTrName() const
 
101
{
 
102
        return QObject::tr("SVG Import");
 
103
}
 
104
 
 
105
const ScActionPlugin::AboutData* SVGImportPlugin::getAboutData() const
 
106
{
 
107
        AboutData* about = new AboutData;
 
108
        about->authors = "Franz Schmid <franz@scribus.info>";
 
109
        about->shortDescription = tr("Imports SVG Files");
 
110
        about->description = tr("Imports most SVG files into the current document,\nconverting their vector data into Scribus objects.");
 
111
        about->license = "GPL";
 
112
        Q_CHECK_PTR(about);
 
113
        return about;
 
114
}
 
115
 
 
116
void SVGImportPlugin::deleteAboutData(const AboutData* about) const
 
117
{
 
118
        Q_ASSERT(about);
 
119
        delete about;
 
120
}
 
121
 
 
122
void SVGImportPlugin::registerFormats()
 
123
{
 
124
        FileFormat fmt(this);
 
125
        fmt.trName = FormatsManager::instance()->nameOfFormat(FormatsManager::SVG);
 
126
        fmt.formatId = FORMATID_SVGIMPORT;
 
127
        fmt.filter = FormatsManager::instance()->extensionsForFormat(FormatsManager::SVG);
 
128
        fmt.nameMatch = QRegExp("\\."+FormatsManager::instance()->extensionListForFormat(FormatsManager::SVG, 1)+"$", Qt::CaseInsensitive);
 
129
        fmt.load = true;
 
130
        fmt.save = false;
 
131
        fmt.mimeTypes = FormatsManager::instance()->mimetypeOfFormat(FormatsManager::SVG);
 
132
        fmt.priority = 64;
 
133
        registerFormat(fmt);
 
134
}
 
135
 
 
136
bool SVGImportPlugin::fileSupported(QIODevice* /* file */, const QString & fileName) const
 
137
{
 
138
        // TODO: identify valid SVG
 
139
        return true;
 
140
}
 
141
 
 
142
bool SVGImportPlugin::loadFile(const QString & fileName, const FileFormat & /* fmt */, int flags, int /*index*/)
 
143
{
 
144
        // For now, "load file" and import are the same thing for this plugin
 
145
        return import(fileName, flags);
 
146
}
 
147
 
 
148
bool SVGImportPlugin::import(QString filename, int flags)
 
149
{
 
150
        if (!checkFlags(flags))
 
151
                return false;
 
152
        m_Doc=ScCore->primaryMainWindow()->doc;
 
153
        ScribusMainWindow* mw=(m_Doc==0) ? ScCore->primaryMainWindow() : m_Doc->scMW();
 
154
        if (filename.isEmpty())
 
155
        {
 
156
                flags |= lfInteractive;
 
157
                PrefsContext* prefs = PrefsManager::instance()->prefsFile->getPluginContext("SVGPlugin");
 
158
                QString wdir = prefs->get("wdir", ".");
 
159
                CustomFDialog diaf(mw, wdir, QObject::tr("Open"), FormatsManager::instance()->fileDialogFormatList(FormatsManager::SVG));
 
160
                if (diaf.exec())
 
161
                {
 
162
                        filename = diaf.selectedFile();
 
163
                        prefs->set("wdir", filename.left(filename.lastIndexOf("/")));
 
164
                }
 
165
                else
 
166
                        return true;
 
167
        }
 
168
        
 
169
        UndoTransaction* activeTransaction = NULL;
 
170
        bool emptyDoc = (m_Doc == NULL);
 
171
        bool hasCurrentPage = (m_Doc && m_Doc->currentPage());
 
172
        TransactionSettings trSettings;
 
173
        trSettings.targetName   = hasCurrentPage ? m_Doc->currentPage()->getUName() : "";
 
174
        trSettings.targetPixmap = Um::IImageFrame;
 
175
        trSettings.actionName   = Um::ImportSVG;
 
176
        trSettings.description  = filename;
 
177
        trSettings.actionPixmap = Um::ISVG;
 
178
        if (emptyDoc || !(flags & lfInteractive) || !(flags & lfScripted))
 
179
                UndoManager::instance()->setUndoEnabled(false);
 
180
        if (UndoManager::undoEnabled())
 
181
                activeTransaction = new UndoTransaction(UndoManager::instance()->beginTransaction(trSettings));
 
182
        SVGPlug *dia = new SVGPlug(mw, flags);
 
183
        Q_CHECK_PTR(dia);
 
184
        dia->import(filename, trSettings, flags);
 
185
        if (activeTransaction)
 
186
        {
 
187
                activeTransaction->commit();
 
188
                delete activeTransaction;
 
189
                activeTransaction = NULL;
 
190
        }
 
191
        if (emptyDoc || !(flags & lfInteractive) || !(flags & lfScripted))
 
192
                UndoManager::instance()->setUndoEnabled(true);
 
193
        if (dia->importCanceled)
 
194
        {
 
195
                if (dia->importFailed)
 
196
                        QMessageBox::warning(mw, CommonStrings::trWarning, tr("The file could not be imported"), 1, 0, 0);
 
197
                else if (dia->unsupported)
 
198
                        QMessageBox::warning(mw, CommonStrings::trWarning, tr("SVG file contains some unsupported features"), 1, 0, 0);
 
199
        }
 
200
 
 
201
        delete dia;
 
202
        return true;
 
203
}
 
204
 
 
205
SVGPlug::SVGPlug( ScribusMainWindow* mw, int flags ) :
 
206
        QObject(mw)
 
207
{       
 
208
        tmpSel=new Selection(this, false);
 
209
        m_Doc=mw->doc;
 
210
        unsupported = false;
 
211
        importFailed = false;
 
212
        importCanceled = true;
 
213
        importedColors.clear();
 
214
        importedPatterns.clear();
 
215
        docDesc = "";
 
216
        docTitle = "";
 
217
        groupLevel = 0;
 
218
        interactive = (flags & LoadSavePlugin::lfInteractive);
 
219
//      m_gc.setAutoDelete( true );
 
220
}
 
221
 
 
222
bool SVGPlug::import(QString fname, const TransactionSettings& trSettings, int flags)
 
223
{
 
224
        if (!loadData(fname))
 
225
        {
 
226
                importFailed = true;
 
227
                return false;
 
228
        }
 
229
        QString CurDirP = QDir::currentPath();
 
230
        QFileInfo efp(fname);
 
231
        QDir::setCurrent(efp.path());
 
232
        convert(trSettings, flags);
 
233
        QDir::setCurrent(CurDirP);
 
234
        return true;
 
235
}
 
236
 
 
237
bool SVGPlug::loadData(QString fName)
 
238
{
 
239
        QString f("");
 
240
        bool isCompressed = false, success = false;
 
241
        QByteArray bb(3, ' ');
 
242
        QFile fi(fName);
 
243
        if (fi.open(QIODevice::ReadOnly))
 
244
        {
 
245
                fi.read(bb.data(), 2);
 
246
                fi.close();
 
247
                // Qt4 bb[0]->QChar(bb[0])
 
248
                if ((QChar(bb[0]) == QChar(0x1F)) && (QChar(bb[1]) == QChar(0x8B)))
 
249
                        isCompressed = true;
 
250
        }
 
251
        if ((fName.right(2) == "gz") || (isCompressed))
 
252
        {
 
253
                ScGzFile file(fName);
 
254
                if (!file.open(QIODevice::ReadOnly))
 
255
                        return false;
 
256
                success = inpdoc.setContent(&file);
 
257
                file.close();
 
258
        }
 
259
        else
 
260
        {
 
261
                QFile file(fName);
 
262
                if (!file.open(QIODevice::ReadOnly))
 
263
                        return false;
 
264
                success = inpdoc.setContent(&file);
 
265
                file.close();
 
266
        }
 
267
        return success;
 
268
}
 
269
 
 
270
void SVGPlug::convert(const TransactionSettings& trSettings, int flags)
 
271
{
 
272
        bool ret = false;
 
273
        SvgStyle *gc = new SvgStyle;
 
274
        QDomElement docElem = inpdoc.documentElement();
 
275
        QSize wh = parseWidthHeight(docElem);
 
276
        double width = wh.width();
 
277
        double height = wh.height();
 
278
        if (!interactive || (flags & LoadSavePlugin::lfInsertPage))
 
279
        {
 
280
                m_Doc->setPage(width, height, 0, 0, 0, 0, 0, 0, false, false);
 
281
                m_Doc->addPage(0);
 
282
                m_Doc->view()->addPage(0);
 
283
        }
 
284
        else
 
285
        {
 
286
                if (!m_Doc || (flags & LoadSavePlugin::lfCreateDoc))
 
287
                {
 
288
                        m_Doc=ScCore->primaryMainWindow()->doFileNew(width, height, 0, 0, 0, 0, 0, 0, false, false, 0, false, 0, 1, "Custom", true);
 
289
                        ScCore->primaryMainWindow()->HaveNewDoc();
 
290
                        ret = true;
 
291
                }
 
292
        }
 
293
        if ((ret) || (!interactive))
 
294
        {
 
295
                if (width > height)
 
296
                        m_Doc->PageOri = 1;
 
297
                else
 
298
                        m_Doc->PageOri = 0;
 
299
                m_Doc->m_pageSize = "Custom";
 
300
        }
 
301
        FPoint minSize = m_Doc->minCanvasCoordinate;
 
302
        FPoint maxSize = m_Doc->maxCanvasCoordinate;
 
303
        FPoint cOrigin = m_Doc->view()->canvasOrigin();
 
304
        m_Doc->view()->Deselect();
 
305
        m_Doc->setLoading(true);
 
306
        m_Doc->DoDrawing = false;
 
307
        m_Doc->view()->updatesOn(false);
 
308
        m_Doc->scMW()->setScriptRunning(true);
 
309
        qApp->changeOverrideCursor(QCursor(Qt::WaitCursor));
 
310
        gc->FontFamily = m_Doc->toolSettings.defFont;
 
311
        if (!m_Doc->PageColors.contains("Black"))
 
312
                m_Doc->PageColors.insert("Black", ScColor(0, 0, 0, 255));
 
313
        m_gc.push( gc );
 
314
        viewTransformX = 0;
 
315
        viewTransformY = 0;
 
316
        viewScaleX = 1;
 
317
        viewScaleY = 1;
 
318
        if( !docElem.attribute( "viewBox" ).isEmpty() )
 
319
        {
 
320
                QString viewbox( docElem.attribute( "viewBox" ) );
 
321
                QStringList points = viewbox.replace( QRegExp(","), " ").simplified().split( ' ', QString::SkipEmptyParts );
 
322
                if (points.size() > 3)
 
323
                {
 
324
                        QMatrix matrix;
 
325
                        QSize wh2 = parseWidthHeight(docElem);
 
326
                        double w2 = wh2.width();
 
327
                        double h2 = wh2.height();
 
328
                        addGraphicContext();
 
329
                        viewTransformX = ScCLocale::toDoubleC(points[0]);
 
330
                        viewTransformY = ScCLocale::toDoubleC(points[1]);
 
331
                        viewScaleX = w2 / ScCLocale::toDoubleC(points[2]);
 
332
                        viewScaleY = h2 / ScCLocale::toDoubleC(points[3]);
 
333
                        matrix.translate(-viewTransformX * viewScaleX, -viewTransformY * viewScaleY);
 
334
                        matrix.scale(viewScaleX, viewScaleY);
 
335
                        m_gc.top()->matrix = matrix;
 
336
                }
 
337
        }
 
338
        QList<PageItem*> Elements = parseGroup( docElem );
 
339
        if (flags & LoadSavePlugin::lfCreateDoc)
 
340
        {
 
341
                m_Doc->documentInfo.setTitle(docTitle);
 
342
                m_Doc->documentInfo.setComments(docDesc);
 
343
        }
 
344
        tmpSel->clear();
 
345
        if (Elements.count() == 0)
 
346
        {
 
347
                importFailed = true;
 
348
                if (importedColors.count() != 0)
 
349
                {
 
350
                        for (int cd = 0; cd < importedColors.count(); cd++)
 
351
                        {
 
352
                                m_Doc->PageColors.remove(importedColors[cd]);
 
353
                        }
 
354
                }
 
355
                if (importedPatterns.count() != 0)
 
356
                {
 
357
                        for (int cd = 0; cd < importedPatterns.count(); cd++)
 
358
                        {
 
359
                                m_Doc->docPatterns.remove(importedPatterns[cd]);
 
360
                        }
 
361
                }
 
362
        }
 
363
        if (Elements.count() > 1)
 
364
        {
 
365
                bool isGroup = true;
 
366
                int firstElem = -1;
 
367
                if (Elements.at(0)->Groups.count() != 0)
 
368
                        firstElem = Elements.at(0)->Groups.top();
 
369
                for (int bx = 0; bx < Elements.count(); ++bx)
 
370
                {
 
371
                        PageItem* bxi = Elements.at(bx);
 
372
                        if (bxi->Groups.count() != 0)
 
373
                        {
 
374
                                if (bxi->Groups.top() != firstElem)
 
375
                                        isGroup = false;
 
376
                        }
 
377
                        else
 
378
                                isGroup = false;
 
379
                }
 
380
                if (!isGroup)
 
381
                {
 
382
                        double minx = 99999.9;
 
383
                        double miny = 99999.9;
 
384
                        double maxx = -99999.9;
 
385
                        double maxy = -99999.9;
 
386
                        uint lowestItem = 999999;
 
387
                        uint highestItem = 0;
 
388
                        for (int a = 0; a < Elements.count(); ++a)
 
389
                        {
 
390
                                Elements.at(a)->Groups.push(m_Doc->GroupCounter);
 
391
                                PageItem* currItem = Elements.at(a);
 
392
                                lowestItem = qMin(lowestItem, currItem->ItemNr);
 
393
                                highestItem = qMax(highestItem, currItem->ItemNr);
 
394
                                double x1, x2, y1, y2;
 
395
                                currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
 
396
                                minx = qMin(minx, x1);
 
397
                                miny = qMin(miny, y1);
 
398
                                maxx = qMax(maxx, x2);
 
399
                                maxy = qMax(maxy, y2);
 
400
                        }
 
401
                        double gx = minx;
 
402
                        double gy = miny;
 
403
                        double gw = maxx - minx;
 
404
                        double gh = maxy - miny;
 
405
                        PageItem *high = m_Doc->Items->at(highestItem);
 
406
                        int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, gx, gy, gw, gh, 0, m_Doc->toolSettings.dBrush, m_Doc->toolSettings.dPen, true);
 
407
                        PageItem *neu = m_Doc->Items->takeAt(z);
 
408
                        m_Doc->Items->insert(lowestItem, neu);
 
409
                        neu->Groups.push(m_Doc->GroupCounter);
 
410
                        neu->setItemName( tr("Group%1").arg(neu->Groups.top()));
 
411
                        neu->AutoName = false;
 
412
                        neu->isGroupControl = true;
 
413
                        neu->groupsLastItem = high;
 
414
                        for (int a = 0; a < m_Doc->Items->count(); ++a)
 
415
                        {
 
416
                                m_Doc->Items->at(a)->ItemNr = a;
 
417
                        }
 
418
                        neu->setRedrawBounding();
 
419
                        neu->setTextFlowMode(PageItem::TextFlowDisabled);
 
420
                        Elements.prepend(neu);
 
421
                        m_Doc->GroupCounter++;
 
422
                }
 
423
        }
 
424
        m_Doc->DoDrawing = true;
 
425
        m_Doc->scMW()->setScriptRunning(false);
 
426
        if (interactive)
 
427
                m_Doc->setLoading(false);
 
428
        qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
 
429
        if ((Elements.count() > 0) && (!ret) && (interactive))
 
430
        {
 
431
                if (flags & LoadSavePlugin::lfScripted)
 
432
                {
 
433
                        bool loadF = m_Doc->isLoading();
 
434
                        m_Doc->setLoading(false);
 
435
                        m_Doc->changed();
 
436
                        m_Doc->setLoading(loadF);
 
437
                        m_Doc->m_Selection->delaySignalsOn();
 
438
                        for (int dre=0; dre<Elements.count(); ++dre)
 
439
                        {
 
440
                                m_Doc->m_Selection->addItem(Elements.at(dre), true);
 
441
                        }
 
442
                        m_Doc->m_Selection->delaySignalsOff();
 
443
                        m_Doc->m_Selection->setGroupRect();
 
444
                        m_Doc->view()->updatesOn(true);
 
445
                        importCanceled = false;
 
446
                }
 
447
                else
 
448
                {
 
449
                        m_Doc->DragP = true;
 
450
                        m_Doc->DraggedElem = 0;
 
451
                        m_Doc->DragElements.clear();
 
452
                        m_Doc->m_Selection->delaySignalsOn();
 
453
                        for (int dre=0; dre<Elements.count(); ++dre)
 
454
                        {
 
455
                                m_Doc->DragElements.append(Elements.at(dre)->ItemNr);
 
456
                                tmpSel->addItem(Elements.at(dre), true);
 
457
                        }
 
458
                        ScriXmlDoc *ss = new ScriXmlDoc();
 
459
                        tmpSel->setGroupRect();
 
460
                        ScElemMimeData* md = new ScElemMimeData();
 
461
                        md->setScribusElem(ss->WriteElem(m_Doc, m_Doc->view(), tmpSel));
 
462
                        delete ss;
 
463
/*#ifndef Q_WS_MAC*/
 
464
// see #2526
 
465
                        m_Doc->itemSelection_DeleteItem(tmpSel);
 
466
/*#endif*/
 
467
                        m_Doc->view()->updatesOn(true);
 
468
                        if (importedColors.count() != 0)
 
469
                        {
 
470
                                for (int cd = 0; cd < importedColors.count(); cd++)
 
471
                                {
 
472
                                        m_Doc->PageColors.remove(importedColors[cd]);
 
473
                                }
 
474
                        }
 
475
                        if (importedPatterns.count() != 0)
 
476
                        {
 
477
                                for (int cd = 0; cd < importedPatterns.count(); cd++)
 
478
                                {
 
479
                                        m_Doc->docPatterns.remove(importedPatterns[cd]);
 
480
                                }
 
481
                        }
 
482
                        m_Doc->m_Selection->delaySignalsOff();
 
483
                        // We must copy the TransationSettings object as it is owned
 
484
                        // by handleObjectImport method afterwards
 
485
                        TransactionSettings* transacSettings = new TransactionSettings(trSettings);
 
486
                        m_Doc->view()->handleObjectImport(md, transacSettings);
 
487
                        m_Doc->DragP = false;
 
488
                        m_Doc->DraggedElem = 0;
 
489
                        m_Doc->DragElements.clear();
 
490
                }
 
491
        }
 
492
        else
 
493
        {
 
494
                bool loadF = m_Doc->isLoading();
 
495
                m_Doc->setLoading(false);
 
496
                m_Doc->changed();
 
497
                m_Doc->reformPages();
 
498
                m_Doc->view()->updatesOn(true);
 
499
                m_Doc->setLoading(loadF);
 
500
        }
 
501
}
 
502
 
 
503
void SVGPlug::addGraphicContext()
 
504
{
 
505
        SvgStyle *gc = new SvgStyle;
 
506
        if ( m_gc.top() )
 
507
                *gc = *( m_gc.top() );
 
508
        m_gc.push( gc );
 
509
}
 
510
 
 
511
void SVGPlug::setupNode( const QDomElement &e )
 
512
{
 
513
        addGraphicContext();
 
514
        setupTransform( e );
 
515
        parseStyle(m_gc.top(), e);
 
516
}
 
517
 
 
518
void SVGPlug::setupTransform( const QDomElement &e )
 
519
{
 
520
        SvgStyle *gc = m_gc.top();
 
521
        QMatrix mat = parseTransform( e.attribute( "transform" ) );
 
522
        if (!e.attribute("transform").isEmpty())
 
523
                gc->matrix = mat * gc->matrix;
 
524
}
 
525
 
 
526
void SVGPlug::finishNode( const QDomNode &e, PageItem* item)
 
527
{
 
528
        SvgStyle *gc = m_gc.top();
 
529
        QMatrix gcm = gc->matrix;
 
530
        double BaseX = m_Doc->currentPage()->xOffset();
 
531
        double BaseY = m_Doc->currentPage()->yOffset();
 
532
        double coeff1 = sqrt(gcm.m11() * gcm.m11() + gcm.m12() * gcm.m12());
 
533
        double coeff2 = sqrt(gcm.m21() * gcm.m21() + gcm.m22() * gcm.m22());
 
534
        switch (item->itemType())
 
535
        {
 
536
        case PageItem::ImageFrame:
 
537
                {
 
538
                        item->ClipEdited = true;
 
539
                        item->FrameType = 3;
 
540
                        QMatrix mm = gc->matrix;
 
541
                        item->PoLine.map(mm);
 
542
                        item->setLineWidth(item->lineWidth() * (coeff1 + coeff2) / 2.0);
 
543
                        FPoint wh = getMaxClipF(&item->PoLine);
 
544
                        item->setWidthHeight(wh.x(), wh.y());
 
545
                        m_Doc->AdjustItemSize(item);
 
546
//                      item->moveBy(mm.dx(), mm.dy());
 
547
//                      item->setWidthHeight(item->width() * mm.m11(), item->height() * mm.m22());
 
548
//                      item->setLineWidth(item->lineWidth() * (coeff1 + coeff2) / 2.0);
 
549
                        if (item->PictureIsAvailable)
 
550
                        {
 
551
                                item->setImageXYOffset(0.0, 0.0);
 
552
                                item->setImageXYScale(item->width() / (item->pixm.width() * (item->pixm.imgInfo.xres / 72.0)),
 
553
                                                                          item->height() / (item->pixm.height() * (item->pixm.imgInfo.yres / 72.0)));
 
554
                                item->setImageScalingMode(false, false); // fit to frame
 
555
                        }
 
556
                        break;
 
557
                }
 
558
        case PageItem::TextFrame:
 
559
                {
 
560
                        QMatrix mm = gc->matrix;
 
561
                        item->setLineWidth(item->lineWidth() * (coeff1 + coeff2) / 2.0);
 
562
                }
 
563
                break;
 
564
        default:
 
565
                {
 
566
                        item->ClipEdited = true;
 
567
                        item->FrameType = 3;
 
568
                        QMatrix mm = gc->matrix;
 
569
                        item->PoLine.map(mm);
 
570
                        /*if (haveViewBox)
 
571
                        {
 
572
                                QMatrix mv;
 
573
                                mv.translate(viewTransformX, viewTransformY);
 
574
                                mv.scale(viewScaleX, viewScaleY);
 
575
                                ite->PoLine.map(mv);
 
576
                        }*/
 
577
                        item->setLineWidth(item->lineWidth() * (coeff1 + coeff2) / 2.0);
 
578
                        FPoint wh = getMaxClipF(&item->PoLine);
 
579
                        item->setWidthHeight(wh.x(), wh.y());
 
580
//                      if (item->asPolyLine())
 
581
//                              item->setPolyClip(qRound(qMax(item->lineWidth() / 2.0, 1)));
 
582
//                      else
 
583
//                              item->Clip = FlattenPath(item->PoLine, item->Segments);
 
584
                        FPoint wx = getMinClipF(&item->PoLine);
 
585
                        inGroupXOrigin = qMin(inGroupXOrigin, wx.x());
 
586
                        inGroupYOrigin = qMin(inGroupYOrigin, wx.y());
 
587
                        m_Doc->AdjustItemSize(item);
 
588
                        break;
 
589
                }
 
590
        }
 
591
        item->setRedrawBounding();
 
592
        item->OwnPage = m_Doc->OnPage(item);
 
593
        if (e.isElement())
 
594
        {
 
595
                QString nodeId = e.toElement().attribute("id");
 
596
                if( !nodeId.isEmpty() )
 
597
                {
 
598
                        item->setItemName(" "+nodeId);
 
599
                        item->AutoName = false;
 
600
                }
 
601
        }
 
602
        item->setFillTransparency( 1 - gc->FillOpacity * gc->Opacity );
 
603
        item->setLineTransparency( 1 - gc->StrokeOpacity * gc->Opacity );
 
604
        item->PLineEnd = gc->PLineEnd;
 
605
        item->PLineJoin = gc->PLineJoin;
 
606
        if (item->fillColor() == CommonStrings::None)
 
607
                item->setTextFlowMode(PageItem::TextFlowDisabled);
 
608
        else
 
609
                item->setTextFlowMode(PageItem::TextFlowUsesFrameShape);
 
610
        item->DashOffset = gc->dashOffset;
 
611
        item->DashValues = gc->dashArray;
 
612
        if (gc->Gradient != 0)
 
613
        {
 
614
                if (gc->Gradient == 8)
 
615
                {
 
616
                        item->GrType = gc->Gradient;
 
617
                        item->setPattern(importedPattTrans[gc->GCol1]);
 
618
                        QMatrix mm = gc->matrixg;
 
619
                        double rot = getRotationFromMatrix(mm, 0.0) * 180 / M_PI;
 
620
                        mm.rotate(rot);
 
621
                        double patDx = (item->xPos() - BaseX) - mm.dx();
 
622
                        double patDy = (item->yPos() - BaseY) - mm.dy();
 
623
                        item->setPatternTransform(mm.m11() * 100.0, mm.m22() * 100.0, patDx, patDy, -rot);
 
624
                }
 
625
                else
 
626
                {
 
627
                        if (gc->GradCo.Stops() > 1)
 
628
                        {
 
629
                                item->fill_gradient = gc->GradCo;
 
630
                                if (!gc->CSpace)
 
631
                                {
 
632
                                        item->GrStartX = gc->GX1 * item->width();
 
633
                                        item->GrStartY = gc->GY1 * item->height();
 
634
                                        item->GrEndX = gc->GX2 * item->width();
 
635
                                        item->GrEndY = gc->GY2 * item->height();
 
636
                                        double angle1 = atan2(gc->GY2-gc->GY1,gc->GX2-gc->GX1)*(180.0/M_PI);
 
637
                                        double angle2 = atan2(item->GrEndY - item->GrStartX, item->GrEndX - item->GrStartX)*(180.0/M_PI);
 
638
                                        double dx = item->GrStartX + (item->GrEndX - item->GrStartX) / 2.0;
 
639
                                        double dy = item->GrStartY + (item->GrEndY - item->GrStartY) / 2.0;
 
640
                                        QMatrix mm, mm2;
 
641
                                        if ((gc->GY1 < gc->GY2) && (gc->GX1 < gc->GX2))
 
642
                                        {
 
643
                                                mm.rotate(-angle2);
 
644
                                                mm2.rotate(angle1);
 
645
                                        }
 
646
                                        FPointArray gra;
 
647
                                        gra.setPoints(2, item->GrStartX-dx, item->GrStartY-dy, item->GrEndX-dx, item->GrEndY-dy);
 
648
                                        gra.map(mm*mm2);
 
649
                                        gra.translate(dx, dy);
 
650
                                        item->GrStartX = gra.point(0).x();
 
651
                                        item->GrStartY = gra.point(0).y();
 
652
                                        item->GrEndX = gra.point(1).x();
 
653
                                        item->GrEndY = gra.point(1).y();
 
654
                                }
 
655
                                else
 
656
                                {
 
657
                                        QMatrix mm = gc->matrix;
 
658
                                        mm = gc->matrixg * mm;
 
659
                                        FPointArray gra;
 
660
                                        gra.setPoints(2, gc->GX1, gc->GY1, gc->GX2, gc->GY2);
 
661
                                        gra.map(mm);
 
662
                                        gc->GX1 = gra.point(0).x();
 
663
                                        gc->GY1 = gra.point(0).y();
 
664
                                        gc->GX2 = gra.point(1).x();
 
665
                                        gc->GY2 = gra.point(1).y();
 
666
                                        item->GrStartX = gc->GX1 - item->xPos() + BaseX;
 
667
                                        item->GrStartY = gc->GY1 - item->yPos() + BaseY;
 
668
                                        item->GrEndX = gc->GX2 - item->xPos() + BaseX;
 
669
                                        item->GrEndY = gc->GY2 - item->yPos() + BaseY;
 
670
                                }
 
671
                                item->GrType = gc->Gradient;
 
672
                        }
 
673
                        else
 
674
                        {
 
675
                                item->GrType = 0;
 
676
                                QList<VColorStop*> cstops = gc->GradCo.colorStops();
 
677
                                item->setFillColor(cstops.at(0)->name);
 
678
                                item->setFillShade(cstops.at(0)->shade);
 
679
                        }
 
680
                }
 
681
        }
 
682
}
 
683
 
 
684
bool SVGPlug::isIgnorableNode( const QDomElement &e )
 
685
{
 
686
        QString nodeName(e.tagName());
 
687
        return isIgnorableNodeName(nodeName);
 
688
}
 
689
 
 
690
bool SVGPlug::isIgnorableNodeName( const QString &n )
 
691
{
 
692
        if (n.startsWith("sodipodi") || n.startsWith("inkscape") || n == "metadata")
 
693
                return true;
 
694
        return false;
 
695
}
 
696
 
 
697
FPoint SVGPlug::parseTextPosition(const QDomElement &e, const FPoint* pos)
 
698
{
 
699
        // FIXME According to spec, we should in fact return a point list
 
700
        double  x = pos ? pos->x() : 0.0;
 
701
        double  y = pos ? pos->y() : 0.0;
 
702
 
 
703
        if (e.hasAttribute( "x" ))
 
704
        {
 
705
                QString xatt =  e.attribute( "x" , "0" );
 
706
                if ( xatt.contains(',') || xatt.contains(' ') )
 
707
                {
 
708
                        xatt.replace(QChar(','), QChar(' '));
 
709
                        QStringList xl(xatt.split(QChar(' '), QString::SkipEmptyParts));
 
710
                        xatt = xl.first();
 
711
                }
 
712
                x = parseUnit( xatt ); 
 
713
        }
 
714
 
 
715
        if (e.hasAttribute( "y" ))
 
716
        {
 
717
                QString yatt =  e.attribute( "y" , "0" );
 
718
                if ( yatt.contains(',') || yatt.contains(' ') )
 
719
                {
 
720
                        yatt.replace(QChar(','), QChar(' '));
 
721
                        QStringList yl(yatt.split(QChar(' '), QString::SkipEmptyParts));
 
722
                        yatt = yl.first();
 
723
                }
 
724
                y = parseUnit( yatt );
 
725
        }
 
726
 
 
727
        if (e.hasAttribute( "dx" ))
 
728
        {
 
729
                QString dxatt =  e.attribute( "dx" , "0" );
 
730
                if ( dxatt.contains(',') || dxatt.contains(' ') )
 
731
                {
 
732
                        dxatt.replace(QChar(','), QChar(' '));
 
733
                        QStringList xl(dxatt.split(QChar(' '), QString::SkipEmptyParts));
 
734
                        dxatt = xl.first();
 
735
                }
 
736
                x += parseUnit( dxatt ); 
 
737
        }
 
738
 
 
739
        if (e.hasAttribute( "dy" ))
 
740
        {
 
741
                QString dyatt =  e.attribute( "dy" , "0" );
 
742
                if ( dyatt.contains(',') || dyatt.contains(' ') )
 
743
                {
 
744
                        dyatt.replace(QChar(','), QChar(' '));
 
745
                        QStringList xl(dyatt.split(QChar(' '), QString::SkipEmptyParts));
 
746
                        dyatt = xl.first();
 
747
                }
 
748
                y += parseUnit( dyatt ); 
 
749
        }
 
750
 
 
751
        return FPoint(x, y);
 
752
}
 
753
 
 
754
QSize SVGPlug::parseWidthHeight(const QDomElement &e)
 
755
{
 
756
        QSize size(550, 841);
 
757
        QString sw = e.attribute("width", "100%");
 
758
        QString sh = e.attribute("height", "100%");
 
759
        double w =  550, h = 841;
 
760
        if (!sw.isEmpty())
 
761
                w = sw.endsWith("%") ? fromPercentage(sw) : parseUnit(sw);
 
762
        if (!sh.isEmpty())
 
763
                h = sh.endsWith("%") ? fromPercentage(sh) : parseUnit(sh);
 
764
        if (!e.attribute("viewBox").isEmpty())
 
765
        {
 
766
                QRect viewBox = parseViewBox(e);
 
767
                double scw = (viewBox.width() > 0 && viewBox.height() > 0) ? viewBox.width()  : size.width();
 
768
                double sch = (viewBox.width() > 0 && viewBox.height() > 0) ? viewBox.height() : size.height();
 
769
                w *= (sw.endsWith("%") ? scw : 1.0);
 
770
                h *= (sh.endsWith("%") ? sch : 1.0);
 
771
        }
 
772
        else
 
773
        {
 
774
                w *= (sw.endsWith("%") ? size.width() : 1.0);
 
775
                h *= (sh.endsWith("%") ? size.height() : 1.0);
 
776
        }
 
777
        // OpenOffice files may not have width and height attributes, so avoid unnecessary large dimensions
 
778
        if (w > 10000 || h > 10000)
 
779
        {
 
780
                double m = max(w, h);
 
781
                w = w / m * 842;
 
782
                h = h / m * 842;
 
783
        }
 
784
        size.setWidth(qRound(w));
 
785
        size.setHeight(qRound(h));
 
786
        return size;
 
787
}
 
788
 
 
789
QRect SVGPlug::parseViewBox(const QDomElement &e)
 
790
{
 
791
        QRect box(0, 0, 0, 0);
 
792
        if ( !e.attribute( "viewBox" ).isEmpty() )
 
793
        {
 
794
                QString viewbox( e.attribute( "viewBox" ) );
 
795
                QStringList points = viewbox.replace( QRegExp(","), " ").simplified().split( ' ', QString::SkipEmptyParts );
 
796
                if (points.size() > 3)
 
797
                {
 
798
                        double left   = ScCLocale::toDoubleC(points[0]);
 
799
                        double bottom = ScCLocale::toDoubleC(points[1]);
 
800
                        double width  = ScCLocale::toDoubleC(points[2]);
 
801
                        double height = ScCLocale::toDoubleC(points[3]);
 
802
                        box.setCoords((int) left, (int) bottom, (int) (left + width), (int) (bottom + height));
 
803
                }
 
804
        }
 
805
        return box;
 
806
}
 
807
 
 
808
void SVGPlug::parseDefs(const QDomElement &e)
 
809
{
 
810
        for ( QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling() )
 
811
        {
 
812
                QDomElement b = n.toElement();
 
813
                if ( b.isNull() )
 
814
                        continue;
 
815
                SvgStyle svgStyle;
 
816
                parseStyle( &svgStyle, b );
 
817
                if ( !svgStyle.Display) 
 
818
                        continue;
 
819
                QString STag2 = b.tagName();
 
820
                if ( STag2 == "g" )
 
821
                {
 
822
                        QString id = b.attribute("id", "");
 
823
                        if (!id.isEmpty())
 
824
                                m_nodeMap.insert(id, b);
 
825
                        parseDefs(b);
 
826
                }
 
827
                else if ( STag2 == "linearGradient" || STag2 == "radialGradient" )
 
828
                        parseGradient( b );
 
829
                else if (STag2 == "clipPath")
 
830
                        parseClipPath(b);
 
831
                else if (STag2 == "pattern")
 
832
                        parsePattern(b);
 
833
                else if ( b.hasAttribute("id") )
 
834
                {
 
835
                        QString id = b.attribute("id");
 
836
                        if (!id.isEmpty())
 
837
                                m_nodeMap.insert(id, b);
 
838
                }
 
839
        }
 
840
}
 
841
 
 
842
void SVGPlug::parseClipPath(const QDomElement &e)
 
843
{
 
844
        QString id(e.attribute("id"));
 
845
        if (!id.isEmpty())
 
846
        {
 
847
                FPointArray clip;
 
848
                QDomNode n2 = e.firstChild();
 
849
                QDomElement b2 = n2.toElement();
 
850
                while (b2.nodeName() == "use")
 
851
                        b2 = getReferencedNode(b2);
 
852
                if (b2.nodeName() == "path")
 
853
                        parseSVG( b2.attribute( "d" ), &clip );
 
854
                else if (b2.nodeName() == "rect")
 
855
                {
 
856
                        double x = parseUnit( b2.attribute( "x", "0.0" ));
 
857
                        double y = parseUnit( b2.attribute( "y", "0.0" ));
 
858
                        double width  = parseUnit( b2.attribute( "width" ));
 
859
                        double height = parseUnit( b2.attribute( "height" ) );
 
860
                        clip.addQuadPoint(x, y, x, y, width+x, y, width+x, y);
 
861
                        clip.addQuadPoint(width+x, y, width+x, y, width+x, height+y, width+x, height+y);
 
862
                        clip.addQuadPoint(width+x, height+y, width+x, height+y, x, height+y, x, height+y);
 
863
                        clip.addQuadPoint(x, height+y, x, height+y, x, y, x, y);
 
864
                }
 
865
                if (clip.size() >= 2)
 
866
                        m_clipPaths.insert(id, clip);
 
867
        }
 
868
}
 
869
 
 
870
void SVGPlug::parseClipPathAttr(const QDomElement &e, FPointArray& clipPath)
 
871
{
 
872
        clipPath.resize(0);
 
873
/*      if (e.hasAttribute("style"))
 
874
        {
 
875
                QString style = e.attribute( "style" ).simplified();
 
876
                QStringList substyles = style.split(';', QString::SkipEmptyParts);
 
877
                for( QStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it )
 
878
                {
 
879
                        QStringList substyle = (*it).split(':', QString::SkipEmptyParts);
 
880
                        QString command(substyle[0].trimmed());
 
881
                        QString params(substyle[1].trimmed());
 
882
                        if (command == "clip-path")
 
883
                        {
 
884
                                if (params.startsWith( "url("))
 
885
                                {
 
886
                                        unsigned int start = params.indexOf("#") + 1;
 
887
                                        unsigned int end = params.lastIndexOf(")");
 
888
                                        QString key = params.mid(start, end - start);
 
889
                                        QMap<QString, FPointArray>::iterator it = m_clipPaths.find(key);
 
890
                                        if (it != m_clipPaths.end())
 
891
                                                clipPath = it.value().copy();
 
892
                                }
 
893
                        }
 
894
                }
 
895
        } */
 
896
        if (e.hasAttribute("clip-path"))
 
897
        {
 
898
                QString attr = e.attribute("clip-path");
 
899
                if (attr.startsWith( "url("))
 
900
                {
 
901
                        unsigned int start = attr.indexOf("#") + 1;
 
902
                        unsigned int end = attr.lastIndexOf(")");
 
903
                        QString key = attr.mid(start, end - start);
 
904
                        QMap<QString, FPointArray>::iterator it = m_clipPaths.find(key);
 
905
                        if (it != m_clipPaths.end())
 
906
                                clipPath = it.value().copy();
 
907
                }
 
908
        }
 
909
}
 
910
 
 
911
QList<PageItem*> SVGPlug::parseA(const QDomElement &e)
 
912
{
 
913
        QList<PageItem*> aElements;
 
914
        for ( QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling() )
 
915
        {
 
916
                QDomElement b = n.toElement();
 
917
                if( b.isNull() || isIgnorableNode(b) )
 
918
                        continue;
 
919
                SvgStyle svgStyle;
 
920
                parseStyle( &svgStyle, b);
 
921
                if (!svgStyle.Display) 
 
922
                        continue;
 
923
                QList<PageItem*> el = parseElement(b);
 
924
                for (int ec = 0; ec < el.count(); ++ec)
 
925
                        aElements.append(el.at(ec));
 
926
        }
 
927
        return aElements;
 
928
}
 
929
 
 
930
QList<PageItem*> SVGPlug::parseGroup(const QDomElement &e)
 
931
{
 
932
        FPointArray clipPath;
 
933
        QList<PageItem*> GElements, gElements;
 
934
        double BaseX = m_Doc->currentPage()->xOffset();
 
935
        double BaseY = m_Doc->currentPage()->yOffset();
 
936
        groupLevel++;
 
937
        setupNode(e);
 
938
        parseClipPathAttr(e, clipPath);
 
939
        int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, BaseX, BaseY, 1, 1, 0, CommonStrings::None, CommonStrings::None, true);
 
940
        PageItem *neu = m_Doc->Items->at(z);
 
941
        for ( QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling() )
 
942
        {
 
943
                QDomElement b = n.toElement();
 
944
                if( b.isNull() || isIgnorableNode(b) )
 
945
                        continue;
 
946
                SvgStyle svgStyle;
 
947
                parseStyle( &svgStyle, b);
 
948
                if (!svgStyle.Display) 
 
949
                        continue;
 
950
                QList<PageItem*> el = parseElement(b);
 
951
                for (int ec = 0; ec < el.count(); ++ec)
 
952
                        gElements.append(el.at(ec));
 
953
        }
 
954
        groupLevel--;
 
955
        SvgStyle *gc = m_gc.top();
 
956
        if (clipPath.size() == 0)
 
957
        {
 
958
                if (gc->clipPath.size() != 0)
 
959
                        clipPath = gc->clipPath.copy();
 
960
        }
 
961
        if (gElements.count() == 0 || (gElements.count() < 2 && (clipPath.size() == 0) && (gc->Opacity == 1.0)))
 
962
        {
 
963
                // Unfortunately we have to take the long route here, or we risk crash on undo/redo
 
964
                // FIXME : create group object after parsing grouped objects
 
965
                /*m_Doc->Items->takeAt(z);
 
966
                delete neu;*/
 
967
                Selection tmpSelection(m_Doc, false);
 
968
                tmpSelection.addItem(neu);
 
969
                m_Doc->itemSelection_DeleteItem(&tmpSelection);
 
970
                for (int a = 0; a < m_Doc->Items->count(); ++a)
 
971
                {
 
972
                        m_Doc->Items->at(a)->ItemNr = a;
 
973
                }
 
974
                for (int gr = 0; gr < gElements.count(); ++gr)
 
975
                {
 
976
                        GElements.append(gElements.at(gr));
 
977
                }
 
978
        }
 
979
        else
 
980
        {
 
981
                double minx = 99999.9;
 
982
                double miny = 99999.9;
 
983
                double maxx = -99999.9;
 
984
                double maxy = -99999.9;
 
985
                GElements.append(neu);
 
986
                for (int gr = 0; gr < gElements.count(); ++gr)
 
987
                {
 
988
                        PageItem* currItem = gElements.at(gr);
 
989
                        double x1, x2, y1, y2;
 
990
                        currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
 
991
                        minx = qMin(minx, x1);
 
992
                        miny = qMin(miny, y1);
 
993
                        maxx = qMax(maxx, x2);
 
994
                        maxy = qMax(maxy, y2);
 
995
                }
 
996
                double gx = minx;
 
997
                double gy = miny;
 
998
                double gw = maxx - minx;
 
999
                double gh = maxy - miny;
 
1000
                neu->setXYPos(gx, gy);
 
1001
                neu->setWidthHeight(gw, gh);
 
1002
                if (clipPath.size() != 0)
 
1003
                {
 
1004
                        QMatrix mm = gc->matrix;
 
1005
                        neu->PoLine = clipPath.copy();
 
1006
                        neu->PoLine.map(mm);
 
1007
                        neu->PoLine.translate(-gx + BaseX, -gy + BaseY);
 
1008
                        clipPath.resize(0);
 
1009
 
 
1010
                }
 
1011
                else
 
1012
                        neu->SetRectFrame();
 
1013
                neu->Clip = FlattenPath(neu->PoLine, neu->Segments);
 
1014
                neu->Groups.push(m_Doc->GroupCounter);
 
1015
                neu->isGroupControl = true;
 
1016
                neu->groupsLastItem = gElements.at(gElements.count()-1);
 
1017
                if( !e.attribute("id").isEmpty() )
 
1018
                        neu->setItemName(e.attribute("id"));
 
1019
                else
 
1020
                        neu->setItemName( tr("Group%1").arg(neu->Groups.top()));
 
1021
                neu->AutoName = false;
 
1022
                neu->setFillTransparency(1 - gc->Opacity);
 
1023
                neu->gXpos = neu->xPos() - gx;
 
1024
                neu->gYpos = neu->yPos() - gy;
 
1025
                neu->gWidth = gw;
 
1026
                neu->gHeight = gh;
 
1027
                for (int gr = 0; gr < gElements.count(); ++gr)
 
1028
                {
 
1029
                        gElements.at(gr)->Groups.push(m_Doc->GroupCounter);
 
1030
                        gElements.at(gr)->gXpos = gElements.at(gr)->xPos() - gx;
 
1031
                        gElements.at(gr)->gYpos = gElements.at(gr)->yPos() - gy;
 
1032
                        gElements.at(gr)->gWidth = gw;
 
1033
                        gElements.at(gr)->gHeight = gh;
 
1034
                        GElements.append(gElements.at(gr));
 
1035
                }
 
1036
                neu->setRedrawBounding();
 
1037
                neu->setTextFlowMode(PageItem::TextFlowDisabled);
 
1038
                m_Doc->GroupCounter++;
 
1039
        }
 
1040
        delete( m_gc.pop() );
 
1041
        return GElements;
 
1042
}
 
1043
 
 
1044
QList<PageItem*> SVGPlug::parseElement(const QDomElement &e)
 
1045
{
 
1046
        QList<PageItem*> GElements;
 
1047
        if (e.hasAttribute("id"))
 
1048
                m_nodeMap.insert(e.attribute("id"), e);
 
1049
        QString STag = e.tagName();
 
1050
        if ( STag == "g" )
 
1051
        {
 
1052
                GElements = parseGroup( e );
 
1053
                return GElements;
 
1054
        }
 
1055
        if ( STag == "defs" )
 
1056
                parseDefs(e);
 
1057
        else if ( STag == "a" )
 
1058
                GElements = parseA(e);
 
1059
        else if ( STag == "switch" )
 
1060
                GElements = parseSwitch(e);
 
1061
        else if ( STag == "symbol" )
 
1062
                GElements = parseSymbol(e);
 
1063
        else if ( STag == "use" )
 
1064
                GElements = parseUse(e);
 
1065
        else if ( STag == "linearGradient" || STag == "radialGradient" )
 
1066
                parseGradient( e );
 
1067
        else if ( STag == "rect" )
 
1068
                GElements = parseRect(e);
 
1069
        else if ( STag == "ellipse" )
 
1070
                GElements = parseEllipse(e);
 
1071
        else if ( STag == "circle" )
 
1072
                GElements = parseCircle(e);
 
1073
        else if ( STag == "line" )
 
1074
                GElements = parseLine(e);
 
1075
        else if ( STag == "path" )
 
1076
                GElements = parsePath(e);
 
1077
        else if ( STag == "polyline" || e.tagName() == "polygon" )
 
1078
                GElements = parsePolyline(e);
 
1079
        else if ( STag == "text" )
 
1080
                GElements = parseText(e);
 
1081
        else if ( STag == "clipPath" )
 
1082
                parseClipPath(e);
 
1083
        else if ( STag == "desc" )
 
1084
        {
 
1085
                if (groupLevel == 1)
 
1086
                        docDesc = e.text();
 
1087
        }
 
1088
        else if ( STag == "title" )
 
1089
        {
 
1090
                if (groupLevel == 1)
 
1091
                        docTitle = e.text();
 
1092
        }
 
1093
        else if ( STag == "image" )
 
1094
                GElements = parseImage(e);
 
1095
/*      else if ( STag == "i:pgf" )
 
1096
        {
 
1097
                QByteArray cdat;
 
1098
                QByteArray ddat;
 
1099
                cdat = e.text().simplified();
 
1100
                QList<QByteArray> cdlist = cdat.split(' ');
 
1101
                for (int cd = 0; cd < cdlist.count(); cd++)
 
1102
                {
 
1103
                        ddat += QByteArray::fromBase64(cdlist[cd]);
 
1104
                }
 
1105
                QFile outf("/home/franz/testdata.txt");
 
1106
                outf.open(QIODevice::WriteOnly);
 
1107
                outf.write(ddat);
 
1108
                outf.close();
 
1109
                QString f2 = "/home/franz/testdata_decom.ai";
 
1110
                FILE *source = fopen("/home/franz/testdata.txt", "rb");
 
1111
                FILE *dest = fopen(f2, "wb");
 
1112
                int ret;
 
1113
                unsigned have;
 
1114
                z_stream strm;
 
1115
                char in[4096];
 
1116
                char out[4096];
 
1117
                strm.zalloc = Z_NULL;
 
1118
                strm.zfree = Z_NULL;
 
1119
                strm.opaque = Z_NULL;
 
1120
                strm.avail_in = 0;
 
1121
                strm.next_in = Z_NULL;
 
1122
                ret = inflateInit(&strm);
 
1123
                if (ret != Z_OK)
 
1124
                        return GElements;
 
1125
                do
 
1126
                {
 
1127
                        strm.avail_in = fread(in, 1, 4096, source);
 
1128
                        if (ferror(source))
 
1129
                        {
 
1130
                                (void)inflateEnd(&strm);
 
1131
                                return GElements;
 
1132
                        }
 
1133
                        if (strm.avail_in == 0)
 
1134
                                break;
 
1135
                        strm.next_in = (Bytef*)in;
 
1136
                        do
 
1137
                        {
 
1138
                                strm.avail_out = 4096;
 
1139
                                strm.next_out = (Bytef*)out;
 
1140
                                ret = inflate(&strm, Z_NO_FLUSH);
 
1141
                                assert(ret != Z_STREAM_ERROR);
 
1142
                                switch (ret)
 
1143
                                {
 
1144
                                        case Z_NEED_DICT:
 
1145
                                                ret = Z_DATA_ERROR;
 
1146
                                        case Z_DATA_ERROR:
 
1147
                                        case Z_MEM_ERROR:
 
1148
                                                (void)inflateEnd(&strm);
 
1149
                                                return GElements;
 
1150
                                }
 
1151
                                have = 4096 - strm.avail_out;
 
1152
                                if (fwrite(out, 1, have, dest) != have || ferror(dest))
 
1153
                                {
 
1154
                                        (void)inflateEnd(&strm);
 
1155
                                        return GElements;
 
1156
                                }
 
1157
                        }
 
1158
                        while (strm.avail_out == 0);
 
1159
                }
 
1160
                while (ret != Z_STREAM_END);
 
1161
                (void)inflateEnd(&strm);
 
1162
                fclose(source);
 
1163
                fclose(dest);
 
1164
        } */
 
1165
/*      else if( STag == "image" )
 
1166
                GElements = parseImage(e);
 
1167
        } */
 
1168
        else if (!isIgnorableNodeName(STag) )
 
1169
        {
 
1170
                // warn if unsupported SVG feature are encountered
 
1171
                if (!m_unsupportedFeatures.contains(STag))
 
1172
                {
 
1173
                        m_unsupportedFeatures.insert(STag, STag);
 
1174
                        qDebug() << QString("unsupported SVG feature: %1").arg(STag);
 
1175
                        unsupported = true;
 
1176
                }
 
1177
        }
 
1178
        return GElements;
 
1179
}
 
1180
 
 
1181
QList<PageItem*> SVGPlug::parseCircle(const QDomElement &e)
 
1182
{
 
1183
        QList<PageItem*> CElements;
 
1184
        double BaseX = m_Doc->currentPage()->xOffset();
 
1185
        double BaseY = m_Doc->currentPage()->yOffset();
 
1186
        double r = parseUnit( e.attribute( "r" ) );
 
1187
        double x = parseUnit( e.attribute( "cx" ) ) - r;
 
1188
        double y = parseUnit( e.attribute( "cy" ) ) - r;
 
1189
        setupNode(e);
 
1190
        SvgStyle *gc = m_gc.top();
 
1191
        int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Ellipse, BaseX, BaseY, r * 2.0, r * 2.0, gc->LWidth, gc->FillCol, gc->StrokeCol, true);
 
1192
        PageItem* ite = m_Doc->Items->at(z);
 
1193
        QMatrix mm = QMatrix();
 
1194
        mm.translate(x, y);
 
1195
        ite->PoLine.map(mm);
 
1196
        FPoint wh = getMaxClipF(&ite->PoLine);
 
1197
        ite->setWidthHeight(wh.x(), wh.y());
 
1198
        finishNode(e, ite);
 
1199
        CElements.append(ite);
 
1200
        delete( m_gc.pop() );
 
1201
        return CElements;
 
1202
}
 
1203
 
 
1204
QList<PageItem*> SVGPlug::parseEllipse(const QDomElement &e)
 
1205
{
 
1206
        QList<PageItem*> EElements;
 
1207
        double BaseX = m_Doc->currentPage()->xOffset();
 
1208
        double BaseY = m_Doc->currentPage()->yOffset();
 
1209
        double rx = parseUnit( e.attribute( "rx" ) );
 
1210
        double ry = parseUnit( e.attribute( "ry" ) );
 
1211
        double x = parseUnit( e.attribute( "cx" ) ) - rx;
 
1212
        double y = parseUnit( e.attribute( "cy" ) ) - ry;
 
1213
        setupNode(e);
 
1214
        SvgStyle *gc = m_gc.top();
 
1215
        int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Ellipse, BaseX, BaseY, rx * 2.0, ry * 2.0, gc->LWidth, gc->FillCol, gc->StrokeCol, true);
 
1216
        PageItem* ite = m_Doc->Items->at(z);
 
1217
        QMatrix mm = QMatrix();
 
1218
        mm.translate(x, y);
 
1219
        ite->PoLine.map(mm);
 
1220
        FPoint wh = getMaxClipF(&ite->PoLine);
 
1221
        ite->setWidthHeight(wh.x(), wh.y());
 
1222
        finishNode(e, ite);
 
1223
        EElements.append(ite);
 
1224
        delete( m_gc.pop() );
 
1225
        return EElements;
 
1226
}
 
1227
 
 
1228
QList<PageItem*> SVGPlug::parseImage(const QDomElement &e)
 
1229
{
 
1230
        FPointArray clipPath;
 
1231
        QList<PageItem*> IElements;
 
1232
        QString fname = e.attribute("xlink:href");
 
1233
        double BaseX = m_Doc->currentPage()->xOffset();
 
1234
        double BaseY = m_Doc->currentPage()->yOffset();
 
1235
        double x = e.attribute( "x" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "x" ) );
 
1236
        double y = e.attribute( "y" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "y" ) );
 
1237
        double w = e.attribute( "width" ).isEmpty() ? 1.0 : parseUnit( e.attribute( "width" ) );
 
1238
        double h = e.attribute( "height" ).isEmpty() ? 1.0 : parseUnit( e.attribute( "height" ) );
 
1239
        setupNode(e);
 
1240
        parseClipPathAttr(e, clipPath);
 
1241
        int z = m_Doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, x+BaseX, y+BaseY, w, h, 1, m_Doc->toolSettings.dBrushPict, CommonStrings::None, true);
 
1242
        PageItem* ite = m_Doc->Items->at(z);
 
1243
        if (!fname.isEmpty())
 
1244
        {
 
1245
                if (!fname.startsWith("data:"))
 
1246
                        m_Doc->LoadPict(fname, z);
 
1247
                else
 
1248
                {
 
1249
                        int startData = fname.indexOf(",");
 
1250
                        QString dataType = fname.left(startData);
 
1251
                        fname.remove(0, startData+1);
 
1252
                        QByteArray ba;
 
1253
                        ba.append(fname);
 
1254
                        if (dataType.contains("base64"))
 
1255
                                ba = QByteArray::fromBase64(ba);
 
1256
                        ite->tempImageFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_svg_XXXXXX.png");
 
1257
                        ite->tempImageFile->open();
 
1258
                        QString fileName = getLongPathName(ite->tempImageFile->fileName());
 
1259
                        ite->tempImageFile->close();
 
1260
                        ite->isInlineImage = true;
 
1261
                        QImage img;
 
1262
                        img.loadFromData(ba);
 
1263
                        img.save(fileName, "PNG");
 
1264
                        m_Doc->LoadPict(fileName, z);
 
1265
                }
 
1266
        }
 
1267
        if (clipPath.size() != 0)
 
1268
                ite->PoLine = clipPath.copy();
 
1269
        clipPath.resize(0);
 
1270
        ite->Clip = FlattenPath(ite->PoLine, ite->Segments);
 
1271
        finishNode(e, ite);
 
1272
        IElements.append(ite);
 
1273
        delete( m_gc.pop() );
 
1274
        return IElements;
 
1275
}
 
1276
 
 
1277
QList<PageItem*> SVGPlug::parseLine(const QDomElement &e)
 
1278
{
 
1279
        QList<PageItem*> LElements;
 
1280
        double BaseX = m_Doc->currentPage()->xOffset();
 
1281
        double BaseY = m_Doc->currentPage()->yOffset();
 
1282
        double x1 = e.attribute( "x1" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "x1" ) );
 
1283
        double y1 = e.attribute( "y1" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "y1" ) );
 
1284
        double x2 = e.attribute( "x2" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "x2" ) );
 
1285
        double y2 = e.attribute( "y2" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "y2" ) );
 
1286
        setupNode(e);
 
1287
        SvgStyle *gc = m_gc.top();
 
1288
        int z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol, true);
 
1289
        PageItem* ite = m_Doc->Items->at(z);
 
1290
        ite->PoLine.resize(4);
 
1291
        ite->PoLine.setPoint(0, FPoint(x1, y1));
 
1292
        ite->PoLine.setPoint(1, FPoint(x1, y1));
 
1293
        ite->PoLine.setPoint(2, FPoint(x2, y2));
 
1294
        ite->PoLine.setPoint(3, FPoint(x2, y2));
 
1295
        finishNode(e, ite);
 
1296
        LElements.append(ite);
 
1297
        delete( m_gc.pop() );
 
1298
        return LElements;
 
1299
}
 
1300
 
 
1301
QList<PageItem*> SVGPlug::parsePath(const QDomElement &e)
 
1302
{
 
1303
        FPointArray pArray;
 
1304
        QList<PageItem*> PElements;
 
1305
        double BaseX = m_Doc->currentPage()->xOffset();
 
1306
        double BaseY = m_Doc->currentPage()->yOffset();
 
1307
        setupNode(e);
 
1308
        SvgStyle *gc = m_gc.top();
 
1309
        PageItem::ItemType itype = parseSVG(e.attribute("d"), &pArray) ? PageItem::PolyLine : PageItem::Polygon; 
 
1310
        int z = m_Doc->itemAdd(itype, PageItem::Unspecified, BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol, true);
 
1311
        PageItem* ite = m_Doc->Items->at(z);
 
1312
        ite->fillRule = (gc->fillRule != "nonzero");
 
1313
        ite->PoLine = pArray;
 
1314
        if (ite->PoLine.size() < 4)
 
1315
        {
 
1316
//                      m_Doc->m_Selection->addItem(ite);
 
1317
                tmpSel->addItem(ite);
 
1318
//                      m_Doc->itemSelection_DeleteItem();
 
1319
                m_Doc->itemSelection_DeleteItem(tmpSel);
 
1320
//                      m_Doc->m_Selection->clear();
 
1321
        }
 
1322
        else
 
1323
        {
 
1324
                finishNode(e, ite);
 
1325
                PElements.append(ite);
 
1326
        }
 
1327
        delete( m_gc.pop() );
 
1328
        return PElements;
 
1329
}
 
1330
 
 
1331
QList<PageItem*> SVGPlug::parsePolyline(const QDomElement &e)
 
1332
{
 
1333
        int z;
 
1334
        QList<PageItem*> PElements;
 
1335
        double BaseX = m_Doc->currentPage()->xOffset();
 
1336
        double BaseY = m_Doc->currentPage()->yOffset();
 
1337
        setupNode(e);
 
1338
        SvgStyle *gc = m_gc.top();
 
1339
        QString points = e.attribute( "points" );
 
1340
        if (!points.isEmpty())
 
1341
        {
 
1342
                QString STag = e.tagName();
 
1343
                points = points.simplified().replace(',', " ");
 
1344
                QStringList pointList = points.split( ' ', QString::SkipEmptyParts );
 
1345
                if (( e.tagName() == "polygon" ) && (pointList.count() > 4))
 
1346
                        z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol, true);
 
1347
                else
 
1348
                        z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol, true);
 
1349
                PageItem* ite = m_Doc->Items->at(z);
 
1350
                ite->fillRule = (gc->fillRule != "nonzero"); 
 
1351
                ite->PoLine.resize(0);
 
1352
                ite->PoLine.svgInit();
 
1353
                bool bFirst = true;
 
1354
                double x = 0.0;
 
1355
                double y = 0.0;
 
1356
                for( QStringList::Iterator it = pointList.begin(); it != pointList.end(); it++ )
 
1357
                {
 
1358
                        if( bFirst )
 
1359
                        {
 
1360
                                x = ScCLocale::toDoubleC(*(it++));
 
1361
                                y = ScCLocale::toDoubleC(*it);
 
1362
                                ite->PoLine.svgMoveTo(x, y);
 
1363
                                bFirst = false;
 
1364
                        }
 
1365
                        else
 
1366
                        {
 
1367
                                x = ScCLocale::toDoubleC(*(it++));
 
1368
                                y = ScCLocale::toDoubleC(*it);
 
1369
                                ite->PoLine.svgLineTo(x, y);
 
1370
                        }
 
1371
                }
 
1372
                if (( STag == "polygon" ) && (pointList.count() > 4))
 
1373
                        ite->PoLine.svgClosePath();
 
1374
                else
 
1375
                        ite->convertTo(PageItem::PolyLine);
 
1376
                finishNode(e, ite);
 
1377
                PElements.append(ite);
 
1378
        }
 
1379
        delete( m_gc.pop() );
 
1380
        return PElements;
 
1381
}
 
1382
 
 
1383
QList<PageItem*> SVGPlug::parseRect(const QDomElement &e)
 
1384
{
 
1385
        QList<PageItem*> RElements;
 
1386
        double BaseX = m_Doc->currentPage()->xOffset();
 
1387
        double BaseY = m_Doc->currentPage()->yOffset();
 
1388
        double x = parseUnit( e.attribute( "x" ) );
 
1389
        double y = parseUnit( e.attribute( "y" ) );
 
1390
        double width = parseUnit( e.attribute( "width" ));
 
1391
        double height = parseUnit( e.attribute( "height" ) );
 
1392
        double rx = e.attribute( "rx" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "rx" ) );
 
1393
        double ry = e.attribute( "ry" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "ry" ) );
 
1394
        setupNode(e);
 
1395
        SvgStyle *gc = m_gc.top();
 
1396
        int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, BaseX, BaseY, width, height, gc->LWidth, gc->FillCol, gc->StrokeCol, true);
 
1397
        PageItem* ite = m_Doc->Items->at(z);
 
1398
        if ((rx != 0) || (ry != 0))
 
1399
        {
 
1400
                ite->setCornerRadius(qMax(rx, ry));
 
1401
                ite->SetFrameRound();
 
1402
                m_Doc->setRedrawBounding(ite);
 
1403
        }
 
1404
        QMatrix mm = QMatrix();
 
1405
        mm.translate(x, y);
 
1406
        ite->PoLine.map(mm);
 
1407
        FPoint wh = getMaxClipF(&ite->PoLine);
 
1408
        ite->setWidthHeight(wh.x(), wh.y());
 
1409
        finishNode(e, ite);
 
1410
        RElements.append(ite);
 
1411
        delete( m_gc.pop() );
 
1412
        return RElements;
 
1413
}
 
1414
 
 
1415
QList<PageItem*> SVGPlug::parseText(const QDomElement &e)
 
1416
{
 
1417
        QList<PageItem*> GElements;
 
1418
        setupNode(e);
 
1419
        double chunkWidth = 0;
 
1420
        FPoint currentPos = parseTextPosition(e);
 
1421
        SvgStyle *gc      = m_gc.top();
 
1422
        if (gc->textAnchor != "start")
 
1423
                getTextChunkWidth(e, chunkWidth);
 
1424
        for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling())
 
1425
        {
 
1426
                if (n.isElement() && (n.toElement().tagName() == "tspan"))
 
1427
                {
 
1428
                        QList<PageItem*> el = parseTextSpan(n.toElement(), currentPos, chunkWidth);
 
1429
                        for (int ec = 0; ec < el.count(); ++ec)
 
1430
                                GElements.append(el.at(ec));
 
1431
                }
 
1432
                if (n.isText())
 
1433
                {
 
1434
                        QList<PageItem*> el = parseTextNode(n.toText(), currentPos, chunkWidth);
 
1435
                        for (int ec = 0; ec < el.count(); ++ec)
 
1436
                                GElements.append(el.at(ec));
 
1437
                }
 
1438
        }
 
1439
        delete( m_gc.pop() );
 
1440
        return GElements;
 
1441
}
 
1442
 
 
1443
QList<PageItem*> SVGPlug::parseTextSpan(const QDomElement& e, FPoint& currentPos, double chunkW)
 
1444
{
 
1445
        QList<PageItem*> GElements;
 
1446
        setupNode(e);
 
1447
        currentPos   = parseTextPosition(e, &currentPos);
 
1448
        SvgStyle *gc = m_gc.top();
 
1449
        if ((e.hasAttribute("x") || e.hasAttribute("y")) && (gc->textAnchor != "start"))
 
1450
        {
 
1451
                chunkW = 0;
 
1452
                getTextChunkWidth(e, chunkW);
 
1453
        }
 
1454
        for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling())
 
1455
        {
 
1456
                if (n.isElement() && (n.toElement().tagName() == "tspan"))
 
1457
                {
 
1458
                        QList<PageItem*> el = parseTextSpan(n.toElement(), currentPos, chunkW);
 
1459
                        for (int ec = 0; ec < el.count(); ++ec)
 
1460
                                GElements.append(el.at(ec));
 
1461
                }
 
1462
                if (n.isText())
 
1463
                {
 
1464
                        QList<PageItem*> el = parseTextNode(n.toText(), currentPos, chunkW);
 
1465
                        for (int ec = 0; ec < el.count(); ++ec)
 
1466
                                GElements.append(el.at(ec));
 
1467
                }
 
1468
        }
 
1469
        delete( m_gc.pop() );
 
1470
        return GElements;
 
1471
}
 
1472
 
 
1473
QList<PageItem*> SVGPlug::parseTextNode(const QDomText& e, FPoint& currentPos, double chunkW)
 
1474
{
 
1475
        QList<PageItem*> GElements;
 
1476
        double BaseX  = m_Doc->currentPage()->xOffset();
 
1477
        double BaseY  = m_Doc->currentPage()->yOffset();
 
1478
        double StartX = currentPos.x(), StartY = currentPos.y();
 
1479
        
 
1480
        QString textString = e.data().simplified();
 
1481
        if ( textString.isEmpty() )
 
1482
                return GElements;
 
1483
        
 
1484
        SvgStyle *gc   = m_gc.top();
 
1485
        QFont textFont = getFontFromStyle(*gc);
 
1486
        QFontMetrics fm(textFont);
 
1487
    double width   = fm.width(textString);
 
1488
 
 
1489
        if( gc->textAnchor == "middle" )
 
1490
                StartX -= chunkW / 2.0;
 
1491
        else if( gc->textAnchor == "end")
 
1492
                StartX -= chunkW;
 
1493
 
 
1494
        FPointArray textPath;
 
1495
        QString textFillColor   = gc->FillCol;
 
1496
        QString textStrokeColor = gc->StrokeCol;
 
1497
        QPainterPath painterPath;
 
1498
        painterPath.addText( StartX, StartY, textFont, textString );
 
1499
        textPath.fromQPainterPath(painterPath);
 
1500
        if (textPath.size() > 0)
 
1501
        {
 
1502
//              double  lineWidth = 0.0;
 
1503
                int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, BaseX, BaseY, 10, 10, gc->LWidth, textFillColor, textStrokeColor, true);
 
1504
                PageItem* ite = m_Doc->Items->at(z);
 
1505
                ite->PoLine = textPath;
 
1506
                finishNode(e, ite);
 
1507
                GElements.append(ite);
 
1508
        }
 
1509
        currentPos.setX( currentPos.x() + width );
 
1510
        return GElements;
 
1511
}
 
1512
 
 
1513
QList<PageItem*> SVGPlug::parseSwitch(const QDomElement &e)
 
1514
{
 
1515
        QString href;
 
1516
        QStringList hrefs;
 
1517
        QList<PageItem*> SElements;
 
1518
        for (QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling())
 
1519
        {
 
1520
                QDomElement de = n.toElement();
 
1521
                QString STag = de.tagName();
 
1522
                if (STag == "foreignObject")
 
1523
                {
 
1524
                        if (de.hasAttribute("xlink:href"))
 
1525
                        {
 
1526
                                href = de.attribute("xlink:href").mid(1);
 
1527
                                if (!href.isEmpty())
 
1528
                                        hrefs.append(href);
 
1529
                        }
 
1530
                        for (QDomNode n1 = de.firstChild(); !n1.isNull(); n1 = n1.nextSibling())
 
1531
                        {
 
1532
                                QDomElement de1 = n1.toElement();
 
1533
                                if (de1.hasAttribute("xlink:href"))
 
1534
                                {
 
1535
                                        href = de1.attribute("xlink:href").mid(1);
 
1536
                                        if (!href.isEmpty())
 
1537
                                                hrefs.append(href);
 
1538
                                }
 
1539
                        }
 
1540
                }
 
1541
                else 
 
1542
                {
 
1543
                        if (de.hasAttribute("requiredExtensions") || de.hasAttribute("requiredFeatures"))
 
1544
                                continue;
 
1545
                        else if (de.hasAttribute("id") && hrefs.contains(de.attribute("id")))
 
1546
                                continue;
 
1547
                        else
 
1548
                        {
 
1549
                                SElements = parseElement(de);
 
1550
                                if (SElements.count() > 0)
 
1551
                                        break;
 
1552
                        }
 
1553
                }
 
1554
        }
 
1555
        return SElements;
 
1556
}
 
1557
 
 
1558
QList<PageItem*> SVGPlug::parseSymbol(const QDomElement &e)
 
1559
{
 
1560
        QList<PageItem*> SElements;
 
1561
        QString id = e.attribute("id");
 
1562
        if( !id.isEmpty() )
 
1563
                m_nodeMap.insert(id, e);
 
1564
        return SElements;
 
1565
}
 
1566
 
 
1567
QList<PageItem*> SVGPlug::parseUse(const QDomElement &e)
 
1568
{
 
1569
        QList<PageItem*> UElements;
 
1570
        setupNode(e);
 
1571
        if( e.hasAttribute("x") || e.hasAttribute("y") )
 
1572
        {
 
1573
                QMatrix matrix;
 
1574
                double  xAtt = ScCLocale::toDoubleC(e.attribute("x", "0.0"));
 
1575
                double  yAtt = ScCLocale::toDoubleC(e.attribute("y", "0.0"));
 
1576
                SvgStyle *gc = m_gc.top();
 
1577
                gc->matrix   = QMatrix(1.0, 0.0, 0.0, 1.0, xAtt, yAtt) * gc->matrix;
 
1578
        }
 
1579
        QString href = e.attribute("xlink:href").mid(1);
 
1580
        QMap<QString, QDomElement>::Iterator it = m_nodeMap.find(href);
 
1581
        if (it != m_nodeMap.end())
 
1582
        {
 
1583
                QDomElement elem = it.value().toElement();
 
1584
                if( elem.tagName() == "symbol" )
 
1585
                        UElements = parseGroup(elem);
 
1586
                else
 
1587
                        UElements = parseElement(elem);
 
1588
        }
 
1589
        delete (m_gc.pop());
 
1590
        return UElements;
 
1591
}
 
1592
 
 
1593
QFont SVGPlug::getFontFromStyle(SvgStyle& style)
 
1594
{
 
1595
        QFont font(QApplication::font());
 
1596
        font.setStyleStrategy( QFont::PreferOutline );
 
1597
 
 
1598
        if (!style.FontFamily.isEmpty())
 
1599
                font.setFamily(style.FontFamily);
 
1600
 
 
1601
        if (!style.FontStyle.isEmpty())
 
1602
        {
 
1603
                if (style.FontStyle == "normal")
 
1604
                        font.setStyle(QFont::StyleNormal);
 
1605
                else if (style.FontStyle == "italic")
 
1606
                        font.setStyle(QFont::StyleItalic);
 
1607
                else if (style.FontStyle == "oblique")
 
1608
                        font.setStyle(QFont::StyleOblique);
 
1609
        }
 
1610
 
 
1611
        if (!style.FontWeight.isEmpty())
 
1612
        {
 
1613
                if (style.FontWeight == "normal")
 
1614
                        font.setWeight(QFont::Normal);
 
1615
                else if (style.FontWeight == "bold")
 
1616
                        font.setWeight(QFont::Bold);
 
1617
                else if (style.FontWeight == "bolder")
 
1618
                        font.setWeight(QFont::DemiBold);
 
1619
                else if (style.FontWeight == "lighter")
 
1620
                        font.setWeight(QFont::Light);
 
1621
                else
 
1622
                {
 
1623
                        bool weightIsNum = false;
 
1624
                        int  fontWeight  = style.FontWeight.toInt(&weightIsNum);
 
1625
                        if (weightIsNum)
 
1626
                        {
 
1627
                                if (fontWeight == 100 || fontWeight == 200)
 
1628
                                        font.setWeight(QFont::Light);
 
1629
                                else if (fontWeight == 300 || fontWeight == 400)
 
1630
                                        font.setWeight(QFont::Normal);
 
1631
                                else if (fontWeight == 500 || fontWeight == 600)
 
1632
                                        font.setWeight(QFont::DemiBold);
 
1633
                                else if (fontWeight == 700 || fontWeight == 800)
 
1634
                                        font.setWeight(QFont::Bold);
 
1635
                                else if (fontWeight == 900)
 
1636
                                        font.setWeight(QFont::Black);
 
1637
                        }
 
1638
                }
 
1639
        }
 
1640
 
 
1641
        if (!style.FontStretch.isEmpty())
 
1642
        {
 
1643
                if (style.FontStretch == "normal")
 
1644
                        font.setStretch(QFont::Unstretched);
 
1645
                else if (style.FontStretch == "ultra-condensed")
 
1646
                        font.setStretch(QFont::UltraCondensed);
 
1647
                else if (style.FontStretch == "extra-condensed")
 
1648
                        font.setStretch(QFont::ExtraCondensed);
 
1649
                else if (style.FontStretch == "condensed")
 
1650
                        font.setStretch(QFont::Condensed);
 
1651
                else if (style.FontStretch == "semi-condensed")
 
1652
                        font.setStretch(QFont::SemiCondensed);
 
1653
                else if (style.FontStretch == "semi-expanded")
 
1654
                        font.setStretch(QFont::SemiExpanded);
 
1655
                else if (style.FontStretch == "expanded")
 
1656
                        font.setStretch(QFont::Expanded);
 
1657
                else if (style.FontStretch == "extra-expanded")
 
1658
                        font.setStretch(QFont::ExtraExpanded);
 
1659
                else if (style.FontStretch == "ultra-expanded")
 
1660
                        font.setStretch(QFont::UltraExpanded);
 
1661
                else if (style.FontStretch == "narrower")
 
1662
                        font.setStretch(QFont::SemiCondensed);
 
1663
                else if (style.FontStretch == "wider")
 
1664
                        font.setStretch(QFont::SemiExpanded);
 
1665
        }
 
1666
        if (!style.textDecoration.isEmpty())
 
1667
        {
 
1668
                bool underline = false, overline  = false;
 
1669
                bool strikeOut = false;
 
1670
                if (style.textDecoration == "underline")
 
1671
                        underline = true;
 
1672
                else if (style.textDecoration == "overline")
 
1673
                        overline = true;
 
1674
                else if (style.textDecoration == "line-through")
 
1675
                        strikeOut = true;
 
1676
                font.setUnderline(underline);
 
1677
                font.setOverline(overline);
 
1678
                font.setStrikeOut(strikeOut);
 
1679
        }
 
1680
        font.setPointSize(style.FontSize / 10);
 
1681
        return font;
 
1682
}
 
1683
 
 
1684
QDomElement SVGPlug::getReferencedNode(const QDomElement &e)
 
1685
{
 
1686
        QDomElement ret;
 
1687
        QMap<QString, QDomElement>::Iterator it;
 
1688
        QString href = e.attribute("xlink:href").mid(1);
 
1689
        it = m_nodeMap.find(href);
 
1690
        if (it != m_nodeMap.end())
 
1691
                ret = it.value().toElement();
 
1692
        return ret;
 
1693
}
 
1694
 
 
1695
bool SVGPlug::getTextChunkWidth(const QDomElement &e, double& width)
 
1696
{
 
1697
        bool doBreak = false;
 
1698
        setupNode(e);
 
1699
        QDomNode c = e.firstChild();
 
1700
        for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling())
 
1701
        {
 
1702
                if (n.isElement() && (n.toElement().tagName() == "tspan"))
 
1703
                {
 
1704
                        QDomElement elem = n.toElement();
 
1705
                        if (elem.hasAttribute("x") || elem.hasAttribute("y"))
 
1706
                        {
 
1707
                                doBreak = true;
 
1708
                                break;
 
1709
                        }
 
1710
                        doBreak = getTextChunkWidth(n.toElement(), width);
 
1711
                        if (doBreak) break;
 
1712
                }
 
1713
                if (n.isText())
 
1714
                {
 
1715
                        QDomText text = n.toText();
 
1716
                        QString  textString = text.data().simplified();
 
1717
                        if (textString.length() > 0)
 
1718
                        {
 
1719
                                SvgStyle *gc   = m_gc.top();
 
1720
                                QFont textFont = getFontFromStyle(*gc);
 
1721
                                QFontMetrics fm(textFont);
 
1722
                                width += fm.width(textString);
 
1723
                        }
 
1724
                }
 
1725
        }
 
1726
        delete (m_gc.pop());
 
1727
        return doBreak;
 
1728
}
 
1729
 
 
1730
double SVGPlug::fromPercentage( const QString &s )
 
1731
{
 
1732
        QString s1 = s;
 
1733
        if (s1.endsWith( ";" ))
 
1734
                s1 = s1.left(s1.length() - 1);
 
1735
        if (s1.endsWith( "%" ))
 
1736
        {
 
1737
                s1 = s1.left(s1.length() - 1);
 
1738
                return ScCLocale::toDoubleC(s1) / 100.0;
 
1739
        }
 
1740
        else
 
1741
                return ScCLocale::toDoubleC(s1);
 
1742
}
 
1743
 
 
1744
double SVGPlug::parseFontSize(const QString& fsize)
 
1745
{
 
1746
        bool noUnit  = true;
 
1747
        QString unit = fsize.right(2);
 
1748
        if (unit == "pt" || unit == "cm" || unit == "mm" || 
 
1749
                unit == "in" || unit == "px")
 
1750
        {
 
1751
                noUnit = false;
 
1752
        }
 
1753
        double value = parseUnit(fsize);
 
1754
        if (noUnit)
 
1755
                value *= 0.8;
 
1756
        return value;
 
1757
}
 
1758
 
 
1759
double SVGPlug::parseUnit(const QString &unit)
 
1760
{
 
1761
        bool noUnit = false;
 
1762
        QString unitval=unit;
 
1763
        if( unit.right( 2 ) == "pt" )
 
1764
                unitval.replace( "pt", "" );
 
1765
        else if( unit.right( 2 ) == "cm" )
 
1766
                unitval.replace( "cm", "" );
 
1767
        else if( unit.right( 2 ) == "mm" )
 
1768
                unitval.replace( "mm" , "" );
 
1769
        else if( unit.right( 2 ) == "in" )
 
1770
                unitval.replace( "in", "" );
 
1771
        else if( unit.right( 2 ) == "px" )
 
1772
                unitval.replace( "px", "" );
 
1773
        if (unitval == unit)
 
1774
                noUnit = true;
 
1775
        double value = ScCLocale::toDoubleC(unitval);
 
1776
        if( unit.right( 2 ) == "pt" )
 
1777
                value = value;
 
1778
        else if( unit.right( 2 ) == "cm" )
 
1779
                value = ( value / 2.54 ) * 72;
 
1780
        else if( unit.right( 2 ) == "mm" )
 
1781
                value = ( value / 25.4 ) * 72;
 
1782
        else if( unit.right( 2 ) == "in" )
 
1783
                value = value * 72;
 
1784
        else if( unit.right( 2 ) == "px" )
 
1785
                value = value * 0.8;
 
1786
        else if(noUnit)
 
1787
                value = value;
 
1788
        return value;
 
1789
}
 
1790
 
 
1791
QMatrix SVGPlug::parseTransform( const QString &transform )
 
1792
{
 
1793
        QMatrix ret;
 
1794
        // Workaround for QString::split() bug when string ends with space
 
1795
        QString trans = transform.simplified();
 
1796
        // Split string for handling 1 transform statement at a time
 
1797
        QStringList subtransforms = trans.split(')', QString::SkipEmptyParts);
 
1798
        QStringList::ConstIterator it = subtransforms.begin();
 
1799
        QStringList::ConstIterator end = subtransforms.end();
 
1800
        for(; it != end; ++it)
 
1801
        {
 
1802
                QMatrix result;
 
1803
                QStringList subtransform = it->split('(', QString::SkipEmptyParts);
 
1804
                subtransform[0] = subtransform[0].trimmed().toLower();
 
1805
                subtransform[1] = subtransform[1].simplified();
 
1806
                QRegExp reg("[,( ]");
 
1807
                QStringList params = subtransform[1].split(reg, QString::SkipEmptyParts);
 
1808
                if(subtransform[0].startsWith(";") || subtransform[0].startsWith(","))
 
1809
                        subtransform[0] = subtransform[0].right(subtransform[0].length() - 1);
 
1810
                if(subtransform[0] == "rotate")
 
1811
                {
 
1812
                        if(params.count() == 3)
 
1813
                        {
 
1814
                                double x = ScCLocale::toDoubleC(params[1]);
 
1815
                                double y = ScCLocale::toDoubleC(params[2]);
 
1816
                                result.translate(x, y);
 
1817
                                result.rotate(ScCLocale::toDoubleC(params[0]));
 
1818
                                result.translate(-x, -y);
 
1819
                        }
 
1820
                        else
 
1821
                                result.rotate(ScCLocale::toDoubleC(params[0]));
 
1822
                }
 
1823
                else if(subtransform[0] == "translate")
 
1824
                {
 
1825
                        if(params.count() == 2)
 
1826
                                result.translate(ScCLocale::toDoubleC(params[0]), ScCLocale::toDoubleC(params[1]));
 
1827
                        else    // Spec : if only one param given, assume 2nd param to be 0
 
1828
                                result.translate(ScCLocale::toDoubleC(params[0]), 0);
 
1829
                }
 
1830
                else if(subtransform[0] == "scale")
 
1831
                {
 
1832
                        if(params.count() == 2)
 
1833
                                result.scale(ScCLocale::toDoubleC(params[0]), ScCLocale::toDoubleC(params[1]));
 
1834
                        else    // Spec : if only one param given, assume uniform scaling
 
1835
                                result.scale(ScCLocale::toDoubleC(params[0]), ScCLocale::toDoubleC(params[0]));
 
1836
                }
 
1837
                else if(subtransform[0] == "skewx")
 
1838
                        result.shear(tan(ScCLocale::toDoubleC(params[0]) * 0.01745329251994329576), 0.0F);
 
1839
                else if(subtransform[0] == "skewy")
 
1840
                        result.shear(0.0F, tan(ScCLocale::toDoubleC(params[0]) * 0.01745329251994329576));
 
1841
                else if(subtransform[0] == "matrix")
 
1842
                {
 
1843
                        if(params.count() >= 6)
 
1844
                        {
 
1845
                                double sx = ScCLocale::toDoubleC(params[0]);
 
1846
                                double sy = ScCLocale::toDoubleC(params[3]);
 
1847
                                double p1 = ScCLocale::toDoubleC(params[1]);
 
1848
                                double p2 = ScCLocale::toDoubleC(params[2]);
 
1849
                                double p4 = ScCLocale::toDoubleC(params[4]);
 
1850
                                double p5 = ScCLocale::toDoubleC(params[5]);
 
1851
                                result.setMatrix(sx, p1, p2, sy, p4, p5);
 
1852
                        }
 
1853
                }
 
1854
                ret = result * ret;
 
1855
        }
 
1856
        return ret;
 
1857
}
 
1858
 
 
1859
const char * SVGPlug::getCoord( const char *ptr, double &number )
 
1860
{
 
1861
        int integer, exponent;
 
1862
        double decimal, frac;
 
1863
        int sign, expsign;
 
1864
 
 
1865
        exponent = 0;
 
1866
        integer = 0;
 
1867
        frac = 1.0;
 
1868
        decimal = 0;
 
1869
        sign = 1;
 
1870
        expsign = 1;
 
1871
 
 
1872
        // read the sign
 
1873
        if(*ptr == '+')
 
1874
                ptr++;
 
1875
        else if(*ptr == '-')
 
1876
        {
 
1877
                ptr++;
 
1878
                sign = -1;
 
1879
        }
 
1880
 
 
1881
        // read the integer part
 
1882
        while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
 
1883
                integer = (integer * 10) + *(ptr++) - '0';
 
1884
        if(*ptr == '.') // read the decimals
 
1885
        {
 
1886
                ptr++;
 
1887
                while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
 
1888
                        decimal += (*(ptr++) - '0') * (frac *= 0.1);
 
1889
        }
 
1890
 
 
1891
        if(*ptr == 'e' || *ptr == 'E') // read the exponent part
 
1892
        {
 
1893
                ptr++;
 
1894
 
 
1895
                // read the sign of the exponent
 
1896
                if(*ptr == '+')
 
1897
                        ptr++;
 
1898
                else if(*ptr == '-')
 
1899
                {
 
1900
                        ptr++;
 
1901
                        expsign = -1;
 
1902
                }
 
1903
 
 
1904
                exponent = 0;
 
1905
                while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
 
1906
                {
 
1907
                        exponent *= 10;
 
1908
                        exponent += *ptr - '0';
 
1909
                        ptr++;
 
1910
                }
 
1911
        }
 
1912
        number = integer + decimal;
 
1913
        number *= sign * pow( static_cast<double>(10), static_cast<double>( expsign * exponent ) );
 
1914
        // skip the following space
 
1915
        if(*ptr == ' ')
 
1916
                ptr++;
 
1917
 
 
1918
        return ptr;
 
1919
}
 
1920
 
 
1921
bool SVGPlug::parseSVG( const QString &s, FPointArray *ite )
 
1922
{
 
1923
        return ite->parseSVG(s);
 
1924
}
 
1925
 
 
1926
 
 
1927
QColor SVGPlug::parseColorN( const QString &rgbColor )
 
1928
{
 
1929
        int r, g, b;
 
1930
        keywordToRGB( rgbColor.toLower(), r, g, b );
 
1931
        return QColor( r, g, b );
 
1932
}
 
1933
 
 
1934
 
 
1935
QString SVGPlug::parseColor( const QString &s )
 
1936
{
 
1937
        QColor c;
 
1938
        QString ret = CommonStrings::None;
 
1939
        if (s.length() > 11) // icc-color()
 
1940
        {
 
1941
                int iccColorIndex  = s.indexOf("icc-color");
 
1942
                if (iccColorIndex >= 0)
 
1943
                {
 
1944
                        QString iccColorName = parseIccColor(s);
 
1945
                        if (iccColorName.length() > 0)
 
1946
                                return iccColorName;
 
1947
                }
 
1948
        }
 
1949
        if (s.startsWith( "rgb(" ) )
 
1950
        {
 
1951
                QString parse = s.trimmed();
 
1952
                QStringList colors = parse.split(',', QString::SkipEmptyParts);
 
1953
                QString r = colors[0].right( ( colors[0].length() - 4 ) );
 
1954
                QString g = colors[1];
 
1955
                QString b = colors[2].left( ( colors[2].length() - 1 ) );
 
1956
                if (r.contains( "%" ))
 
1957
                {
 
1958
                        r = r.left( r.length() - 1 );
 
1959
                        r = QString::number( static_cast<int>( ( static_cast<double>( 255 * ScCLocale::toDoubleC(r) ) / 100.0 ) ) );
 
1960
                }
 
1961
                if (g.contains( "%" ))
 
1962
                {
 
1963
                        g = g.left( g.length() - 1 );
 
1964
                        g = QString::number( static_cast<int>( ( static_cast<double>( 255 * ScCLocale::toDoubleC(g) ) / 100.0 ) ) );
 
1965
                }
 
1966
                if (b.contains( "%" ))
 
1967
                {
 
1968
                        b = b.left( b.length() - 1 );
 
1969
                        b = QString::number( static_cast<int>( ( static_cast<double>( 255 * ScCLocale::toDoubleC(b) ) / 100.0 ) ) );
 
1970
                }
 
1971
                c = QColor(r.toInt(), g.toInt(), b.toInt());
 
1972
        }
 
1973
        else
 
1974
        {
 
1975
                QString rgbColor = s.trimmed();
 
1976
                if (rgbColor.startsWith( "#" ))
 
1977
                {
 
1978
                        rgbColor = rgbColor.left(7);
 
1979
                        c.setNamedColor( rgbColor );
 
1980
                }
 
1981
                else
 
1982
                        c = parseColorN( rgbColor );
 
1983
        }
 
1984
        ColorList::Iterator it;
 
1985
        bool found = false;
 
1986
        int r, g, b;
 
1987
        QColor tmpR;
 
1988
        for (it = m_Doc->PageColors.begin(); it != m_Doc->PageColors.end(); ++it)
 
1989
        {
 
1990
                if (it.value().getColorModel() == colorModelRGB)
 
1991
                {
 
1992
                        it.value().getRGB(&r, &g, &b);
 
1993
                        tmpR.setRgb(r, g, b);
 
1994
                        if (c == tmpR)
 
1995
                        {
 
1996
                                ret = it.key();
 
1997
                                found = true;
 
1998
                                break;
 
1999
                        }
 
2000
                }
 
2001
        }
 
2002
        if (!found)
 
2003
        {
 
2004
                ScColor tmp;
 
2005
                tmp.fromQColor(c);
 
2006
                tmp.setSpotColor(false);
 
2007
                tmp.setRegistrationColor(false);
 
2008
                QString newColorName = "FromSVG"+c.name();
 
2009
                m_Doc->PageColors.insert(newColorName, tmp);
 
2010
                importedColors.append(newColorName);
 
2011
                ret = newColorName;
 
2012
        }
 
2013
        return ret;
 
2014
}
 
2015
 
 
2016
QString SVGPlug::parseIccColor( const QString &s )
 
2017
{
 
2018
        QColor color, tmpR;
 
2019
        QString ret;
 
2020
        bool iccColorFound = false, found = false;
 
2021
        int iccColorIndex  = s.indexOf("icc-color");
 
2022
        if (iccColorIndex < 0)
 
2023
                return ret;
 
2024
        int iccFirst = s.indexOf("(", iccColorIndex);
 
2025
        int iccLast  = s.indexOf(")", iccColorIndex);
 
2026
        if (iccFirst >= 0 && iccLast >= 0)
 
2027
        {
 
2028
                QString iccColor = s.mid(iccFirst + 1, iccLast - iccFirst - 1);
 
2029
                iccColor = iccColor.trimmed();
 
2030
                QStringList colors = iccColor.split(',', QString::SkipEmptyParts);
 
2031
                if (colors.count() == 5) // then we assume this is a cmyk color
 
2032
                {
 
2033
                        QString cs = colors[1], ms = colors[2], ys = colors[3], ks = colors[4];
 
2034
                        if (cs.contains( "%" ))
 
2035
                        {
 
2036
                                cs = cs.left( cs.length() - 1 );
 
2037
                                cs = QString::number(ScCLocale::toDoubleC(cs) / 100);
 
2038
                        }
 
2039
                        if (ms.contains( "%" ))
 
2040
                        {
 
2041
                                ms = ms.left( ms.length() - 1 );
 
2042
                                ms = QString::number(ScCLocale::toDoubleC(ms) / 100);
 
2043
                        }
 
2044
                        if (ys.contains( "%" ))
 
2045
                        {
 
2046
                                ys = ys.left( ys.length() - 1 );
 
2047
                                ys = QString::number(ScCLocale::toDoubleC(ys) / 100);
 
2048
                        }
 
2049
                        if (ks.contains( "%" ))
 
2050
                        {
 
2051
                                ks = ks.left( ks.length() - 1 );
 
2052
                                ks = QString::number(ScCLocale::toDoubleC(ks) / 100);
 
2053
                        }
 
2054
                        double cv = ScCLocale::toDoubleC(cs);
 
2055
                        double mv = ScCLocale::toDoubleC(ms);
 
2056
                        double yv = ScCLocale::toDoubleC(ys);
 
2057
                        double kv = ScCLocale::toDoubleC(ks);
 
2058
                        color.setCmykF(cv, mv, yv, kv);
 
2059
                        iccColorFound = true;
 
2060
                }
 
2061
        }
 
2062
        if (iccColorFound == false)
 
2063
                return ret;
 
2064
        int  c, m, y, k;
 
2065
        ColorList::Iterator it;
 
2066
        for (it = m_Doc->PageColors.begin(); it != m_Doc->PageColors.end(); ++it)
 
2067
        {
 
2068
                colorModel colorMod = it.value().getColorModel();
 
2069
                if (colorMod == colorModelCMYK)
 
2070
                {
 
2071
                        it.value().getCMYK(&c, &m, &y, &k);
 
2072
                        tmpR.setCmyk(c, m, y, k);
 
2073
                        if (color == tmpR)
 
2074
                        {
 
2075
                                ret = it.key();
 
2076
                                found = true;
 
2077
                                break;
 
2078
                        }
 
2079
                }
 
2080
        }
 
2081
        if (!found)
 
2082
        {
 
2083
                ScColor tmp;
 
2084
                tmp.fromQColor(color);
 
2085
                tmp.setSpotColor(false);
 
2086
                tmp.setRegistrationColor(false);
 
2087
                QString newColorName = "FromSVG"+tmp.name();
 
2088
                m_Doc->PageColors.insert(newColorName, tmp);
 
2089
                importedColors.append(newColorName);
 
2090
                ret = newColorName;
 
2091
        }
 
2092
        return ret;
 
2093
}
 
2094
 
 
2095
void SVGPlug::parsePA( SvgStyle *obj, const QString &command, const QString &params )
 
2096
{
 
2097
        if( command == "display" )
 
2098
                obj->Display = (params == "none") ? false : true;
 
2099
        else if( command == "stroke-opacity" )
 
2100
                obj->StrokeOpacity  = fromPercentage(params);
 
2101
        else if( command == "fill-opacity" )
 
2102
                obj->FillOpacity = fromPercentage(params);
 
2103
        else if( command == "opacity" )
 
2104
                obj->Opacity = fromPercentage(params);
 
2105
        else if( command == "fill" )
 
2106
        {
 
2107
//              if ((obj->InherCol) && (params == "currentColor"))
 
2108
                if (params == "currentColor")
 
2109
                        obj->FillCol = obj->CurCol;
 
2110
                else if (params == "none")
 
2111
                {
 
2112
                        obj->FillCol = CommonStrings::None;
 
2113
                }
 
2114
                else if( params.startsWith( "url(" ) )
 
2115
                {
 
2116
                        unsigned int start = params.indexOf("#") + 1;
 
2117
                        unsigned int end = params.lastIndexOf(")");
 
2118
                        QString key = params.mid(start, end - start);
 
2119
                        obj->Gradient = 0;
 
2120
                        obj->matrixg = QMatrix();
 
2121
                        bool firstMatrixValid = false;
 
2122
                        if (m_gradients[key].matrixValid)
 
2123
                        {
 
2124
                                firstMatrixValid = true;
 
2125
                                obj->matrixg = m_gradients[key].matrix;
 
2126
                        }
 
2127
                        while (!m_gradients[key].reference.isEmpty())
 
2128
                        {
 
2129
                                QString key2 = m_gradients[key].reference;
 
2130
                                if (m_gradients[key2].typeValid)
 
2131
                                        obj->Gradient = m_gradients[key2].Type;
 
2132
                                if (obj->Gradient != 8)
 
2133
                                {
 
2134
                                        if (m_gradients[key2].gradientValid)
 
2135
                                                obj->GradCo = m_gradients[key2].gradient;
 
2136
                                        if (m_gradients[key2].cspaceValid)
 
2137
                                                obj->CSpace = m_gradients[key2].CSpace;
 
2138
                                        if (m_gradients[key2].x1Valid)
 
2139
                                                obj->GX1 = m_gradients[key2].X1;
 
2140
                                        if (m_gradients[key2].y1Valid)
 
2141
                                                obj->GY1 = m_gradients[key2].Y1;
 
2142
                                        if (m_gradients[key2].x2Valid)
 
2143
                                                obj->GX2 = m_gradients[key2].X2;
 
2144
                                        if (m_gradients[key2].y2Valid)
 
2145
                                                obj->GY2 = m_gradients[key2].Y2;
 
2146
                                        if (m_gradients[key2].matrixValid)
 
2147
                                                obj->matrixg = m_gradients[key2].matrix;
 
2148
                                }
 
2149
                                else
 
2150
                                {
 
2151
                                        obj->GCol1 = key2;
 
2152
                                        if ((m_gradients[key2].matrixValid) && (!firstMatrixValid))
 
2153
                                                obj->matrixg *= m_gradients[key2].matrix;
 
2154
                                }
 
2155
                                key = m_gradients[key].reference;
 
2156
                        }
 
2157
                        if (obj->Gradient != 8)
 
2158
                        {
 
2159
                                key = params.mid(start, end - start);
 
2160
                                if (m_gradients[key].typeValid)
 
2161
                                        obj->Gradient = m_gradients[key].Type;
 
2162
                                if (obj->Gradient != 8)
 
2163
                                {
 
2164
                                        if (m_gradients[key].gradientValid)
 
2165
                                                obj->GradCo = m_gradients[key].gradient;
 
2166
                                        if (m_gradients[key].cspaceValid)
 
2167
                                                obj->CSpace = m_gradients[key].CSpace;
 
2168
                                        if (m_gradients[key].x1Valid)
 
2169
                                                obj->GX1 = m_gradients[key].X1;
 
2170
                                        if (m_gradients[key].y1Valid)
 
2171
                                                obj->GY1 = m_gradients[key].Y1;
 
2172
                                        if (m_gradients[key].x2Valid)
 
2173
                                                obj->GX2 = m_gradients[key].X2;
 
2174
                                        if (m_gradients[key].y2Valid)
 
2175
                                                obj->GY2 = m_gradients[key].Y2;
 
2176
                                        if (m_gradients[key].matrixValid)
 
2177
                                                obj->matrixg = m_gradients[key].matrix;
 
2178
                                }
 
2179
                                else
 
2180
                                {
 
2181
                                        obj->GCol1 = key;
 
2182
                                        if (m_gradients[key].matrixValid)
 
2183
                                                obj->matrixg = m_gradients[key].matrix;
 
2184
                                }
 
2185
                        }
 
2186
                        obj->FillCol = CommonStrings::None;
 
2187
                }
 
2188
                else
 
2189
                        obj->FillCol = parseColor(params);
 
2190
        }
 
2191
        else if( command == "fill-rule" )
 
2192
        {
 
2193
                obj->fillRule = params;
 
2194
        }
 
2195
        else if( command == "color" )
 
2196
        {
 
2197
                if (params == "none")
 
2198
                        obj->CurCol = CommonStrings::None;
 
2199
                else if( params.startsWith( "url(" ) )
 
2200
                        obj->CurCol = CommonStrings::None;
 
2201
                else if (params == "currentColor")
 
2202
                        obj->CurCol = obj->CurCol;
 
2203
                else
 
2204
                        obj->CurCol = parseColor(params);
 
2205
        }
 
2206
        else if( command == "stroke" )
 
2207
        {
 
2208
//              if ((obj->InherCol) && (params == "currentColor"))
 
2209
                if (params == "currentColor")
 
2210
                        obj->StrokeCol = obj->CurCol;
 
2211
                else if (params == "none")
 
2212
                {
 
2213
                        obj->StrokeCol = CommonStrings::None;
 
2214
                }
 
2215
                else if( params.startsWith( "url(" ) )
 
2216
                {
 
2217
                        obj->StrokeCol = CommonStrings::None;
 
2218
                }
 
2219
                else
 
2220
                        obj->StrokeCol = parseColor(params);
 
2221
                /*              if( params == "none" )
 
2222
                                        gc->stroke.setType( VStroke::none );
 
2223
                                else if( params.startsWith( "url(" ) )
 
2224
                                {
 
2225
                                        unsigned int start = params.find("#") + 1;
 
2226
                                        unsigned int end = params.lastIndexOf(")");
 
2227
                                        QString key = params.mid( start, end - start );
 
2228
                                        gc->stroke.gradient() = m_gradients[ key ].gradient;
 
2229
                                        gc->stroke.gradient().transform( m_gradients[ key ].gradientTransform );
 
2230
                                        gc->stroke.gradient().transform( gc->matrix );
 
2231
                                        gc->stroke.setType( VStroke::grad );
 
2232
                                }
 
2233
                                else
 
2234
                                {
 
2235
                                        parseColor( strokecolor, params );
 
2236
                                        gc->stroke.setType( VStroke::solid );
 
2237
                                } */
 
2238
        }
 
2239
        else if( command == "stroke-width" )
 
2240
                obj->LWidth = parseUnit( params );
 
2241
        else if( command == "stroke-linejoin" )
 
2242
        {
 
2243
                if( params == "miter" )
 
2244
                        obj->PLineJoin = Qt::MiterJoin;
 
2245
                else if( params == "round" )
 
2246
                        obj->PLineJoin = Qt::RoundJoin;
 
2247
                else if( params == "bevel" )
 
2248
                        obj->PLineJoin = Qt::BevelJoin;
 
2249
        }
 
2250
        else if( command == "stroke-linecap" )
 
2251
        {
 
2252
                if( params == "butt" )
 
2253
                        obj->PLineEnd = Qt::FlatCap;
 
2254
                else if( params == "round" )
 
2255
                        obj->PLineEnd = Qt::RoundCap;
 
2256
                else if( params == "square" )
 
2257
                        obj->PLineEnd = Qt::SquareCap;
 
2258
        }
 
2259
        //      else if( command == "stroke-miterlimit" )
 
2260
        //              gc->stroke.setMiterLimit( params.todouble() );
 
2261
        else if( command == "stroke-dasharray" )
 
2262
        {
 
2263
                QVector<double> array;
 
2264
                if(params != "none")
 
2265
                {
 
2266
                        QString params2 = params.simplified().replace(',', " ");
 
2267
                        QStringList dashes = params2.split(' ', QString::SkipEmptyParts);
 
2268
                        for( QStringList::Iterator it = dashes.begin(); it != dashes.end(); ++it )
 
2269
                                array.append( ScCLocale::toDoubleC(*it) );
 
2270
                }
 
2271
                obj->dashArray = array;
 
2272
        }
 
2273
        else if( command == "stroke-dashoffset" )
 
2274
                obj->dashOffset = ScCLocale::toDoubleC(params);
 
2275
        else if( command == "font-family" )
 
2276
                obj->FontFamily = params;
 
2277
        else if( command == "font-style" )
 
2278
                obj->FontStyle = params;
 
2279
        else if( command == "font-weight" )
 
2280
                obj->FontWeight = params;
 
2281
        else if( command == "font-stretch" )
 
2282
                obj->FontStretch = params;
 
2283
        else if( command == "font-size" )
 
2284
                obj->FontSize = static_cast<int>(parseFontSize(params) * 10.0);
 
2285
        else if( command == "text-anchor" )
 
2286
                obj->textAnchor = params;
 
2287
        else if( command == "text-decoration" )
 
2288
                obj->textDecoration = params;
 
2289
        else if (command == "clip-path")
 
2290
        {
 
2291
                if (params.startsWith( "url("))
 
2292
                {
 
2293
                        unsigned int start = params.indexOf("#") + 1;
 
2294
                        unsigned int end = params.lastIndexOf(")");
 
2295
                        QString key = params.mid(start, end - start);
 
2296
                        QMap<QString, FPointArray>::iterator it = m_clipPaths.find(key);
 
2297
                        if (it != m_clipPaths.end())
 
2298
                                obj->clipPath = it.value().copy();
 
2299
                }
 
2300
        }
 
2301
        else if( !isIgnorableNodeName(command) )
 
2302
        {
 
2303
                if (!m_unsupportedFeatures.contains(command))
 
2304
                {
 
2305
                        m_unsupportedFeatures.insert(command, command);
 
2306
                        qDebug() << QString("unsupported SVG feature: %1").arg(command);
 
2307
                        unsupported = true;
 
2308
                }
 
2309
        }
 
2310
}
 
2311
 
 
2312
void SVGPlug::parseStyle( SvgStyle *obj, const QDomElement &e )
 
2313
{
 
2314
        SvgStyle *gc = m_gc.top();
 
2315
        if (!gc)
 
2316
                return;
 
2317
        if( !e.attribute( "display" ).isEmpty() )
 
2318
                parsePA( obj, "display", e.attribute( "display" ) );
 
2319
        if( !e.attribute( "color" ).isEmpty() )
 
2320
        {
 
2321
                if (e.attribute( "color" ) == "inherit")
 
2322
                        gc->InherCol = true;
 
2323
                else
 
2324
                        parsePA( obj, "color", e.attribute( "color" ) );
 
2325
        }
 
2326
        if( !e.attribute( "fill" ).isEmpty() )
 
2327
                parsePA( obj, "fill", e.attribute( "fill" ) );
 
2328
        if( !e.attribute( "stroke" ).isEmpty() )
 
2329
                parsePA( obj, "stroke", e.attribute( "stroke" ) );
 
2330
        if( !e.attribute( "stroke-width" ).isEmpty() )
 
2331
                parsePA( obj, "stroke-width", e.attribute( "stroke-width" ) );
 
2332
        if( !e.attribute( "stroke-linejoin" ).isEmpty() )
 
2333
                parsePA( obj, "stroke-linejoin", e.attribute( "stroke-linejoin" ) );
 
2334
        if( !e.attribute( "stroke-linecap" ).isEmpty() )
 
2335
                parsePA( obj, "stroke-linecap", e.attribute( "stroke-linecap" ) );
 
2336
        if( !e.attribute( "stroke-dasharray" ).isEmpty() )
 
2337
                parsePA( obj, "stroke-dasharray", e.attribute( "stroke-dasharray" ) );
 
2338
        if( !e.attribute( "stroke-dashoffset" ).isEmpty() )
 
2339
                parsePA( obj, "stroke-dashoffset", e.attribute( "stroke-dashoffset" ) );
 
2340
        if( !e.attribute( "stroke-opacity" ).isEmpty() )
 
2341
                parsePA( obj, "stroke-opacity", e.attribute( "stroke-opacity" ) );
 
2342
        /*      if( !e.attribute( "stroke-miterlimit" ).isEmpty() )
 
2343
                        parsePA( obj, "stroke-miterlimit", e.attribute( "stroke-miterlimit" ) );   */
 
2344
        if( !e.attribute( "fill-rule" ).isEmpty() )
 
2345
                parsePA( obj, "fill-rule", e.attribute( "fill-rule" ) );
 
2346
        if( !e.attribute( "fill-opacity" ).isEmpty() )
 
2347
                parsePA( obj, "fill-opacity", e.attribute( "fill-opacity" ) );
 
2348
        if( !e.attribute( "opacity" ).isEmpty() )
 
2349
                parsePA( obj, "opacity", e.attribute( "opacity" ) );
 
2350
        if( !e.attribute( "font-family" ).isEmpty() )
 
2351
                parsePA( obj, "font-family", e.attribute( "font-family" ) );
 
2352
        if( !e.attribute( "font-style" ).isEmpty() )
 
2353
                parsePA( obj, "font-style", e.attribute( "font-style" ) );
 
2354
        if( !e.attribute( "font-weight" ).isEmpty() )
 
2355
                parsePA( obj, "font-weight", e.attribute( "font-weight" ) );
 
2356
        if( !e.attribute( "font-stretch" ).isEmpty() )
 
2357
                parsePA( obj, "font-stretch", e.attribute( "font-stretch" ) );
 
2358
        if( !e.attribute( "font-size" ).isEmpty() )
 
2359
                parsePA( obj, "font-size", e.attribute( "font-size" ) );
 
2360
        if( !e.attribute( "text-anchor" ).isEmpty() )
 
2361
                parsePA( obj, "text-anchor", e.attribute( "text-anchor" ) );
 
2362
        if( !e.attribute( "text-decoration" ).isEmpty() )
 
2363
                parsePA( obj, "text-decoration", e.attribute( "text-decoration" ) );
 
2364
        QString style = e.attribute( "style" ).simplified();
 
2365
        QStringList substyles = style.split(';', QString::SkipEmptyParts);
 
2366
        for( QStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it )
 
2367
        {
 
2368
                QStringList substyle = (*it).split(':', QString::SkipEmptyParts);
 
2369
                QString command(substyle[0].trimmed());
 
2370
                QString params(substyle[1].trimmed());
 
2371
                parsePA( obj, command, params );
 
2372
        }
 
2373
        return;
 
2374
}
 
2375
 
 
2376
void SVGPlug::parseColorStops(GradientHelper *gradient, const QDomElement &e)
 
2377
{
 
2378
        QString Col = "Black";
 
2379
        double offset = 0;
 
2380
        double opa;
 
2381
        SvgStyle svgStyle;
 
2382
        parseStyle( &svgStyle, e );
 
2383
        for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling())
 
2384
        {
 
2385
                opa = 1.0;
 
2386
                QDomElement stop = n.toElement();
 
2387
                if(stop.tagName() == "stop")
 
2388
                {
 
2389
                        QString temp = stop.attribute( "offset" );
 
2390
                        if( temp.contains( '%' ) )
 
2391
                        {
 
2392
                                temp = temp.left( temp.length() - 1 );
 
2393
                                offset = ScCLocale::toDoubleC(temp) / 100.0;
 
2394
                        }
 
2395
                        else
 
2396
                                offset = ScCLocale::toDoubleC(temp);
 
2397
                        if( !stop.attribute( "stop-opacity" ).isEmpty() )
 
2398
                                opa = fromPercentage(stop.attribute("stop-opacity"));
 
2399
                        if( !stop.attribute( "stop-color" ).isEmpty() )
 
2400
                        {
 
2401
                                if (stop.attribute("stop-color") == "currentColor")
 
2402
                                        Col = svgStyle.CurCol;
 
2403
                                else
 
2404
                                        Col = parseColor(stop.attribute("stop-color"));
 
2405
                        }
 
2406
                        else
 
2407
                        {
 
2408
                                QString style = stop.attribute( "style" ).simplified();
 
2409
                                QStringList substyles = style.split(';', QString::SkipEmptyParts);
 
2410
                                for( QStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it )
 
2411
                                {
 
2412
                                        QStringList substyle = (*it).split(':', QString::SkipEmptyParts);
 
2413
                                        QString command(substyle[0].trimmed());
 
2414
                                        QString params(substyle[1].trimmed());
 
2415
                                        if( command == "stop-color" )
 
2416
                                                Col = parseColor(params);
 
2417
                                        if( command == "stop-opacity" )
 
2418
                                                opa = fromPercentage(params);
 
2419
                                }
 
2420
                        }
 
2421
                }
 
2422
                const ScColor& gradC = m_Doc->PageColors[Col];
 
2423
                gradient->gradient.addStop( ScColorEngine::getRGBColor(gradC, m_Doc), offset, 0.5, opa, Col, 100 );
 
2424
                gradient->gradientValid = true;
 
2425
        }
 
2426
        if (gradient->gradientValid)
 
2427
                gradient->gradient.filterStops();
 
2428
}
 
2429
 
 
2430
void SVGPlug::parsePattern(const QDomElement &b)
 
2431
{
 
2432
        GradientHelper gradhelper;
 
2433
        QString href = b.attribute("xlink:href").mid(1);
 
2434
        if (!href.isEmpty())
 
2435
        {
 
2436
                if (m_gradients.contains(href))
 
2437
                {
 
2438
                        gradhelper.Type = m_gradients[href].Type;
 
2439
                        gradhelper.gradientValid = m_gradients[href].gradientValid;
 
2440
                        gradhelper.typeValid = m_gradients[href].typeValid;
 
2441
                        gradhelper.matrix = m_gradients[href].matrix;
 
2442
                        gradhelper.matrixValid = m_gradients[href].matrixValid;
 
2443
                }
 
2444
                gradhelper.reference = href;
 
2445
        }
 
2446
        QString id = b.attribute("id", "");
 
2447
        QString origName = id;
 
2448
        if (!id.isEmpty())
 
2449
        {
 
2450
                inGroupXOrigin = 999999;
 
2451
                inGroupYOrigin = 999999;
 
2452
                double wpat = parseUnit(b.attribute("width", "0"));
 
2453
                double hpat = parseUnit(b.attribute("height", "0"));
 
2454
                int ac = m_Doc->Items->count();
 
2455
                QList<PageItem*> GElements;
 
2456
                GElements = parseGroup( b );
 
2457
                int ae = m_Doc->Items->count();
 
2458
                if (GElements.count() > 0)
 
2459
                {
 
2460
                        ScPattern pat = ScPattern();
 
2461
                        pat.setDoc(m_Doc);
 
2462
                        PageItem* currItem = GElements.at(0);
 
2463
                        m_Doc->DoDrawing = true;
 
2464
                        pat.pattern = currItem->DrawObj_toImage();
 
2465
                        double xOrg = 0.0;
 
2466
                        double yOrg = 0.0;
 
2467
                        if (inGroupXOrigin < 0.0)
 
2468
                                xOrg = inGroupXOrigin;
 
2469
                        if (inGroupYOrigin < 0.0)
 
2470
                                yOrg = inGroupYOrigin;
 
2471
                        if ((xOrg != 0.0) || (yOrg != 0.0))
 
2472
                                pat.pattern = pat.pattern.copy(-xOrg, -yOrg, wpat, hpat);
 
2473
                        pat.xoffset = xOrg;
 
2474
                        pat.yoffset = yOrg;
 
2475
                        m_Doc->DoDrawing = false;
 
2476
                        pat.width = qMin(currItem->gWidth, wpat);
 
2477
                        pat.height = qMin(currItem->gHeight, hpat);
 
2478
                        bool more = false;
 
2479
                        for (int as = ac; as < ae; ++as)
 
2480
                        {
 
2481
                                PageItem* Neu = m_Doc->Items->takeAt(ac);
 
2482
                                if (more)
 
2483
                                {
 
2484
                                        Neu->moveBy(xOrg, yOrg, true);
 
2485
                                        Neu->gXpos += xOrg;
 
2486
                                        Neu->gYpos += yOrg;
 
2487
                                }
 
2488
                                more = true;
 
2489
                                Neu->ItemNr = pat.items.count();
 
2490
                                pat.items.append(Neu);
 
2491
                        }
 
2492
                        m_Doc->addPattern(id, pat);
 
2493
                        importedPatterns.append(id);
 
2494
                        importedPattTrans.insert(origName, id);
 
2495
                }
 
2496
                m_nodeMap.insert(origName, b);
 
2497
                QString transf = b.attribute("patternTransform");
 
2498
                if( !transf.isEmpty() )
 
2499
                {
 
2500
                        gradhelper.matrix = parseTransform( b.attribute("patternTransform") );
 
2501
                        gradhelper.matrixValid = true;
 
2502
                }
 
2503
                else
 
2504
                        gradhelper.matrixValid = false;
 
2505
                gradhelper.gradientValid = true;
 
2506
                gradhelper.gradient.clearStops();
 
2507
                gradhelper.gradient.setRepeatMethod( VGradient::none );
 
2508
                gradhelper.Type = 8;
 
2509
                gradhelper.typeValid = true;
 
2510
                m_gradients.insert(origName, gradhelper);
 
2511
        }
 
2512
}
 
2513
 
 
2514
void SVGPlug::parseGradient( const QDomElement &e )
 
2515
{
 
2516
        GradientHelper gradhelper;
 
2517
        gradhelper.gradientValid = false;
 
2518
        gradhelper.gradient.clearStops();
 
2519
        gradhelper.gradient.setRepeatMethod( VGradient::none );
 
2520
 
 
2521
        QString href = e.attribute("xlink:href").mid(1);
 
2522
        double x1=0, y1=0, x2=0, y2=0;
 
2523
        if (!href.isEmpty())
 
2524
        {
 
2525
                if (m_gradients.contains(href))
 
2526
                {
 
2527
                        gradhelper.Type = m_gradients[href].Type;
 
2528
                        gradhelper.gradient = m_gradients[href].gradient;
 
2529
                        gradhelper.X1 = m_gradients[href].X1;
 
2530
                        gradhelper.Y1 = m_gradients[href].Y1;
 
2531
                        gradhelper.X2 = m_gradients[href].X2;
 
2532
                        gradhelper.Y2 = m_gradients[href].Y2;
 
2533
                        gradhelper.CSpace = m_gradients[href].CSpace;
 
2534
                        gradhelper.matrix = m_gradients[href].matrix;
 
2535
                        gradhelper.x1Valid = m_gradients[href].x1Valid;
 
2536
                        gradhelper.x2Valid = m_gradients[href].x2Valid;
 
2537
                        gradhelper.y1Valid = m_gradients[href].y1Valid;
 
2538
                        gradhelper.y2Valid = m_gradients[href].y2Valid;
 
2539
                        gradhelper.cspaceValid = m_gradients[href].cspaceValid;
 
2540
                        gradhelper.matrixValid = m_gradients[href].matrixValid;
 
2541
                        gradhelper.gradientValid = m_gradients[href].gradientValid;
 
2542
                        gradhelper.typeValid = m_gradients[href].typeValid;
 
2543
                }
 
2544
                gradhelper.reference = href;
 
2545
        }
 
2546
        if (e.tagName() == "linearGradient")
 
2547
        {
 
2548
                if (e.hasAttribute("x1"))
 
2549
                {
 
2550
                        gradhelper.X1 = parseUnit(e.attribute("x1", "0"));
 
2551
                        gradhelper.x1Valid = true;
 
2552
                }
 
2553
                if (e.hasAttribute("y1"))
 
2554
                {
 
2555
                        gradhelper.Y1 = parseUnit(e.attribute("y1", "0"));
 
2556
                        gradhelper.y1Valid = true;
 
2557
                }
 
2558
                if (e.hasAttribute("x2"))
 
2559
                {
 
2560
                        gradhelper.X2 = parseUnit(e.attribute("x2", "1"));
 
2561
                        gradhelper.x2Valid = true;
 
2562
                }
 
2563
                if (e.hasAttribute("y2"))
 
2564
                {
 
2565
                        gradhelper.Y2 = parseUnit(e.attribute("y2", "0"));
 
2566
                        gradhelper.y2Valid = true;
 
2567
                }
 
2568
                gradhelper.Type = 6;
 
2569
                gradhelper.typeValid = true;
 
2570
        }
 
2571
        else
 
2572
        {
 
2573
                if (e.hasAttribute("cx"))
 
2574
                {
 
2575
                        x1 = parseUnit(e.attribute("cx","0.5"));
 
2576
                        gradhelper.x1Valid = true;
 
2577
                }
 
2578
                if (e.hasAttribute("cy"))
 
2579
                {
 
2580
                        y1 = parseUnit(e.attribute("cy", "0.5"));
 
2581
                        gradhelper.y1Valid = true;
 
2582
                }
 
2583
                if (e.hasAttribute("r"))
 
2584
                {
 
2585
                        x2 = parseUnit(e.attribute("r", "0.5"));
 
2586
                        gradhelper.x2Valid = true;
 
2587
                }
 
2588
                y2 = y1;
 
2589
                gradhelper.y2Valid = true;
 
2590
                gradhelper.X1 = x1;
 
2591
                gradhelper.Y1 = y1;
 
2592
                gradhelper.X2 = x1 + x2;
 
2593
                gradhelper.Y2 = y1;
 
2594
                gradhelper.Type = 7;
 
2595
                gradhelper.typeValid = true;
 
2596
        }
 
2597
        if ( !e.attribute( "gradientUnits" ).isEmpty() )
 
2598
        {
 
2599
                QString uni = e.attribute( "gradientUnits");
 
2600
                if (uni == "userSpaceOnUse")
 
2601
                        gradhelper.CSpace = true;
 
2602
                else
 
2603
                        gradhelper.CSpace = false;
 
2604
                gradhelper.cspaceValid = true;
 
2605
        }
 
2606
        else
 
2607
        {
 
2608
                gradhelper.CSpace = false;
 
2609
                gradhelper.cspaceValid = false;
 
2610
        }
 
2611
        QString transf = e.attribute("gradientTransform");
 
2612
        if( !transf.isEmpty() )
 
2613
        {
 
2614
                gradhelper.matrix = parseTransform( e.attribute("gradientTransform") );
 
2615
                gradhelper.matrixValid = true;
 
2616
        }
 
2617
        else
 
2618
                gradhelper.matrixValid = false;
 
2619
        QString spreadMethod = e.attribute( "spreadMethod" );
 
2620
        if( !spreadMethod.isEmpty() )
 
2621
        {
 
2622
                if( spreadMethod == "reflect" )
 
2623
                        gradhelper.gradient.setRepeatMethod( VGradient::reflect );
 
2624
                else if( spreadMethod == "repeat" )
 
2625
                        gradhelper.gradient.setRepeatMethod( VGradient::repeat );
 
2626
        }
 
2627
        parseColorStops(&gradhelper, e);
 
2628
        m_gradients.insert(e.attribute("id"), gradhelper);
 
2629
}
 
2630
 
 
2631
SVGPlug::~SVGPlug()
 
2632
{
 
2633
        delete tmpSel;
 
2634
}