Subversion Repositories Scribus

Rev

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

Rev Author Line No. Line
68 Franz 1
#include "svgplugin.h"
2
#include "svgplugin.moc"
2688 craig 3
 
4
#include "scconfig.h"
5
 
68 Franz 6
#include "customfdialog.h"
7
#include "color.h"
3207 craig 8
#include "scribus.h"
68 Franz 9
#include "scribusXml.h"
265 Franz 10
#include "mpalette.h"
415 Franz 11
#include "prefsfile.h"
68 Franz 12
#include <qfile.h>
13
#include <qtextstream.h>
1525 cbradney 14
#include <qdragobject.h>
68 Franz 15
#include <qregexp.h>
282 Franz 16
#include <qcursor.h>
68 Franz 17
#include <cmath>
18
#ifdef HAVE_LIBZ
19
#include <zlib.h>
20
#endif
1435 tsoots 21
#include "undomanager.h"
2529 craig 22
#include "util.h"
23
#include "scfontmetrics.h"
2834 cbradney 24
#include "prefsmanager.h"
3207 craig 25
#include "pageitem.h"
26
#include "scribusdoc.h"
3210 craig 27
#include "fpointarray.h"
68 Franz 28
 
504 cbradney 29
using namespace std;
30
 
3207 craig 31
int svgimplugin_getPluginAPIVersion()
68 Franz 32
{
3207 craig 33
        return PLUGIN_API_VERSION;
68 Franz 34
}
35
 
3207 craig 36
ScPlugin* svgimplugin_getPlugin()
68 Franz 37
{
3207 craig 38
        SVGImportPlugin* plug = new SVGImportPlugin();
39
        Q_CHECK_PTR(plug);
40
        return plug;
68 Franz 41
}
42
 
3207 craig 43
void svgimplugin_freePlugin(ScPlugin* plugin)
512 fschmid 44
{
3207 craig 45
        SVGImportPlugin* plug = dynamic_cast<SVGImportPlugin*>(plugin);
46
        Q_ASSERT(plug);
47
        delete plug;
512 fschmid 48
}
49
 
3487 craig 50
SVGImportPlugin::SVGImportPlugin() : LoadSavePlugin()
1208 cbradney 51
{
3207 craig 52
        // Set action info in languageChange, so we only have to do
53
        // it in one place.
54
        languageChange();
1208 cbradney 55
}
56
 
3207 craig 57
SVGImportPlugin::~SVGImportPlugin() {};
58
 
59
void SVGImportPlugin::languageChange()
1208 cbradney 60
{
3207 craig 61
        // Note that we leave the unused members unset. They'll be initialised
62
        // with their default ctors during construction.
63
        // Action name
64
        m_actionInfo.name = "ImportSVG";
65
        // Action text for menu, including accel
66
        m_actionInfo.text = tr("Import &SVG...");
67
        // Menu
68
        m_actionInfo.menu = "FileImport";
69
        m_actionInfo.enabledOnStartup = true;
1208 cbradney 70
}
71
 
3207 craig 72
const QString SVGImportPlugin::fullTrName() const
1208 cbradney 73
{
3207 craig 74
        return QObject::tr("SVG Import");
1208 cbradney 75
}
76
 
3207 craig 77
const ScActionPlugin::AboutData* SVGImportPlugin::getAboutData() const
1208 cbradney 78
{
3241 craig 79
        AboutData* about = new AboutData;
3344 fschmid 80
        about->authors = "Franz Schmid <franz@scribus.info>";
3355 cbradney 81
        about->shortDescription = tr("Imports SVG Files");
3357 cbradney 82
        about->description = tr("Imports most SVG files into the current document,\nconverting their vector data into Scribus objects.");
3344 fschmid 83
        about->license = "GPL";
3241 craig 84
        Q_CHECK_PTR(about);
85
        return about;
1208 cbradney 86
}
87
 
3241 craig 88
void SVGImportPlugin::deleteAboutData(const AboutData* about) const
1208 cbradney 89
{
3241 craig 90
        Q_ASSERT(about);
91
        delete about;
1208 cbradney 92
}
93
 
3487 craig 94
QValueList<LoadSavePlugin::FormatSupport> SVGImportPlugin::supportedFormats() const
95
{
96
        QValueList<FormatSupport> formats;
97
        QString svgName = tr("Scalable Vector Graphics");
98
        FormatSupport fmt = {
99
                svgName, "svgim", svgName + " (*.svg *.svgz)",
100
                Format_Import|Format_Load, QStringList("image/svg+xml"), 64};
101
        formats.append(fmt);
102
        return formats;
103
}
104
 
105
bool SVGImportPlugin::fileSupported(QIODevice* /* file */) const
106
{
107
        // TODO: identify valid SVG
108
        return true;
109
}
110
 
202 Franz 111
/*!
3207 craig 112
 \fn void Run(QString filename)
202 Franz 113
 \author Franz Schmid
114
 \date
115
 \brief Run the SVG import
3207 craig 116
 \retval true for success
202 Franz 117
 */
3207 craig 118
bool SVGImportPlugin::run(QString filename)
68 Franz 119
{
3207 craig 120
        bool interactive = false;
121
        if (filename.isEmpty())
506 fschmid 122
        {
3207 craig 123
                interactive = true;
2856 cbradney 124
                PrefsContext* prefs = PrefsManager::instance()->prefsFile->getPluginContext("SVGPlugin");
506 fschmid 125
                QString wdir = prefs->get("wdir", ".");
68 Franz 126
#ifdef HAVE_LIBZ
3207 craig 127
                CustomFDialog diaf(ScApp, wdir, QObject::tr("Open"), QObject::tr("SVG-Images (*.svg *.svgz);;All Files (*)"));
68 Franz 128
#else
3207 craig 129
                CustomFDialog diaf(ScApp, wdir, QObject::tr("Open"), QObject::tr("SVG-Images (*.svg);;All Files (*)"));
68 Franz 130
#endif
506 fschmid 131
                if (diaf.exec())
132
                {
3207 craig 133
                        filename = diaf.selectedFile();
134
                        prefs->set("wdir", filename.left(filename.findRev("/")));
506 fschmid 135
                }
136
                else
3207 craig 137
                        return true;
415 Franz 138
        }
3207 craig 139
        if (UndoManager::undoEnabled() && ScApp->HaveDoc)
1439 tsoots 140
        {
3207 craig 141
                UndoManager::instance()->beginTransaction(ScApp->doc->currentPage->getUName(),Um::IImageFrame,Um::ImportSVG, filename, Um::ISVG);
1439 tsoots 142
        }
3207 craig 143
        else if (UndoManager::undoEnabled() && !ScApp->HaveDoc)
1439 tsoots 144
                UndoManager::instance()->setUndoEnabled(false);
3207 craig 145
        SVGPlug *dia = new SVGPlug(filename, interactive);
146
        Q_CHECK_PTR(dia);
1435 tsoots 147
        if (UndoManager::undoEnabled())
148
                UndoManager::instance()->commit();
1439 tsoots 149
        else
150
                UndoManager::instance()->setUndoEnabled(true);
217 Franz 151
        delete dia;
3207 craig 152
        return true;
68 Franz 153
}
154
 
202 Franz 155
/*!
3207 craig 156
 \fn SVGPlug::SVGPlug( QString fName )
202 Franz 157
 \author Franz Schmid
158
 \date
159
 \brief Create the SVG importer window
160
 \param fName QString
161
 \retval SVGPlug plugin
162
 */
3207 craig 163
SVGPlug::SVGPlug( QString fName, bool isInteractive ) :
164
        QObject(ScApp)
68 Franz 165
{
3207 craig 166
        interactive = isInteractive;
68 Franz 167
        QString f = "";
168
#ifdef HAVE_LIBZ
169
        if(fName.right(2) == "gz")
217 Franz 170
        {
68 Franz 171
                gzFile gzDoc;
172
                char buff[4097];
173
                int i;
174
                gzDoc = gzopen(fName.latin1(),"rb");
175
                if(gzDoc == NULL)
176
                        return;
177
                while((i = gzread(gzDoc,&buff,4096)) > 0)
217 Franz 178
                {
68 Franz 179
                        buff[i] = '\0';
180
                        f.append(buff);
217 Franz 181
                }
68 Franz 182
                gzclose(gzDoc);
217 Franz 183
        }
68 Franz 184
        else
185
                loadText(fName, &f);
186
#else
187
        loadText(fName, &f);
188
#endif
189
        if(!inpdoc.setContent(f))
190
                return;
191
        m_gc.setAutoDelete( true );
192
        QString CurDirP = QDir::currentDirPath();
193
        QFileInfo efp(fName);
194
        QDir::setCurrent(efp.dirPath());
195
        convert();
196
        QDir::setCurrent(CurDirP);
197
}
198
 
202 Franz 199
/*!
200
 \fn void SVGPlug::convert()
201
 \author Franz Schmid
202
 \date
203
 \brief
204
 \param None
205
 \retval None
206
 */
68 Franz 207
void SVGPlug::convert()
208
{
209
        bool ret = false;
210
        SvgStyle *gc = new SvgStyle;
2607 fschmid 211
        Conversion = 0.8;
68 Franz 212
        QDomElement docElem = inpdoc.documentElement();
456 fschmid 213
        double width = !docElem.attribute("width").isEmpty() ? parseUnit(docElem.attribute( "width" )) : 550.0;
214
        double height = !docElem.attribute("height").isEmpty() ? parseUnit(docElem.attribute( "height" )) : 841.0;
2607 fschmid 215
        Conversion = 0.8;
3207 craig 216
        if (!interactive)
217 Franz 217
        {
3207 craig 218
                ScApp->doc->setPage(width, height, 0, 0, 0, 0, 0, 0, false, false);
219
                ScApp->view->addPage(0);
217 Franz 220
        }
506 fschmid 221
        else
222
        {
3207 craig 223
                if (!ScApp->HaveDoc)
506 fschmid 224
                {
3207 craig 225
                        ScApp->doFileNew(width, height, 0, 0, 0, 0, 0, 0, false, false, 0, false, 0, 1, "Custom");
506 fschmid 226
                        ret = true;
227
                }
228
        }
3207 craig 229
        if ((ret) || (!interactive))
550 fschmid 230
        {
231
                if (width > height)
3207 craig 232
                        ScApp->doc->PageOri = 1;
550 fschmid 233
                else
3207 craig 234
                        ScApp->doc->PageOri = 0;
235
                ScApp->doc->PageSize = "Custom";
550 fschmid 236
        }
3292 cbradney 237
        currDoc = ScApp->doc;
238
        FPoint minSize = currDoc->minCanvasCoordinate;
239
        FPoint maxSize = currDoc->maxCanvasCoordinate;
3207 craig 240
        ScApp->view->Deselect();
68 Franz 241
        Elements.clear();
3292 cbradney 242
        currDoc->setLoading(true);
243
        currDoc->DoDrawing = false;
3207 craig 244
        ScApp->view->setUpdatesEnabled(false);
245
        ScApp->ScriptRunning = true;
282 Franz 246
        qApp->setOverrideCursor(QCursor(waitCursor), true);
3292 cbradney 247
        gc->Family = currDoc->toolSettings.defFont;
248
        if (!currDoc->PageColors.contains("Black"))
249
                currDoc->PageColors.insert("Black", ScColor(0, 0, 0, 255));
68 Franz 250
        m_gc.push( gc );
1013 fschmid 251
        viewTransformX = 0;
252
        viewTransformY = 0;
253
        viewScaleX = 1;
254
        viewScaleY = 1;
255
        haveViewBox = false;
256
        if( !docElem.attribute( "viewBox" ).isEmpty() )
257
        {
2607 fschmid 258
                Conversion = 1.0;
259
                double w2 = !docElem.attribute("width").isEmpty() ? parseUnit(docElem.attribute( "width" )) : 550.0;
260
                double h2 = !docElem.attribute("height").isEmpty() ? parseUnit(docElem.attribute( "height" )) : 841.0;
261
                Conversion = 0.8;
1013 fschmid 262
                QString viewbox( docElem.attribute( "viewBox" ) );
263
                QStringList points = QStringList::split( ' ', viewbox.replace( QRegExp(","), " ").simplifyWhiteSpace() );
264
                viewTransformX = points[0].toDouble();
265
                viewTransformY = points[1].toDouble();
2607 fschmid 266
                viewScaleX = w2 / points[2].toDouble();
267
                viewScaleY = h2 / points[3].toDouble();
1013 fschmid 268
                haveViewBox = true;
269
        }
68 Franz 270
        parseGroup( docElem );
3207 craig 271
        ScApp->view->SelItem.clear();
302 Franz 272
        if (Elements.count() > 1)
217 Franz 273
        {
68 Franz 274
                for (uint a = 0; a < Elements.count(); ++a)
217 Franz 275
                {
3292 cbradney 276
                        Elements.at(a)->Groups.push(currDoc->GroupCounter);
217 Franz 277
                }
3292 cbradney 278
                currDoc->GroupCounter++;
217 Franz 279
        }
3292 cbradney 280
        currDoc->DoDrawing = true;
3207 craig 281
        ScApp->view->setUpdatesEnabled(true);
282
        ScApp->ScriptRunning = false;
283
        if (interactive)
3292 cbradney 284
                currDoc->setLoading(false);
282 Franz 285
        qApp->setOverrideCursor(QCursor(arrowCursor), true);
3207 craig 286
        if ((Elements.count() > 0) && (!ret) && (interactive))
217 Franz 287
        {
3292 cbradney 288
                currDoc->DragP = true;
289
                currDoc->DraggedElem = 0;
290
                currDoc->DragElements.clear();
68 Franz 291
                for (uint dre=0; dre<Elements.count(); ++dre)
217 Franz 292
                {
3292 cbradney 293
                        currDoc->DragElements.append(Elements.at(dre)->ItemNr);
3207 craig 294
                        ScApp->view->SelItem.append(Elements.at(dre));
217 Franz 295
                }
296
                ScriXmlDoc *ss = new ScriXmlDoc();
3207 craig 297
                ScApp->view->setGroupRect();
3292 cbradney 298
                QDragObject *dr = new QTextDrag(ss->WriteElem(&ScApp->view->SelItem, currDoc, ScApp->view), ScApp->view->viewport());
3207 craig 299
                ScApp->view->DeleteItem();
300
                ScApp->view->resizeContents(qRound((maxSize.x() - minSize.x()) * ScApp->view->getScale()), qRound((maxSize.y() - minSize.y()) * ScApp->view->getScale()));
3292 cbradney 301
                ScApp->view->scrollBy(qRound((currDoc->minCanvasCoordinate.x() - minSize.x()) * ScApp->view->getScale()), qRound((currDoc->minCanvasCoordinate.y() - minSize.y()) * ScApp->view->getScale()));
302
                currDoc->minCanvasCoordinate = minSize;
303
                currDoc->maxCanvasCoordinate = maxSize;
68 Franz 304
                dr->setPixmap(loadIcon("DragPix.xpm"));
305
                dr->drag();
306
                delete ss;
3292 cbradney 307
                currDoc->DragP = false;
308
                currDoc->DraggedElem = 0;
309
                currDoc->DragElements.clear();
217 Franz 310
        }
68 Franz 311
        else
357 Franz 312
        {
3292 cbradney 313
                currDoc->setModified(false);
3207 craig 314
                ScApp->slotDocCh();
357 Franz 315
        }
68 Franz 316
}
317
 
