Subversion Repositories Scribus

Rev

Rev 544 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
541 fschmid 1
#include "oodrawimp.h"
2
#include "oodrawimp.moc"
3
#if (_MSC_VER >= 1200)
4
        #include "win-config.h"
5
#else
6
        #include "config.h"
7
#endif
8
#include "customfdialog.h"
9
#include "color.h"
10
#include "scribusXml.h"
11
#include "mpalette.h"
12
#include "prefsfile.h"
13
#include "prefscontext.h"
14
#include "prefstable.h"
15
#include "sxwunzip.h"
16
#include <qfile.h>
17
#include <qtextstream.h>
18
#include <qregexp.h>
19
#include <qcursor.h>
20
#include <qdragobject.h>
21
#include <qdir.h>
22
#include <qstring.h>
23
#include <cmath>
24
 
25
using namespace std;
26
 
27
extern QPointArray FlattenPath(FPointArray ina, QValueList<uint> &Segs);
28
extern bool loadText(QString nam, QString *Buffer);
29
extern QPixmap loadIcon(QString nam);
30
extern double RealCWidth(ScribusDoc *doc, QString name, QString ch, int Siz);
31
extern FPoint GetMaxClipF(FPointArray Clip);
32
extern PrefsFile* prefsFile;
33
 
34
/*!
35
 \fn QString Name()
36
 \author Franz Schmid
37
 \date
38
 \brief Returns name of plugin
39
 \param None
40
 \retval QString containing name of plugin: Import SVG-Image...
41
 */
42
QString Name()
43
{
44
        return QObject::tr("Import &Open Office Draw...");
45
}
46
 
47
/*!
48
 \fn int Type()
49
 \author Franz Schmid
50
 \date
51
 \brief Returns type of plugin
52
 \param None
53
 \retval int containing type of plugin (1: Extra, 2: Import, 3: Export, 4: )
54
 */
55
int Type()
56
{
57
        return 2;
58
}
59
 
60
int ID()
61
{
62
        return 12;
63
}
64
 
65
void Run(QWidget *d, ScribusApp *plug)
66
{
67
        QString fileName;
68
        if (plug->DLLinput != "")
69
                fileName = plug->DLLinput;
70
        else
71
        {
72
                PrefsContext* prefs = prefsFile->getPluginContext("OODrawImport");
73
                QString wdir = prefs->get("wdir", ".");
74
                CustomFDialog diaf(d, wdir, QObject::tr("Open"), QObject::tr("Open Office Draw (*.sxd);;All Files (*)"));
75
                if (diaf.exec())
76
                {
77
                        fileName = diaf.selectedFile();
78
                        prefs->set("wdir", fileName.left(fileName.findRev("/")));
79
                }
80
                else
81
                        return;
82
        }
83
        OODPlug *dia = new OODPlug(plug, fileName);
84
        delete dia;
85
}
86
 
87
OODPlug::OODPlug( ScribusApp *plug, QString fileName )
88
{
89
        QString f, f2;
90
        m_styles.setAutoDelete( true );
91
        SxwUnzip* sun = new SxwUnzip(fileName);
92
        stylePath   = sun->getFile("styles.xml");
93
        contentPath = sun->getFile("content.xml");
94
        delete sun;
95
        if ((stylePath != NULL) && (contentPath != NULL))
96
        {
97
                QString docname = fileName.right(fileName.length() - fileName.findRev("/") - 1);
98
                docname = docname.left(docname.findRev("."));
99
                loadText(stylePath, &f);
100
                if(!inpStyles.setContent(f))
101
                        return;
102
                loadText(contentPath, &f2);
103
                if(!inpContents.setContent(f2))
104
                        return;
105
                QFile f1(stylePath);
106
                f1.remove();
107
                QFile f2(contentPath);
108
                f2.remove();
109
        }
110
        else if ((stylePath == NULL) && (contentPath != NULL))
111
        {
112
                QFile f2(contentPath);
113
                f2.remove();
114
        }
115
        else if ((stylePath != NULL) && (contentPath == NULL))
116
        {
117
                QFile f1(stylePath);
118
                f1.remove();
119
        }
120
        Prog = plug;
121
        QString CurDirP = QDir::currentDirPath();
122
        QFileInfo efp(fileName);
123
        QDir::setCurrent(efp.dirPath());
124
        convert();
125
        QDir::setCurrent(CurDirP);
126
}
127
 
128
void OODPlug::convert()
129
{
130
        bool ret = false;
131
        createStyleMap( inpStyles );
132
        QDomElement docElem = inpContents.documentElement();
133
        QDomNode automaticStyles = docElem.namedItem( "office:automatic-styles" );
134
        if( !automaticStyles.isNull() )
135
                insertStyles( automaticStyles.toElement() );
136
        QDomNode body = docElem.namedItem( "office:body" );
137
        QDomNode drawPage = body.namedItem( "draw:page" );
138
        QDomElement dp = drawPage.toElement();
139
        QDomElement *master = m_styles[dp.attribute( "draw:master-page-name" )];
140
        QDomElement *style = m_styles[master->attribute( "style:page-master-name" )];
141
        QDomElement properties = style->namedItem( "style:properties" ).toElement();
142
        double width = !properties.attribute( "fo:page-width" ).isEmpty() ? parseUnit(properties.attribute( "fo:page-width" ) ) : 550.0;
143
        double height = !properties.attribute( "fo:page-height" ).isEmpty() ? parseUnit(properties.attribute( "fo:page-height" ) ) : 841.0;
144
        if (Prog->DLLinput != "")
145
        {
146
                Prog->doc->setPage(width, height, 0, 0, 0, 0, 0, 0, false, false);
147
                Prog->view->addPage(0);
148
        }
149
        else
150
        {
151
                if (!Prog->HaveDoc)
152
                {
153
                        Prog->doFileNew(width, height, 0, 0, 0, 0, 0, 0, false, false, 0, false, 0, 1, "Custom");
154
                        ret = true;
155
                }
156
        }
157
        Doku = Prog->doc;
158
        Prog->view->Deselect();
159
        Elements.clear();
160
        Doku->loading = true;
161
        Doku->DoDrawing = false;
162
        Prog->view->setUpdatesEnabled(false);
163
        Prog->ScriptRunning = true;
164
        qApp->setOverrideCursor(QCursor(Qt::waitCursor), true);
165
        if (!Doku->PageColors.contains("Black"))
166
                Doku->PageColors.insert("Black", CMYKColor(0, 0, 0, 255));
167
        for( QDomNode drawPag = body.firstChild(); !drawPag.isNull(); drawPag = drawPag.nextSibling() )
168
        {
169
                QDomElement dpg = drawPag.toElement();
170
                m_styleStack.clear();
171
                fillStyleStack( dpg );
172
                parseGroup( dpg );
173
        }
174
        if (Elements.count() > 1)
175
        {
176
                Prog->view->SelItem.clear();
177
                for (uint a = 0; a < Elements.count(); ++a)
178
                {
179
                        Elements.at(a)->Groups.push(Doku->GroupCounter);
180
                        if (!ret)
181
                                Prog->view->SelItem.append(Elements.at(a));
182
                }
183
                Doku->GroupCounter++;
184
        }
185
        Doku->DoDrawing = true;
186
        Prog->view->setUpdatesEnabled(true);
187
        Prog->ScriptRunning = false;
188
        if (Prog->DLLinput == "")
189
                Doku->loading = false;
190
        qApp->setOverrideCursor(QCursor(Qt::arrowCursor), true);
191
        if ((Elements.count() > 0) && (!ret) && (Prog->DLLinput == ""))
192
        {
193
                Doku->DragP = true;
194
                Doku->DraggedElem = 0;
195
                Doku->DragElements.clear();
196
                for (uint dre=0; dre<Elements.count(); ++dre)
197
                {
198
                        Doku->DragElements.append(Elements.at(dre)->ItemNr);
199
                }
200
                ScriXmlDoc *ss = new ScriXmlDoc();
201
                Prog->view->setGroupRect();
202
                QDragObject *dr = new QTextDrag(ss->WriteElem(&Prog->view->SelItem, Doku, Prog->view), Prog->view->viewport());
203
                Prog->view->DeleteItem();
204
                dr->setPixmap(loadIcon("DragPix.xpm"));
205
                dr->drag();
206
                delete ss;
207
                Doku->DragP = false;
208
                Doku->DraggedElem = 0;
209
                Doku->DragElements.clear();
210
        }
211
        else
212
        {
213
                Doku->setUnModified();
214
                Prog->slotDocCh();
215
        }
216
}
217
 
