Subversion Repositories Scribus

Rev

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