202 Franz 318
/*!
319
 \fn void SVGPlug::addGraphicContext()
320
 \author Franz Schmid
321
 \date
322
 \brief
323
 \param None
324
 \retval None
325
 */
68 Franz 326
void SVGPlug::addGraphicContext()
327
{
328
        SvgStyle *gc = new SvgStyle;
329
        if ( m_gc.current() )
330
                *gc = *( m_gc.current() );
331
        m_gc.push( gc );
332
}
333
 
202 Franz 334
/*!
335
 \fn void SVGPlug::setupTransform( const QDomElement &e )
336
 \author Franz Schmid
337
 \date
338
 \brief
339
 \param e const QDomElement &
340
 \retval None
341
 */
68 Franz 342
void SVGPlug::setupTransform( const QDomElement &e )
343
{
344
        SvgStyle *gc = m_gc.current();
345
        QWMatrix mat = parseTransform( e.attribute( "transform" ) );
346
        if (!e.attribute("transform").isEmpty())
347
                gc->matrix = mat * gc->matrix;
348
}
349
 
202 Franz 350
/*!
351
 \fn void SVGPlug::parseGroup(const QDomElement &e)
352
 \author Franz Schmid
353
 \date
354
 \brief
355
 \param e const QDomElement &
356
 \retval None
357
 */
991 fschmid 358
QPtrList<PageItem> SVGPlug::parseGroup(const QDomElement &e)
68 Franz 359
{
360
        QPtrList<PageItem> GElements;
361
        FPointArray ImgClip;
362
        ImgClip.resize(0);
3292 cbradney 363
        double BaseX = currDoc->currentPage->xOffset();
364
        double BaseY = currDoc->currentPage->yOffset();
68 Franz 365
        for( QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling() )
217 Franz 366
        {
68 Franz 367
                int z = -1;
368
                QDomElement b = n.toElement();
369
                if( b.isNull() )
370
                        continue;
371
                QString STag = b.tagName();
372
                if( STag == "g" )
217 Franz 373
                {
68 Franz 374
                        addGraphicContext();
375
                        SvgStyle *gc = m_gc.current();
376
                        setupTransform( b );
377
                        parseStyle( gc, b );
991 fschmid 378
                        QPtrList<PageItem> gElements = parseGroup( b );
379
                        for (uint gr = 0; gr < gElements.count(); ++gr)
217 Franz 380
                        {
3292 cbradney 381
                                gElements.at(gr)->Groups.push(currDoc->GroupCounter);
991 fschmid 382
                                GElements.append(gElements.at(gr));
217 Franz 383
                        }
68 Franz 384
                        delete( m_gc.pop() );
3292 cbradney 385
                        currDoc->GroupCounter++;
68 Franz 386
                        continue;
217 Franz 387
                }
68 Franz 388
                if( b.tagName() == "defs" )
217 Franz 389
                {
68 Franz 390
                        parseGroup( b );        // try for gradients at least
391
                        continue;
217 Franz 392
                }
68 Franz 393
                else if( STag == "linearGradient" || STag == "radialGradient" )
217 Franz 394
                {
68 Franz 395
                        parseGradient( b );
396
                        continue;
217 Franz 397
                }
68 Franz 398
                else if( STag == "rect" )
217 Franz 399
                {
68 Franz 400
                        addGraphicContext();
3292 cbradney 401
                        double x = parseUnit( b.attribute( "x" ) );
402
                        double y = parseUnit( b.attribute( "y" ) );
456 fschmid 403
                        double width = parseUnit( b.attribute( "width" ));
404
                        double height = parseUnit( b.attribute( "height" ) );
68 Franz 405
                        double rx = b.attribute( "rx" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "rx" ) );
406
                        double ry = b.attribute( "ry" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "ry" ) );
407
                        SvgStyle *gc = m_gc.current();
408
                        parseStyle( gc, b );
3292 cbradney 409
                        //z = ScApp->view->PaintRect(BaseX, BaseY, width, height, gc->LWidth, gc->FillCol, gc->StrokeCol);
410
                        z = currDoc->itemAdd(PageItem::Polygon, PageItem::Rectangle, BaseX, BaseY, width, height, gc->LWidth, gc->FillCol, gc->StrokeCol, !ScApp->view->Mpressed);
411
                        PageItem* ite = currDoc->Items.at(z);
68 Franz 412
                        if ((rx != 0) || (ry != 0))
217 Franz 413
                        {
68 Franz 414
                                ite->RadRect = QMAX(rx, ry);
3242 cbradney 415
                                ite->SetFrameRound();
416
                                ScApp->view->setRedrawBounding(ite);
217 Franz 417
                        }
68 Franz 418
                        QWMatrix mm = QWMatrix();
419
                        mm.translate(x, y);
420
                        ite->PoLine.map(mm);
1065 cbradney 421
                        FPoint wh = getMaxClipF(&ite->PoLine);
95 Franz 422
                        ite->Width = wh.x();
423
                        ite->Height = wh.y();
217 Franz 424
                }
68 Franz 425
                else if( STag == "ellipse" )
217 Franz 426
                {
68 Franz 427
                        addGraphicContext();
456 fschmid 428
                        double rx = parseUnit( b.attribute( "rx" ) );
429
                        double ry = parseUnit( b.attribute( "ry" ) );
430
                        double x = parseUnit( b.attribute( "cx" ) ) - rx;
431
                        double y = parseUnit( b.attribute( "cy" ) ) - ry;
68 Franz 432
                        SvgStyle *gc = m_gc.current();
433
                        parseStyle( gc, b );
3292 cbradney 434
                        //z = ScApp->view->PaintEllipse(BaseX, BaseY, rx * 2.0, ry * 2.0, gc->LWidth, gc->FillCol, gc->StrokeCol);
435
                        z = currDoc->itemAdd(PageItem::Polygon, PageItem::Ellipse, BaseX, BaseY, rx * 2.0, ry * 2.0, gc->LWidth, gc->FillCol, gc->StrokeCol, !ScApp->view->Mpressed);
436
                        PageItem* ite = currDoc->Items.at(z);
68 Franz 437
                        QWMatrix mm = QWMatrix();
438
                        mm.translate(x, y);
439
                        ite->PoLine.map(mm);
1065 cbradney 440
                        FPoint wh = getMaxClipF(&ite->PoLine);
95 Franz 441
                        ite->Width = wh.x();
442
                        ite->Height = wh.y();
217 Franz 443
                }
68 Franz 444
                else if( STag == "circle" )
217 Franz 445
                {
68 Franz 446
                        addGraphicContext();
3292 cbradney 447
                        double r = parseUnit( b.attribute( "r" ) );
448
                        double x = parseUnit( b.attribute( "cx" ) ) - r;
449
                        double y = parseUnit( b.attribute( "cy" ) ) - r;
68 Franz 450
                        SvgStyle *gc = m_gc.current();
451
                        parseStyle( gc, b );
3292 cbradney 452
                        //z = ScApp->view->PaintEllipse(BaseX, BaseY, r * 2.0, r * 2.0, gc->LWidth, gc->FillCol, gc->StrokeCol);
453
                        z = currDoc->itemAdd(PageItem::Polygon, PageItem::Ellipse, BaseX, BaseY, r * 2.0, r * 2.0, gc->LWidth, gc->FillCol, gc->StrokeCol, !ScApp->view->Mpressed);
454
                        PageItem* ite = currDoc->Items.at(z);
68 Franz 455
                        QWMatrix mm = QWMatrix();
456
                        mm.translate(x, y);
457
                        ite->PoLine.map(mm);
1065 cbradney 458
                        FPoint wh = getMaxClipF(&ite->PoLine);
95 Franz 459
                        ite->Width = wh.x();
460
                        ite->Height = wh.y();
217 Franz 461
                }
68 Franz 462
                else if( STag == "line" )
217 Franz 463
                {
68 Franz 464
                        addGraphicContext();
465
                        double x1 = b.attribute( "x1" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "x1" ) );
466
                        double y1 = b.attribute( "y1" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "y1" ) );
467
                        double x2 = b.attribute( "x2" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "x2" ) );
468
                        double y2 = b.attribute( "y2" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "y2" ) );
469
                        SvgStyle *gc = m_gc.current();
470
                        parseStyle( gc, b );
3292 cbradney 471
                        //z = ScApp->view->PaintPoly(BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol);
472
                        z = currDoc->itemAdd(PageItem::Polygon, PageItem::Unspecified, BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol, !ScApp->view->Mpressed);
473
                        PageItem* ite = currDoc->Items.at(z);
68 Franz 474
                        ite->PoLine.resize(4);
475
                        ite->PoLine.setPoint(0, FPoint(x1, y1));
476
                        ite->PoLine.setPoint(1, FPoint(x1, y1));
477
                        ite->PoLine.setPoint(2, FPoint(x2, y2));
478
                        ite->PoLine.setPoint(3, FPoint(x2, y2));
217 Franz 479
                }
68 Franz 480
                else if( STag == "clipPath" )