218
void OODPlug::parseGroup(const QDomElement &e)
219
{
220
        QPtrList<PageItem> GElements;
221
        FPointArray ImgClip;
222
        ImgClip.resize(0);
223
        double BaseX = Doku->ActPage->Xoffset;
224
        double BaseY = Doku->ActPage->Yoffset;
225
        double lwidth = 0;
226
        for (QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling())
227
        {
228
                QString StrokeColor = "None";
229
                QString FillColor = "None";
230
                int z = -1;
231
                QDomElement b = n.toElement();
232
                if( b.isNull() )
233
                        continue;
234
                QString STag = b.tagName();
235
                QString drawID = b.attribute("draw:id");
236
                storeObjectStyles(b);
237
                if( m_styleStack.hasAttribute("draw:stroke"))
238
                {
239
                        if( m_styleStack.hasAttribute("svg:stroke-width"))
240
                                lwidth = parseUnit(m_styleStack.attribute("svg:stroke-width"));
241
                        if( m_styleStack.hasAttribute("svg:stroke-color"))
242
                                StrokeColor = parseColor(m_styleStack.attribute("svg:stroke-color"));
243
                }
244
                if( m_styleStack.hasAttribute( "draw:fill" ) )
245
                {
246
                        QString fill = m_styleStack.attribute( "draw:fill" );
247
                        if( fill == "solid" )
248
                        {
249
                                if( m_styleStack.hasAttribute( "draw:fill-color" ) )
250
                                        FillColor = parseColor( m_styleStack.attribute("draw:fill-color"));
251
                        }
252
                }
253
                if( STag == "draw:rect" )
254
                {
255
                        double x = parseUnit(b.attribute("svg:x"));
256
                        double y = parseUnit(b.attribute("svg:y")) ;
257
                        double w = parseUnit(b.attribute("svg:width"));
258
                        double h = parseUnit(b.attribute("svg:height"));
259
                        double corner = parseUnit(b.attribute("draw:corner-radius"));
260
                        z = Prog->view->PaintRect(BaseX+x, BaseY+y, w, h, lwidth, FillColor, StrokeColor);
261
                        PageItem* ite = Doku->Items.at(z);
262
                        if (corner != 0)
263
                        {
264
                                ite->RadRect = corner;
265
                                Prog->view->SetFrameRound(ite);
266
                        }
267
                }
268
                else
269
                        continue;
270
                if (z != -1)
271
                {
272
                        PageItem* ite = Doku->Items.at(z);
273
                        if (b.hasAttribute("draw:transform"))
274
                        {
275
                                double rot = 0;
276
                                double dx = 0;
277
                                double dy = 0;
278
                                parseTransform(b.attribute("draw:transform"), &rot, &dx, &dy);
279
                                ite->Xpos = BaseX+dx;
280
                                ite->Ypos = BaseY+dy;
281
                                ite->Rot = rot;
282
                                Prog->view->setRedrawBounding(ite);
283
                        }
284
                        GElements.append(ite);
285
                        Elements.append(ite);
286
                }
287
        }
288
}
289
 
290
void OODPlug::createStyleMap( QDomDocument &docstyles )
291
{
292
        QDomElement styles = docstyles.documentElement();
293
        if( styles.isNull() )
294
                return;
295
 
296
        QDomNode fixedStyles = styles.namedItem( "office:styles" );
297
        if( !fixedStyles.isNull() )
298
        {
299
//              insertDraws( fixedStyles.toElement() );
300
                insertStyles( fixedStyles.toElement() );
301
        }
302
        QDomNode automaticStyles = styles.namedItem( "office:automatic-styles" );
303
        if( !automaticStyles.isNull() )
304
                insertStyles( automaticStyles.toElement() );
305
 
306
        QDomNode masterStyles = styles.namedItem( "office:master-styles" );
307
        if( !masterStyles.isNull() )
308
                insertStyles( masterStyles.toElement() );
309
}
310
 
311
void OODPlug::insertStyles( const QDomElement& styles )
312
{
313
        for ( QDomNode n = styles.firstChild(); !n.isNull(); n = n.nextSibling() )
314
        {
315
                QDomElement e = n.toElement();
316
                if( !e.hasAttribute( "style:name" ) )
317
                        continue;
318
                QString name = e.attribute( "style:name" );
319
                m_styles.insert( name, new QDomElement( e ) );
320
        }
321
}
322
 
323
void OODPlug::fillStyleStack( const QDomElement& object )
324
{
325
        if( object.hasAttribute( "presentation:style-name" ) )
326
                addStyles( m_styles[object.attribute( "presentation:style-name" )] );
327
        if( object.hasAttribute( "draw:style-name" ) )
328
                addStyles( m_styles[object.attribute( "draw:style-name" )] );
329
        if( object.hasAttribute( "draw:text-style-name" ) )
330
                addStyles( m_styles[object.attribute( "draw:text-style-name" )] );
331
        if( object.hasAttribute( "text:style-name" ) )
332
                addStyles( m_styles[object.attribute( "text:style-name" )] );
333
}
334
 
335
void OODPlug::addStyles( const QDomElement* style )
336
{
337
        if( style->hasAttribute( "style:parent-style-name" ) )
338
                addStyles( m_styles[style->attribute( "style:parent-style-name" )] );
339
        m_styleStack.push( *style );
340
}
341
 
342
void OODPlug::storeObjectStyles( const QDomElement& object )
343
{
344
        fillStyleStack( object );
345
}
346
 
347
double OODPlug::parseUnit(const QString &unit)
348
{
349
        QString unitval=unit;
350
        if (unit == "")
351
                return 0.0;
352
        if( unit.right( 2 ) == "pt" )
353
                unitval.replace( "pt", "" );
354
        else if( unit.right( 2 ) == "cm" )
355
                unitval.replace( "cm", "" );
356
        else if( unit.right( 2 ) == "mm" )
357
                unitval.replace( "mm" , "" );
358
        else if( unit.right( 2 ) == "in" )
359
                unitval.replace( "in", "" );
360
        else if( unit.right( 2 ) == "px" )
361
                unitval.replace( "px", "" );
362
        double value = unitval.toDouble();
363
        if( unit.right( 2 ) == "pt" )
364
                value = value;
365
        else if( unit.right( 2 ) == "cm" )
366
                value = ( value / 2.54 ) * 72;
367
        else if( unit.right( 2 ) == "mm" )
368
                value = ( value / 25.4 ) * 72;
369
        else if( unit.right( 2 ) == "in" )
370
                value = value * 72;
371
        else if( unit.right( 2 ) == "px" )
372
                value = value;
373
        return value;
374
}
375
 
