Subversion Repositories Scribus

Rev

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