217 Franz 481
                {
68 Franz 482
                        QDomNode n2 = b.firstChild();
483
                        QDomElement b2 = n2.toElement();
484
                        parseSVG( b2.attribute( "d" ), &ImgClip );
485
                        continue;
217 Franz 486
                }
68 Franz 487
                else if( STag == "path" )
217 Franz 488
                {
68 Franz 489
                        addGraphicContext();
490
                        SvgStyle *gc = m_gc.current();
491
                        parseStyle( gc, b );
3292 cbradney 492
                        //z = ScApp->view->PaintPoly(BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol);
493
                        z = currDoc->itemAdd(PageItem::Polygon, PageItem::Unspecified, BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol, !ScApp->view->Mpressed);
494
                        PageItem* ite = currDoc->Items.at(z);
68 Franz 495
                        ite->PoLine.resize(0);
496
                        if (parseSVG( b.attribute( "d" ), &ite->PoLine ))
1460 cbradney 497
                                ite->convertTo(PageItem::PolyLine);
68 Franz 498
                        if (ite->PoLine.size() < 4)
217 Franz 499
                        {
3207 craig 500
                                ScApp->view->SelItem.append(ite);
501
                                ScApp->view->DeleteItem();
68 Franz 502
                                z = -1;
503
                        }
217 Franz 504
                }
68 Franz 505
                else if( STag == "polyline" || b.tagName() == "polygon" )
217 Franz 506
                {
68 Franz 507
                        addGraphicContext();
508
                        SvgStyle *gc = m_gc.current();
509
                        parseStyle( gc, b );
510
                        if( b.tagName() == "polygon" )
3292 cbradney 511
                                //z = ScApp->view->PaintPoly(BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol);
512
                                z = currDoc->itemAdd(PageItem::Polygon, PageItem::Unspecified, BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol, !ScApp->view->Mpressed);
68 Franz 513
                        else
3292 cbradney 514
                                //z = ScApp->view->PaintPolyLine(BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol);
515
                                z = currDoc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, BaseX, BaseY, 10, 10, gc->LWidth, gc->FillCol, gc->StrokeCol, !ScApp->view->Mpressed);
516
                        PageItem* ite = currDoc->Items.at(z);
68 Franz 517
                        ite->PoLine.resize(0);
518
                        bool bFirst = true;
519
                        double x = 0.0;
520
                        double y = 0.0;
521
                        QString points = b.attribute( "points" ).simplifyWhiteSpace();
522
                        points.replace( QRegExp( "," ), " " );
523
                        points.replace( QRegExp( "\r" ), "" );
217 Franz 524
                        points.replace( QRegExp( "\n" ), "" );
68 Franz 525
                        QStringList pointList = QStringList::split( ' ', points );
526
                        FirstM = true;
527
                        for( QStringList::Iterator it = pointList.begin(); it != pointList.end(); it++ )
217 Franz 528
                        {
529
                                if( bFirst )
68 Franz 530
                                {
531
                                        x = (*(it++)).toDouble();
532
                                        y = (*it).toDouble();
2597 fschmid 533
                                        svgMoveTo(x * Conversion, y * Conversion);
68 Franz 534
                                        bFirst = false;
535
                                        WasM = true;
217 Franz 536
                                }
68 Franz 537
                                else
217 Franz 538
                                {
68 Franz 539
                                        x = (*(it++)).toDouble();
540
                                        y = (*it).toDouble();
2597 fschmid 541
                                        svgLineTo(&ite->PoLine, x * Conversion, y * Conversion);
68 Franz 542
                                }
217 Franz 543
                        }
68 Franz 544
                        if( STag == "polygon" )
545
                                svgClosePath(&ite->PoLine);
546
                        else
1460 cbradney 547
                                ite->convertTo(PageItem::PolyLine);
217 Franz 548
                }
68 Franz 549
                else if( STag == "text" )
217 Franz 550
                {
68 Franz 551
                        addGraphicContext();
552
                        SvgStyle *gc = m_gc.current();
553
                        double x = b.attribute( "x" ).isEmpty() ? 0.0 : parseUnit(b.attribute("x"));
554
                        double y = b.attribute( "y" ).isEmpty() ? 0.0 : parseUnit(b.attribute("y"));
555
                        parseStyle(gc, b);
456 fschmid 556
                        QPtrList<PageItem> el = parseText(x+BaseX, y+BaseY, b);
215 Franz 557
                        for (uint ec = 0; ec < el.count(); ++ec)
558
                        {
559
                                GElements.append(el.at(ec));
68 Franz 560
                        }
215 Franz 561
                        z = -1;
217 Franz 562
                }
68 Franz 563
                else if( STag == "image" )
217 Franz 564
                {
68 Franz 565
                        addGraphicContext();
566
                        QString fname = b.attribute("xlink:href");
567
                        double x = b.attribute( "x" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "x" ) );
568
                        double y = b.attribute( "y" ).isEmpty() ? 0.0 : parseUnit( b.attribute( "y" ) );
569
                        double w = b.attribute( "width" ).isEmpty() ? 1.0 : parseUnit( b.attribute( "width" ) );
570
                        double h = b.attribute( "height" ).isEmpty() ? 1.0 : parseUnit( b.attribute( "height" ) );
3292 cbradney 571
                        //z = ScApp->view->PaintPict(x+BaseX, y+BaseY, w, h);
572
                        z = currDoc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, x+BaseX, y+BaseY, w, h, 1, currDoc->toolSettings.dBrushPict, "None", !ScApp->view->Mpressed);
2877 cbradney 573
                        if (!fname.isEmpty())
3207 craig 574
                                ScApp->view->LoadPict(fname, z);
3292 cbradney 575
                        PageItem* ite = currDoc->Items.at(z);
68 Franz 576
                        if (ImgClip.size() != 0)
577
                                ite->PoLine = ImgClip.copy();
578
                        ImgClip.resize(0);
579
                        ite->Clip = FlattenPath(ite->PoLine, ite->Segments);
217 Franz 580
                }
68 Franz 581
                else
582
                        continue;
583
                if (z != -1)
217 Franz 584
                {
68 Franz 585
                        setupTransform( b );
586
                        SvgStyle *gc = m_gc.current();
3292 cbradney 587
                        PageItem* ite = currDoc->Items.at(z);
1460 cbradney 588
                        switch (ite->itemType())
217 Franz 589
                        {
1460 cbradney 590
                        case PageItem::ImageFrame:
68 Franz 591
                                {
592
                                        QWMatrix mm = gc->matrix;
593
                                        ite->Xpos += mm.dx();
594
                                        ite->Ypos += mm.dy();
595
                                        ite->Width = ite->Width * mm.m11();
596
                                        ite->Height = ite->Height * mm.m22();
330 Franz 597
                                        ite->Pwidth = ite->Pwidth * ((mm.m11() + mm.m22()) / 2.0);
68 Franz 598
                                        if (ite->PicAvail)
217 Franz 599
                                        {
68 Franz 600
                                                ite->LocalScX = ite->Width / ite->pixm.width();
601
                                                ite->LocalScY = ite->Height / ite->pixm.height();
602
                                        }
603
                                        break;
217 Franz 604
                                }
1460 cbradney 605
                        case PageItem::TextFrame:
330 Franz 606
                                {
607
                                        QWMatrix mm = gc->matrix;
608
                                        ite->Pwidth = ite->Pwidth * ((mm.m11() + mm.m22()) / 2.0);
609
                                }
217 Franz 610
                                break;
611
                        default:
612
                                {
68 Franz 613
                                        ite->ClipEdited = true;
614
                                        ite->FrameType = 3;
615
                                        QWMatrix mm = gc->matrix;
616
                                        ite->PoLine.map(mm);
1013 fschmid 617
                                        if (haveViewBox)
618
                                        {
619
                                                QWMatrix mv;
620
                                                mv.translate(viewTransformX, viewTransformY);
621
                                                mv.scale(viewScaleX, viewScaleY);
622
                                                ite->PoLine.map(mv);
623
                                        }
330 Franz 624
                                        ite->Pwidth = ite->Pwidth * ((mm.m11() + mm.m22()) / 2.0);
1065 cbradney 625
                                        FPoint wh = getMaxClipF(&ite->PoLine);
95 Franz 626
                                        ite->Width = wh.x();
627
                                        ite->Height = wh.y();
68 Franz 628
                                        ite->Clip = FlattenPath(ite->PoLine, ite->Segments);
3207 craig 629
                                        ScApp->view->AdjustItemSize(ite);
68 Franz 630
                                        break;
631
                                }
217 Franz 632
                        }
68 Franz 633
                        if( !b.attribute("id").isEmpty() )
1361 tsoots 634
                                ite->setItemName(" "+b.attribute("id"));
1394 cbradney 635
                        ite->setFillTransparency(gc->Transparency);
636
                        ite->setLineTransparency(gc->TranspStroke);
68 Franz 637
                        ite->PLineEnd = gc->PLineEnd;
638
                        ite->PLineJoin = gc->PLineJoin;
1653 craig 639
                        ite->setTextFlowsAroundFrame(false);
68 Franz 640
                        ite->DashOffset = gc->dashOffset;
641
                        ite->DashValues = gc->dashArray;
642
                        if (gc->Gradient != 0)
217 Franz 643
                        {
298 Franz 644
                                ite->fill_gradient = gc->GradCo;
645
                                if (!gc->CSpace)
296 Franz 646
                                {
298 Franz 647
                                        ite->GrStartX = gc->GX1 * ite->Width;
648
                                        ite->GrStartY = gc->GY1 * ite->Height;
649
                                        ite->GrEndX = gc->GX2 * ite->Width;
650
                                        ite->GrEndY = gc->GY2 * ite->Height;
302 Franz 651
                                        double angle1 = atan2(gc->GY2-gc->GY1,gc->GX2-gc->GX1)*(180.0/M_PI);
652
                                        double angle2 = atan2(ite->GrEndY-ite->GrStartX,ite->GrEndX-ite->GrStartX)*(180.0/M_PI);
653
                                        double dx = ite->GrStartX + (ite->GrEndX-ite->GrStartX) / 2.0;
654
                                        double dy = ite->GrStartY + (ite->GrEndY-ite->GrStartY) / 2.0;
776 fschmid 655
                                        QWMatrix mm, mm2;
308 Franz 656
                                        if ((gc->GY1 < gc->GY2) && (gc->GX1 < gc->GX2))
302 Franz 657
                                        {
658
                                                mm.rotate(-angle2);
776 fschmid 659
                                                mm2.rotate(angle1);
302 Franz 660
                                        }
661
                                        FPointArray gra;
662
                                        gra.setPoints(2, ite->GrStartX-dx, ite->GrStartY-dy, ite->GrEndX-dx, ite->GrEndY-dy);
776 fschmid 663
                                        gra.map(mm*mm2);
302 Franz 664
                                        gra.translate(dx, dy);
665
                                        ite->GrStartX = gra.point(0).x();
666
                                        ite->GrStartY = gra.point(0).y();
667
                                        ite->GrEndX = gra.point(1).x();
668
                                        ite->GrEndY = gra.point(1).y();
298 Franz 669
                                }
670
                                else
671
                                {
296 Franz 672
                                        QWMatrix mm = gc->matrix;
302 Franz 673
                                        mm = mm * gc->matrixg;
296 Franz 674
                                        FPointArray gra;
675
                                        gra.setPoints(2, gc->GX1, gc->GY1, gc->GX2, gc->GY2);
676
                                        gra.map(mm);
677
                                        gc->GX1 = gra.point(0).x();
678
                                        gc->GY1 = gra.point(0).y();
679
                                        gc->GX2 = gra.point(1).x();
680
                                        gc->GY2 = gra.point(1).y();
456 fschmid 681
                                        ite->GrStartX = gc->GX1 - ite->Xpos+BaseX;
682
                                        ite->GrStartY = gc->GY1 - ite->Ypos+BaseY;
683
                                        ite->GrEndX = gc->GX2 - ite->Xpos+BaseX;
684
                                        ite->GrEndY = gc->GY2 - ite->Ypos+BaseY;
298 Franz 685
                                }
296 Franz 686
                                ite->GrType = gc->Gradient;
217 Franz 687
                        }
68 Franz 688
                        GElements.append(ite);
689
                        Elements.append(ite);
217 Franz 690
                }
68 Franz 691
                delete( m_gc.pop() );