376
QColor OODPlug::parseColorN( const QString &rgbColor )
377
{
378
        int r, g, b;
379
        keywordToRGB( rgbColor, r, g, b );
380
        return QColor( r, g, b );
381
}
382
 
383
QString OODPlug::parseColor( const QString &s )
384
{
385
        QColor c;
386
        QString ret = "None";
387
        if( s.startsWith( "rgb(" ) )
388
        {
389
                QString parse = s.stripWhiteSpace();
390
                QStringList colors = QStringList::split( ',', parse );
391
                QString r = colors[0].right( ( colors[0].length() - 4 ) );
392
                QString g = colors[1];
393
                QString b = colors[2].left( ( colors[2].length() - 1 ) );
394
                if( r.contains( "%" ) )
395
                {
396
                        r = r.left( r.length() - 1 );
397
                        r = QString::number( static_cast<int>( ( static_cast<double>( 255 * r.toDouble() ) / 100.0 ) ) );
398
                }
399
                if( g.contains( "%" ) )
400
                {
401
                        g = g.left( g.length() - 1 );
402
                        g = QString::number( static_cast<int>( ( static_cast<double>( 255 * g.toDouble() ) / 100.0 ) ) );
403
                }
404
                if( b.contains( "%" ) )
405
                {
406
                        b = b.left( b.length() - 1 );
407
                        b = QString::number( static_cast<int>( ( static_cast<double>( 255 * b.toDouble() ) / 100.0 ) ) );
408
                }
409
                c = QColor(r.toInt(), g.toInt(), b.toInt());
410
        }
411
        else
412
        {
413
                QString rgbColor = s.stripWhiteSpace();
414
                if( rgbColor.startsWith( "#" ) )
415
                        c.setNamedColor( rgbColor );
416
                else
417
                        c = parseColorN( rgbColor );
418
        }
419
        CListe::Iterator it;
420
        bool found = false;
421
        for (it = Doku->PageColors.begin(); it != Doku->PageColors.end(); ++it)
422
        {
423
                if (c == Doku->PageColors[it.key()].getRGBColor())
424
                {
425
                        ret = it.key();
426
                        found = true;
427
                }
428
        }
429
        if (!found)
430
        {
431
                CMYKColor tmp;
432
                tmp.fromQColor(c);
433
                Doku->PageColors.insert("FromOODraw"+c.name(), tmp);
434
                Prog->Mpal->Cpal->SetColors(Doku->PageColors);
435
                ret = "FromOODraw"+c.name();
436
        }
437
        return ret;
438
}
439
 
440
void OODPlug::parseTransform( const QString &transform, double *rot, double *dx, double *dy )
441
{
442
        QStringList subtransforms = QStringList::split(')', transform);
443
        QStringList::ConstIterator it = subtransforms.begin();
444
        QStringList::ConstIterator end = subtransforms.end();
445
        for(; it != end; ++it)
446
        {
447
                QStringList subtransform = QStringList::split('(', (*it));
448
 
449
                subtransform[0] = subtransform[0].stripWhiteSpace().lower();
450
                subtransform[1] = subtransform[1].simplifyWhiteSpace();
451
                QRegExp reg("[,( ]");
452
                QStringList params = QStringList::split(reg, subtransform[1]);
453
 
454
                if(subtransform[0].startsWith(";") || subtransform[0].startsWith(","))
455
                        subtransform[0] = subtransform[0].right(subtransform[0].length() - 1);
456
 
457
                if(subtransform[0] == "rotate")
458
                {
459
                        *rot = -parseUnit(params[0]) * 180 / 3.1415927;
460
                }
461
                else if(subtransform[0] == "translate")
462
                {
463
                        if(params.count() == 2)
464
                        {
465
                                *dx = parseUnit(params[0]);
466
                                *dy = parseUnit(params[1]);
467
                        }
468
                        else
469
                        {
470
                                *dx = parseUnit(params[0]);
471
                                *dy =0.0;
472
                        }
473
                }
474
        }
475
}
476
 
477
OODPlug::~OODPlug()
478
{}
479
 
480
 
