Subversion Repositories Scribus

Rev

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

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