217 Franz 692
        }
991 fschmid 693
        return GElements;
68 Franz 694
}
695
 
202 Franz 696
/*!
697
 \fn double SVGPlug::fromPercentage( const QString &s )
698
 \author Franz Schmid
699
 \date
700
 \brief
701
 \param s const QString &
702
 \retval double
703
 */
68 Franz 704
double SVGPlug::fromPercentage( const QString &s )
705
{
706
        if( s.endsWith( "%" ) )
707
                return s.toDouble() / 100.0;
708
        else
709
                return s.toDouble();
710
}
711
 
202 Franz 712
/*!
713
 \fn double SVGPlug::parseUnit(const QString &unit)
714
 \author Franz Schmid
715
 \date
716
 \brief
717
 \param unit const QString &
718
 \retval double
719
 */
68 Franz 720
double SVGPlug::parseUnit(const QString &unit)
721
{
693 fschmid 722
        bool noUnit = false;
270 Franz 723
        QString unitval=unit;
724
        if( unit.right( 2 ) == "pt" )
725
                unitval.replace( "pt", "" );
726
        else if( unit.right( 2 ) == "cm" )
727
                unitval.replace( "cm", "" );
728
        else if( unit.right( 2 ) == "mm" )
729
                unitval.replace( "mm" , "" );
730
        else if( unit.right( 2 ) == "in" )
731
                unitval.replace( "in", "" );
732
        else if( unit.right( 2 ) == "px" )
733
                unitval.replace( "px", "" );
693 fschmid 734
        if (unitval == unit)
735
                noUnit = true;
270 Franz 736
        double value = unitval.toDouble();
737
        if( unit.right( 2 ) == "pt" )
738
                value = value;
739
        else if( unit.right( 2 ) == "cm" )
740
                value = ( value / 2.54 ) * 72;
741
        else if( unit.right( 2 ) == "mm" )
742
                value = ( value / 25.4 ) * 72;
743
        else if( unit.right( 2 ) == "in" )
744
                value = value * 72;
745
        else if( unit.right( 2 ) == "px" )
865 fschmid 746
                value = value * 0.8;
693 fschmid 747
        else if(noUnit)
976 fschmid 748
                value = value * Conversion;
68 Franz 749
        return value;
750
}
751
 
202 Franz 752
/*!
753
 \fn QWMatrix SVGPlug::parseTransform( const QString &transform )
754
 \author Franz Schmid
755
 \date
756
 \brief
757
 \param transform const QString
758
 \retval QWMatrix
759
 */
68 Franz 760
QWMatrix SVGPlug::parseTransform( const QString &transform )
761
{
2597 fschmid 762
        QWMatrix ret;
68 Franz 763
        // Split string for handling 1 transform statement at a time
764
        QStringList subtransforms = QStringList::split(')', transform);
765
        QStringList::ConstIterator it = subtransforms.begin();
766
        QStringList::ConstIterator end = subtransforms.end();
767
        for(; it != end; ++it)
768
        {
2597 fschmid 769
                QWMatrix result;
68 Franz 770
                QStringList subtransform = QStringList::split('(', (*it));
771
                subtransform[0] = subtransform[0].stripWhiteSpace().lower();
772
                subtransform[1] = subtransform[1].simplifyWhiteSpace();
773
                QRegExp reg("[,( ]");
774
                QStringList params = QStringList::split(reg, subtransform[1]);
775
                if(subtransform[0].startsWith(";") || subtransform[0].startsWith(","))
776
                        subtransform[0] = subtransform[0].right(subtransform[0].length() - 1);
777
                if(subtransform[0] == "rotate")
778
                {
779
                        if(params.count() == 3)
780
                        {
976 fschmid 781
                                double x = params[1].toDouble() * Conversion;
782
                                double y = params[2].toDouble() * Conversion;
68 Franz 783
                                result.translate(x, y);
784
                                result.rotate(params[0].toDouble());
785
                                result.translate(-x, -y);
786
                        }
787
                        else
788
                                result.rotate(params[0].toDouble());
789
                }
790
                else if(subtransform[0] == "translate")
791
                {
792
                        if(params.count() == 2)
976 fschmid 793
                                result.translate(params[0].toDouble() * Conversion, params[1].toDouble() * Conversion);
68 Franz 794
                        else    // Spec : if only one param given, assume 2nd param to be 0
2597 fschmid 795
                                result.translate(params[0].toDouble() * Conversion, 0);
68 Franz 796
                }
797
                else if(subtransform[0] == "scale")
798
                {
799
                        if(params.count() == 2)
800
                                result.scale(params[0].toDouble(), params[1].toDouble());
801
                        else    // Spec : if only one param given, assume uniform scaling
802
                                result.scale(params[0].toDouble(), params[0].toDouble());
803
                }
804
                else if(subtransform[0] == "skewx")
805
                        result.shear(tan(params[0].toDouble() * 0.01745329251994329576), 0.0F);
806
                else if(subtransform[0] == "skewy")
807
                        result.shear(0.0F, tan(params[0].toDouble() * 0.01745329251994329576));
808
                else if(subtransform[0] == "matrix")
809
                {
810
                        if(params.count() >= 6)
332 Franz 811
                        {
812
                                double sx = params[0].toDouble();
813
                                double sy = params[3].toDouble();
976 fschmid 814
                                result.setMatrix(sx, params[1].toDouble(), params[2].toDouble(), sy, params[4].toDouble() * Conversion, params[5].toDouble() * Conversion);
332 Franz 815
                        }
68 Franz 816
                }
2597 fschmid 817
                ret = ret * result;
68 Franz 818
        }
2597 fschmid 819
        return ret;
68 Franz 820
}
821
 
202 Franz 822
/*!
823
 \fn const char * SVGPlug::getCoord( const char *ptr, double &number )
824
 \author Franz Schmid
825
 \date
826
 \brief
827
 \param ptr const char *
828
 \param number double &
829
 \retval const char *
830
 */
68 Franz 831
const char * SVGPlug::getCoord( const char *ptr, double &number )
832
{
833
        int integer, exponent;
834
        double decimal, frac;
835
        int sign, expsign;
836
 
837
        exponent = 0;
838
        integer = 0;
839
        frac = 1.0;
840
        decimal = 0;
841
        sign = 1;
842
        expsign = 1;
843
 
844
        // read the sign
845
        if(*ptr == '+')
846
                ptr++;
847
        else if(*ptr == '-')
848
        {
849
                ptr++;
850
                sign = -1;
851
        }
852
 
853
        // read the integer part
854
        while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
855
                integer = (integer * 10) + *(ptr++) - '0';
856
        if(*ptr == '.') // read the decimals
217 Franz 857
        {
68 Franz 858
                ptr++;
859
                while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
860
                        decimal += (*(ptr++) - '0') * (frac *= 0.1);
217 Franz 861
        }
68 Franz 862
 
863
        if(*ptr == 'e' || *ptr == 'E') // read the exponent part
864
        {
865
                ptr++;
866
 
867
                // read the sign of the exponent
868
                if(*ptr == '+')
869
                        ptr++;
870
                else if(*ptr == '-')
871
                {
872
                        ptr++;
873
                        expsign = -1;
874
                }
875
 
876
                exponent = 0;
877
                while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
878
                {
879
                        exponent *= 10;
880
                        exponent += *ptr - '0';
881
                        ptr++;
882
                }
217 Franz 883
        }
68 Franz 884
        number = integer + decimal;
80 Franz 885
        number *= sign * pow( static_cast<double>(10), static_cast<double>( expsign * exponent ) );
68 Franz 886
        // skip the following space
887
        if(*ptr == ' ')
888
                ptr++;
889
 
890
        return ptr;
891
}
892
 
202 Franz 893
/*!
894
 \fn bool SVGPlug::parseSVG( const QString &s, FPointArray *ite )
895
 \author Franz Schmid
896
 \date
897
 \brief
898
 \param s const QString &
899
 \param ite FPointArray *
900
 \retval bool
901
 */