481
/*
482
void SVGPlug::addGraphicContext()
483
{
484
        SvgStyle *gc = new SvgStyle;
485
        if ( m_gc.current() )
486
                *gc = *( m_gc.current() );
487
        m_gc.push( gc );
488
}
489
 
490
void SVGPlug::setupTransform( const QDomElement &e )
491
{
492
        SvgStyle *gc = m_gc.current();
493
        QWMatrix mat = parseTransform( e.attribute( "transform" ) );
494
        if (!e.attribute("transform").isEmpty())
495
                gc->matrix = mat * gc->matrix;
496
}
497
 
498
double SVGPlug::fromPercentage( const QString &s )
499
{
500
        if( s.endsWith( "%" ) )
501
                return s.toDouble() / 100.0;
502
        else
503
                return s.toDouble();
504
}
505
 
506
const char * SVGPlug::getCoord( const char *ptr, double &number )
507
{
508
        int integer, exponent;
509
        double decimal, frac;
510
        int sign, expsign;
511
 
512
        exponent = 0;
513
        integer = 0;
514
        frac = 1.0;
515
        decimal = 0;
516
        sign = 1;
517
        expsign = 1;
518
 
519
        if(*ptr == '+')
520
                ptr++;
521
        else if(*ptr == '-')
522
        {
523
                ptr++;
524
                sign = -1;
525
        }
526
 
527
        while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
528
                integer = (integer * 10) + *(ptr++) - '0';
529
        if(*ptr == '.')
530
        {ecimals
531
        {
532
                ptr++;
533
                while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
534
                        decimal += (*(ptr++) - '0') * (frac *= 0.1);
535
        }
536
 
537
        if(*ptr == 'e' || *ptr == 'E')
538
        {
539
                ptr++;
540
 
541
                if(*ptr == '+')
542
                        ptr++;
543
                else if(*ptr == '-')
544
                {
545
                        ptr++;
546
                        expsign = -1;
547
                }
548
 
549
                exponent = 0;
550
                while(*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
551
                {
552
                        exponent *= 10;
553
                        exponent += *ptr - '0';
554
                        ptr++;
555
                }
556
        }
557
        number = integer + decimal;
558
        number *= sign * pow( static_cast<double>(10), static_cast<double>( expsign * exponent ) );
559
 
560
        if(*ptr == ' ')
561
                ptr++;
562
 
563
        return ptr;
564
}
565
 
566
bool SVGPlug::parseSVG( const QString &s, FPointArray *ite )
567
{
568
        QString d = s;
569
        d = d.replace( QRegExp( "," ), " ");
570
        bool ret = false;
571
        if( !d.isEmpty() )
572
        {
573
                d = d.simplifyWhiteSpace();
574
                const char *ptr = d.latin1();
575
                const char *end = d.latin1() + d.length() + 1;
576
                double contrlx, contrly, curx, cury, subpathx, subpathy, tox, toy, x1, y1, x2, y2, xc, yc;
577
                double px1, py1, px2, py2, px3, py3;
578
                bool relative;
579
                FirstM = true;
580
                char command = *(ptr++), lastCommand = ' ';
581
                subpathx = subpathy = curx = cury = contrlx = contrly = 0.0;
582
                while( ptr < end )
583
                {
584
                        if( *ptr == ' ' )
585
                                ptr++;
586
                        relative = false;
587
                        switch( command )
588
                        {
589
                        case 'm':
590
                                relative = true;
591
                        case 'M':
592
                                {
593
                                        ptr = getCoord( ptr, tox );
594
                                        ptr = getCoord( ptr, toy );
595
                                        WasM = true;
596
                                        subpathx = curx = relative ? curx + tox : tox;
597
                                        subpathy = cury = relative ? cury + toy : toy;
598
                                        svgMoveTo(curx, cury );
599
                                        break;
600
                                }
601
                        case 'l':
602
                                relative = true;
603
                        case 'L':
604
                                {
605
                                        ptr = getCoord( ptr, tox );
606
                                        ptr = getCoord( ptr, toy );
607
                                        curx = relative ? curx + tox : tox;
608
                                        cury = relative ? cury + toy : toy;
609
                                        svgLineTo(ite, curx, cury );
610
                                        break;
611
                                }
612
                        case 'h':
613
                                {
614
                                        ptr = getCoord( ptr, tox );
615
                                        curx = curx + tox;
616
                                        svgLineTo(ite, curx, cury );
617
                                        break;
618
                                }
619
                        case 'H':
620
                                {
621
                                        ptr = getCoord( ptr, tox );
622
                                        curx = tox;
623
                                        svgLineTo(ite, curx, cury );
624
                                        break;
625
                                }
626
                        case 'v':
627
                                {
628
                                        ptr = getCoord( ptr, toy );
629
                                        cury = cury + toy;
630
                                        svgLineTo(ite, curx, cury );
631
                                        break;
632
                                }
633
                        case 'V':
634
                                {
635
                                        ptr = getCoord( ptr, toy );
636
                                        cury = toy;
637
                                        svgLineTo(ite,  curx, cury );
638
                                        break;
639
                                }
640
                        case 'z':
641
                        case 'Z':
642
                                {
643
                                        curx = subpathx;
644
                                        cury = subpathy;
645
                                        svgClosePath(ite);
646
                                        break;
647
                                }
648
                        case 'c':
649
                                relative = true;
650
                        case 'C':
651
                                {
652
                                        ptr = getCoord( ptr, x1 );
653
                                        ptr = getCoord( ptr, y1 );
654
                                        ptr = getCoord( ptr, x2 );
655
                                        ptr = getCoord( ptr, y2 );
656
                                        ptr = getCoord( ptr, tox );
657
                                        ptr = getCoord( ptr, toy );
658
                                        px1 = relative ? curx + x1 : x1;
659
                                        py1 = relative ? cury + y1 : y1;
660
                                        px2 = relative ? curx + x2 : x2;
661
                                        py2 = relative ? cury + y2 : y2;
662
                                        px3 = relative ? curx + tox : tox;
663
                                        py3 = relative ? cury + toy : toy;
664
                                        svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 );
665
                                        contrlx = relative ? curx + x2 : x2;
666
                                        contrly = relative ? cury + y2 : y2;
667
                                        curx = relative ? curx + tox : tox;
668
                                        cury = relative ? cury + toy : toy;
669
                                        break;
670
                                }
671
                        case 's':
672
                                relative = true;
673
                        case 'S':
674
                                {
675
                                        ptr = getCoord( ptr, x2 );
676
                                        ptr = getCoord( ptr, y2 );
677
                                        ptr = getCoord( ptr, tox );
678
                                        ptr = getCoord( ptr, toy );
679
                                        px1 = 2 * curx - contrlx;
680
                                        py1 = 2 * cury - contrly;
681
                                        px2 = relative ? curx + x2 : x2;
682
                                        py2 = relative ? cury + y2 : y2;
683
                                        px3 = relative ? curx + tox : tox;
684
                                        py3 = relative ? cury + toy : toy;
685
                                        svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 );
686
                                        contrlx = relative ? curx + x2 : x2;
687
                                        contrly = relative ? cury + y2 : y2;
688
                                        curx = relative ? curx + tox : tox;
689
                                        cury = relative ? cury + toy : toy;
690
                                        break;
691
                                }
692
                        case 'q':
693
                                relative = true;
694
                        case 'Q':
695
                                {
696
                                        ptr = getCoord( ptr, x1 );
697
                                        ptr = getCoord( ptr, y1 );
698
                                        ptr = getCoord( ptr, tox );
699
                                        ptr = getCoord( ptr, toy );
700
                                        px1 = relative ? (curx + 2 * (x1 + curx)) * (1.0 / 3.0) : (curx + 2 * x1) * (1.0 / 3.0);
701
                                        py1 = relative ? (cury + 2 * (y1 + cury)) * (1.0 / 3.0) : (cury + 2 * y1) * (1.0 / 3.0);
702
                                        px2 = relative ? ((curx + tox) + 2 * (x1 + curx)) * (1.0 / 3.0) : (tox + 2 * x1) * (1.0 / 3.0);
703
                                        py2 = relative ? ((cury + toy) + 2 * (y1 + cury)) * (1.0 / 3.0) : (toy + 2 * y1) * (1.0 / 3.0);
704
                                        px3 = relative ? curx + tox : tox;
705
                                        py3 = relative ? cury + toy : toy;
706
                                        svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 );
707
                                        contrlx = relative ? curx + x1 : (tox + 2 * x1) * (1.0 / 3.0);
708
                                        contrly = relative ? cury + y1 : (toy + 2 * y1) * (1.0 / 3.0);
709
                                        curx = relative ? curx + tox : tox;
710
                                        cury = relative ? cury + toy : toy;
711
                                        break;
712
                                }
713
                        case 't':
714
                                relative = true;
715
                        case 'T':
716
                                {
717
                                        ptr = getCoord(ptr, tox);
718
                                        ptr = getCoord(ptr, toy);
719
                                        xc = 2 * curx - contrlx;
720
                                        yc = 2 * cury - contrly;
721
                                        px1 = relative ? (curx + 2 * xc) * (1.0 / 3.0) : (curx + 2 * xc) * (1.0 / 3.0);
722
                                        py1 = relative ? (cury + 2 * yc) * (1.0 / 3.0) : (cury + 2 * yc) * (1.0 / 3.0);
723
                                        px2 = relative ? ((curx + tox) + 2 * xc) * (1.0 / 3.0) : (tox + 2 * xc) * (1.0 / 3.0);
724
                                        py2 = relative ? ((cury + toy) + 2 * yc) * (1.0 / 3.0) : (toy + 2 * yc) * (1.0 / 3.0);
725
                                        px3 = relative ? curx + tox : tox;
726
                                        py3 = relative ? cury + toy : toy;
727
                                        svgCurveToCubic(ite, px1, py1, px2, py2, px3, py3 );
728
                                        contrlx = xc;
729
                                        contrly = yc;
730
                                        curx = relative ? curx + tox : tox;
731
                                        cury = relative ? cury + toy : toy;
732
                                        break;
733
                                }
734
                        case 'a':
735
                                relative = true;
736
                        case 'A':
737
                                {
738
                                        bool largeArc, sweep;
739
                                        double angle, rx, ry;
740
                                        ptr = getCoord( ptr, rx );
741
                                        ptr = getCoord( ptr, ry );
742
                                        ptr = getCoord( ptr, angle );
743
                                        ptr = getCoord( ptr, tox );
744
                                        largeArc = tox == 1;
745
                                        ptr = getCoord( ptr, tox );
746
                                        sweep = tox == 1;
747
                                        ptr = getCoord( ptr, tox );
748
                                        ptr = getCoord( ptr, toy );
749
                                        calculateArc(ite, relative, curx, cury, angle, tox, toy, rx, ry, largeArc, sweep );
750
                                }
751
                        }
752
                        lastCommand = command;
753
                        if(*ptr == '+' || *ptr == '-' || (*ptr >= '0' && *ptr <= '9'))
754
                        {
755
                                // there are still coords in this command
756
                                if(command == 'M')
757
                                        command = 'L';
758
                                else if(command == 'm')
759
                                        command = 'l';
760
                        }
761
                        else
762
                                command = *(ptr++);
763
 
764
                        if( lastCommand != 'C' && lastCommand != 'c' &&
765
                                lastCommand != 'S' && lastCommand != 's' &&
766
                                lastCommand != 'Q' && lastCommand != 'q' &&
767
                                lastCommand != 'T' && lastCommand != 't')
768
                        {
769
                                contrlx = curx;
770
                                contrly = cury;
771
                        }
772
                }
773
                if ((lastCommand != 'z') && (lastCommand != 'Z'))
774
                        ret = true;
775
                if (ite->size() > 2)
776
                {
777
                        if ((ite->point(0).x() == ite->point(ite->size()-2).x()) && (ite->point(0).y() == ite->point(ite->size()-2).y()))
778
                                ret = false;
779
                }
780
        }
781
        return ret;
782
}
783
 
784
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)
785
{
786
        double sin_th, cos_th;
787
        double a00, a01, a10, a11;
788
        double x0, y0, x1, y1, xc, yc;
789
        double d, sfactor, sfactor_sq;
790
        double th0, th1, th_arc;
791
        int i, n_segs;
792
        sin_th = sin(angle * (M_PI / 180.0));
793
        cos_th = cos(angle * (M_PI / 180.0));
794
        double dx;
795
        if(!relative)
796
                dx = (curx - x) / 2.0;
797
        else
798
                dx = -x / 2.0;
799
        double dy;
800
        if(!relative)
801
                dy = (cury - y) / 2.0;
802
        else
803
                dy = -y / 2.0;
804
        double _x1 =  cos_th * dx + sin_th * dy;
805
        double _y1 = -sin_th * dx + cos_th * dy;
806
        double Pr1 = r1 * r1;
807
        double Pr2 = r2 * r2;
808
        double Px = _x1 * _x1;
809
        double Py = _y1 * _y1;
810
        double check = Px / Pr1 + Py / Pr2;
811
        if(check > 1)
812
        {
813
                r1 = r1 * sqrt(check);
814
                r2 = r2 * sqrt(check);
815
        }
816
        a00 = cos_th / r1;
817
        a01 = sin_th / r1;
818
        a10 = -sin_th / r2;
819
        a11 = cos_th / r2;
820
        x0 = a00 * curx + a01 * cury;
821
        y0 = a10 * curx + a11 * cury;
822
        if(!relative)
823
                x1 = a00 * x + a01 * y;
824
        else
825
                x1 = a00 * (curx + x) + a01 * (cury + y);
826
        if(!relative)
827
                y1 = a10 * x + a11 * y;
828
        else
829
                y1 = a10 * (curx + x) + a11 * (cury + y);
830
        d = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0);
831
        sfactor_sq = 1.0 / d - 0.25;
832
        if(sfactor_sq < 0)
833
                sfactor_sq = 0;
834
        sfactor = sqrt(sfactor_sq);
835
        if(sweepFlag == largeArcFlag)
836
                sfactor = -sfactor;
837
        xc = 0.5 * (x0 + x1) - sfactor * (y1 - y0);
838
        yc = 0.5 * (y0 + y1) + sfactor * (x1 - x0);
839
 
840
        th0 = atan2(y0 - yc, x0 - xc);
841
        th1 = atan2(y1 - yc, x1 - xc);
842
        th_arc = th1 - th0;
843
        if(th_arc < 0 && sweepFlag)
844
                th_arc += 2 * M_PI;
845
        else if(th_arc > 0 && !sweepFlag)
846
                th_arc -= 2 * M_PI;
847
        n_segs = static_cast<int>(ceil(fabs(th_arc / (M_PI * 0.5 + 0.001))));
848
        for(i = 0; i < n_segs; i++)
849
        {
850
                {
851
                        double sin_th, cos_th;
852
                        double a00, a01, a10, a11;
853
                        double x1, y1, x2, y2, x3, y3;
854
                        double t;
855
                        double th_half;
856
                        double _th0 = th0 + i * th_arc / n_segs;
857
                        double _th1 = th0 + (i + 1) * th_arc / n_segs;
858
                        sin_th = sin(angle * (M_PI / 180.0));
859
                        cos_th = cos(angle * (M_PI / 180.0));
860
                        a00 = cos_th * r1;
861
                        a01 = -sin_th * r2;
862
                        a10 = sin_th * r1;
863
                        a11 = cos_th * r2;
864
                        th_half = 0.5 * (_th1 - _th0);
865
                        t = (8.0 / 3.0) * sin(th_half * 0.5) * sin(th_half * 0.5) / sin(th_half);
866
                        x1 = xc + cos(_th0) - t * sin(_th0);
867
                        y1 = yc + sin(_th0) + t * cos(_th0);
868
                        x3 = xc + cos(_th1);
869
                        y3 = yc + sin(_th1);
870
                        x2 = x3 + t * sin(_th1);
871
                        y2 = y3 - t * cos(_th1);
872
                        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 );
873
                }
874
        }
875
        if(!relative)
876
                curx = x;
877
        else
878
                curx += x;
879
        if(!relative)
880
                cury = y;
881
        else
882
                cury += y;
883
}
884
 
885
void SVGPlug::svgMoveTo(double x1, double y1)
886
{
887
        CurrX = x1;
888
        CurrY = y1;
889
        StartX = x1;
890
        StartY = y1;
891
        PathLen = 0;
892
}
893
 
894
void SVGPlug::svgLineTo(FPointArray *i, double x1, double y1)
895
{
896
        if ((!FirstM) && (WasM))
897
        {
898
                i->setMarker();
899
                PathLen += 4;
900
        }
901
        FirstM = false;
902
        WasM = false;
903
        if (i->size() > 3)
904
        {
905
                FPoint b1 = i->point(i->size()-4);
906
                FPoint b2 = i->point(i->size()-3);
907
                FPoint b3 = i->point(i->size()-2);
908
                FPoint b4 = i->point(i->size()-1);
909
                FPoint n1 = FPoint(CurrX, CurrY);
910
                FPoint n2 = FPoint(x1, y1);
911
                if ((b1 == n1) && (b2 == n1) && (b3 == n2) && (b4 == n2))
912
                        return;
913
        }
914
        i->addPoint(FPoint(CurrX, CurrY));
915
        i->addPoint(FPoint(CurrX, CurrY));
916
        i->addPoint(FPoint(x1, y1));
917
        i->addPoint(FPoint(x1, y1));
918
        CurrX = x1;
919
        CurrY = y1;
920
        PathLen += 4;
921
}
922
 
923
void SVGPlug::svgCurveToCubic(FPointArray *i, double x1, double y1, double x2, double y2, double x3, double y3)
924
{
925
        if ((!FirstM) && (WasM))
926
        {
927
                i->setMarker();
928
                PathLen += 4;
929
        }
930
        FirstM = false;
931
        WasM = false;
932
        if (PathLen > 3)
933
        {
934
                FPoint b1 = i->point(i->size()-4);
935
                FPoint b2 = i->point(i->size()-3);
936
                FPoint b3 = i->point(i->size()-2);
937
                FPoint b4 = i->point(i->size()-1);
938
                FPoint n1 = FPoint(CurrX, CurrY);
939
                FPoint n2 = FPoint(x1, y1);
940
                FPoint n3 = FPoint(x3, y3);
941
                FPoint n4 = FPoint(x2, y2);
942
                if ((b1 == n1) && (b2 == n2) && (b3 == n3) && (b4 == n4))
943
                        return;
944
        }
945
        i->addPoint(FPoint(CurrX, CurrY));
946
        i->addPoint(FPoint(x1, y1));
947
        i->addPoint(FPoint(x3, y3));
948
        i->addPoint(FPoint(x2, y2));
949
        CurrX = x3;
950
        CurrY = y3;
951
        PathLen += 4;
952
}
953
 
954
void SVGPlug::svgClosePath(FPointArray *i)
955
{
956
        if (PathLen > 2)
957
        {
958
                if ((PathLen == 4) || (i->point(i->size()-2).x() != StartX) || (i->point(i->size()-2).y() != StartY))
959
                {
960
                        i->addPoint(i->point(i->size()-2));
961
                        i->addPoint(i->point(i->size()-3));
962
                        i->addPoint(FPoint(StartX, StartY));
963
                        i->addPoint(FPoint(StartX, StartY));
964
                }
965
        }
966
}
967
 
968
QColor SVGPlug::parseColorN( const QString &rgbColor )
969
{
970
        int r, g, b;
971
        keywordToRGB( rgbColor, r, g, b );
972
        return QColor( r, g, b );
973
}
974
 
975
void SVGPlug::parsePA( SvgStyle *obj, const QString &command, const QString &params )
976
{
977
        if( command == "fill" )
978
        {
979
                if ((obj->InherCol) && (params == "currentColor"))
980
                        obj->FillCol = obj->CurCol;
981
                else if (params == "none")
982
                {
983
                        obj->FillCol = "None";
984
                }
985
                else if( params.startsWith( "url(" ) )
986
                {
987
                        unsigned int start = params.find("#") + 1;
988
                        unsigned int end = params.findRev(")");
989
                        QString key = params.mid(start, end - start);
990
                        obj->Gradient = m_gradients[key].Type;
991
                        obj->GradCo = m_gradients[key].gradient;
992
                        obj->CSpace = m_gradients[key].CSpace;
993
                        obj->GX1 = m_gradients[key].X1;
994
                        obj->GY1 = m_gradients[key].Y1;
995
                        obj->GX2 = m_gradients[key].X2;
996
                        obj->GY2 = m_gradients[key].Y2;
997
                        obj->matrixg = m_gradients[key].matrix;
998
                        obj->FillCol = "None";
999
                }
1000
                else
1001
                        obj->FillCol = parseColor(params);
1002
        }
1003
        else if( command == "color" )
1004
        {
1005
                if (params == "none")
1006
                        obj->CurCol = "None";
1007
                else if( params.startsWith( "url(" ) )
1008
                {
1009
                        obj->CurCol = "None";
1010
                }
1011
                else
1012
                {
1013
                        obj->CurCol = parseColor(params);
1014
                }
1015
        }
1016
        else if( command == "stroke" )
1017
        {
1018
                if ((obj->InherCol) && (params == "currentColor"))
1019
                        obj->StrokeCol = obj->CurCol;
1020
                else if (params == "none")
1021
                {
1022
                        obj->StrokeCol = "None";
1023
                }
1024
                else if( params.startsWith( "url(" ) )
1025
                {
1026
                        obj->StrokeCol = "None";
1027
                }
1028
                else
1029
                        obj->StrokeCol = parseColor(params);
1030
        }
1031
        else if( command == "stroke-width" )
1032
                obj->LWidth = parseUnit( params );
1033
        else if( command == "stroke-linejoin" )
1034
        {
1035
                if( params == "miter" )
1036
                        obj->PLineJoin = Qt::MiterJoin;
1037
                else if( params == "round" )
1038
                        obj->PLineJoin = Qt::RoundJoin;
1039
                else if( params == "bevel" )
1040
                        obj->PLineJoin = Qt::BevelJoin;
1041
        }
1042
        else if( command == "stroke-linecap" )
1043
        {
1044
                if( params == "butt" )
1045
                        obj->PLineEnd = Qt::FlatCap;
1046
                else if( params == "round" )
1047
                        obj->PLineEnd = Qt::RoundCap;
1048
                else if( params == "square" )
1049
                        obj->PLineEnd = Qt::SquareCap;
1050
        }
1051
        else if( command == "stroke-dasharray" )
1052
        {
1053
                QValueList<double> array;
1054
                if(params != "none")
1055
                {
1056
                        QStringList dashes = QStringList::split( ' ', params );
1057
                        for( QStringList::Iterator it = dashes.begin(); it != dashes.end(); ++it )
1058
                                array.append( (*it).toDouble() );
1059
                }
1060
                obj->dashArray = array;
1061
        }
1062
        else if( command == "stroke-dashoffset" )
1063
                obj->dashOffset = params.toDouble();
1064
        else if( command == "stroke-opacity" )
1065
                obj->TranspStroke = 1.0 - fromPercentage(params);
1066
        else if( command == "fill-opacity" )
1067
                obj->Transparency = 1.0 - fromPercentage(params);
1068
        else if( command == "opacity" )
1069
        {
1070
                obj->Transparency = 1.0 - fromPercentage(params);
1071
                obj->TranspStroke = 1.0 - fromPercentage(params);
1072
        }
1073
        else if( command == "font-family" )
1074
        {
1075
                QString family = params;
1076
                QString ret = "";
1077
                family.replace( QRegExp( "'" ) , QChar( ' ' ) );
1078
                obj->Family = Doku->Dfont; // family;
1079
                bool found = false;
1080
                SCFontsIterator it(Prog->Prefs.AvailFonts);
1081
                for ( ; it.current(); ++it)
1082
                {
1083
                        QString fam;
1084
                        QString &fn = it.current()->SCName;
1085
                        int     pos=fn.find(" ");
1086
                        fam = fn.left(pos);
1087
                        if (fam == family)
1088
                        {
1089
                                found = true;
1090
                                ret = fn;
1091
                        }
1092
                }
1093
                if (found)
1094
                        obj->Family = ret;
1095
                else
1096
                        obj->Family = Doku->Dfont;
1097
        }
1098
        else if( command == "font-size" )
1099
                obj->FontSize = static_cast<int>(parseUnit(params) * 10.0);
1100
}
1101
 
1102
void SVGPlug::parseStyle( SvgStyle *obj, const QDomElement &e )
1103
{
1104
        SvgStyle *gc = m_gc.current();
1105
        if (!gc)
1106
                return;
1107
        if( !e.attribute( "color" ).isEmpty() )
1108
        {
1109
                if (e.attribute( "color" ) == "inherit")
1110
                        gc->InherCol = true;
1111
                else
1112
                        parsePA( obj, "color", e.attribute( "color" ) );
1113
        }
1114
        if( !e.attribute( "fill" ).isEmpty() )
1115
                parsePA( obj, "fill", e.attribute( "fill" ) );
1116
        if( !e.attribute( "stroke" ).isEmpty() )
1117
                parsePA( obj, "stroke", e.attribute( "stroke" ) );
1118
        if( !e.attribute( "stroke-width" ).isEmpty() )
1119
                parsePA( obj, "stroke-width", e.attribute( "stroke-width" ) );
1120
        if( !e.attribute( "stroke-linejoin" ).isEmpty() )
1121
                parsePA( obj, "stroke-linejoin", e.attribute( "stroke-linejoin" ) );
1122
        if( !e.attribute( "stroke-linecap" ).isEmpty() )
1123
                parsePA( obj, "stroke-linecap", e.attribute( "stroke-linecap" ) );
1124
        if( !e.attribute( "stroke-dasharray" ).isEmpty() )
1125
                parsePA( obj, "stroke-dasharray", e.attribute( "stroke-dasharray" ) );
1126
        if( !e.attribute( "stroke-dashoffset" ).isEmpty() )
1127
                parsePA( obj, "stroke-dashoffset", e.attribute( "stroke-dashoffset" ) );
1128
        if( !e.attribute( "stroke-opacity" ).isEmpty() )
1129
                parsePA( obj, "stroke-opacity", e.attribute( "stroke-opacity" ) );
1130
        if( !e.attribute( "fill-opacity" ).isEmpty() )
1131
                parsePA( obj, "fill-opacity", e.attribute( "fill-opacity" ) );
1132
        if( !e.attribute( "opacity" ).isEmpty() )
1133
                parsePA( obj, "opacity", e.attribute( "opacity" ) );
1134
        if( !e.attribute( "font-family" ).isEmpty() )
1135
                parsePA( obj, "font-family", e.attribute( "font-family" ) );
1136
        if( !e.attribute( "font-size" ).isEmpty() )
1137
                parsePA( obj, "font-size", e.attribute( "font-size" ) );
1138
        QString style = e.attribute( "style" ).simplifyWhiteSpace();
1139
        QStringList substyles = QStringList::split( ';', style );
1140
        for( QStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it )
1141
        {
1142
                QStringList substyle = QStringList::split( ':', (*it) );
1143
                QString command = substyle[0].stripWhiteSpace();
1144
                QString params  = substyle[1].stripWhiteSpace();
1145
                parsePA( obj, command, params );
1146
        }
1147
        return;
1148
}
1149
 
1150
void SVGPlug::parseColorStops(GradientHelper *gradient, const QDomElement &e)
1151
{
1152
        QString Col = "Black";
1153
        double offset, opa;
1154
        for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling())
1155
        {
1156
                opa = 1.0;
1157
                QDomElement stop = n.toElement();
1158
                if(stop.tagName() == "stop")
1159
                {
1160
                        QString temp = stop.attribute( "offset" );
1161
                        if( temp.contains( '%' ) )
1162
                        {
1163
                                temp = temp.left( temp.length() - 1 );
1164
                                offset = temp.toDouble() / 100.0;
1165
                        }
1166
                        else
1167
                                offset = temp.toDouble();
1168
                        if( !stop.attribute( "stop-opacity" ).isEmpty() )
1169
                                opa = fromPercentage(stop.attribute("stop-opacity"));
1170
                        if( !stop.attribute( "stop-color" ).isEmpty() )
1171
                                Col = parseColor(stop.attribute("stop-color"));
1172
                        else
1173
                        {
1174
                                QString style = stop.attribute( "style" ).simplifyWhiteSpace();
1175
                                QStringList substyles = QStringList::split( ';', style );
1176
                                for( QStringList::Iterator it = substyles.begin(); it != substyles.end(); ++it )
1177
                                {
1178
                                        QStringList substyle = QStringList::split( ':', (*it) );
1179
                                        QString command = substyle[0].stripWhiteSpace();
1180
                                        QString params  = substyle[1].stripWhiteSpace();
1181
                                        if( command == "stop-color" )
1182
                                                Col = parseColor(params);
1183
                                        if( command == "stop-opacity" )
1184
                                                opa = fromPercentage(params);
1185
                                }
1186
                        }
1187
                }
1188
                gradient->gradient.addStop( Doku->PageColors[Col].getRGBColor(), offset, 0.5, opa, Col, 100 );
1189
        }
1190
}
1191
 
1192
void SVGPlug::parseGradient( const QDomElement &e )
1193
{
1194
        GradientHelper gradhelper;
1195
        gradhelper.gradient.clearStops();
1196
        gradhelper.gradient.setRepeatMethod( VGradient::none );
1197
 
1198
        QString href = e.attribute("xlink:href").mid(1);
1199
        double x1, y1, x2, y2;
1200
        if (!href.isEmpty())
1201
        {
1202
                gradhelper.Type = m_gradients[href].Type;
1203
                gradhelper.gradient = m_gradients[href].gradient;
1204
                gradhelper.X1 = m_gradients[href].X1;
1205
                gradhelper.Y1 = m_gradients[href].Y1;
1206
                gradhelper.X2 = m_gradients[href].X2;
1207
                gradhelper.Y2 = m_gradients[href].Y2;
1208
                gradhelper.CSpace = m_gradients[href].CSpace;
1209
                gradhelper.matrix = m_gradients[href].matrix;
1210
        }
1211
        if (e.tagName() == "linearGradient")
1212
        {
1213
                x1 = e.attribute( "x1", "0").toDouble();
1214
                y1 = e.attribute( "y1", "0" ).toDouble();
1215
                x2 = e.attribute( "x2", "1" ).toDouble();
1216
                y2 = e.attribute( "y2", "0" ).toDouble();
1217
                gradhelper.X1 = x1;
1218
                gradhelper.Y1 = y1;
1219
                gradhelper.X2 = x2;
1220
                gradhelper.Y2 = y2;
1221
                gradhelper.Type = 6;
1222
        }
1223
        else
1224
        {
1225
                x1 = e.attribute( "cx", "0.5").toDouble();
1226
                y1 = e.attribute( "cy", "0.5" ).toDouble();
1227
                x2 = e.attribute( "r", "0.5" ).toDouble();
1228
                y2 = y1;
1229
                gradhelper.X1 = x1;
1230
                gradhelper.Y1 = y1;
1231
                gradhelper.X2 = x1 + x2;
1232
                gradhelper.Y2 = y1;
1233
                gradhelper.Type = 7;
1234
        }
1235
        if ( !e.attribute( "gradientUnits" ).isEmpty() )
1236
        {
1237
                QString uni = e.attribute( "gradientUnits");
1238
                if (uni == "userSpaceOnUse")
1239
                        gradhelper.CSpace = true;
1240
                else
1241
                        gradhelper.CSpace = false;
1242
        }
1243
        else
1244
                gradhelper.CSpace = false;
1245
        QString transf = e.attribute("gradientTransform");
1246
        if( !transf.isEmpty() )
1247
        {
1248
                gradhelper.matrix = parseTransform( e.attribute( "gradientTransform" ) );
1249
        }
1250
        QString spreadMethod = e.attribute( "spreadMethod" );
1251
        if( !spreadMethod.isEmpty() )
1252
        {
1253
                if( spreadMethod == "reflect" )
1254
                        gradhelper.gradient.setRepeatMethod( VGradient::reflect );
1255
                else if( spreadMethod == "repeat" )
1256
                        gradhelper.gradient.setRepeatMethod( VGradient::repeat );
1257
        }
1258
        parseColorStops(&gradhelper, e);
1259
        m_gradients.insert(e.attribute("id"), gradhelper);
1260
}
1261
 
1262
QPtrList<PageItem> SVGPlug::parseText(double x, double y, const QDomElement &e)
1263
{
1264
        struct Pti *hg;
1265
        QPainter p;
1266
        QPtrList<PageItem> GElements;
1267
        p.begin(Prog->view->viewport());
1268
        QFont ff(Doku->UsedFonts[m_gc.current()->Family]);
1269
        ff.setPointSize(QMAX(qRound(m_gc.current()->FontSize / 10.0), 1));
1270
        p.setFont(ff);
1271
        setupTransform(e);
1272
        int desc = p.fontMetrics().descent();
1273
        int asce = p.fontMetrics().ascent();
1274
        QString Text = QString::fromUtf8(e.text()).stripWhiteSpace();
1275
        QDomNode c = e.firstChild();
1276
        if ((!c.isNull()) && (c.toElement().tagName() == "tspan"))
1277
        {
1278
                double tempW = 0;
1279
                for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling())
1280
                {
1281
                        tempW = 0;
1282
                        QDomElement tspan = n.toElement();
1283
                        addGraphicContext();
1284
                        SvgStyle *gc = m_gc.current();
1285
                        parseStyle(gc, tspan);
1286
                        int z = Prog->view->PaintText(x, y, 10, 10, gc->LWidth, gc->FillCol);
1287
                        PageItem* ite = Doku->Items.at(z);
1288
                        ite->Extra = 0;
1289
                        ite->TExtra = 0;
1290
                        ite->BExtra = 0;
1291
                        ite->RExtra = 0;
1292
                        ite->LineSp = gc->FontSize / 10.0 + 2;
1293
                        ite->Height = ite->LineSp+desc+2;
1294
                        Prog->SetNewFont(gc->Family);
1295
                        QWMatrix mm = gc->matrix;
1296
                        if( (!tspan.attribute("x").isEmpty()) && (!tspan.attribute("y").isEmpty()) )
1297
                        {
1298
                                double x1 = parseUnit( tspan.attribute( "x", "0" ) );
1299
                                double y1 = parseUnit( tspan.attribute( "y", "0" ) );
1300
                                double mx = mm.m11() * x1 + mm.m21() * y1 + mm.dx();
1301
                                double my = mm.m22() * y1 + mm.m12() * x1 + mm.dy();
1302
                                ite->Xpos = mx;
1303
                                ite->Ypos = my;
1304
                        }
1305
                        else
1306
                        {
1307
                                double mx = mm.m11() * x + mm.m21() * y + mm.dx();
1308
                                double my = mm.m22() * y + mm.m12() * x + mm.dy();
1309
                                ite->Xpos = mx;
1310
                                ite->Ypos = my;
1311
                        }
1312
                        if (!tspan.text().isNull())
1313
                                Text = QString::fromUtf8(tspan.text()).stripWhiteSpace();
1314
                        else
1315
                                Text = " ";
1316
                        ite->IFont = gc->Family;
1317
                        ite->TxtFill = gc->FillCol;
1318
                        ite->ShTxtFill = 100;
1319
                        ite->TxtStroke = gc->StrokeCol;
1320
                        ite->ShTxtStroke = 100;
1321
                        ite->ISize = gc->FontSize;
1322
                        ite->TxTStyle = 0;
1323
                        ite->TxtScale = 100;
1324
                        for (uint tt = 0; tt < Text.length(); ++tt)
1325
                        {
1326
                                hg = new Pti;
1327
                                hg->ch = Text.at(tt);
1328
                                hg->cfont = gc->Family;
1329
                                hg->csize = gc->FontSize;
1330
                                hg->ccolor = gc->FillCol;
1331
                                hg->cextra = 0;
1332
                                hg->cshade = 100;
1333
                                hg->cstroke = gc->StrokeCol;
1334
                                hg->cshade2 = 100;
1335
                                hg->cscale = 100;
1336
                                hg->cselect = false;
1337
                                if( !tspan.attribute( "stroke" ).isEmpty() )
1338
                                        hg->cstyle = 4;
1339
                                else
1340
                                        hg->cstyle = 0;
1341
                                hg->cab = 0;
1342
                                hg->xp = 0;
1343
                                hg->yp = 0;
1344
                                hg->PRot = 0;
1345
                                hg->PtransX = 0;
1346
                                hg->PtransY = 0;
1347
                                ite->Ptext.append(hg);
1348
                                tempW += RealCWidth(Doku, hg->cfont, hg->ch, hg->csize)+1;
1349
                                if (hg->ch == QChar(13))
1350
                                {
1351
                                        ite->Height += ite->LineSp+desc;
1352
                                        ite->Width = QMAX(ite->Width, tempW);
1353
                                        tempW = 0;
1354
                                }
1355
                        }
1356
                        ite->Width = QMAX(ite->Width, tempW);
1357
                        Prog->view->SetRectFrame(ite);
1358
                        ite->Clip = FlattenPath(ite->PoLine, ite->Segments);
1359
                        Prog->view->SelItem.append(ite);
1360
                        Prog->view->HowTo = 1;
1361
                        Prog->view->setGroupRect();
1362
                        Prog->view->scaleGroup(mm.m11(), mm.m22());
1363
                        Prog->view->Deselect();
1364
                        ite->Ypos -= asce * mm.m22();
1365
                        if( !e.attribute("id").isEmpty() )
1366
                                ite->AnName += " "+e.attribute("id");
1367
                        ite->Transparency = gc->Transparency;
1368
                        ite->TranspStroke = gc->TranspStroke;
1369
                        ite->PLineEnd = gc->PLineEnd;
1370
                        ite->PLineJoin = gc->PLineJoin;
1371
                        ite->Textflow = false;
1372
                        ite->DashOffset = gc->dashOffset;
1373
                        ite->DashValues = gc->dashArray;
1374
                        GElements.append(ite);
1375
                        Elements.append(ite);
1376
                        delete( m_gc.pop() );
1377
                }
1378
        }
1379
        else
1380
        {
1381
                SvgStyle *gc = m_gc.current();
1382
                int z = Prog->view->PaintText(x, y - qRound(gc->FontSize / 10.0), 10, 10, gc->LWidth, gc->FillCol);
1383
                PageItem* ite = Doku->Items.at(z);
1384
                ite->Extra = 0;
1385
                ite->TExtra = 0;
1386
                ite->BExtra = 0;
1387
                ite->RExtra = 0;
1388
                ite->LineSp = gc->FontSize / 10.0 + 2;
1389
                Prog->SetNewFont(gc->Family);
1390
                ite->IFont = gc->Family;
1391
                ite->TxtFill = gc->FillCol;
1392
                ite->ShTxtFill = 100;
1393
                ite->TxtStroke = gc->StrokeCol;
1394
                ite->ShTxtStroke = 100;
1395
                ite->ISize = gc->FontSize;
1396
                ite->TxTStyle = 0;
1397
                ite->TxtScale = 100;
1398
                for (uint cc = 0; cc<Text.length(); ++cc)
1399
                {
1400
                        hg = new Pti;
1401
                        hg->ch = Text.at(cc);
1402
                        hg->cfont = gc->Family;
1403
                        hg->csize = gc->FontSize;
1404
                        hg->ccolor = gc->FillCol;
1405
                        hg->cextra = 0;
1406
                        hg->cshade = 100;
1407
                        hg->cstroke = gc->StrokeCol;
1408
                        hg->cshade2 = 100;
1409
                        hg->cscale = 100;
1410
                        hg->cselect = false;
1411
                        if( !e.attribute( "stroke" ).isEmpty() )
1412
                                hg->cstyle = 4;
1413
                        else
1414
                                hg->cstyle = 0;
1415
                        hg->cab = 0;
1416
                        hg->xp = 0;
1417
                        hg->yp = 0;
1418
                        hg->PRot = 0;
1419
                        hg->PtransX = 0;
1420
                        hg->PtransY = 0;
1421
                        ite->Ptext.append(hg);
1422
                        ite->Width += RealCWidth(Doku, hg->cfont, hg->ch, hg->csize)+1;
1423
                        ite->Height = ite->LineSp+desc+2;
1424
                }
1425
                Prog->view->SetRectFrame(ite);
1426
                if( !e.attribute("id").isEmpty() )
1427
                        ite->AnName += " "+e.attribute("id");
1428
                ite->Transparency = gc->Transparency;
1429
                ite->TranspStroke = gc->TranspStroke;
1430
                ite->PLineEnd = gc->PLineEnd;
1431
                ite->PLineJoin = gc->PLineJoin;
1432
                ite->Textflow = false;
1433
                ite->DashOffset = gc->dashOffset;
1434
                ite->DashValues = gc->dashArray;
1435
                GElements.append(ite);
1436
                Elements.append(ite);
1437
        }
1438
        p.end();
1439
        return GElements;
1440
}
1441
*/