Subversion Repositories Scribus

Rev

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

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