68 Franz 902
bool SVGPlug::parseSVG( const QString &s, FPointArray *ite )
903
{
904
        QString d = s;
905
        d = d.replace( QRegExp( "," ), " ");
906
        bool ret = false;
907
        if( !d.isEmpty() )
217 Franz 908
        {
68 Franz 909
                d = d.simplifyWhiteSpace();
910
                const char *ptr = d.latin1();
911
                const char *end = d.latin1() + d.length() + 1;
912
                double contrlx, contrly, curx, cury, subpathx, subpathy, tox, toy, x1, y1, x2, y2, xc, yc;
913
                double px1, py1, px2, py2, px3, py3;
914
                bool relative;
915
                FirstM = true;
916
                char command = *(ptr++), lastCommand = ' ';
917
                subpathx = subpathy = curx = cury = contrlx = contrly = 0.0;
918
                while( ptr < end )
217 Franz 919
                {
68 Franz 920
                        if( *ptr == ' ' )
921
                                ptr++;
922
                        relative = false;
923
                        switch( command )
924
                        {
217 Franz 925
                        case 'm':
926
                                relative = true;
927
                        case 'M':
928
                                {
68 Franz 929
                                        ptr = getCoord( ptr, tox );
930
                                        ptr = getCoord( ptr, toy );
976 fschmid 931
                                        tox *= Conversion;
932
                                        toy *= Conversion;
68 Franz 933
                                        WasM = true;
934
                                        subpathx = curx = relative ? curx + tox : tox;
935
                                        subpathy = cury = relative ? cury + toy : toy;
456 fschmid 936
                                        svgMoveTo(curx, cury );
68 Franz 937
                                        break;
217 Franz 938
                                }
939
                        case 'l':
940
                                relative = true;
941
                        case 'L':
942
                                {
68 Franz 943
                                        ptr = getCoord( ptr, tox );
944
                                        ptr = getCoord( ptr, toy );
976 fschmid 945
                                        tox *= Conversion;
946
                                        toy *= Conversion;
68 Franz 947
                                        curx = relative ? curx + tox : tox;
948
                                        cury = relative ? cury + toy : toy;
949
                                        svgLineTo(ite, curx, cury );
950
                                        break;
217 Franz 951
                                }
952
                        case 'h':
953
                                {
68 Franz 954
                                        ptr = getCoord( ptr, tox );
976 fschmid 955
                                        tox *= Conversion;
68 Franz 956
                                        curx = curx + tox;
957
                                        svgLineTo(ite, curx, cury );
958
                                        break;
217 Franz 959
                                }
960
                        case 'H':
961
                                {
68 Franz 962
                                        ptr = getCoord( ptr, tox );
976 fschmid 963
                                        tox *= Conversion;
68 Franz 964
                                        curx = tox;
965
                                        svgLineTo(ite, curx, cury );
966
                                        break;
217 Franz 967
                                }
968
                        case 'v':
969
                                {
68 Franz 970
                                        ptr = getCoord( ptr, toy );
976 fschmid 971
                                        toy *= Conversion;
68 Franz 972
                                        cury = cury + toy;
973
                                        svgLineTo(ite, curx, cury );
974
                                        break;
217 Franz 975
                                }
976
                        case 'V':
977
                                {
68 Franz 978
                                        ptr = getCoord( ptr, toy );
976 fschmid 979
                                        toy *= Conversion;
68 Franz 980
                                        cury = toy;
981
                                        svgLineTo(ite,  curx, cury );
982
                                        break;
217 Franz 983
                                }
984
                        case 'z':
985
                        case 'Z':
986
                                {
68 Franz 987
                                        curx = subpathx;
988
                                        cury = subpathy;
989
                                        svgClosePath(ite);
990
                                        break;
217 Franz 991
                                }
992
                        case 'c':
993
                                relative = true;
994
                        case 'C':
995
                                {
68 Franz 996
                                        ptr = getCoord( ptr, x1 );
997
                                        ptr = getCoord( ptr, y1 );
998
                                        ptr = getCoord( ptr, x2 );
999
                                        ptr = getCoord( ptr, y2 );
1000
                                        ptr = getCoord( ptr, tox );
1001
                                        ptr = getCoord( ptr, toy );
976 fschmid 1002
                                        tox *= Conversion;
1003
                                        toy *= Conversion;
1004
                                        x1 *= Conversion;
1005
                                        y1 *= Conversion;
1006
                                        x2 *= Conversion;
1007
                                        y2 *= Conversion;
68 Franz 1008
                                        px1 = relative ? curx + x1 : x1;
1009
                                        py1 = relative ? cury + y1 : y1;
1010
                                        px2 = relative ? curx + x2 : x2;
1011
                                        py2 = relative ? cury + y2 : y2;
1012
                                        px3 = relative ? curx + tox : tox;
1013
                                        py3 = relative ? cury + toy : toy;
217 Franz 1014
                                        svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 );
1015
                                        contrlx = relative ? curx + x2 : x2;
68 Franz 1016
                                        contrly = relative ? cury + y2 : y2;
1017
                                        curx = relative ? curx + tox : tox;
1018
                                        cury = relative ? cury + toy : toy;
1019
                                        break;
217 Franz 1020
                                }
1021
                        case 's':
1022
                                relative = true;
1023
                        case 'S':
1024
                                {
68 Franz 1025
                                        ptr = getCoord( ptr, x2 );
1026
                                        ptr = getCoord( ptr, y2 );
1027
                                        ptr = getCoord( ptr, tox );
1028
                                        ptr = getCoord( ptr, toy );
976 fschmid 1029
                                        tox *= Conversion;
1030
                                        toy *= Conversion;
1031
                                        x2 *= Conversion;
1032
                                        y2 *= Conversion;
68 Franz 1033
                                        px1 = 2 * curx - contrlx;
1034
                                        py1 = 2 * cury - contrly;
1035
                                        px2 = relative ? curx + x2 : x2;
1036
                                        py2 = relative ? cury + y2 : y2;
1037
                                        px3 = relative ? curx + tox : tox;
1038
                                        py3 = relative ? cury + toy : toy;
1039
                                        svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 );
1040
                                        contrlx = relative ? curx + x2 : x2;
1041
                                        contrly = relative ? cury + y2 : y2;
1042
                                        curx = relative ? curx + tox : tox;
1043
                                        cury = relative ? cury + toy : toy;
1044
                                        break;
217 Franz 1045
                                }
1046
                        case 'q':
1047
                                relative = true;
1048
                        case 'Q':
1049
                                {
68 Franz 1050
                                        ptr = getCoord( ptr, x1 );
1051
                                        ptr = getCoord( ptr, y1 );
1052
                                        ptr = getCoord( ptr, tox );
1053
                                        ptr = getCoord( ptr, toy );
976 fschmid 1054
                                        tox *= Conversion;
1055
                                        toy *= Conversion;
1056
                                        x1 *= Conversion;
1057
                                        y1 *= Conversion;
68 Franz 1058
                                        px1 = relative ? (curx + 2 * (x1 + curx)) * (1.0 / 3.0) : (curx + 2 * x1) * (1.0 / 3.0);
1059
                                        py1 = relative ? (cury + 2 * (y1 + cury)) * (1.0 / 3.0) : (cury + 2 * y1) * (1.0 / 3.0);
1060
                                        px2 = relative ? ((curx + tox) + 2 * (x1 + curx)) * (1.0 / 3.0) : (tox + 2 * x1) * (1.0 / 3.0);
1061
                                        py2 = relative ? ((cury + toy) + 2 * (y1 + cury)) * (1.0 / 3.0) : (toy + 2 * y1) * (1.0 / 3.0);
1062
                                        px3 = relative ? curx + tox : tox;
1063
                                        py3 = relative ? cury + toy : toy;
1064
                                        svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 );
1065
                                        contrlx = relative ? curx + x1 : (tox + 2 * x1) * (1.0 / 3.0);
1066
                                        contrly = relative ? cury + y1 : (toy + 2 * y1) * (1.0 / 3.0);
1067
                                        curx = relative ? curx + tox : tox;
1068
                                        cury = relative ? cury + toy : toy;
1069
                                        break;
217 Franz 1070
                                }
1071
                        case 't':
1072
                                relative = true;
1073
                        case 'T':
1074
                                {
68 Franz 1075
                                        ptr = getCoord(ptr, tox);
1076
                                        ptr = getCoord(ptr, toy);
976 fschmid 1077
                                        tox *= Conversion;
1078
                                        toy *= Conversion;
68 Franz 1079
                                        xc = 2 * curx - contrlx;
1080
                                        yc = 2 * cury - contrly;
1081
                                        px1 = relative ? (curx + 2 * xc) * (1.0 / 3.0) : (curx + 2 * xc) * (1.0 / 3.0);
1082
                                        py1 = relative ? (cury + 2 * yc) * (1.0 / 3.0) : (cury + 2 * yc) * (1.0 / 3.0);
1083
                                        px2 = relative ? ((curx + tox) + 2 * xc) * (1.0 / 3.0) : (tox + 2 * xc) * (1.0 / 3.0);
1084
                                        py2 = relative ? ((cury + toy) + 2 * yc) * (1.0 / 3.0) : (toy + 2 * yc) * (1.0 / 3.0);
1085
                                        px3 = relative ? curx + tox : tox;
1086
                                        py3 = relative ? cury + toy : toy;
1087
                                        svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 );
1088
                                        contrlx = xc;
1089
                                        contrly = yc;
1090
                                        curx = relative ? curx + tox : tox;
1091
                                        cury = relative ? cury + toy : toy;
1092
                                        break;
217 Franz 1093
                                }
1094
                        case 'a':
1095
                                relative = true;
1096
                        case 'A':
1097
                                {
68 Franz 1098
                                        bool largeArc, sweep;
1099
                                        double angle, rx, ry;
1100
                                        ptr = getCoord( ptr, rx );
1101
                                        ptr = getCoord( ptr, ry );
1102
                                        ptr = getCoord( ptr, angle );
1103
                                        ptr = getCoord( ptr, tox );
976 fschmid 1104
                                        ry *= Conversion;
1105
                                        rx *= Conversion;
68 Franz 1106
                                        largeArc = tox == 1;
1107
                                        ptr = getCoord( ptr, tox );
1108
                                        sweep = tox == 1;
1109
                                        ptr = getCoord( ptr, tox );
1110
                                        ptr = getCoord( ptr, toy );
976 fschmid 1111
                                        tox *= Conversion;
1112
                                        toy *= Conversion;
68 Franz 1113
                                        calculateArc(ite, relative, curx, cury, angle, tox, toy, rx, ry, largeArc, sweep );
1114
                                }
217 Franz 1115
                        }
68 Franz 1116
                        lastCommand = command;
1117
                        if(*ptr == '+' || *ptr == '-' || (*ptr >= '0' && *ptr <= '9'))
217 Franz 1118
                        {
68 Franz 1119
                                // there are still coords in this command
1120
                                if(command == 'M')
1121
                                        command = 'L';
1122
                                else if(command == 'm')
1123
                                        command = 'l';
217 Franz 1124
                        }
68 Franz 1125
                        else
1126
                                command = *(ptr++);
1127
 
1128
                        if( lastCommand != 'C' && lastCommand != 'c' &&
217 Franz 1129
                                lastCommand != 'S' && lastCommand != 's' &&
1130
                                lastCommand != 'Q' && lastCommand != 'q' &&
1131
                                lastCommand != 'T' && lastCommand != 't')
68 Franz 1132
                        {
1133
                                contrlx = curx;
1134
                                contrly = cury;
1135
                        }
1136
                }
1137
                if ((lastCommand != 'z') && (lastCommand != 'Z'))
1138
                        ret = true;
1139
                if (ite->size() > 2)
217 Franz 1140
                {
68 Franz 1141
                        if ((ite->point(0).x() == ite->point(ite->size()-2).x()) && (ite->point(0).y() == ite->point(ite->size()-2).y()))
1142
                                ret = false;
217 Franz 1143
                }
68 Franz 1144
        }
1145
        return ret;
1146
}
1147
 
202 Franz 1148
/*!
1149
 \fn void SVGPlug::calculateArc(FPointArray *ite, bool relative, double &curx, double &cury, double angle, double x, double y, double r1, double r2, bool largeArcFlag, bool sweepFlag)
1150
 \author Franz Schmid
1151
 \date
1152
 \brief
1153
 \param ite FPointArray *
1154
 \param relative bool
1155
 \param curx double &
1156
 \param cury double &
1157
 \param angle double
1158
 \param x double
1159
 \param y double
1160
 \param r1 double
1161
 \param r2 double
1162
 \param largeArcFlag bool
1163
 \param sweepFlag bool
1164
 \retval None
1165
 */
68 Franz 1166
void SVGPlug::calculateArc(FPointArray *ite, bool relative, double &curx, double &cury, double angle, double x, double y, double r1, double r2, bool largeArcFlag, bool sweepFlag)
1167
{
1168
        double sin_th, cos_th;
1169
        double a00, a01, a10, a11;
1170
        double x0, y0, x1, y1, xc, yc;
1171
        double d, sfactor, sfactor_sq;
1172
        double th0, th1, th_arc;
1173
        int i, n_segs;
1174
        sin_th = sin(angle * (M_PI / 180.0));
1175
        cos_th = cos(angle * (M_PI / 180.0));
1176
        double dx;
1177
        if(!relative)
1178
                dx = (curx - x) / 2.0;
1179
        else
1180
                dx = -x / 2.0;
1181
        double dy;
1182
        if(!relative)
1183
                dy = (cury - y) / 2.0;
1184
        else
1185
                dy = -y / 2.0;
1186
        double _x1 =  cos_th * dx + sin_th * dy;
1187
        double _y1 = -sin_th * dx + cos_th * dy;
1188
        double Pr1 = r1 * r1;
1189
        double Pr2 = r2 * r2;
1190
        double Px = _x1 * _x1;
1191
        double Py = _y1 * _y1;
1192
        // Spec : check if radii are large enough
1193
        double check = Px / Pr1 + Py / Pr2;
1194
        if(check > 1)
1195
        {
1196
                r1 = r1 * sqrt(check);
1197
                r2 = r2 * sqrt(check);
1198
        }
1199
        a00 = cos_th / r1;
1200
        a01 = sin_th / r1;
1201
        a10 = -sin_th / r2;
1202
        a11 = cos_th / r2;
1203
        x0 = a00 * curx + a01 * cury;
1204
        y0 = a10 * curx + a11 * cury;
1205
        if(!relative)
1206
                x1 = a00 * x + a01 * y;
1207
        else
1208
                x1 = a00 * (curx + x) + a01 * (cury + y);
1209
        if(!relative)
1210
                y1 = a10 * x + a11 * y;
1211
        else
1212
                y1 = a10 * (curx + x) + a11 * (cury + y);
1213
        /* (x0, y0) is current point in transformed coordinate space.
1214
           (x1, y1) is new point in transformed coordinate space.
1215
 
1216
           The arc fits a unit-radius circle in this space.
217 Franz 1217
            */
68 Franz 1218
        d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
1219
        sfactor_sq = 1.0 / d - 0.25;
1220
        if(sfactor_sq < 0)
1221
                sfactor_sq = 0;
1222
        sfactor = sqrt(sfactor_sq);
1223
        if(sweepFlag == largeArcFlag)
1224
                sfactor = -sfactor;
1225
        xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
1226
        yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
1227
 
1228
        /* (xc, yc) is center of the circle. */
1229
        th0 = atan2(y0 - yc, x0 - xc);
1230
        th1 = atan2(y1 - yc, x1 - xc);
1231
        th_arc = th1 - th0;
1232
        if(th_arc < 0 && sweepFlag)
1233
                th_arc += 2 * M_PI;
1234
        else if(th_arc > 0 && !sweepFlag)
1235
                th_arc -= 2 * M_PI;
80 Franz 1236
        n_segs = static_cast<int>(ceil(fabs(th_arc / (M_PI * 0.5 + 0.001))));
68 Franz 1237
        for(i = 0; i < n_segs; i++)
1238
        {
1239
                {
1240
                        double sin_th, cos_th;
1241
                        double a00, a01, a10, a11;
1242
                        double x1, y1, x2, y2, x3, y3;
1243
                        double t;
1244
                        double th_half;
1245
                        double _th0 = th0 + i * th_arc / n_segs;
1246
                        double _th1 = th0 + (i + 1) * th_arc / n_segs;
1247
                        sin_th = sin(angle * (M_PI / 180.0));
1248
                        cos_th = cos(angle * (M_PI / 180.0));
1249
                        /* inverse transform compared with rsvg_path_arc */
1250
                        a00 = cos_th * r1;
1251
                        a01 = -sin_th * r2;
1252
                        a10 = sin_th * r1;
1253
                        a11 = cos_th * r2;
1254
                        th_half = 0.5 * (_th1 - _th0);
1255
                        t = (8.0 / 3.0) * sin(th_half * 0.5) * sin(th_half * 0.5) / sin(th_half);
1256
                        x1 = xc + cos(_th0) - t * sin(_th0);
1257
                        y1 = yc + sin(_th0) + t * cos(_th0);
1258
                        x3 = xc + cos(_th1);
1259
                        y3 = yc + sin(_th1);
1260
                        x2 = x3 + t * sin(_th1);
1261
                        y2 = y3 - t * cos(_th1);
1262
                        svgCurveToCubic(ite, a00 * x1 + a01 * y1, a10 * x1 + a11 * y1, a00 * x2 + a01 * y2, a10 * x2 + a11 * y2, a00 * x3 + a01 * y3, a10 * x3 + a11 * y3 );
1263
                }
1264
        }
1265
        if(!relative)
1266
                curx = x;
1267
        else
1268
                curx += x;
1269
        if(!relative)
1270
                cury = y;
1271
        else
1272
                cury += y;
1273
}
1274
 
