Subversion Repositories Scribus

Rev

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