Subversion Repositories Scribus

Rev

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