202 Franz 1275
/*!
1227 cbradney 1276
 \fn void SVGPlug::svgMoveTo(double x1, double y1)
202 Franz 1277
 \author Franz Schmid
1278
 \date
1279
 \brief
1280
 \param i FPointArray *
1281
 \param x1 double
1282
 \param y1 double
1283
 \retval None
1284
 */
456 fschmid 1285
void SVGPlug::svgMoveTo(double x1, double y1)
68 Franz 1286
{
1287
        CurrX = x1;
1288
        CurrY = y1;
1289
        StartX = x1;
1290
        StartY = y1;
1291
        PathLen = 0;
1292
}
1293
 
202 Franz 1294
/*!
1295
 \fn void SVGPlug::svgLineTo(FPointArray *i, double x1, double y1)
1296
 \author Franz Schmid
1297
 \date
1298
 \brief
1299
 \param i FPointArray *
1300
 \param x1 double
1301
 \param y1 double
1302
 \retval None
1303
 */
68 Franz 1304
void SVGPlug::svgLineTo(FPointArray *i, double x1, double y1)
1305
{
1306
        if ((!FirstM) && (WasM))
217 Franz 1307
        {
68 Franz 1308
                i->setMarker();
1309
                PathLen += 4;
217 Franz 1310
        }
68 Franz 1311
        FirstM = false;
1312
        WasM = false;
87 Franz 1313
        if (i->size() > 3)
217 Franz 1314
        {
87 Franz 1315
                FPoint b1 = i->point(i->size()-4);
1316
                FPoint b2 = i->point(i->size()-3);
1317
                FPoint b3 = i->point(i->size()-2);
1318
                FPoint b4 = i->point(i->size()-1);
1319
                FPoint n1 = FPoint(CurrX, CurrY);
1320
                FPoint n2 = FPoint(x1, y1);
1321
                if ((b1 == n1) && (b2 == n1) && (b3 == n2) && (b4 == n2))
1322
                        return;
217 Franz 1323
        }
87 Franz 1324
        i->addPoint(FPoint(CurrX, CurrY));
1325
        i->addPoint(FPoint(CurrX, CurrY));
1326
        i->addPoint(FPoint(x1, y1));
1327
        i->addPoint(FPoint(x1, y1));
68 Franz 1328
        CurrX = x1;
1329
        CurrY = y1;
1330
        PathLen += 4;
1331
}
1332
 
202 Franz 1333
/*!
1334
 \fn void SVGPlug::svgCurveToCubic(FPointArray *i, double x1, double y1, double x2, double y2, double x3, double y3)
1335
 \author Franz Schmid
1336
 \date
1337
 \brief
1338
 \param i FPointArray *
1339
 \param x1 double
1340
 \param y1 double
1341
 \param x2 double
1342
 \param y2 double
1343
 \param x3 double
1344
 \param y3 double
1345
 \retval None
1346
 */
68 Franz 1347
void SVGPlug::svgCurveToCubic(FPointArray *i, double x1, double y1, double x2, double y2, double x3, double y3)
1348
{
1349
        if ((!FirstM) && (WasM))
217 Franz 1350
        {
68 Franz 1351
                i->setMarker();
1352
                PathLen += 4;
217 Franz 1353
        }
68 Franz 1354
        FirstM = false;
1355
        WasM = false;
87 Franz 1356
        if (PathLen > 3)
217 Franz 1357
        {
87 Franz 1358
                FPoint b1 = i->point(i->size()-4);
1359
                FPoint b2 = i->point(i->size()-3);
1360
                FPoint b3 = i->point(i->size()-2);
1361
                FPoint b4 = i->point(i->size()-1);
1362
                FPoint n1 = FPoint(CurrX, CurrY);
1363
                FPoint n2 = FPoint(x1, y1);
1364
                FPoint n3 = FPoint(x3, y3);
1365
                FPoint n4 = FPoint(x2, y2);
1366
                if ((b1 == n1) && (b2 == n2) && (b3 == n3) && (b4 == n4))
1367
                        return;
217 Franz 1368
        }
87 Franz 1369
        i->addPoint(FPoint(CurrX, CurrY));
1370
        i->addPoint(FPoint(x1, y1));
1371
        i->addPoint(FPoint(x3, y3));
1372
        i->addPoint(FPoint(x2, y2));
68 Franz 1373
        CurrX = x3;
1374
        CurrY = y3;
1375
        PathLen += 4;
1376
}
1377
 
202 Franz 1378
/*!
1379
 \fn void SVGPlug::svgClosePath(FPointArray *i)
1380
 \author Franz Schmid
1381
 \date
1382
 \brief
1383
 \param i FPointArray *
1384
 \retval None
1385
 */
68 Franz 1386
void SVGPlug::svgClosePath(FPointArray *i)
1387
{
501 fschmid 1388
        if (PathLen > 2)
217 Franz 1389
        {
501 fschmid 1390
                if ((PathLen == 4) || (i->point(i->size()-2).x() != StartX) || (i->point(i->size()-2).y() != StartY))
1391
                {
1392
                        i->addPoint(i->point(i->size()-2));
1393
                        i->addPoint(i->point(i->size()-3));
1394
                        i->addPoint(FPoint(StartX, StartY));
1395
                        i->addPoint(FPoint(StartX, StartY));
1396
                }
217 Franz 1397
        }
68 Franz 1398
}
1399
 
202 Franz 1400
/*!
1401
 \fn QColor SVGPlug::parseColorN( const QString &rgbColor )
1402
 \author Franz Schmid
1403
 \date
1404
 \brief
1405
 \param rgbColor const QString &
1406
 \retval Qcolor
1407
 */
68 Franz 1408
QColor SVGPlug::parseColorN( const QString &rgbColor )
1409
{
1410
        int r, g, b;
1411
        keywordToRGB( rgbColor, r, g, b );
1412
        return QColor( r, g, b );
1413
}
1414
 
202 Franz 1415
/*!
1416
 \fn QString SVGPlug::parseColor( const QString &s )
1417
 \author Franz Schmid
1418
 \date
1419
 \brief
1420
 \param s const QString &
1421
 \retval QString
1422
 */
68 Franz 1423
QString SVGPlug::parseColor( const QString &s )
1424
{
1425
        QColor c;
1426
        QString ret = "None";
1427
        if( s.startsWith( "rgb(" ) )
217 Franz 1428
        {
68 Franz 1429
                QString parse = s.stripWhiteSpace();
1430
                QStringList colors = QStringList::split( ',', parse );
1431
                QString r = colors[0].right( ( colors[0].length() - 4 ) );
1432
                QString g = colors[1];
1433
                QString b = colors[2].left( ( colors[2].length() - 1 ) );
1434
                if( r.contains( "%" ) )
217 Franz 1435
                {
68 Franz 1436
                        r = r.left( r.length() - 1 );
80 Franz 1437
                        r = QString::number( static_cast<int>( ( static_cast<double>( 255 * r.toDouble() ) / 100.0 ) ) );
217 Franz 1438
                }
68 Franz 1439
                if( g.contains( "%" ) )
217 Franz 1440
                {
68 Franz 1441
                        g = g.left( g.length() - 1 );
80 Franz 1442
                        g = QString::number( static_cast<int>( ( static_cast<double>( 255 * g.toDouble() ) / 100.0 ) ) );
217 Franz 1443
                }
68 Franz 1444
                if( b.contains( "%" ) )
217 Franz 1445
                {
68 Franz 1446
                        b = b.left( b.length() - 1 );
80 Franz 1447
                        b = QString::number( static_cast<int>( ( static_cast<double>( 255 * b.toDouble() ) / 100.0 ) ) );
217 Franz 1448
                }
68 Franz 1449
                c = QColor(r.toInt(), g.toInt(), b.toInt());
217 Franz 1450
        }
68 Franz 1451
        else
217 Franz 1452
        {
68 Franz 1453
                QString rgbColor = s.stripWhiteSpace();
1454
                if( rgbColor.startsWith( "#" ) )
1455
                        c.setNamedColor( rgbColor );
1456
                else
1457
                        c = parseColorN( rgbColor );
217 Franz 1458
        }
1065 cbradney 1459
        ColorList::Iterator it;
68 Franz 1460
        bool found = false;
1488 fschmid 1461
        int r, g, b;
1462
        QColor tmpR;
3292 cbradney 1463
        for (it = currDoc->PageColors.begin(); it != currDoc->PageColors.end(); ++it)
217 Franz 1464
        {
3292 cbradney 1465
                currDoc->PageColors[it.key()].getRGB(&r, &g, &b);
1488 fschmid 1466
                tmpR.setRgb(r, g, b);
3292 cbradney 1467
                if (c == tmpR && currDoc->PageColors[it.key()].getColorModel() == colorModelRGB)
68 Franz 1468
                {
1469
                        ret = it.key();
1470
                        found = true;
1471
                }
217 Franz 1472
        }
68 Franz 1473
        if (!found)
217 Franz 1474
        {
2886 fschmid 1475
                ScColor tmp;
68 Franz 1476
                tmp.fromQColor(c);
3292 cbradney 1477
                currDoc->PageColors.insert("FromSVG"+c.name(), tmp);
3540 cbradney 1478
                ScApp->propertiesPalette->updateColorList();
68 Franz 1479
                ret = "FromSVG"+c.name();
217 Franz 1480
        }
68 Franz 1481
        return ret;
1482
}
1483
 
202 Franz 1484
/*!
1485
 \fn void SVGPlug::parsePA( SvgStyle *obj, const QString &command, const QString &params )
1486
 \author Franz Schmid
1487
 \date
1488
 \brief
1489
 \param obj SvgStyle *
1490
 \param command const QString &
1491
 \param params const QString &
1492
 \retval None
1493
 */
68 Franz 1494
void SVGPlug::parsePA( SvgStyle *obj, const QString &command, const QString &params )
1495
{
976 fschmid 1496
        if( command == "stroke-opacity" )
1394 cbradney 1497
                obj->TranspStroke  = 1.0 - fromPercentage(params);
976 fschmid 1498
        else if( command == "fill-opacity" )
1499
                obj->Transparency = 1.0 - fromPercentage(params);
1500
        else if( command == "opacity" )
68 Franz 1501
        {
976 fschmid 1502
                obj->Transparency = 1.0 - fromPercentage(params);
1503
                obj->TranspStroke = 1.0 - fromPercentage(params);
1504
        }
1505
        else if( command == "fill" )
1506
        {
217 Franz 1507
                if ((obj->InherCol) && (params == "currentColor"))
1508
                        obj->FillCol = obj->CurCol;
1509
                else if (params == "none")
68 Franz 1510
                {
217 Franz 1511
                        obj->FillCol = "None";
68 Franz 1512
                }
217 Franz 1513
                else if( params.startsWith( "url(" ) )
68 Franz 1514
                {
217 Franz 1515
                        unsigned int start = params.find("#") + 1;
1516
                        unsigned int end = params.findRev(")");
1517
                        QString key = params.mid(start, end - start);
2877 cbradney 1518
                        while (!m_gradients[key].reference.isEmpty())
943 fschmid 1519
                        {
976 fschmid 1520
                                QString key2 = m_gradients[key].reference;
1521
                                if (m_gradients[key2].typeValid)
1522
                                        obj->Gradient = m_gradients[key2].Type;
1523
                                if (m_gradients[key2].gradientValid)
1524
                                        obj->GradCo = m_gradients[key2].gradient;
1525
                                if (m_gradients[key2].cspaceValid)
1526
                                        obj->CSpace = m_gradients[key2].CSpace;
1527
                                if (m_gradients[key2].x1Valid)
1528
                                        obj->GX1 = m_gradients[key2].X1;
1529
                                if (m_gradients[key2].y1Valid)
1530
                                        obj->GY1 = m_gradients[key2].Y1;
1531
                                if (m_gradients[key2].x2Valid)
1532
                                        obj->GX2 = m_gradients[key2].X2;
1533
                                if (m_gradients[key2].y2Valid)
1534
                                        obj->GY2 = m_gradients[key2].Y2;
1535
                                if (m_gradients[key2].matrixValid)
1536
                                        obj->matrixg = m_gradients[key2].matrix;
1537
                                key = m_gradients[key].reference;
943 fschmid 1538
                        }
976 fschmid 1539
                        key = params.mid(start, end - start);
943 fschmid 1540
                        if (m_gradients[key].typeValid)
1541
                                obj->Gradient = m_gradients[key].Type;
1542
                        if (m_gradients[key].gradientValid)
1543
                                obj->GradCo = m_gradients[key].gradient;
1544
                        if (m_gradients[key].cspaceValid)
1545
                                obj->CSpace = m_gradients[key].CSpace;
1546
                        if (m_gradients[key].x1Valid)
1547
                                obj->GX1 = m_gradients[key].X1;
1548
                        if (m_gradients[key].y1Valid)
1549
                                obj->GY1 = m_gradients[key].Y1;
1550
                        if (m_gradients[key].x2Valid)
1551
                                obj->GX2 = m_gradients[key].X2;
1552
                        if (m_gradients[key].y2Valid)
1553
                                obj->GY2 = m_gradients[key].Y2;
1554
                        if (m_gradients[key].matrixValid)
1555
                                obj->matrixg = m_gradients[key].matrix;
217 Franz 1556
                        obj->FillCol = "None";
68 Franz 1557
                }
217 Franz 1558
                else
1559
                        obj->FillCol = parseColor(params);
68 Franz 1560
        }
1561
        else if( command == "color" )
1562
        {
1563
                if (params == "none")
1564
                        obj->CurCol = "None";
1565
                else if( params.startsWith( "url(" ) )
217 Franz 1566
                {
68 Franz 1567
                        obj->CurCol = "None";
217 Franz 1568
                }
68 Franz 1569
                else
217 Franz 1570
                {
68 Franz 1571
                        obj->CurCol = parseColor(params);
217 Franz 1572
                }
68 Franz 1573
        }
1574
        else if( command == "stroke" )
1575
        {
217 Franz 1576
                if ((obj->InherCol) && (params == "currentColor"))
1577
                        obj->StrokeCol = obj->CurCol;
1578
                else if (params == "none")
68 Franz 1579
                {
217 Franz 1580
                        obj->StrokeCol = "None";
68 Franz 1581
                }
1582
                else if( params.startsWith( "url(" ) )
1583
                {
217 Franz 1584
                        obj->StrokeCol = "None";
68 Franz 1585
                }
1586
                else
217 Franz 1587
                        obj->StrokeCol = parseColor(params);
1588
                /*              if( params == "none" )
1589
                                        gc->stroke.setType( VStroke::none );
1590
                                else if( params.startsWith( "url(" ) )
1591
                                {
1592
                                        unsigned int start = params.find("#") + 1;
1593
                                        unsigned int end = params.findRev(")");
1594
                                        QString key = params.mid( start, end - start );
1595
                                        gc->stroke.gradient() = m_gradients[ key ].gradient;
1596
                                        gc->stroke.gradient().transform( m_gradients[ key ].gradientTransform );
1597
                                        gc->stroke.gradient().transform( gc->matrix );
1598
                                        gc->stroke.setType( VStroke::grad );
1599
                                }
1600
                                else
1601
                                {
1602
                                        parseColor( strokecolor, params );
1603
                                        gc->stroke.setType( VStroke::solid );
1604
                                } */
68 Franz 1605
        }
1606
        else if( command == "stroke-width" )
1607
                obj->LWidth = parseUnit( params );
1608
        else if( command == "stroke-linejoin" )
217 Franz 1609
        {
68 Franz 1610
                if( params == "miter" )
1611
                        obj->PLineJoin = Qt::MiterJoin;
1612
                else if( params == "round" )
1613
                        obj->PLineJoin = Qt::RoundJoin;
1614
                else if( params == "bevel" )
1615
                        obj->PLineJoin = Qt::BevelJoin;
217 Franz 1616
        }
68 Franz 1617
        else if( command == "stroke-linecap" )
217 Franz 1618
        {
68 Franz 1619
                if( params == "butt" )
1620
                        obj->PLineEnd = Qt::FlatCap;
1621
                else if( params == "round" )
1622
                        obj->PLineEnd = Qt::RoundCap;
1623
                else if( params == "square" )
1624
                        obj->PLineEnd = Qt::SquareCap;
217 Franz 1625
        }
1626
        //      else if( command == "stroke-miterlimit" )
1627
        //              gc->stroke.setMiterLimit( params.todouble() );
68 Franz 1628
        else if( command == "stroke-dasharray" )
217 Franz 1629
        {
80 Franz 1630
                QValueList<double> array;
68 Franz 1631
                if(params != "none")
217 Franz 1632
                {
68 Franz 1633
                        QStringList dashes = QStringList::split( ' ', params );
217 Franz 1634
                        for( QStringList::Iterator it = dashes.begin(); it != dashes.end(); ++it )
80 Franz 1635
                                array.append( (*it).toDouble() );
217 Franz 1636
                }
68 Franz 1637
                obj->dashArray = array;
217 Franz 1638
        }
68 Franz 1639
        else if( command == "stroke-dashoffset" )
80 Franz 1640
                obj->dashOffset = params.toDouble();
68 Franz 1641
        else if( command == "font-family" )
217 Franz 1642
        {
68 Franz 1643
                QString family = params;
1644
                QString ret = "";
1645
                family.replace( QRegExp( "'" ) , QChar( ' ' ) );
3292 cbradney 1646
                obj->Family = currDoc->toolSettings.defFont; // family;
68 Franz 1647
                bool found = false;
2834 cbradney 1648
                SCFontsIterator it(PrefsManager::instance()->appPrefs.AvailFonts);
68 Franz 1649
                for ( ; it.current(); ++it)
217 Franz 1650
                {
68 Franz 1651
                        QString fam;
3544 avox 1652
                        QString fn = it.current()->scName();
68 Franz 1653
                        int     pos=fn.find(" ");
1654
                        fam = fn.left(pos);
1655
                        if (fam == family)
217 Franz 1656
                        {
68 Franz 1657
                                found = true;
1658
                                ret = fn;
1659
                        }
217 Franz 1660
                }
68 Franz 1661
                if (found)
1662
                        obj->Family = ret;
1663
                else
3292 cbradney 1664
                        obj->Family = currDoc->toolSettings.defFont;
217 Franz 1665
        }
68 Franz 1666
        else if( command == "font-size" )
111 Franz 1667
                obj->FontSize = static_cast<int>(parseUnit(params) * 10.0);
68 Franz 1668
}
1669
 
202 Franz 1670
/*!
1671
 \fn void SVGPlug::parseStyle( SvgStyle *obj, const QDomElement &e )
1672
 \author Franz Schmid
1673
 \date
1674
 \brief
1675
 \param obj SvgStyle *
1676
 \param e const QDomElement &
1677
 \retval None
1678
 */
68 Franz 1679
void SVGPlug::parseStyle( SvgStyle *obj, const QDomElement &e )
1680
{
1681
        SvgStyle *gc = m_gc.current();
1682
        if (!gc)
1683
                return;
1684
        if( !e.attribute( "color" ).isEmpty() )
217 Franz 1685
        {
68 Franz 1686
                if (e.attribute( "color" ) == "inherit")
1687
                        gc->InherCol = true;
1688
                else
1689
                        parsePA( obj, "color", e.attribute( "color" ) );
217 Franz 1690
        }
68 Franz 1691
        if( !e.attribute( "fill" ).isEmpty() )
1692
                parsePA( obj, "fill", e.attribute( "fill" ) );
1693
        if( !e.attribute( "stroke" ).isEmpty() )
1694
                parsePA( obj, "stroke", e.attribute( "stroke" ) );
1695
        if( !e.attribute( "stroke-width" ).isEmpty() )
1696
                parsePA( obj, "stroke-width", e.attribute( "stroke-width" ) );
1697
        if( !e.attribute( "stroke-linejoin" ).isEmpty() )
1698
                parsePA( obj, "stroke-linejoin", e.attribute( "stroke-linejoin" ) );
1699
        if( !e.attribute( "stroke-linecap" ).isEmpty() )
1700
                parsePA( obj, "stroke-linecap", e.attribute( "stroke-linecap" ) );
1701
        if( !e.attribute( "stroke-dasharray" ).isEmpty() )
1702
                parsePA( obj, "stroke-dasharray", e.attribute( "stroke-dasharray" ) );
1703
        if( !e.attribute( "stroke-dashoffset" ).isEmpty() )
1704
                parsePA( obj, "stroke-dashoffset", e.attribute( "stroke-dashoffset" ) );
1705
        if( !e.attribute( "stroke-opacity" ).isEmpty() )
1706
                parsePA( obj, "stroke-opacity", e.attribute( "stroke-opacity" ) );
217 Franz 1707
        /*      if( !e.attribute( "stroke-miterlimit" ).isEmpty() )
1708
                        parsePA( obj, "stroke-miterlimit", e.attribute( "stroke-miterlimit" ) );   */
68 Franz 1709
        if( !e.attribute( "fill-opacity" ).isEmpty() )
1710
                parsePA( obj, "fill-opacity", e.attribute( "fill-opacity" ) );
1711
        if( !e.attribute( "opacity" ).isEmpty() )
1712
                parsePA( obj, "opacity", e.attribute( "opacity" ) );
1713
        if( !e.attribute( "font-family" ).isEmpty() )
1714
                parsePA( obj, "font-family", e.attribute( "font-family" ) );
1715
        if( !e.attribute( "font-size" ).isEmpty() )
1716
                parsePA( obj, "font-size", e.attribute( "font-size" ) );
1717
        QString style = e.attribute( "style" ).simplifyWhiteSpace();
1718
        QStringList substyles = QStringList::split( ';', style );
217 Franz 1719
        for( QStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it )
1720
        {
68 Franz 1721
                QStringList substyle = QStringList::split( ':', (*it) );
1722
                QString command = substyle[0].stripWhiteSpace();
1723
                QString params  = substyle[1].stripWhiteSpace();
1724
                parsePA( obj, command, params );
217 Franz 1725
        }
68 Franz 1726
        return;
1727
}
1728
 
202 Franz 1729
/*!
1730
 \fn void SVGPlug::parseColorStops(GradientHelper *gradient, const QDomElement &e)
1731
 \author Franz Schmid
1732
 \date
1733
 \brief
1734
 \param gradient GradientHelper *
1735
 \param e const QDomElement &
1736
 \retval None
1737
 */
68 Franz 1738
void SVGPlug::parseColorStops(GradientHelper *gradient, const QDomElement &e)
1739
{
1740
        QString Col = "Black";
705 fschmid 1741
        double offset = 0;
1742
        double opa;
68 Franz 1743
        for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling())
217 Franz 1744
        {
296 Franz 1745
                opa = 1.0;
68 Franz 1746
                QDomElement stop = n.toElement();
1747
                if(stop.tagName() == "stop")
217 Franz 1748
                {
68 Franz 1749
                        QString temp = stop.attribute( "offset" );
1750
                        if( temp.contains( '%' ) )
217 Franz 1751
                        {
68 Franz 1752
                                temp = temp.left( temp.length() - 1 );
80 Franz 1753
                                offset = temp.toDouble() / 100.0;
217 Franz 1754
                        }
68 Franz 1755
                        else
80 Franz 1756
                                offset = temp.toDouble();
296 Franz 1757
                        if( !stop.attribute( "stop-opacity" ).isEmpty() )
1758
                                opa = fromPercentage(stop.attribute("stop-opacity"));
68 Franz 1759
                        if( !stop.attribute( "stop-color" ).isEmpty() )
1760
                                Col = parseColor(stop.attribute("stop-color"));
1761
                        else
217 Franz 1762
                        {
68 Franz 1763
                                QString style = stop.attribute( "style" ).simplifyWhiteSpace();
1764
                                QStringList substyles = QStringList::split( ';', style );
217 Franz 1765
                                for( QStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it )
1766
                                {
68 Franz 1767
                                        QStringList substyle = QStringList::split( ':', (*it) );
1768
                                        QString command = substyle[0].stripWhiteSpace();
1769
                                        QString params  = substyle[1].stripWhiteSpace();
1770
                                        if( command == "stop-color" )
1771
                                                Col = parseColor(params);
296 Franz 1772
                                        if( command == "stop-opacity" )
1773
                                                opa = fromPercentage(params);
68 Franz 1774
                                }
1775
                        }
217 Franz 1776
                }
3292 cbradney 1777
                gradient->gradient.addStop( currDoc->PageColors[Col].getRGBColor(), offset, 0.5, opa, Col, 100 );
943 fschmid 1778
                gradient->gradientValid = true;
217 Franz 1779
        }
68 Franz 1780
}
1781
 
202 Franz 1782
/*!
1783
 \fn void SVGPlug::parseGradient( const QDomElement &e )
1784
 \author Franz Schmid
1785
 \date
1786
 \brief
1787
 \param e const QDomElement &
1788
 \retval None
1789
 */
68 Franz 1790
void SVGPlug::parseGradient( const QDomElement &e )
1791
{
1792
        GradientHelper gradhelper;
943 fschmid 1793
        gradhelper.gradientValid = false;
68 Franz 1794
        gradhelper.gradient.clearStops();
1795
        gradhelper.gradient.setRepeatMethod( VGradient::none );
1796
 
1797
        QString href = e.attribute("xlink:href").mid(1);
1798
        double x1, y1, x2, y2;
1799
        if (!href.isEmpty())
217 Franz 1800
        {
943 fschmid 1801
                if (m_gradients.contains(href))
1802
                {
1803
                        gradhelper.Type = m_gradients[href].Type;
1804
                        gradhelper.gradient = m_gradients[href].gradient;
1805
                        gradhelper.X1 = m_gradients[href].X1;
1806
                        gradhelper.Y1 = m_gradients[href].Y1;
1807
                        gradhelper.X2 = m_gradients[href].X2;
1808
                        gradhelper.Y2 = m_gradients[href].Y2;
1809
                        gradhelper.CSpace = m_gradients[href].CSpace;
1810
                        gradhelper.matrix = m_gradients[href].matrix;
1811
                        gradhelper.x1Valid = m_gradients[href].x1Valid;
1812
                        gradhelper.x2Valid = m_gradients[href].x2Valid;
1813
                        gradhelper.y1Valid = m_gradients[href].y1Valid;
1814
                        gradhelper.y2Valid = m_gradients[href].y2Valid;
1815
                        gradhelper.cspaceValid = m_gradients[href].cspaceValid;
1816
                        gradhelper.matrixValid = m_gradients[href].matrixValid;
1817
                        gradhelper.gradientValid = m_gradients[href].gradientValid;
1818
                        gradhelper.typeValid = m_gradients[href].typeValid;
1819
                }
1820
                gradhelper.reference = href;
217 Franz 1821
        }
296 Franz 1822
        if (e.tagName() == "linearGradient")
1823
        {
943 fschmid 1824
                if (e.hasAttribute("x1"))
1825
                {
1826
                        gradhelper.X1 = e.attribute( "x1", "0").toDouble();
1827
                        gradhelper.x1Valid = true;
1828
                }
1829
                if (e.hasAttribute("y1"))
1830
                {
1831
                        gradhelper.Y1 = e.attribute( "y1", "0" ).toDouble();
1832
                        gradhelper.y1Valid = true;
1833
                }
1834
                if (e.hasAttribute("x2"))
1835
                {
1836
                        gradhelper.X2 = e.attribute( "x2", "1" ).toDouble();
1837
                        gradhelper.x2Valid = true;
1838
                }
1839
                if (e.hasAttribute("y2"))
1840
                {
1841
                        gradhelper.Y2 = e.attribute( "y2", "0" ).toDouble();
1842
                        gradhelper.y2Valid = true;
1843
                }
296 Franz 1844
                gradhelper.Type = 6;
943 fschmid 1845
                gradhelper.typeValid = true;
296 Franz 1846
        }
1847
        else
1848
        {
943 fschmid 1849
                if (e.hasAttribute("x1"))
1850
                {
1851
                        x1 = e.attribute( "cx", "0.5").toDouble();
1852
                        gradhelper.x1Valid = true;
1853
                }
1854
                if (e.hasAttribute("y1"))
1855
                {
1856
                        y1 = e.attribute( "cy", "0.5" ).toDouble();
1857
                        gradhelper.y1Valid = true;
1858
                }
1859
                if (e.hasAttribute("x2"))
1860
                {
1861
                        x2 = e.attribute( "r", "0.5" ).toDouble();
1862
                        gradhelper.x2Valid = true;
1863
                }
296 Franz 1864
                y2 = y1;
943 fschmid 1865
                gradhelper.y2Valid = true;
296 Franz 1866
                gradhelper.X1 = x1;
1867
                gradhelper.Y1 = y1;
1868
                gradhelper.X2 = x1 + x2;
1869
                gradhelper.Y2 = y1;
1870
                gradhelper.Type = 7;
943 fschmid 1871
                gradhelper.typeValid = true;
296 Franz 1872
        }
298 Franz 1873
        if ( !e.attribute( "gradientUnits" ).isEmpty() )
1874
        {
1875
                QString uni = e.attribute( "gradientUnits");
1876
                if (uni == "userSpaceOnUse")
1877
                        gradhelper.CSpace = true;
1878
                else
1879
                        gradhelper.CSpace = false;
943 fschmid 1880
                gradhelper.cspaceValid = true;
298 Franz 1881
        }
1882
        else
943 fschmid 1883
        {
298 Franz 1884
                gradhelper.CSpace = false;
943 fschmid 1885
                gradhelper.cspaceValid = false;
1886
        }
296 Franz 1887
        QString transf = e.attribute("gradientTransform");
1888
        if( !transf.isEmpty() )
1889
        {
302 Franz 1890
                gradhelper.matrix = parseTransform( e.attribute( "gradientTransform" ) );
943 fschmid 1891
                gradhelper.matrixValid = true;
296 Franz 1892
        }
943 fschmid 1893
        else
1894
                gradhelper.matrixValid = false;
296 Franz 1895
        QString spreadMethod = e.attribute( "spreadMethod" );
1896
        if( !spreadMethod.isEmpty() )
1897
        {
1898
                if( spreadMethod == "reflect" )
1899
                        gradhelper.gradient.setRepeatMethod( VGradient::reflect );
1900
                else if( spreadMethod == "repeat" )
1901
                        gradhelper.gradient.setRepeatMethod( VGradient::repeat );
1902
        }
1903
        parseColorStops(&gradhelper, e);
68 Franz 1904
        m_gradients.insert(e.attribute("id"), gradhelper);
1905
}
1906
 
202 Franz 1907
/*!
1908
 \fn void SVGPlug::parseText(PageItem *ite, const QDomElement &e)
1909
 \author Franz Schmid
1910
 \date
1911
 \brief
1912
 \param ite PageItem *
1913
 \param e const QDomElement &
1914
 \retval None
1915
 */
215 Franz 1916
QPtrList<PageItem> SVGPlug::parseText(double x, double y, const QDomElement &e)
68 Franz 1917
{
1065 cbradney 1918
        struct ScText *hg;
68 Franz 1919
        QPainter p;
215 Franz 1920
        QPtrList<PageItem> GElements;
3207 craig 1921
        p.begin(ScApp->view->viewport());
3547 avox 1922
//      QFont ff(currDoc->UsedFonts[m_gc.current()->Family]);
1923
        QFont ff(m_gc.current()->Family);
111 Franz 1924
        ff.setPointSize(QMAX(qRound(m_gc.current()->FontSize / 10.0), 1));
68 Franz 1925
        p.setFont(ff);
215 Franz 1926
        setupTransform(e);
1927
        int desc = p.fontMetrics().descent();
1928
        int asce = p.fontMetrics().ascent();
214 Franz 1929
        QString Text = QString::fromUtf8(e.text()).stripWhiteSpace();
68 Franz 1930
        QDomNode c = e.firstChild();
1931
        if ((!c.isNull()) && (c.toElement().tagName() == "tspan"))
215 Franz 1932
        {
80 Franz 1933
                double tempW = 0;
68 Franz 1934
                for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling())
215 Franz 1935
                {
1936
                        tempW = 0;
68 Franz 1937
                        QDomElement tspan = n.toElement();
1938
                        addGraphicContext();
1939
                        SvgStyle *gc = m_gc.current();
1940
                        parseStyle(gc, tspan);
3292 cbradney 1941
                        //int z = ScApp->view->PaintText(x, y, 10, 10, gc->LWidth, gc->FillCol);
1942
                        int z = currDoc->itemAdd(PageItem::TextFrame, PageItem::Unspecified, x, y, 10, 10, gc->LWidth, "None", gc->FillCol, !ScApp->view->Mpressed);
1943
                        PageItem* ite = currDoc->Items.at(z);
215 Franz 1944
                        ite->Extra = 0;
1945
                        ite->TExtra = 0;
1946
                        ite->BExtra = 0;
1947
                        ite->RExtra = 0;
111 Franz 1948
                        ite->LineSp = gc->FontSize / 10.0 + 2;
215 Franz 1949
                        ite->Height = ite->LineSp+desc+2;
3207 craig 1950
                        ScApp->SetNewFont(gc->Family);
215 Franz 1951
                        QWMatrix mm = gc->matrix;
1952
                        if( (!tspan.attribute("x").isEmpty()) && (!tspan.attribute("y").isEmpty()) )
1953
                        {
1954
                                double x1 = parseUnit( tspan.attribute( "x", "0" ) );
1955
                                double y1 = parseUnit( tspan.attribute( "y", "0" ) );
1956
                                double mx = mm.m11() * x1 + mm.m21() * y1 + mm.dx();
1957
                                double my = mm.m22() * y1 + mm.m12() * x1 + mm.dy();
1958
                                ite->Xpos = mx;
1959
                                ite->Ypos = my;
1960
                        }
1961
                        else
1962
                        {
1963
                                double mx = mm.m11() * x + mm.m21() * y + mm.dx();
1964
                                double my = mm.m22() * y + mm.m12() * x + mm.dy();
1965
                                ite->Xpos = mx;
1966
                                ite->Ypos = my;
1967
                        }
68 Franz 1968
                        if (!tspan.text().isNull())
214 Franz 1969
                                Text = QString::fromUtf8(tspan.text()).stripWhiteSpace();
68 Franz 1970
                        else
1971
                                Text = " ";
217 Franz 1972
                        ite->IFont = gc->Family;
1973
                        ite->TxtFill = gc->FillCol;
1974
                        ite->ShTxtFill = 100;
1975
                        ite->TxtStroke = gc->StrokeCol;
1976
                        ite->ShTxtStroke = 100;
1977
                        ite->ISize = gc->FontSize;
1978
                        ite->TxTStyle = 0;
2242 fschmid 1979
                        ite->TxtScale = 1000;
1980
                        ite->TxtScaleV = 1000;
1981
                        ite->TxtBase = 0;
2247 fschmid 1982
                        ite->TxtShadowX = 50;
1983
                        ite->TxtShadowY = -50;
2257 fschmid 1984
                        ite->TxtOutline = 10;
2262 fschmid 1985
                        ite->TxtUnderPos = -1;
1986
                        ite-