Subversion Repositories Scribus

Rev

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

Rev Author Line No. Line
4430 cbradney 1
/*
2
For general Scribus (>=1.3.2) copyright and licensing information please refer
3
to the COPYING file provided with the program. Following this notice may exist
4
a copyright and/or license notice that predates the release of Scribus 1.3.2
5
for which a new license (GPL+exception) is in place.
6
*/
21 Franz 7
/***************************************************************************
8
                          svgexplugin.cpp  -  description
9
                             -------------------
10
    begin                : Sun Aug 3 08:00:00 CEST 2002
11
    copyright            : (C) 2002 by Franz Schmid
12
    email                : Franz.Schmid@altmuehlnet.de
13
 ***************************************************************************/
14
 
15
/***************************************************************************
16
 *                                                                         *
17
 *   This program is free software; you can redistribute it and/or modify  *
18
 *   it under the terms of the GNU General Public License as published by  *
19
 *   the Free Software Foundation; either version 2 of the License, or     *
20
 *   (at your option) any later version.                                   *
21
 *                                                                         *
22
 ***************************************************************************/
766 cbradney 23
 
17941 jghali 24
#include <QBuffer>
25
#include <QByteArray>
26
#include <QCheckBox>
27
#include <QDataStream>
10223 cbradney 28
#include <QFile>
9856 fschmid 29
#include <QList>
17941 jghali 30
#include <QMessageBox>
16238 fschmid 31
#include <QScopedPointer>
17941 jghali 32
#include <QTextStream>
766 cbradney 33
 
21 Franz 34
#include "svgexplugin.h"
512 fschmid 35
 
2688 craig 36
#include "scconfig.h"
10532 avox 37
#include "canvas.h"
5781 cbradney 38
#include "cmsettings.h"
4546 subik 39
#include "commonstrings.h"
17023 fschmid 40
#include "pageitem_pathtext.h"
17315 fschmid 41
#include "pageitem_table.h"
2856 cbradney 42
#include "prefsmanager.h"
3670 cbradney 43
#include "prefsfile.h"
44
#include "prefscontext.h"
18910 fschmid 45
#include "qtiocompressor.h"
16736 jghali 46
#include "scpage.h"
12623 fschmid 47
#include "scpattern.h"
14170 jghali 48
#include "scribuscore.h"
49
#include "sctextstruct.h"
17315 fschmid 50
#include "tableutils.h"
2533 craig 51
#include "util.h"
13552 cbradney 52
#include "ui/customfdialog.h"
13544 cbradney 53
#include "ui/guidemanager.h"
19605 jghali 54
#include "ui/scmessagebox.h"
7481 jghali 55
#include "sccolorengine.h"
10292 cbradney 56
#include "util_formats.h"
14170 jghali 57
#include "util_math.h"
21107 craig 58
#include "text/textlayout.h"
59
#include "text/textlayoutpainter.h"
60
#include "text/boxes.h"
1552 subik 61
 
3207 craig 62
int svgexplugin_getPluginAPIVersion()
21 Franz 63
{
3207 craig 64
        return PLUGIN_API_VERSION;
21 Franz 65
}
66
 
3207 craig 67
ScPlugin* svgexplugin_getPlugin()
21 Franz 68
{
3207 craig 69
        SVGExportPlugin* plug = new SVGExportPlugin();
70
        Q_CHECK_PTR(plug);
71
        return plug;
21 Franz 72
}
73
 
3207 craig 74
void svgexplugin_freePlugin(ScPlugin* plugin)
512 fschmid 75
{
3207 craig 76
        SVGExportPlugin* plug = dynamic_cast<SVGExportPlugin*>(plugin);
77
        Q_ASSERT(plug);
78
        delete plug;
512 fschmid 79
}
80
 
17315 fschmid 81
using namespace TableUtils;
82
 
3686 craig 83
SVGExportPlugin::SVGExportPlugin() : ScActionPlugin()
1208 cbradney 84
{
3207 craig 85
        // Set action info in languageChange, so we only have to do
86
        // it in one place.
87
        languageChange();
1208 cbradney 88
}
89
 
3207 craig 90
SVGExportPlugin::~SVGExportPlugin() {};
91
 
92
void SVGExportPlugin::languageChange()
1208 cbradney 93
{
3207 craig 94
        // Note that we leave the unused members unset. They'll be initialised
95
        // with their default ctors during construction.
96
        // Action name
97
        m_actionInfo.name = "ExportAsSVG";
98
        // Action text for menu, including accel
5357 cbradney 99
        m_actionInfo.text = tr("Save as &SVG...");
3207 craig 100
        // Menu
101
        m_actionInfo.menu = "FileExport";
12566 cbradney 102
        m_actionInfo.enabledOnStartup = false;
10956 fschmid 103
        m_actionInfo.needsNumObjects = -1;
1208 cbradney 104
}
105
 
3207 craig 106
const QString SVGExportPlugin::fullTrName() const
1208 cbradney 107
{
3207 craig 108
        return QObject::tr("SVG Export");
1208 cbradney 109
}
110
 
3207 craig 111
const ScActionPlugin::AboutData* SVGExportPlugin::getAboutData() const
1208 cbradney 112
{
3241 craig 113
        AboutData* about = new AboutData;
3344 fschmid 114
        about->authors = "Franz Schmid <franz@scribus.info>";
3355 cbradney 115
        about->shortDescription = tr("Exports SVG Files");
3357 cbradney 116
        about->description = tr("Exports the current page into an SVG file.");
3344 fschmid 117
        about->license = "GPL";
3241 craig 118
        Q_CHECK_PTR(about);
119
        return about;
1208 cbradney 120
}
121
 
3241 craig 122
void SVGExportPlugin::deleteAboutData(const AboutData* about) const
1208 cbradney 123
{
3241 craig 124
        Q_ASSERT(about);
125
        delete about;
1208 cbradney 126
}
127
 
5781 cbradney 128
bool SVGExportPlugin::run(ScribusDoc* doc, QString filename)
21 Franz 129
{
3207 craig 130
        Q_ASSERT(filename.isEmpty());
4182 subik 131
        QString fileName;
5781 cbradney 132
        if (doc!=0)
2875 subik 133
        {
2856 cbradney 134
                PrefsContext* prefs = PrefsManager::instance()->prefsFile->getPluginContext("svgex");
415 Franz 135
                QString wdir = prefs->get("wdir", ".");
16238 fschmid 136
                QScopedPointer<CustomFDialog> openDia( new CustomFDialog(doc->scMW(), wdir, QObject::tr("Save as"), QObject::tr("%1;;All Files (*)").arg(FormatsManager::instance()->extensionsForFormat(FormatsManager::SVG)), fdHidePreviewCheckBox) );
5781 cbradney 137
                openDia->setSelection(getFileNameByPage(doc, doc->currentPage()->pageNr(), "svg"));
4182 subik 138
                openDia->setExtension("svg");
139
                openDia->setZipExtension("svgz");
15224 jghali 140
                QCheckBox* compress = new QCheckBox(openDia.data());
12623 fschmid 141
                compress->setText( tr("Compress File"));
142
                compress->setChecked(false);
143
                openDia->addWidgets(compress);
15224 jghali 144
                QCheckBox* inlineImages = new QCheckBox(openDia.data());
12623 fschmid 145
                inlineImages->setText( tr("Save Images inline"));
146
                inlineImages->setToolTip( tr("Adds all Images on the Page inline to the SVG.\nCaution: this will increase the file size!"));
147
                inlineImages->setChecked(true);
148
                openDia->addWidgets(inlineImages);
15224 jghali 149
                QCheckBox* exportBack = new QCheckBox(openDia.data());
12623 fschmid 150
                exportBack->setText( tr("Export Page background"));
20272 craig 151
                exportBack->setToolTip( tr("Adds the Page itself as background to the SVG"));
12623 fschmid 152
                exportBack->setChecked(false);
153
                openDia->addWidgets(exportBack);
19104 jghali 154
 
15225 jghali 155
                if (!openDia->exec())
156
                        return true;
157
                fileName = openDia->selectedFile();
158
                QFileInfo fi(fileName);
159
                QString baseDir = fi.absolutePath();
160
                if (compress->isChecked())
161
                        fileName = baseDir + "/" + fi.baseName() + ".svgz";
12623 fschmid 162
                else
15225 jghali 163
                        fileName = baseDir + "/" + fi.baseName() + ".svg";
164
 
12623 fschmid 165
                SVGOptions Options;
166
                Options.inlineImages = inlineImages->isChecked();
167
                Options.exportPageBackground = exportBack->isChecked();
168
                Options.compressFile = compress->isChecked();
4182 subik 169
 
15225 jghali 170
                if (fileName.isEmpty())
171
                        return true;
172
                prefs->set("wdir", fileName.left(fileName.lastIndexOf("/")));
173
                QFile f(fileName);
174
                if (f.exists())
2875 subik 175
                {
19605 jghali 176
                        int exit = ScMessageBox::warning(doc->scMW(), CommonStrings::trWarning,
15225 jghali 177
                                QObject::tr("Do you really want to overwrite the file:\n%1 ?").arg(fileName),
19605 jghali 178
                                QMessageBox::Yes | QMessageBox::No,
179
                                QMessageBox::NoButton// GUI default
180
                                QMessageBox::Yes);      // batch default
15225 jghali 181
                        if (exit == QMessageBox::No)
182
                                return true;
2875 subik 183
                }
15225 jghali 184
                SVGExPlug *dia = new SVGExPlug(doc);
185
                dia->doExport(fileName, Options);
186
                delete dia;
2875 subik 187
        }
3207 craig 188
        return true;
21 Franz 189
}
190
 
8043 jghali 191
SVGExPlug::SVGExPlug( ScribusDoc* doc )
21 Franz 192
{
12623 fschmid 193
        m_Doc = doc;
194
        Options.inlineImages = true;
195
        Options.exportPageBackground = false;
196
        Options.compressFile = false;
197
        glyphNames.clear();
8043 jghali 198
}
199
 
12623 fschmid 200
bool SVGExPlug::doExport( QString fName, SVGOptions &Opts )
8043 jghali 201
{
12623 fschmid 202
        Options = Opts;
203
        QFileInfo fiBase(fName);
204
        baseDir = fiBase.absolutePath();
16729 fschmid 205
        ScPage *page;
12623 fschmid 206
        GradCount = 0;
207
        ClipCount = 0;
208
        PattCount = 0;
14858 fschmid 209
        MaskCount = 0;
18787 fschmid 210
        FilterCount = 0;
12627 fschmid 211
        docu = QDomDocument("svgdoc");
68 Franz 212
        QString vo = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
21 Franz 213
        QString st = "<svg></svg>";
214
        docu.setContent(st);
13873 jghali 215
        page = m_Doc->currentPage();
216
        double pageWidth  = page->width();
217
        double pageHeight = page->height();
12623 fschmid 218
        docElement = docu.documentElement();
219
        docElement.setAttribute("width", FToStr(pageWidth)+"pt");
220
        docElement.setAttribute("height", FToStr(pageHeight)+"pt");
221
        docElement.setAttribute("viewBox", QString("0 0 %1 %2").arg(pageWidth).arg(pageHeight));
222
        docElement.setAttribute("xmlns", "http://www.w3.org/2000/svg");
16238 fschmid 223
        docElement.setAttribute("xmlns:inkscape","http://www.inkscape.org/namespaces/inkscape");
12623 fschmid 224
        docElement.setAttribute("xmlns:xlink","http://www.w3.org/1999/xlink");
225
        docElement.setAttribute("version","1.1");
15037 cbradney 226
        if (!m_Doc->documentInfo().title().isEmpty())
12623 fschmid 227
        {
15037 cbradney 228
                QDomText title = docu.createTextNode(m_Doc->documentInfo().title());
12623 fschmid 229
                QDomElement titleElem = docu.createElement("title");
230
                titleElem.appendChild(title);
231
                docElement.appendChild(titleElem);
232
        }
15037 cbradney 233
        if (!m_Doc->documentInfo().comments().isEmpty())
12623 fschmid 234
        {
15037 cbradney 235
                QDomText desc = docu.createTextNode(m_Doc->documentInfo().comments());
12623 fschmid 236
                QDomElement descElem = docu.createElement("desc");
237
                descElem.appendChild(desc);
238
                docElement.appendChild(descElem);
239
        }
240
        globalDefs = docu.createElement("defs");
14169 fschmid 241
        writeBasePatterns();
15077 fschmid 242
        writeBaseSymbols();
12623 fschmid 243
        docElement.appendChild(globalDefs);
244
        if (Options.exportPageBackground)
245
        {
246
                QDomElement backG = docu.createElement("rect");
247
                backG.setAttribute("x", "0");
248
                backG.setAttribute("y", "0");
249
                backG.setAttribute("width", FToStr(pageWidth));
250
                backG.setAttribute("height", FToStr(pageHeight));
14924 cbradney 251
                backG.setAttribute("style", "fill:"+m_Doc->paperColor().name()+";" + "stroke:none;");
12623 fschmid 252
                docElement.appendChild(backG);
253
        }
13873 jghali 254
        ScLayer ll;
255
        ll.isPrintable = false;
256
        for (int la = 0; la < m_Doc->Layers.count(); la++)
257
        {
258
                m_Doc->Layers.levelToLayer(ll, la);
259
                if (ll.isPrintable)
260
                {
261
                        page = m_Doc->MasterPages.at(m_Doc->MasterNames[m_Doc->currentPage()->MPageNam]);
262
                        ProcessPageLayer(page, ll);
263
                        page = m_Doc->currentPage();
264
                        ProcessPageLayer(page, ll);
265
                }
266
        }
12623 fschmid 267
        if(Options.compressFile)
6014 jghali 268
        {
8022 jghali 269
                // zipped saving
18910 fschmid 270
                QString wr = vo;
271
                wr += docu.toString();
272
                QByteArray utf8wr = wr.toUtf8();
273
                QFile file(fName);
274
                QtIOCompressor compressor(&file);
275
                compressor.setStreamFormat(QtIOCompressor::GzipFormat);
276
                compressor.open(QIODevice::WriteOnly);
277
                compressor.write(utf8wr);
278
                compressor.close();
6014 jghali 279
        }
68 Franz 280
        else
6014 jghali 281
        {
68 Franz 282
                QFile f(fName);
8501 cbradney 283
                if(!f.open(QIODevice::WriteOnly))
8043 jghali 284
                        return false;
10004 fschmid 285
                QDataStream s(&f);
68 Franz 286
                QString wr = vo;
6014 jghali 287
                wr += docu.toString();
9535 fschmid 288
                QByteArray utf8wr = wr.toUtf8();
10004 fschmid 289
                s.writeRawData(utf8wr.data(), utf8wr.length());
68 Franz 290
                f.close();
6014 jghali 291
        }
8043 jghali 292
        return true;
21 Franz 293
}
294
 
16729 fschmid 295
void SVGExPlug::ProcessPageLayer(ScPage *page, ScLayer& layer)
21 Franz 296
{
12623 fschmid 297
        QDomElement layerGroup;
21 Franz 298
        PageItem *Item;
9856 fschmid 299
        QList<PageItem*> Items;
16729 fschmid 300
        ScPage* SavedAct = m_Doc->currentPage();
13873 jghali 301
        if (page->pageName().isEmpty())
5781 cbradney 302
                Items = m_Doc->DocItems;
456 fschmid 303
        else
5781 cbradney 304
                Items = m_Doc->MasterItems;
12623 fschmid 305
        if (Items.count() == 0)
306
                return;
13873 jghali 307
        if (!layer.isPrintable)
308
                return;
309
        m_Doc->setCurrentPage(page);
310
 
311
        layerGroup = docu.createElement("g");
312
        layerGroup.setAttribute("id", layer.Name);
16238 fschmid 313
        layerGroup.setAttribute("inkscape:label", layer.Name);
314
        layerGroup.setAttribute("inkscape:groupmode", "layer");
13873 jghali 315
        if (layer.transparency != 1.0)
316
                layerGroup.setAttribute("opacity", FToStr(layer.transparency));
317
        for(int j = 0; j < Items.count(); ++j)
10895 jghali 318
        {
13873 jghali 319
                Item = Items.at(j);
13875 jghali 320
                if (Item->LayerID != layer.ID)
13873 jghali 321
                        continue;
322
                if (!Item->printEnabled())
323
                        continue;
324
                double x = page->xOffset();
325
                double y = page->yOffset();
326
                double w = page->width();
327
                double h = page->height();
328
                double x2 = Item->BoundingX;
329
                double y2 = Item->BoundingY;
330
                double w2 = Item->BoundingW;
331
                double h2 = Item->BoundingH;
332
                if (!( qMax( x, x2 ) <= qMin( x+w, x2+w2 ) && qMax( y, y2 ) <= qMin( y+h, y2+h2 )))
333
                        continue;
15049 jghali 334
                if ((!page->pageName().isEmpty()) && (Item->OwnPage != static_cast<int>(page->pageNr())) && (Item->OwnPage != -1))
335
                        continue;
13873 jghali 336
                ProcessItemOnPage(Item->xPos()-page->xOffset(), Item->yPos()-page->yOffset(), Item, &layerGroup);
12623 fschmid 337
        }
13873 jghali 338
        docElement.appendChild(layerGroup);
339
 
12623 fschmid 340
        m_Doc->setCurrentPage(SavedAct);
341
}
342
 
12627 fschmid 343
void SVGExPlug::ProcessItemOnPage(double xOffset, double yOffset, PageItem *Item, QDomElement *parentElem)
12623 fschmid 344
{
345
        QDomElement ob;
346
        QString trans = "translate("+FToStr(xOffset)+", "+FToStr(yOffset)+")";
347
        if (Item->rotation() != 0)
348
                trans += " rotate("+FToStr(Item->rotation())+")";
12627 fschmid 349
        QString fill = getFillStyle(Item);
18790 fschmid 350
        fill += processDropShadow(Item);
12627 fschmid 351
        QString stroke = "stroke:none";
17418 fschmid 352
        stroke = getStrokeStyle(Item);
12623 fschmid 353
        switch (Item->itemType())
354
        {
16215 fschmid 355
                case PageItem::Arc:
12623 fschmid 356
                case PageItem::Polygon:
357
                case PageItem::PolyLine:
16191 fschmid 358
                case PageItem::RegularPolygon:
16311 fschmid 359
                case PageItem::Spiral:
12627 fschmid 360
                        ob = processPolyItem(Item, trans, fill, stroke);
13013 fschmid 361
                        if ((Item->lineColor() != CommonStrings::None) && ((Item->startArrowIndex() != 0) || (Item->endArrowIndex() != 0)))
12627 fschmid 362
                                ob = processArrows(Item, ob, trans);
12623 fschmid 363
                        break;
364
                case PageItem::Line:
12627 fschmid 365
                        ob = processLineItem(Item, trans, stroke);
13013 fschmid 366
                        if ((Item->lineColor() != CommonStrings::None) && ((Item->startArrowIndex() != 0) || (Item->endArrowIndex() != 0)))
12627 fschmid 367
                                ob = processArrows(Item, ob, trans);
12623 fschmid 368
                        break;
369
                case PageItem::ImageFrame:
370
                case PageItem::LatexFrame:
12627 fschmid 371
                        ob = processImageItem(Item, trans, fill, stroke);
12623 fschmid 372
                        break;
373
                case PageItem::TextFrame:
21107 craig 374
                case PageItem::PathText:
12627 fschmid 375
                        ob = processTextItem(Item, trans, fill, stroke);
12623 fschmid 376
                        break;
15077 fschmid 377
                case PageItem::Symbol:
378
                        ob = processSymbolItem(Item, trans);
379
                        break;
16105 fschmid 380
                case PageItem::Group:
381
                        if (Item->groupItemList.count() > 0)
382
                        {
383
                                ob = docu.createElement("g");
384
                                if (!Item->AutoName)
385
                                        ob.setAttribute("id", Item->itemName());
386
                                if (Item->GrMask > 0)
387
                                        ob.setAttribute("mask", handleMask(Item, xOffset, yOffset));
388
                                else
389
                                {
390
                                        if (Item->fillTransparency() != 0)
391
                                                ob.setAttribute("opacity", FToStr(1.0 - Item->fillTransparency()));
392
                                }
18743 jghali 393
                                QString tr = trans;
394
                                if (Item->imageFlippedH())
395
                                {
396
                                        tr += QString(" translate(%1, 0.0)").arg(Item->width());
397
                                        tr += QString(" scale(-1.0, 1.0)");
398
                                }
399
                                if (Item->imageFlippedV())
400
                                {
401
                                        tr += QString(" translate(0.0, %1)").arg(Item->height());
402
                                        tr += QString(" scale(1.0, -1.0)");
403
                                }
404
                                tr += QString(" scale(%1, %2)").arg(Item->width() / Item->groupWidth).arg(Item->height() / Item->groupHeight);
16123 fschmid 405
                                ob.setAttribute("transform", tr);
16105 fschmid 406
                                ob.setAttribute("style", "fill:none; stroke:none");
18779 fschmid 407
                                if (Item->groupClipping())
408
                                {
409
                                        FPointArray clipPath = Item->PoLine;
410
                                        QTransform transform;
411
                                        transform.scale(Item->width() / Item->groupWidth, Item->height() / Item->groupHeight);
412
                                        transform = transform.inverted();
413
                                        clipPath.map(transform);
414
                                        QDomElement obc = createClipPathElement(&clipPath);
415
                                        if (!obc.isNull())
416
                                                ob.setAttribute("clip-path", "url(#"+ obc.attribute("id") + ")");
417
                                        if (Item->fillRule)
418
                                                ob.setAttribute("clip-rule", "evenodd");
419
                                        else
420
                                                ob.setAttribute("clip-rule", "nonzero");
421
                                }
16105 fschmid 422
                                for (int em = 0; em < Item->groupItemList.count(); ++em)
423
                                {
424
                                        PageItem* embed = Item->groupItemList.at(em);
425
                                        ProcessItemOnPage(embed->gXpos, embed->gYpos, embed, &ob);
426
                                }
427
                        }
428
                        break;
17315 fschmid 429
                case PageItem::Table:
430
                        ob = docu.createElement("g");
431
                        ob.setAttribute("transform", trans + QString("translate(%1, %2)").arg(Item->asTable()->gridOffset().x()).arg(Item->asTable()->gridOffset().y()));
432
                        // Paint table fill.
433
                        if (Item->asTable()->fillColor() != CommonStrings::None)
434
                        {
435
                                int lastCol = Item->asTable()->columns() - 1;
436
                                int lastRow = Item->asTable()->rows() - 1;
437
                                double x = Item->asTable()->columnPosition(0);
438
                                double y = Item->asTable()->rowPosition(0);
439
                                double width = Item->asTable()->columnPosition(lastCol) + Item->asTable()->columnWidth(lastCol) - x;
440
                                double height = Item->asTable()->rowPosition(lastRow) + Item->asTable()->rowHeight(lastRow) - y;
441
                                QDomElement cl = docu.createElement("rect");
442
                                cl.setAttribute("fill", SetColor(Item->asTable()->fillColor(), Item->asTable()->fillShade()));
443
                                cl.setAttribute("x", "0");
444
                                cl.setAttribute("y", "0");
445
                                cl.setAttribute("width", FToStr(width));
446
                                cl.setAttribute("height", FToStr(height));
447
                                ob.appendChild(cl);
448
                        }
449
                        // Pass 1: Paint cell fills.
450
                        for (int row = 0; row < Item->asTable()->rows(); ++row)
451
                        {
452
                                int colSpan = 0;
453
                                for (int col = 0; col < Item->asTable()->columns(); col += colSpan)
454
                                {
455
                                        TableCell cell = Item->asTable()->cellAt(row, col);
456
                                        if (row == cell.row())
457
                                        {
458
                                                QString colorName = cell.fillColor();
459
                                                if (colorName != CommonStrings::None)
460
                                                {
461
                                                        int row = cell.row();
462
                                                        int col = cell.column();
463
                                                        int lastRow = row + cell.rowSpan() - 1;
464
                                                        int lastCol = col + cell.columnSpan() - 1;
465
                                                        double x = Item->asTable()->columnPosition(col);
466
                                                        double y = Item->asTable()->rowPosition(row);
467
                                                        double width = Item->asTable()->columnPosition(lastCol) + Item->asTable()->columnWidth(lastCol) - x;
468
                                                        double height = Item->asTable()->rowPosition(lastRow) + Item->asTable()->rowHeight(lastRow) - y;
469
                                                        QDomElement cl = docu.createElement("rect");
470
                                                        cl.setAttribute("fill", SetColor(colorName, cell.fillShade()));
471
                                                        cl.setAttribute("x", FToStr(x));
472
                                                        cl.setAttribute("y", FToStr(y));
473
                                                        cl.setAttribute("width", FToStr(width));
474
                                                        cl.setAttribute("height", FToStr(height));
475
                                                        ob.appendChild(cl);
476
                                                }
477
                                        }
478
                                        colSpan = cell.columnSpan();
479
                                }
480
                        }
481
                        // Pass 2: Paint vertical borders.
482
                        for (int row = 0; row < Item->asTable()->rows(); ++row)
483
                        {
484
                                int colSpan = 0;
485
                                for (int col = 0; col < Item->asTable()->columns(); col += colSpan)
486
                                {
487
                                        TableCell cell = Item->asTable()->cellAt(row, col);
488
                                        if (row == cell.row())
489
                                        {
490
                                                const int lastRow = cell.row() + cell.rowSpan() - 1;
491
                                                const int lastCol = cell.column() + cell.columnSpan() - 1;
492
                                                const double borderX = Item->asTable()->columnPosition(lastCol) + Item->asTable()->columnWidth(lastCol);
493
                                                QPointF start(borderX, 0.0);
494
                                                QPointF end(borderX, 0.0);
495
                                                QPointF startOffsetFactors, endOffsetFactors;
496
                                                int startRow, endRow;
497
                                                for (int row = cell.row(); row <= lastRow; row += endRow - startRow + 1)
498
                                                {
499
                                                        TableCell rightCell = Item->asTable()->cellAt(row, lastCol + 1);
500
                                                        startRow = qMax(cell.row(), rightCell.row());
501
                                                        endRow = qMin(lastRow, rightCell.isValid() ? rightCell.row() + rightCell.rowSpan() - 1 : lastRow);
502
                                                        TableCell topLeftCell = Item->asTable()->cellAt(startRow - 1, lastCol);
503
                                                        TableCell topRightCell = Item->asTable()->cellAt(startRow - 1, lastCol + 1);
504
                                                        TableCell bottomRightCell = Item->asTable()->cellAt(endRow + 1, lastCol + 1);
505
                                                        TableCell bottomLeftCell = Item->asTable()->cellAt(endRow + 1, lastCol);
506
                                                        TableBorder topLeft, top, topRight, border, bottomLeft, bottom, bottomRight;
507
                                                        resolveBordersVertical(topLeftCell, topRightCell, cell, rightCell, bottomLeftCell, bottomRightCell,
508
                                                                                                   &topLeft, &top, &topRight, &border, &bottomLeft, &bottom, &bottomRight, Item->asTable());
509
                                                        if (border.isNull())
510
                                                                continue; // Quit early if the border to paint is null.
511
                                                        start.setY(Item->asTable()->rowPosition(startRow));
512
                                                        end.setY((Item->asTable()->rowPosition(endRow) + Item->asTable()->rowHeight(endRow)));
513
                                                        joinVertical(border, topLeft, top, topRight, bottomLeft, bottom, bottomRight, &start, &end, &startOffsetFactors, &endOffsetFactors);
514
                                                        paintBorder(border, start, end, startOffsetFactors, endOffsetFactors, ob);
515
                                                }
516
                                                if (col == 0)
517
                                                {
518
                                                        const int lastRow = cell.row() + cell.rowSpan() - 1;
519
                                                        const int firstCol = cell.column();
520
                                                        const double borderX = Item->asTable()->columnPosition(firstCol);
521
                                                        QPointF start(borderX, 0.0);
522
                                                        QPointF end(borderX, 0.0);
523
                                                        QPointF startOffsetFactors, endOffsetFactors;
524
                                                        int startRow, endRow;
525
                                                        for (int row = cell.row(); row <= lastRow; row += endRow - startRow + 1)
526
                                                        {
527
                                                                TableCell leftCell = Item->asTable()->cellAt(row, firstCol - 1);
528
                                                                startRow = qMax(cell.row(), leftCell.row());
529
                                                                endRow = qMin(lastRow, leftCell.isValid() ? leftCell.row() + leftCell.rowSpan() - 1 : lastRow);
530
                                                                TableCell topLeftCell = Item->asTable()->cellAt(startRow - 1, firstCol - 1);
531
                                                                TableCell topRightCell = Item->asTable()->cellAt(startRow - 1, firstCol);
532
                                                                TableCell bottomRightCell = Item->asTable()->cellAt(lastRow + 1, firstCol);
533
                                                                TableCell bottomLeftCell = Item->asTable()->cellAt(lastRow + 1, firstCol - 1);
534
                                                                TableBorder topLeft, top, topRight, border, bottomLeft, bottom, bottomRight;
535
                                                                resolveBordersVertical(topLeftCell, topRightCell, leftCell, cell, bottomLeftCell, bottomRightCell,
536
                                                                                                           &topLeft, &top, &topRight, &border, &bottomLeft, &bottom, &bottomRight, Item->asTable());
537
                                                                if (border.isNull())
538
                                                                        continue; // Quit early if the border to paint is null.
539
                                                                start.setY(Item->asTable()->rowPosition(startRow));
540
                                                                end.setY((Item->asTable()->rowPosition(endRow) + Item->asTable()->rowHeight(endRow)));
541
                                                                joinVertical(border, topLeft, top, topRight, bottomLeft, bottom, bottomRight, &start, &end, &startOffsetFactors, &endOffsetFactors);
542
                                                                paintBorder(border, start, end, startOffsetFactors, endOffsetFactors, ob);
543
                                                        }
544
                                                }
545
                                        }
546
                                        colSpan = cell.columnSpan();
547
                                }
548
                        }
549
                        // Pass 3: Paint horizontal borders.
550
                        for (int row = 0; row < Item->asTable()->rows(); ++row)
551
                        {
552
                                int colSpan = 0;
553
                                for (int col = 0; col < Item->asTable()->columns(); col += colSpan)
554
                                {
555
                                        TableCell cell = Item->asTable()->cellAt(row, col);
556
                                        if (row == cell.row())
557
                                        {
558
                                                const int lastRow = cell.row() + cell.rowSpan() - 1;
559
                                                const int lastCol = cell.column() + cell.columnSpan() - 1;
560
                                                const double borderY = (Item->asTable()->rowPosition(lastRow) + Item->asTable()->rowHeight(lastRow));
561
                                                QPointF start(0.0, borderY);
562
                                                QPointF end(0.0, borderY);
563
                                                QPointF startOffsetFactors, endOffsetFactors;
564
                                                int startCol, endCol;
565
                                                for (int col = cell.column(); col <= lastCol; col += endCol - startCol + 1)
566
                                                {
567
                                                        TableCell bottomCell = Item->asTable()->cellAt(lastRow + 1, col);
568
                                                        startCol = qMax(cell.column(), bottomCell.column());
569
                                                        endCol = qMin(lastCol, bottomCell.isValid() ? bottomCell.column() + bottomCell.columnSpan() - 1 : lastCol);
570
                                                        TableCell topLeftCell = Item->asTable()->cellAt(lastRow, startCol - 1);
571
                                                        TableCell topRightCell = Item->asTable()->cellAt(lastRow, endCol + 1);
572
                                                        TableCell bottomRightCell = Item->asTable()->cellAt(lastRow + 1, endCol + 1);
573
                                                        TableCell bottomLeftCell = Item->asTable()->cellAt(lastRow + 1, startCol - 1);
574
                                                        TableBorder topLeft, left, bottomLeft, border, topRight, right, bottomRight;
575
                                                        resolveBordersHorizontal(topLeftCell, cell, topRightCell, bottomLeftCell, bottomCell,
576
                                                                                                         bottomRightCell, &topLeft, &left, &bottomLeft, &border, &topRight, &right, &bottomRight, Item->asTable());
577
                                                        if (border.isNull())
578
                                                                continue; // Quit early if the border is null.
579
                                                        start.setX(Item->asTable()->columnPosition(startCol));
580
                                                        end.setX(Item->asTable()->columnPosition(endCol) + Item->asTable()->columnWidth(endCol));
581
                                                        joinHorizontal(border, topLeft, left, bottomLeft, topRight, right, bottomRight, &start, &end, &startOffsetFactors, &endOffsetFactors);
582
                                                        paintBorder(border, start, end, startOffsetFactors, endOffsetFactors, ob);
583
                                                }
584
                                                if (row == 0)
585
                                                {
586
                                                        const int firstRow = cell.row();
587
                                                        const int lastCol = cell.column() + cell.columnSpan() - 1;
588
                                                        const double borderY = Item->asTable()->rowPosition(firstRow);
589
                                                        QPointF start(0.0, borderY);
590
                                                        QPointF end(0.0, borderY);
591
                                                        QPointF startOffsetFactors, endOffsetFactors;
592
                                                        int startCol, endCol;
593
                                                        for (int col = cell.column(); col <= lastCol; col += endCol - startCol + 1)
594
                                                        {
595
                                                                TableCell topCell = Item->asTable()->cellAt(firstRow - 1, col);
596
                                                                startCol = qMax(cell.column(), topCell.column());
597
                                                                endCol = qMin(lastCol, topCell.isValid() ? topCell.column() + topCell.columnSpan() - 1 : lastCol);
598
                                                                TableCell topLeftCell = Item->asTable()->cellAt(firstRow - 1, startCol - 1);
599
                                                                TableCell topRightCell = Item->asTable()->cellAt(firstRow - 1, endCol + 1);
600
                                                                TableCell bottomRightCell = Item->asTable()->cellAt(firstRow, endCol + 1);
601
                                                                TableCell bottomLeftCell = Item->asTable()->cellAt(firstRow, startCol - 1);
602
                                                                TableBorder topLeft, left, bottomLeft, border, topRight, right, bottomRight;
603
                                                                resolveBordersHorizontal(topLeftCell, topCell, topRightCell, bottomLeftCell, cell,
604
                                                                                                                 bottomRightCell, &topLeft, &left, &bottomLeft, &border, &topRight, &right, &bottomRight, Item->asTable());
605
                                                                if (border.isNull())
606
                                                                        continue; // Quit early if the border is null.
607
                                                                start.setX(Item->asTable()->columnPosition(startCol));
608
                                                                end.setX(Item->asTable()->columnPosition(endCol) + Item->asTable()->columnWidth(endCol));
609
                                                                joinHorizontal(border, topLeft, left, bottomLeft, topRight, right, bottomRight, &start, &end, &startOffsetFactors, &endOffsetFactors);
610
                                                                paintBorder(border, start, end, startOffsetFactors, endOffsetFactors, ob);
611
                                                        }
612
                                                }
613
                                        }
614
                                        colSpan = cell.columnSpan();
615
                                }
616
                        }
617
                        // Pass 4: Paint cell content.
618
                        for (int row = 0; row < Item->asTable()->rows(); ++row)
619
                        {
620
                                for (int col = 0; col < Item->asTable()->columns(); col ++)
621
                                {
622
                                        TableCell cell = Item->asTable()->cellAt(row, col);
623
                                        if (cell.row() == row && cell.column() == col)
624
                                        {
625
                                                PageItem* textFrame = cell.textFrame();
626
                                                ProcessItemOnPage(cell.contentRect().x(), cell.contentRect().y(), textFrame, &ob);
627
                                        }
628
                                }
629
                        }
630
                        break;
12623 fschmid 631
                default:
632
                        break;
633
        }
14858 fschmid 634
        if (Item->GrMask > 0)
635
                ob.setAttribute("mask", handleMask(Item, xOffset, yOffset));
12623 fschmid 636
        if (!Item->AutoName)
637
                ob.setAttribute("id", Item->itemName());
638
        parentElem->appendChild(ob);
639
}
640
 
17315 fschmid 641
void SVGExPlug::paintBorder(const TableBorder& border, const QPointF& start, const QPointF& end, const QPointF& startOffsetFactors, const QPointF& endOffsetFactors, QDomElement &ob)
642
{
643
        QPointF lineStart, lineEnd;
644
        foreach (const TableBorderLine& line, border.borderLines())
645
        {
646
                lineStart.setX(start.x() + line.width() * startOffsetFactors.x());
647
                lineStart.setY(start.y() + line.width() * startOffsetFactors.y());
648
                lineEnd.setX(end.x() + line.width() * endOffsetFactors.x());
649
                lineEnd.setY(end.y() + line.width() * endOffsetFactors.y());
650
                QDomElement cl = docu.createElement("path");
651
                cl.setAttribute("d", "M "+FToStr(lineStart.x())+" "+FToStr(lineStart.y())+" L "+FToStr(lineEnd.x())+" "+FToStr(lineEnd.y()));
652
                QString stroke = "";
653
                if (line.color() != CommonStrings::None)
654
                        cl.setAttribute("stroke", SetColor(line.color(), line.shade()));
655
                if (line.width() != 0.0)
656
                        stroke = "stroke-width:"+FToStr(line.width())+";";
657
                else
658
                        stroke = "stroke-width:1px;";
659
                stroke += " stroke-linecap:butt;";
660
                stroke += " stroke-linejoin:miter;";
661
                stroke += " stroke-dasharray:";
662
                if (line.style() == Qt::SolidLine)
663
                        stroke += "none;";
664
                else
665
                {
666
                        QString Da = getDashString(line.style(), qMax(line.width(), 1.0));
667
                        if (Da.isEmpty())
668
                                stroke += "none;";
669
                        else
670
                                stroke += Da.replace(" ", ", ")+";";
671
                }
672
                cl.setAttribute("style", stroke);
673
                ob.appendChild(cl);
674
        }
675
}
676
 
18790 fschmid 677
QString SVGExPlug::processDropShadow(PageItem *Item)
18787 fschmid 678
{
679
        if (!Item->hasSoftShadow())
18790 fschmid 680
                return "";
18787 fschmid 681
        QString ID = "Filter"+IToStr(FilterCount);
682
        QDomElement filter = docu.createElement("filter");
683
        filter.setAttribute("id", ID);
18790 fschmid 684
        filter.setAttribute("inkscape:label", "Drop shadow");
685
        QDomElement ob = docu.createElement("feGaussianBlur");
686
        ob.setAttribute("id", "feGaussianBlur"+IToStr(FilterCount));
687
        ob.setAttribute("in", "SourceAlpha");
688
        ob.setAttribute("stdDeviation", FToStr(Item->softShadowBlurRadius()));
689
        ob.setAttribute("result", "blur");
690
        filter.appendChild(ob);
691
        QDomElement ob2 = docu.createElement("feColorMatrix");
692
        ob2.setAttribute("id", "feColorMatrix"+IToStr(FilterCount));
693
        const ScColor& col = m_Doc->PageColors[Item->softShadowColor()];
694
        QColor color = ScColorEngine::getShadeColorProof(col, m_Doc, Item->softShadowShade());
695
        ob2.setAttribute("type", "matrix");
696
        ob2.setAttribute("values", QString("1 0 0 %1 0 0 1 0 %2 0 0 0 1 %3 0 0 0 0 %4 0").arg(color.redF()).arg(color.greenF()).arg(color.blueF()).arg(1.0 - Item->softShadowOpacity()));
697
        ob2.setAttribute("result", "bluralpha");
18787 fschmid 698
        filter.appendChild(ob2);
18790 fschmid 699
        QDomElement ob3 = docu.createElement("feOffset");
700
        ob3.setAttribute("id", "feOffset"+IToStr(FilterCount));
701
        ob3.setAttribute("in", "bluralpha");
702
        ob3.setAttribute("dx", FToStr(Item->softShadowXOffset()));
703
        ob3.setAttribute("dy", FToStr(Item->softShadowYOffset()));
704
        ob3.setAttribute("result", "offsetBlur");
705
        filter.appendChild(ob3);
706
        QDomElement ob4 = docu.createElement("feMerge");
707
        ob4.setAttribute("id", "feMerge"+IToStr(FilterCount));
708
        QDomElement ob5 = docu.createElement("feMergeNode");
709
        ob5.setAttribute("id", "feMergeNode1"+IToStr(FilterCount));
710
        ob5.setAttribute("in", "offsetBlur");
711
        ob4.appendChild(ob5);
712
        QDomElement ob6 = docu.createElement("feMergeNode");
713
        ob6.setAttribute("id", "feMergeNode2"+IToStr(FilterCount));
714
        ob6.setAttribute("in", "SourceGraphic");
715
        ob4.appendChild(ob6);
716
        filter.appendChild(ob4);
18787 fschmid 717
        globalDefs.appendChild(filter);
718
        FilterCount++;
18790 fschmid 719
        return "filter:url(#"+ID+");";
18787 fschmid 720
}
721
 
18935 fschmid 722
QDomElement SVGExPlug::processHatchFill(PageItem *Item, QString transl)
723
{
724
        QDomElement ob;
725
        ob = docu.createElement("g");
726
        if (!transl.isEmpty())
727
                ob.setAttribute("transform", transl);
728
        QDomElement obc = createClipPathElement(&Item->PoLine);
729
        if (!obc.isNull())
730
                ob.setAttribute("clip-path", "url(#"+ obc.attribute("id") + ")");
731
        if (Item->fillRule)
732
                ob.setAttribute("clip-rule", "evenodd");
733
        else
734
                ob.setAttribute("clip-rule", "nonzero");
735
        if (Item->hatchUseBackground)
736
        {
737
                QDomElement ob2 = docu.createElement("path");
738
                ob2.setAttribute("d", SetClipPath(&Item->PoLine, true));
739
                ob2.setAttribute("fill", SetColor(Item->hatchBackground, 100));
740
                ob.appendChild(ob2);
741
        }
742
        QString stroke = "";
743
        stroke += "stroke-width:1;";
744
        stroke += " stroke-linecap:butt;";
745
        stroke += " stroke-linejoin:miter;";
746
        double lineLen = sqrt((Item->width() / 2.0) * (Item->width() / 2.0) + (Item->height() / 2.0) * (Item->height() / 2.0));
747
        double dist = 0.0;
748
        while (dist < lineLen)
749
        {
750
                QTransform mpx;
751
                mpx.translate(Item->width() / 2.0, Item->height() / 2.0);
752
                if (Item->hatchAngle != 0.0)
753
                        mpx.rotate(-Item->hatchAngle);
754
                QDomElement ob3 = docu.createElement("path");
755
                ob3.setAttribute("transform", MatrixToStr(mpx));
756
                ob3.setAttribute("d", QString("M %1, %2 L %3, %4").arg(-lineLen).arg(dist).arg(lineLen).arg(dist));
757
                ob3.setAttribute("stroke", SetColor(Item->hatchForeground, 100));
758
                ob3.setAttribute("style", stroke);
759
                ob.appendChild(ob3);
760
                if (dist > 0)
761
                {
762
                        QDomElement ob4 = docu.createElement("path");
763
                        ob4.setAttribute("transform", MatrixToStr(mpx));
764
                        ob4.setAttribute("d", QString("M %1, %2 L %3, %4").arg(-lineLen).arg(-dist).arg(lineLen).arg(-dist));
765
                        ob4.setAttribute("stroke", SetColor(Item->hatchForeground, 100));
766
                        ob4.setAttribute("style", stroke);
767
                        ob.appendChild(ob4);
768
                }
769
                dist += Item->hatchDistance;
770
        }
771
        if ((Item->hatchType == 1) || (Item->hatchType == 2))
772
        {
773
                dist = 0.0;
774
                while (dist < lineLen)
775
                {
776
                        QTransform mpx;
777
                        mpx.translate(Item->width() / 2.0, Item->height() / 2.0);
778
                        if (Item->hatchAngle != 0.0)
779
                                mpx.rotate(-Item->hatchAngle + 90);
780
                        QDomElement ob3 = docu.createElement("path");
781
                        ob3.setAttribute("transform", MatrixToStr(mpx));
782
                        ob3.setAttribute("d", QString("M %1, %2 L %3, %4").arg(-lineLen).arg(dist).arg(lineLen).arg(dist));
783
                        ob3.setAttribute("stroke", SetColor(Item->hatchForeground, 100));
784
                        ob3.setAttribute("style", stroke);
785
                        ob.appendChild(ob3);
786
                        if (dist > 0)
787
                        {
788
                                QDomElement ob4 = docu.createElement("path");
789
                                ob4.setAttribute("transform", MatrixToStr(mpx));
790
                                ob4.setAttribute("d", QString("M %1, %2 L %3, %4").arg(-lineLen).arg(-dist).arg(lineLen).arg(-dist));
791
                                ob4.setAttribute("stroke", SetColor(Item->hatchForeground, 100));
792
                                ob4.setAttribute("style", stroke);
793
                                ob.appendChild(ob4);
794
                        }
795
                        dist += Item->hatchDistance;
796
                }
797
        }
798
        if (Item->hatchType == 2)
799
        {
800
                dist = 0.0;
801
                while (dist < lineLen)
802
                {
803
                        double dDist = dist * sqrt(2.0);
804
                        QTransform mpx;
805
                        mpx.translate(Item->width() / 2.0, Item->height() / 2.0);
806
                        if (Item->hatchAngle != 0.0)
807
                                mpx.rotate(-Item->hatchAngle + 45);
808
                        QDomElement ob3 = docu.createElement("path");
809
                        ob3.setAttribute("transform", MatrixToStr(mpx));
810
                        ob3.setAttribute("d", QString("M %1, %2 L %3, %4").arg(-lineLen).arg(dDist).arg(lineLen).arg(dDist));
811
                        ob3.setAttribute("stroke", SetColor(Item->hatchForeground, 100));
812
                        ob3.setAttribute("style", stroke);
813
                        ob.appendChild(ob3);
814
                        if (dist > 0)
815
                        {
816
                                QDomElement ob4 = docu.createElement("path");
817
                                ob4.setAttribute("transform", MatrixToStr(mpx));
818
                                ob4.setAttribute("d", QString("M %1, %2 L %3, %4").arg(-lineLen).arg(-dDist).arg(lineLen).arg(-dDist));
819
                                ob4.setAttribute("stroke", SetColor(Item->hatchForeground, 100));
820
                                ob4.setAttribute("style", stroke);
821
                                ob.appendChild(ob4);
822
                        }
823
                        dist += Item->hatchDistance;
824
                }
825
        }
826
        return ob;
827
}
828
 
15077 fschmid 829
QDomElement SVGExPlug::processSymbolStroke(PageItem *Item, QString trans)
830
{
831
        QDomElement ob;
832
        ob = docu.createElement("g");
833
        ob.setAttribute("transform", trans);
834
        QPainterPath path = Item->PoLine.toQPainterPath(false);
835
        ScPattern pat = m_Doc->docPatterns[Item->strokePattern()];
836
        double pLen = path.length() - ((pat.width / 2.0) * (Item->patternStrokeScaleX / 100.0));
837
        double adv = pat.width * Item->patternStrokeScaleX / 100.0 * Item->patternStrokeSpace;
838
        double xpos = Item->patternStrokeOffsetX * Item->patternStrokeScaleX / 100.0;
839
        while (xpos < pLen)
840
        {
841
                double currPerc = path.percentAtLength(xpos);
842
                double currAngle = path.angleAtPercent(currPerc);
843
                if (currAngle <= 180.0)
844
                        currAngle *= -1.0;
845
                else
846
                        currAngle = 360.0 - currAngle;
847
                QPointF currPoint = path.pointAtPercent(currPerc);
848
                QTransform trans;
849
                trans.translate(currPoint.x(), currPoint.y());
850
                trans.rotate(-currAngle);
851
                trans.translate(0.0, Item->patternStrokeOffsetY);
852
                trans.rotate(-Item->patternStrokeRotation);
853
                trans.shear(Item->patternStrokeSkewX, -Item->patternStrokeSkewY);
854
                trans.scale(Item->patternStrokeScaleX / 100.0, Item->patternStrokeScaleY / 100.0);
855
                trans.translate(-pat.width / 2.0, -pat.height / 2.0);
856
                QDomElement obS;
857
                obS = docu.createElement("use");
858
                obS.setAttribute("transform", MatrixToStr(trans));
859
                if (Item->patternStrokeMirrorX)
860
                {
861
                        trans.translate(pat.width, 0);
862
                        trans.scale(-1, 1);
863
                }
864
                if (Item->patternStrokeMirrorY)
865
                {
866
                        trans.translate(0, pat.height);
867
                        trans.scale(1, -1);
868
                }
869
                obS.setAttribute("x", "0");
870
                obS.setAttribute("y", "0");
871
                obS.setAttribute("width", FToStr(pat.width));
872
                obS.setAttribute("height", FToStr(pat.height));
873
                obS.setAttribute("xlink:href", "#S"+Item->strokePattern());
874
                ob.appendChild(obS);
875
                xpos += adv;
876
        }
877
        return ob;
878
}
879
 
880
QDomElement SVGExPlug::processSymbolItem(PageItem *Item, QString trans)
881
{
882
        QDomElement ob;
18745 jghali 883
        ScPattern pat = m_Doc->docPatterns[Item->pattern()];
15077 fschmid 884
        ob = docu.createElement("use");
885
        ob.setAttribute("x", "0");
886
        ob.setAttribute("y", "0");
18745 jghali 887
        ob.setAttribute("width", FToStr(pat.width));
888
        ob.setAttribute("height", FToStr(pat.height));
15077 fschmid 889
        ob.setAttribute("xlink:href", "#S"+Item->pattern());
890
        QString tr = trans + QString(" scale(%1, %2)").arg(Item->width() / pat.width).arg(Item->height() / pat.height);
891
        ob.setAttribute("transform", tr);
892
        return ob;
893
}
894
 
12627 fschmid 895
QDomElement SVGExPlug::processPolyItem(PageItem *Item, QString trans, QString fill, QString stroke)
12623 fschmid 896
{
897
        bool closedPath;
898
        QDomElement ob;
16215 fschmid 899
        if ((Item->itemType() == PageItem::Polygon) || (Item->itemType() == PageItem::RegularPolygon) || (Item->itemType() == PageItem::Arc))
12623 fschmid 900
                closedPath = true;
901
        else
902
                closedPath = false;
903
        if (Item->NamedLStyle.isEmpty())
904
        {
15077 fschmid 905
                if ((!Item->strokePattern().isEmpty()) && (Item->patternStrokePath))
906
                {
907
                        ob = docu.createElement("g");
18935 fschmid 908
                        if (Item->GrType == 14)
909
                        {
910
                                QDomElement ob1 = processHatchFill(Item, trans);
911
                                ob.appendChild(ob1);
912
                        }
15077 fschmid 913
                        QDomElement ob2 = docu.createElement("path");
914
                        ob2.setAttribute("d", SetClipPath(&Item->PoLine, closedPath));
915
                        ob2.setAttribute("transform", trans);
18935 fschmid 916
                        if (Item->GrType != 14)
917
                                ob2.setAttribute("style", fill);
918
                        else
919
                        {
920
                                QString drS = processDropShadow(Item);
921
                                if (!drS.isEmpty())
922
                                        ob2.setAttribute("style", "fill:none;" + drS);
923
                        }
15077 fschmid 924
                        ob.appendChild(ob2);
925
                        ob.appendChild(processSymbolStroke(Item, trans));
926
                }
927
                else
928
                {
18935 fschmid 929
                        if (Item->GrType == 14)
930
                        {
931
                                ob = docu.createElement("g");
932
                                ob.setAttribute("transform", trans);
933
                                QDomElement ob1 = processHatchFill(Item);
934
                                ob.appendChild(ob1);
935
                                QDomElement ob2 = docu.createElement("path");
936
                                ob2.setAttribute("d", SetClipPath(&Item->PoLine, closedPath));
937
                                ob2.setAttribute("style", stroke + "fill:none;" + processDropShadow(Item));
938
                                ob.appendChild(ob2);
939
                        }
940
                        else
941
                        {
942
                                ob = docu.createElement("path");
943
                                ob.setAttribute("d", SetClipPath(&Item->PoLine, closedPath));
944
                                ob.setAttribute("transform", trans);
945
                                ob.setAttribute("style", fill + stroke);
946
                        }
15077 fschmid 947
                }
12623 fschmid 948
        }
949
        else
950
        {
12627 fschmid 951
                ob = docu.createElement("g");
12623 fschmid 952
                ob.setAttribute("transform", trans);
18935 fschmid 953
                if (Item->GrType == 14)
954
                {
955
                        QDomElement ob1 = processHatchFill(Item);
956
                        ob.appendChild(ob1);
957
                }
12627 fschmid 958
                QDomElement ob2 = docu.createElement("path");
12623 fschmid 959
                ob2.setAttribute("d", SetClipPath(&Item->PoLine, closedPath));
18935 fschmid 960
                if (Item->GrType != 14)
961
                        ob2.setAttribute("style", fill);
962
                else
963
                {
964
                        QString drS = processDropShadow(Item);
965
                        if (!drS.isEmpty())
966
                                ob2.setAttribute("style", "fill:none;" + drS);
967
                }
12623 fschmid 968
                ob.appendChild(ob2);
969
                multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
970
                for (int it = ml.size()-1; it > -1; it--)
971
                {
972
                        if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0))
973
                        {
12627 fschmid 974
                                QDomElement ob3 = docu.createElement("path");
12623 fschmid 975
                                ob3.setAttribute("d", SetClipPath(&Item->PoLine, closedPath));
976
                                ob3.setAttribute("style", GetMultiStroke(&ml[it], Item));
977
                                ob.appendChild(ob3);
978
                        }
979
                }
980
        }
981
        return ob;
982
}
983
 
12627 fschmid 984
QDomElement SVGExPlug::processLineItem(PageItem *Item, QString trans, QString stroke)
12623 fschmid 985
{
986
        QDomElement ob;
987
        if (Item->NamedLStyle.isEmpty())
988
        {
12627 fschmid 989
                ob = docu.createElement("path");
12623 fschmid 990
                ob.setAttribute("d", "M 0 0 L "+FToStr(Item->width())+" 0");
991
                ob.setAttribute("transform", trans);
992
                ob.setAttribute("style", stroke);
993
        }
994
        else
995
        {
12627 fschmid 996
                ob = docu.createElement("g");
12623 fschmid 997
                ob.setAttribute("transform", trans);
998
                multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
999
                for (int it = ml.size()-1; it > -1; it--)
1000
                {
1001
                        if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0))
1002
                        {
12627 fschmid 1003
                                QDomElement ob2 = docu.createElement("path");
12623 fschmid 1004
                                ob2.setAttribute("d", "M 0 0 L "+FToStr(Item->width())+" 0");
1005
                                ob2.setAttribute("style", GetMultiStroke(&ml[it], Item));
1006
                                ob.appendChild(ob2);
1007
                        }
1008
                }
1009
        }
1010
        return ob;
1011
}
1012
 
12627 fschmid 1013
QDomElement SVGExPlug::processImageItem(PageItem *Item, QString trans, QString fill, QString stroke)
12623 fschmid 1014
{
1015
        QDomElement ob;
12627 fschmid 1016
        ob = docu.createElement("g");
12623 fschmid 1017
        ob.setAttribute("transform", trans);
1018
        if ((Item->fillColor() != CommonStrings::None) || (Item->GrType != 0))
1019
        {
18935 fschmid 1020
                if (Item->GrType == 14)
1021
                {
1022
                        QDomElement ob1 = processHatchFill(Item);
1023
                        ob.appendChild(ob1);
1024
                        QString drS = processDropShadow(Item);
1025
                        if (!drS.isEmpty())
1026
                                ob.setAttribute("style", "fill:none;" + drS);
1027
                }
1028
                else
1029
                {
1030
                        QDomElement ob1 = docu.createElement("path");
1031
                        ob1.setAttribute("d", SetClipPath(&Item->PoLine, true));
1032
                        ob1.setAttribute("style", fill);
1033
                        ob.appendChild(ob1);
1034
                }
12623 fschmid 1035
        }
19834 craig 1036
        if ((Item->imageIsAvailable) && (!Item->Pfile.isEmpty()))
12623 fschmid 1037
        {
18735 jghali 1038
                QDomElement cl, ob2;
12623 fschmid 1039
                if (Item->imageClip.size() != 0)
18735 jghali 1040
                        ob2 = createClipPathElement(&Item->imageClip, &cl);
12623 fschmid 1041
                else
18735 jghali 1042
                        ob2 = createClipPathElement(&Item->PoLine, &cl);
1043
                if (!ob2.isNull())
17042 fschmid 1044
                {
18735 jghali 1045
                        ob2.setAttribute("clipPathUnits", "userSpaceOnUse");
1046
                        ob2.setAttribute("clip-rule", "evenodd");
1047
                        QTransform mpc;
1048
                        if (Item->imageFlippedH())
1049
                        {
1050
                                mpc.translate(Item->width(), 0);
1051
                                mpc.scale(-1, 1);
1052
                        }
1053
                        if (Item->imageFlippedV())
1054
                        {
1055
                                mpc.translate(0, Item->height());
1056
                                mpc.scale(1, -1);
1057
                        }
1058
                        cl.setAttribute("transform", MatrixToStr(mpc));
17042 fschmid 1059
                }
14864 fschmid 1060
                QDomElement ob6 = docu.createElement("g");
18735 jghali 1061
                if (!ob2.isNull())
1062
                        ob6.setAttribute("clip-path", "url(#" + ob2.attribute("id") + ")");
12627 fschmid 1063
                QDomElement ob3 = docu.createElement("image");
12623 fschmid 1064
                ScImage img;
1065
                CMSettings cms(m_Doc, Item->IProfile, Item->IRender);
14467 jghali 1066
                cms.setUseEmbeddedProfile(Item->UseEmbedded);
1067
                cms.allowSoftProofing(true);
1068
                img.loadPicture(Item->Pfile, Item->pixm.imgInfo.actualPageNumber, cms, ScImage::RGBData, 72);
12623 fschmid 1069
                img.applyEffect(Item->effectsInUse, m_Doc->PageColors, true);
1070
                if (Options.inlineImages)
1071
                {
1072
                        QBuffer buffer;
1073
                        buffer.open(QIODevice::WriteOnly);
1074
                        img.qImage().save(&buffer, "PNG");
1075
                        QByteArray ba = buffer.buffer().toBase64();
1076
                        buffer.close();
1077
                        ob3.setAttribute("xlink:href", "data:image/png;base64,"+QString(ba));
1078
                }
1079
                else
1080
                {
1081
                        QFileInfo fi = QFileInfo(Item->Pfile);
1082
                        QString imgFileName = baseDir + "/" + fi.baseName()+".png";
1083
                        QFileInfo im = QFileInfo(imgFileName);
1084
                        if (im.exists())
1085
                                imgFileName = baseDir + "/" + fi.baseName()+"_copy.png";
1086
                        img.qImage().save(imgFileName, "PNG");
1087
                        QFileInfo fi2 = QFileInfo(imgFileName);
1088
                        ob3.setAttribute("xlink:href", fi2.baseName()+".png");
1089
                }
1090
                ob3.setAttribute("x", FToStr(Item->imageXOffset() * Item->imageXScale()));
1091
                ob3.setAttribute("y", FToStr(Item->imageYOffset() * Item->imageYScale()));
1092
                ob3.setAttribute("width", FToStr(img.width() * Item->imageXScale()));
1093
                ob3.setAttribute("height", FToStr(img.height() * Item->imageYScale()));
13951 fschmid 1094
                QTransform mpa;
12623 fschmid 1095
                if (Item->imageFlippedH())
1096
                {
1097
                        mpa.translate(Item->width(), 0);
1098
                        mpa.scale(-1, 1);
1099
                }
1100
                if (Item->imageFlippedV())
1101
                {
1102
                        mpa.translate(0, Item->height());
1103
                        mpa.scale(1, -1);
1104
                }
14861 fschmid 1105
                mpa.rotate(Item->imageRotation());
12623 fschmid 1106
                ob3.setAttribute("transform", MatrixToStr(mpa));
14864 fschmid 1107
                ob6.appendChild(ob3);
1108
                ob.appendChild(ob6);
12623 fschmid 1109
        }
1110
        if (Item->NamedLStyle.isEmpty())
1111
        {
15077 fschmid 1112
                if ((!Item->strokePattern().isEmpty()) && (Item->patternStrokePath))
1113
                {
1114
                        QDomElement ob4 = docu.createElement("g");
1115
                        QDomElement ob2 = docu.createElement("path");
1116
                        ob2.setAttribute("d", SetClipPath(&Item->PoLine, true));
1117
                        ob2.setAttribute("transform", trans);
1118
                        ob2.setAttribute("style", fill);
1119
                        ob4.appendChild(ob2);
1120
                        ob4.appendChild(processSymbolStroke(Item, trans));
1121
                        ob.appendChild(ob4);
1122
                }
1123
                else
1124
                {
1125
                        QDomElement ob4 = docu.createElement("path");
1126
                        ob4.setAttribute("d", SetClipPath(&Item->PoLine, true));
1127
                        ob4.setAttribute("style", "fill:none; "+stroke);
1128
                        ob.appendChild(ob4);
1129
                }
12623 fschmid 1130
        }
1131
        else
1132
        {
1133
                multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
1134
                for (int it = ml.size()-1; it > -1; it--)
1135
                {
1136
                        if ((ml[it].Color != CommonStrings::None) && (ml[it].Width != 0))
1137
                        {
12627 fschmid 1138
                                QDomElement ob5 = docu.createElement("path");
12623 fschmid 1139
                                ob5.setAttribute("d", SetClipPath(&Item->PoLine, true));
1140
                                ob5.setAttribute("style", "fill:none; "+GetMultiStroke(&ml[it], Item));
1141
                                ob.appendChild(ob5);
1142
                        }
1143
                }
1144
        }
1145
        return ob;
1146
}
1147
 
21107 craig 1148
class SvgPainter: public TextLayoutPainter
1149
{
1150
        QDomElement m_elem;
1151
        SVGExPlug *m_svg;
1152
        QString m_trans;
1153
 
1154
public:
1155
        SvgPainter(QString trans, SVGExPlug *svg, QDomElement &elem)
1156
                : m_elem(elem)
1157
                , m_svg(svg)
1158
                , m_trans(trans)
1159
        {}
1160
 
1161
        void drawGlyph(const GlyphLayout gl)
1162
        {
1163
                if (gl.glyph >= ScFace::CONTROL_GLYPHS)
1164
                        return;
1165
 
1166
                QTransform transform = matrix();
1167
                transform.translate(x(), y() - (fontSize() * gl.scaleV));
1168
                transform.scale(gl.scaleH * fontSize() / 10.0, gl.scaleV * fontSize() / 10.0);
1169
 
1170
                QDomElement glyph = m_svg->docu.createElement("use");
1171
                glyph.setAttribute("xlink:href", "#" + m_svg->handleGlyph(gl.glyph, font()));
1172
                glyph.setAttribute("transform", m_svg->MatrixToStr(transform));
1173
                QString fill = "fill:" + m_svg->SetColor(fillColor().color, fillColor().shade) + ";";
1174
                QString stroke = "stroke:none;";
1175
                glyph.setAttribute("style", fill + stroke);
1176
                m_elem.appendChild(glyph);
1177
        }
1178
 
1179
        void drawGlyphOutline(const GlyphLayout gl, bool hasFill)
1180
        {
1181
                if (gl.glyph >= ScFace::CONTROL_GLYPHS)
1182
                        return;
1183
 
1184
                QTransform transform = matrix();
1185
                transform.translate(x(), y() - (fontSize() * gl.scaleV));
1186
                transform.scale(gl.scaleH * fontSize() / 10.0, gl.scaleV * fontSize() / 10.0);
1187
                QDomElement glyph = m_svg->docu.createElement("use");
1188
                glyph.setAttribute("xlink:href", "#" + m_svg->handleGlyph(gl.glyph, font()));
1189
                glyph.setAttribute("transform", m_svg->MatrixToStr(transform));
1190
                QString fill = "fill:none;";
1191
                if (hasFill)
1192
                        fill = "fill:" + m_svg->SetColor(fillColor().color, fillColor().shade) + ";";
1193
                QString stroke ="stroke:" + m_svg->SetColor(strokeColor().color, strokeColor().shade) + ";";
1194
                stroke += " stroke-width:" + m_svg->FToStr(strokeWidth()) + ";";
1195
                glyph.setAttribute("style", fill + stroke);
1196
                m_elem.appendChild(glyph);
1197
        }
1198
 
1199
        void drawLine(QPointF start, QPointF end)
1200
        {
1201
                QTransform transform = matrix();
1202
                transform.translate(x(), y());
1203
                QDomElement path = m_svg-> docu.createElement("path");
1204
                path.setAttribute("d", QString("M %1 %2 L%3 %4").arg(start.x()).arg(start.y()).arg(end.x()).arg(end.y()));
1205
                QString stroke = "stroke:none;";
1206
                if (fillColor().color != CommonStrings::None)
1207
                {
1208
                        stroke = "stroke:" + m_svg->SetColor(fillColor().color, fillColor().shade) + ";";
1209
                        stroke += " stroke-width:" + m_svg->FToStr(strokeWidth()) + ";";
1210
                }
1211
                path.setAttribute("style", "fill:none;" + stroke);
1212
                path.setAttribute("transform", m_svg->MatrixToStr(transform));
1213
                m_elem.appendChild(path);
1214
        }
1215
 
1216
        void drawRect(QRectF rect)
1217
        {
1218
                QTransform transform = matrix();
1219
                transform.translate(x(), y());
1220
                QString paS = QString("M %1 %2 ").arg(rect.x()).arg(rect.y());
1221
                paS += QString("L %1 %2 ").arg(rect.x() + rect.width()).arg(rect.y());
1222
                paS += QString("L %1 %2 ").arg(rect.x() + rect.width()).arg(rect.y() + rect.height());
1223
                paS += QString("L %1 %2 ").arg(rect.x()).arg(rect.y() + rect.height());
1224
                paS += "Z";
1225
                QDomElement path = m_svg-> docu.createElement("path");
1226
                path.setAttribute("d", paS);
1227
                path.setAttribute("transform", m_svg->MatrixToStr(transform));
1228
                path.setAttribute("style", "fill:" + m_svg->SetColor(fillColor().color, fillColor().shade) + ";" + "stroke:none;");
1229
                m_elem.appendChild(path);
1230
        }
1231
 
1232
        void drawObject(PageItem* item)
1233
        {
1234
                QDomElement layerGroup = m_svg->processInlineItem(item, m_trans, scaleH(), scaleV());
1235
                m_elem.appendChild(layerGroup);
1236
        }
1237
};
1238
 
12627 fschmid 1239
QDomElement SVGExPlug::processTextItem(PageItem *Item, QString trans, QString fill, QString stroke)
12623 fschmid 1240
{
1241
        QDomElement ob;
12627 fschmid 1242
        ob = docu.createElement("g");
12623 fschmid 1243
        ob.setAttribute("transform", trans);
1244
        if ((Item->fillColor() != CommonStrings::None) || (Item->GrType != 0))
1245
        {
18935 fschmid 1246
                if (Item->GrType == 14)
1247
                {
1248
                        QDomElement ob1 = processHatchFill(Item);
1249
                        ob.appendChild(ob1);
1250
                        QString drS = processDropShadow(Item);
1251
                        if (!drS.isEmpty())
1252
                                ob.setAttribute("style", "fill:none;" + drS);
1253
                }
1254
                else
1255
                {
1256
                        QDomElement ob1 = docu.createElement("path");
1257
                        ob1.setAttribute("d", SetClipPath(&Item->PoLine, true));
1258
                        ob1.setAttribute("style", fill);
1259
                        ob.appendChild(ob1);
1260
                }
12623 fschmid 1261
        }
20647 fschmid 1262
        bool bFound = false;
1263
        if (bFound)
1264
        {
1265
                QDomElement cl;
1266
                QDomElement ob2 = createClipPathElement(&Item->PoLine, &cl);
1267
                        if (!ob2.isNull())
1268
                {
1269
                        ob2.setAttribute("clipPathUnits", "userSpaceOnUse");
1270
                        ob2.setAttribute("clip-rule", "evenodd");
1271
                }
1272
                if (!ob2.isNull())
1273
                        ob.setAttribute("clip-path", "url(#" + ob2.attribute("id") + ")");
1274
        }
21107 craig 1275
        SvgPainter p(trans, this, ob);
1276
        Item->textLayout.renderBackground(&p);
1277
        Item->textLayout.render(&p);
12623 fschmid 1278
        return ob;
1279
}
1280
 
21107 craig 1281
QDomElement SVGExPlug::processInlineItem(PageItem* embItem, QString trans, double scaleH, double scaleV)
12623 fschmid 1282
{
18987 avox 1283
        QList<PageItem*> emG;
19104 jghali 1284
        if (embItem->isGroup())
1285
                emG = embItem->getItemList();
1286
        else
1287
                emG.append(embItem);
1288
 
12627 fschmid 1289
        QDomElement layerGroup = docu.createElement("g");
1290
        for (int em = 0; em < emG.count(); ++em)
1291
        {
1292
                PageItem* embedded = emG.at(em);
1293
                QDomElement obE;
1294
                QString fill = getFillStyle(embedded);
1295
                QString stroke = "stroke:none";
17418 fschmid 1296
                stroke = getStrokeStyle(embedded);
12627 fschmid 1297
                switch (embedded->itemType())
1298
                {
16215 fschmid 1299
                        case PageItem::Arc:
12627 fschmid 1300
                        case PageItem::Polygon:
1301
                        case PageItem::PolyLine:
16191 fschmid 1302
                        case PageItem::RegularPolygon:
16311 fschmid 1303
                        case PageItem::Spiral:
12627 fschmid 1304
                                obE = processPolyItem(embedded, trans, fill, stroke);
13013 fschmid 1305
                                if ((embedded->lineColor() != CommonStrings::None) && ((embedded->startArrowIndex() != 0) || (embedded->endArrowIndex() != 0)))
12627 fschmid 1306
                                        obE = processArrows(embedded, obE, trans);
1307
                                break;
1308
                        case PageItem::Line:
1309
                                obE = processLineItem(embedded, trans, stroke);
13013 fschmid 1310
                                if ((embedded->lineColor() != CommonStrings::None) && ((embedded->startArrowIndex() != 0) || (embedded->endArrowIndex() != 0)))
12627 fschmid 1311
                                        obE = processArrows(embedded, obE, trans);
1312
                                break;
1313
                        case PageItem::ImageFrame:
1314
                        case PageItem::LatexFrame:
1315
                                obE = processImageItem(embedded, trans, fill, stroke);
1316
                                break;
1317
                        case PageItem::TextFrame:
21107 craig 1318
                        case PageItem::PathText:
12627 fschmid 1319
                                obE = processTextItem(embedded, trans, fill, stroke);
1320
                                break;
15077 fschmid 1321
                        case PageItem::Symbol:
1322
                                obE = processSymbolItem(embedded, trans);
1323
                                break;
12627 fschmid 1324
                        default:
1325
                                break;
1326
                }
13951 fschmid 1327
                QTransform mm;
21107 craig 1328
                if (scaleH != 1.0)
1329
                        mm.scale(scaleH, 1);
1330
                if (scaleV != 1.0)
1331
                        mm.scale(1, scaleV);
12627 fschmid 1332
                mm.rotate(embedded->rotation());
1333
                obE.setAttribute("transform", MatrixToStr(mm));
1334
                layerGroup.appendChild(obE);
1335
        }
1336
        return layerGroup;
1337
}
1338
 
21107 craig 1339
QString SVGExPlug::handleGlyph(uint gid, const ScFace font)
12627 fschmid 1340
{
21107 craig 1341
        QString glName = QString("Gl%1%2").arg(font.psName().simplified().replace(QRegExp("[\\s\\/\\{\\[\\]\\}\\<\\>\\(\\)\\%]"), "_" )).arg(gid);
12623 fschmid 1342
        if (glyphNames.contains(glName))
1343
                return glName;
21107 craig 1344
        FPointArray pts = font.glyphOutline(gid);
12627 fschmid 1345
        QDomElement ob = docu.createElement("path");
12623 fschmid 1346
        ob.setAttribute("d", SetClipPath(&pts, true));
1347
        ob.setAttribute("id", glName);
1348
        globalDefs.appendChild(ob);
1349
        glyphNames.append(glName);
1350
        return glName;
1351
}
1352
 
12627 fschmid 1353
QDomElement SVGExPlug::processArrows(PageItem *Item, QDomElement line, QString trans)
12623 fschmid 1354
{
1355
        QDomElement ob, gr;
12627 fschmid 1356
        gr = docu.createElement("g");
12623 fschmid 1357
        gr.appendChild(line);
1358
        if (Item->startArrowIndex() != 0)
1359
        {
13951 fschmid 1360
                QTransform arrowTrans;
14969 cbradney 1361
                FPointArray arrow = m_Doc->arrowStyles().at(Item->startArrowIndex()-1).points.copy();
12623 fschmid 1362
                if (Item->itemType() == PageItem::Line)
1363
                {
1364
                        arrowTrans.translate(0, 0);
15345 fschmid 1365
                        arrowTrans.scale(Item->startArrowScale() / 100.0, Item->startArrowScale() / 100.0);
13302 fschmid 1366
                        if (Item->NamedLStyle.isEmpty())
1367
                        {
1368
                                if (Item->lineWidth() != 0.0)
1369
                                        arrowTrans.scale(Item->lineWidth(), Item->lineWidth());
1370
                        }
1371
                        else
1372
                        {
1373
                                multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
1374
                                if (ml[ml.size()-1].Width != 0.0)
1375
                                        arrowTrans.scale(ml[ml.size()-1].Width, ml[ml.size()-1].Width);
1376
                        }
12623 fschmid 1377
                        arrowTrans.scale(-1,1);
1378
                }
1379
                else
1380
                {
1381
                        FPoint Start = Item->PoLine.point(0);
18114 jghali 1382
                        for (int xx = 1; xx < Item->PoLine.size(); xx += 2)
12623 fschmid 1383
                        {
1384
                                FPoint Vector = Item->PoLine.point(xx);
1385
                                if ((Start.x() != Vector.x()) || (Start.y() != Vector.y()))
1386
                                {
1387
                                        double r = atan2(Start.y()-Vector.y(),Start.x()-Vector.x())*(180.0/M_PI);
1388
                                        arrowTrans.translate(Start.x(), Start.y());
1389
                                        arrowTrans.rotate(r);
15345 fschmid 1390
                                        arrowTrans.scale(Item->startArrowScale() / 100.0, Item->startArrowScale() / 100.0);
13302 fschmid 1391
                                        if (Item->NamedLStyle.isEmpty())
1392
                                        {
1393
                                                if (Item->lineWidth() != 0.0)
1394
                                                        arrowTrans.scale(Item->lineWidth(), Item->lineWidth());
1395
                                        }
1396
                                        else
1397
                                        {
1398
                                                multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
1399
                                                if (ml[ml.size()-1].Width != 0.0)
1400
                                                        arrowTrans.scale(ml[ml.size()-1].Width, ml[ml.size()-1].Width);
1401
                                        }
456 fschmid 1402
                                        break;
12623 fschmid 1403
                                }
1404
                        }
1405
                }
1406
                arrow.map(arrowTrans);
13302 fschmid 1407
                if (Item->NamedLStyle.isEmpty())
1408
                {
1409
                        ob = docu.createElement("path");
1410
                        ob.setAttribute("d", SetClipPath(&arrow, true));
1411
                        ob.setAttribute("transform", trans);
14169 fschmid 1412
                        QString aFill;
1413
                        if (!Item->strokePattern().isEmpty())
1414
                        {
1415
                                QString pattID = Item->strokePattern()+IToStr(PattCount);
1416
                                PattCount++;
1417
                                ScPattern pa = m_Doc->docPatterns[Item->strokePattern()];
1418
                                QDomElement patt = docu.createElement("pattern");
1419
                                patt.setAttribute("id", pattID);
1420
                                patt.setAttribute("height", pa.height);
1421
                                patt.setAttribute("width", pa.width);
1422
                                patt.setAttribute("patternUnits", "userSpaceOnUse");
14398 fschmid 1423
                                double patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY, patternSpace;
1424
                                Item->strokePatternTransform(patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY, patternSpace);
14276 fschmid 1425
                                bool mirrorX, mirrorY;
1426
                                Item->strokePatternFlip(mirrorX, mirrorY);
14169 fschmid 1427
                                QTransform mpa;
1428
                                mpa.translate(-Item->lineWidth() / 2.0, -Item->lineWidth() / 2.0);
1429
                                mpa.translate(patternOffsetX, patternOffsetY);
1430
                                mpa.rotate(patternRotation);
14260 fschmid 1431
                                mpa.shear(-patternSkewX, patternSkewY);
14169 fschmid 1432
                                mpa.scale(pa.scaleX, pa.scaleY);
1433
                                mpa.scale(patternScaleX / 100.0 , patternScaleY / 100.0);
14276 fschmid 1434
                                if (mirrorX)
1435
                                        mpa.scale(-1, 1);
1436
                                if (mirrorY)
1437
                                        mpa.scale(1, -1);
14169 fschmid 1438
                                patt.setAttribute("patternTransform", MatrixToStr(mpa));
1439
                                patt.setAttribute("xlink:href", "#"+Item->strokePattern());
1440
                                globalDefs.appendChild(patt);
1441
                                aFill += "fill:url(#"+pattID+");";
1442
                        }
14220 fschmid 1443
                        else if (Item->GrTypeStroke > 0)
1444
                        {
1445
                                QDomElement grad;
1446
                                if (Item->GrTypeStroke == 7)
1447
                                {
1448
                                        grad = docu.createElement("radialGradient");
1449
                                        grad.setAttribute("r", FToStr(sqrt(pow(Item->GrStrokeEndX - Item->GrStrokeStartX, 2) + pow(Item->GrStrokeEndY - Item->GrStrokeStartY,2))));
1450
                                        grad.setAttribute("cx", FToStr(Item->GrStrokeStartX));
1451
                                        grad.setAttribute("cy", FToStr(Item->GrStrokeStartY));
1452
                                }
1453
                                else
1454
                                {
1455
                                        grad = docu.createElement("linearGradient");
1456
                                        grad.setAttribute("x1", FToStr(Item->GrStrokeStartX));
1457
                                        grad.setAttribute("y1", FToStr(Item->GrStrokeStartY));
1458
                                        grad.setAttribute("x2", FToStr(Item->GrStrokeEndX));
1459
                                        grad.setAttribute("y2", FToStr(Item->GrStrokeEndY));
1460
                                }
15202 jghali 1461
                                bool   isFirst = true;
1462
                                double actualStop = 0.0, lastStop = 0.0;
14220 fschmid 1463
                                QList<VColorStop*> cstops = Item->stroke_gradient.colorStops();
1464
                                for (uint cst = 0; cst < Item->stroke_gradient.Stops(); ++cst)
1465
                                {
15202 jghali 1466
                                        actualStop = cstops.at(cst)->rampPoint;
1467
                                        if ((actualStop != lastStop) || (isFirst))
1468
                                        {
1469
                                                QDomElement itcl = docu.createElement("stop");
1470
                                                itcl.setAttribute("offset", FToStr(cstops.at(cst)->rampPoint*100)+"%");
1471
                                                if (cstops.at(cst)->name == CommonStrings::None)
1472
                                                        itcl.setAttribute("stop-opacity", FToStr(0));
1473
                                                else
1474
                                                        itcl.setAttribute("stop-opacity", FToStr(cstops.at(cst)->opacity));
1475
                                                itcl.setAttribute("stop-color", SetColor(cstops.at(cst)->name, cstops.at(cst)->shade));
1476
                                                grad.appendChild(itcl);
1477
                                                lastStop = actualStop;
1478
                                                isFirst  = false;
1479
                                        }
14220 fschmid 1480
                                }
1481
                                grad.setAttribute("id", "Grad"+IToStr(GradCount));
1482
                                grad.setAttribute("gradientUnits", "userSpaceOnUse");
1483
                                globalDefs.appendChild(grad);
1484
                                aFill = " fill:url(#Grad"+IToStr(GradCount)+");";
1485
                                GradCount++;
1486
                        }
14169 fschmid 1487
                        else
1488
                                aFill = "fill:"+SetColor(Item->lineColor(), Item->lineShade())+";";
13302 fschmid 1489
                        if (Item->lineTransparency() != 0)
1490
                                aFill += " fill-opacity:"+FToStr(1.0 - Item->lineTransparency())+";";
1491
                        ob.setAttribute("style", aFill + " stroke:none;");
1492
                        gr.appendChild(ob);
1493
                }
1494
                else
1495
                {
1496
                        multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
1497
                        if (ml[0].Color != CommonStrings::None)
1498
                        {
1499
                                ob = docu.createElement("path");
1500
                                ob.setAttribute("d", SetClipPath(&arrow, true));
1501
                                ob.setAttribute("transform", trans);
1502
                                QString aFill = "fill:"+SetColor(ml[0].Color, ml[0].Shade)+";";
1503
                                ob.setAttribute("style", aFill + " stroke:none;");
1504
                                gr.appendChild(ob);
1505
                        }
1506
                        for (int it = ml.size()-1; it > 0; it--)
1507
                        {
1508
                                if (ml[it].Color != CommonStrings::None)
1509
                                {
1510
                                        QDomElement ob5 = docu.createElement("path");
1511
                                        ob5.setAttribute("d", SetClipPath(&arrow, true));
1512
                                        ob5.setAttribute("transform", trans);
1513
                                        QString stroke = "fill:none; stroke:"+SetColor(ml[it].Color, ml[it].Shade)+"; stroke-linecap:butt; stroke-linejoin:miter; stroke-dasharray:none;";
1514
                                        if (ml[it].Width != 0.0)
1515
                                                stroke += " stroke-width:"+FToStr(ml[it].Width)+";";
1516
                                        else
1517
                                                stroke += " stroke-width:1px;";
1518
                                        ob5.setAttribute("style", stroke);
1519
                                        gr.appendChild(ob5);
1520
                                }
1521
                        }
1522
                }
12623 fschmid 1523
        }
1524
        if (Item->endArrowIndex() != 0)
1525
        {
13951 fschmid 1526
                QTransform arrowTrans;
14969 cbradney 1527
                FPointArray arrow = m_Doc->arrowStyles().at(Item->endArrowIndex()-1).points.copy();
12623 fschmid 1528
                if (Item->itemType() == PageItem::Line)
1529
                {
1530
                        arrowTrans.translate(Item->width(), 0);
15345 fschmid 1531
                        arrowTrans.scale(Item->endArrowScale() / 100.0, Item->endArrowScale() / 100.0);
13302 fschmid 1532
                        if (Item->NamedLStyle.isEmpty())
1533
                        {
1534
                                if (Item->lineWidth() != 0.0)
1535
                                        arrowTrans.scale(Item->lineWidth(), Item->lineWidth());
1536
                        }
1537
                        else
1538
                        {
1539
                                multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
1540
                                if (ml[ml.size()-1].Width != 0.0)
1541
                                        arrowTrans.scale(ml[ml.size()-1].Width, ml[ml.size()-1].Width);
1542
                        }
12623 fschmid 1543
                }
1544
                else
1545
                {
1546
                        FPoint End = Item->PoLine.point(Item->PoLine.size()-2);
1547
                        for (uint xx = Item->PoLine.size()-1; xx > 0; xx -= 2)
1548
                        {
1549
                                FPoint Vector = Item->PoLine.point(xx);
1550
                                if ((End.x() != Vector.x()) || (End.y() != Vector.y()))
1551
                                {
1552
                                        double r = atan2(End.y()-Vector.y(),End.x()-Vector.x())*(180.0/M_PI);
1553
                                        arrowTrans.translate(End.x(), End.y());
1554
                                        arrowTrans.rotate(r);
15345 fschmid 1555
                                        arrowTrans.scale(Item->endArrowScale() / 100.0, Item->endArrowScale() / 100.0);
13302 fschmid 1556
                                        if (Item->NamedLStyle.isEmpty())
1557
                                        {
1558
                                                if (Item->lineWidth() != 0.0)
1559
                                                        arrowTrans.scale(Item->lineWidth(), Item->lineWidth());
1560
                                        }
1561
                                        else
1562
                                        {
1563
                                                multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
1564
                                                if (ml[ml.size()-1].Width != 0.0)
1565
                                                        arrowTrans.scale(ml[ml.size()-1].Width, ml[ml.size()-1].Width);
1566
                                        }
12623 fschmid 1567
                                        break;
1568
                                }
1569
                        }
1570
                }
1571
                arrow.map(arrowTrans);
13302 fschmid 1572
                if (Item->NamedLStyle.isEmpty())
1573
                {
1574
                        ob = docu.createElement("path");
1575
                        ob.setAttribute("d", SetClipPath(&arrow, true));
1576
                        ob.setAttribute("transform", trans);
14169 fschmid 1577
                        QString aFill;
1578
                        if (!Item->strokePattern().isEmpty())
1579
                        {
1580
                                QString pattID = Item->strokePattern()+IToStr(PattCount);
1581
                                PattCount++;
1582
                                ScPattern pa = m_Doc->docPatterns[Item->strokePattern()];
1583
                                QDomElement patt = docu.createElement("pattern");
1584
                                patt.setAttribute("id", pattID);
1585
                                patt.setAttribute("height", pa.height);
1586
                                patt.setAttribute("width", pa.width);
1587
                                patt.setAttribute("patternUnits", "userSpaceOnUse");
14398 fschmid 1588
                                double patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY, patternSpace;
1589
                                Item->strokePatternTransform(patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY, patternSpace);
14276 fschmid 1590
                                bool mirrorX, mirrorY;
1591
                                Item->strokePatternFlip(mirrorX, mirrorY);
14169 fschmid 1592
                                QTransform mpa;
1593
                                mpa.translate(-Item->lineWidth() / 2.0, -Item->lineWidth() / 2.0);
1594
                                mpa.translate(patternOffsetX, patternOffsetY);
1595
                                mpa.rotate(patternRotation);
14260 fschmid 1596
                                mpa.shear(-patternSkewX, patternSkewY);
14169 fschmid 1597
                                mpa.scale(pa.scaleX, pa.scaleY);
1598
                                mpa.scale(patternScaleX / 100.0 , patternScaleY / 100.0);
14276 fschmid 1599
                                if (mirrorX)
1600
                                        mpa.scale(-1, 1);
1601
                                if (mirrorY)
1602
                                        mpa.scale(1, -1);
14169 fschmid 1603
                                patt.setAttribute("patternTransform", MatrixToStr(mpa));
1604
                                patt.setAttribute("xlink:href", "#"+Item->strokePattern());
1605
                                globalDefs.appendChild(patt);
1606
                                aFill += "fill:url(#"+pattID+");";
1607
                        }
14220 fschmid 1608
                        else if (Item->GrTypeStroke > 0)
1609
                        {
1610
                                QDomElement grad;
1611
                                if (Item->GrTypeStroke == 7)
1612
                                {
1613
                                        grad = docu.createElement("radialGradient");
1614
                                        grad.setAttribute("r", FToStr(sqrt(pow(Item->GrStrokeEndX - Item->GrStrokeStartX, 2) + pow(Item->GrStrokeEndY - Item->GrStrokeStartY,2))));
1615
                                        grad.setAttribute("cx", FToStr(Item->GrStrokeStartX));
1616
                                        grad.setAttribute("cy", FToStr(Item->GrStrokeStartY));
1617
                                }
1618
                                else
1619
                                {
1620
                                        grad = docu.createElement("linearGradient");
1621
                                        grad.setAttribute("x1", FToStr(Item->GrStrokeStartX));
1622
                                        grad.setAttribute("y1", FToStr(Item->GrStrokeStartY));
1623
                                        grad.setAttribute("x2", FToStr(Item->GrStrokeEndX));
1624
                                        grad.setAttribute("y2", FToStr(Item->GrStrokeEndY));
1625
                                }
15202 jghali 1626
                                bool   isFirst = true;
1627
                                double actualStop = 0.0, lastStop = 0.0;
14220 fschmid 1628
                                QList<VColorStop*> cstops = Item->stroke_gradient.colorStops();
1629
                                for (uint cst = 0; cst < Item->stroke_gradient.Stops(); ++cst)
1630
                                {
15202 jghali 1631
                                        actualStop = cstops.at(cst)->rampPoint;
1632
                                        if ((actualStop != lastStop) || (isFirst))
1633
                                        {
1634
                                                QDomElement itcl = docu.createElement("stop");
1635
                                                itcl.setAttribute("offset", FToStr(cstops.at(cst)->rampPoint*100)+"%");
1636
                                                if (cstops.at(cst)->name == CommonStrings::None)
1637
                                                        itcl.setAttribute("stop-opacity", FToStr(0));
1638
                                                else
1639
                                                        itcl.setAttribute("stop-opacity", FToStr(cstops.at(cst)->opacity));
1640
                                                itcl.setAttribute("stop-color", SetColor(cstops.at(cst)->name, cstops.at(cst)->shade));
1641
                                                grad.appendChild(itcl);
1642
                                                lastStop = actualStop;
1643
                                                isFirst  = false;
1644
                                        }
14220 fschmid 1645
                                }
1646
                                grad.setAttribute("id", "Grad"+IToStr(GradCount));
1647
                                grad.setAttribute("gradientUnits", "userSpaceOnUse");
1648
                                globalDefs.appendChild(grad);
1649
                                aFill = " fill:url(#Grad"+IToStr(GradCount)+");";
1650
                                GradCount++;
1651
                        }
14169 fschmid 1652
                        else
1653
                                aFill = "fill:"+SetColor(Item->lineColor(), Item->lineShade())+";";
13302 fschmid 1654
                        if (Item->lineTransparency() != 0)
1655
                                aFill += " fill-opacity:"+FToStr(1.0 - Item->lineTransparency())+";";
1656
                        ob.setAttribute("style", aFill + " stroke:none;");
1657
                        gr.appendChild(ob);
1658
                }
1659
                else
1660
                {
1661
                        multiLine ml = m_Doc->MLineStyles[Item->NamedLStyle];
1662
                        if (ml[0].Color != CommonStrings::None)
1663
                        {
1664
                                ob = docu.createElement("path");
1665
                                ob.setAttribute("d", SetClipPath(&arrow, true));
1666
                                ob.setAttribute("transform", trans);
1667
                                QString aFill = "fill:"+SetColor(ml[0].Color, ml[0].Shade)+";";
1668
                                ob.setAttribute("style", aFill + " stroke:none;");
1669
                                gr.appendChild(ob);
1670
                        }
1671
                        for (int it = ml.size()-1; it > 0; it--)
1672
                        {
1673
                                if (ml[it].Color != CommonStrings::None)
1674
                                {
1675
                                        QDomElement ob5 = docu.createElement("path");
1676
                                        ob5.setAttribute("d", SetClipPath(&arrow, true));
1677
                                        ob5.setAttribute("transform", trans);
1678
                                        QString stroke = "fill:none; stroke:"+SetColor(ml[it].Color, ml[it].Shade)+"; stroke-linecap:butt; stroke-linejoin:miter; stroke-dasharray:none;";
1679
                                        if (ml[it].Width != 0.0)
1680
                                                stroke += " stroke-width:"+FToStr(ml[it].Width)+";";
1681
                                        else
1682
                                                stroke += " stroke-width:1px;";
1683
                                        ob5.setAttribute("style", stroke);
1684
                                        gr.appendChild(ob5);
1685
                                }
1686
                        }
1687
                }
12623 fschmid 1688
        }
1689
        return gr;
1690
}
1691
 
14858 fschmid 1692
QString SVGExPlug::handleMask(PageItem *Item, double xOffset, double yOffset)
1693
{
1694
        QDomElement grad;
1695
        QString retVal = "";
1696
        if (Item->GrMask != 0)
1697
        {
1698
                QString maskID = "Mask"+IToStr(MaskCount);
1699
                MaskCount++;
1700
                QDomElement mask = docu.createElement("mask");
1701
                mask.setAttribute("id", maskID);
1702
                QDomElement ob = docu.createElement("path");
1703
                ob.setAttribute("d", "M 0 0 L "+FToStr(Item->width())+" 0 L "+FToStr(Item->width())+" "+FToStr(Item->height())+" L 0 "+FToStr(Item->height())+" Z");
16105 fschmid 1704
                if (Item->isGroup())
14858 fschmid 1705
                {
1706
                        QString trans = "translate("+FToStr(xOffset)+", "+FToStr(yOffset)+")";
1707
                        if (Item->rotation() != 0)
1708
                                trans += " rotate("+FToStr(Item->rotation())+")";
1709
                        ob.setAttribute("transform", trans);
1710
                }
1711
                if ((Item->GrMask == 3) || (Item->GrMask == 6))
1712
                {
1713
                        QString pattID = Item->patternMask()+IToStr(PattCount);
1714
                        PattCount++;
1715
                        ScPattern pa = m_Doc->docPatterns[Item->patternMask()];
1716
                        QDomElement patt = docu.createElement("pattern");
1717
                        patt.setAttribute("id", pattID);
1718
                        patt.setAttribute("height", FToStr(pa.height));
1719
                        patt.setAttribute("width", FToStr(pa.width));
1720
                        patt.setAttribute("patternUnits", "userSpaceOnUse");
1721
                        double patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY;
1722
                        Item->maskTransform(patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY);
1723
                        bool mirrorX, mirrorY;
1724
                        Item->maskFlip(mirrorX, mirrorY);
1725
                        QTransform mpa;
1726
                        mpa.translate(patternOffsetX, patternOffsetY);
1727
                        mpa.rotate(patternRotation);
1728
                        mpa.shear(-patternSkewX, patternSkewY);
1729
                        mpa.scale(pa.scaleX, pa.scaleY);
1730
                        mpa.scale(patternScaleX / 100.0 , patternScaleY / 100.0);
1731
                        if (mirrorX)
1732
                                mpa.scale(-1, 1);
1733
                        if (mirrorY)
1734
                                mpa.scale(1, -1);
1735
                        patt.setAttribute("patternTransform", MatrixToStr(mpa));
1736
                        patt.setAttribute("xlink:href", "#"+Item->patternMask());
1737
                        globalDefs.appendChild(patt);
1738
                        ob.setAttribute("fill", "url(#"+pattID+")");
1739
                }
1740
                else if ((Item->GrMask == 1) || (Item->GrMask == 2) || (Item->GrMask == 4) || (Item->GrMask == 5))
1741
                {
18641 fschmid 1742
                        if ((Item->GrMask == 1) || (Item->GrMask == 4))
14858 fschmid 1743
                        {
1744
                                grad = docu.createElement("linearGradient");
1745
                                grad.setAttribute("x1", FToStr(Item->GrMaskStartX));
1746
                                grad.setAttribute("y1", FToStr(Item->GrMaskStartY));
1747
                                grad.setAttribute("x2", FToStr(Item->GrMaskEndX));
1748
                                grad.setAttribute("y2", FToStr(Item->GrMaskEndY));
1749
                        }
1750
                        else
1751
                        {
1752
                                grad = docu.createElement("radialGradient");
1753
                                grad.setAttribute("r", FToStr(sqrt(pow(Item->GrMaskEndX - Item->GrMaskStartX, 2) + pow(Item->GrMaskEndY - Item->GrMaskStartY,2))));
1754
                                grad.setAttribute("cx", FToStr(Item->GrMaskStartX));
1755
                                grad.setAttribute("cy", FToStr(Item->GrMaskStartY));
1756
                                grad.setAttribute("fx", FToStr(Item->GrMaskFocalX));
1757
                                grad.setAttribute("fy", FToStr(Item->GrMaskFocalY));
1758
                        }
1759
                        double gradientSkew;
1760
                        if (Item->GrMaskSkew == 90)
1761
                                gradientSkew = 1;
1762
                        else if (Item->GrMaskSkew == 180)
1763
                                gradientSkew = 0;
1764
                        else if (Item->GrMaskSkew == 270)
1765
                                gradientSkew = -1;
1766
                        else if (Item->GrMaskSkew == 390)
1767
                                gradientSkew = 0;
1768
                        else
1769
                                gradientSkew = tan(M_PI / 180.0 * Item->GrMaskSkew);
1770
                        QTransform qmatrix;
1771
                        if (Item->GrType == 6)
1772
                        {
1773
                                qmatrix.translate(Item->GrMaskStartX, Item->GrMaskStartY);
1774
                                qmatrix.shear(-gradientSkew, 0);
1775
                                qmatrix.translate(-Item->GrMaskStartX, -Item->GrMaskStartY);
1776
                        }
1777
                        else
1778
                        {
1779
                                double rotEnd = xy2Deg(Item->GrMaskEndX - Item->GrMaskStartX, Item->GrMaskEndY - Item->GrMaskStartY);
1780
                                qmatrix.translate(Item->GrMaskStartX, Item->GrMaskStartY);
1781
                                qmatrix.rotate(rotEnd);
1782
                                qmatrix.shear(gradientSkew, 0);
1783
                                qmatrix.translate(0, Item->GrMaskStartY * (1.0 - Item->GrMaskScale));
1784
                                qmatrix.translate(-Item->GrMaskStartX, -Item->GrMaskStartY);
1785
                                qmatrix.scale(1, Item->GrMaskScale);
1786
                        }
1787
                        grad.setAttribute("gradientTransform", MatrixToStr(qmatrix));
1788
                        grad.setAttribute("id", "Grad"+IToStr(GradCount));
1789
                        grad.setAttribute("gradientUnits", "userSpaceOnUse");
1790
                        QList<VColorStop*> cstops = Item->mask_gradient.colorStops();
1791
                        for (uint cst = 0; cst < Item->mask_gradient.Stops(); ++cst)
1792
                        {
1793
                                QDomElement itcl = docu.createElement("stop");
1794
                                itcl.setAttribute("offset", FToStr(cstops.at(cst)->rampPoint*100)+"%");
1795
                                if (cstops.at(cst)->name == CommonStrings::None)
1796
                                        itcl.setAttribute("stop-opacity", FToStr(0));
1797
                                else
1798
                                        itcl.setAttribute("stop-opacity", FToStr(cstops.at(cst)->opacity));
1799
                                itcl.setAttribute("stop-color", SetColor(cstops.at(cst)->name, cstops.at(cst)->shade));
1800
                                grad.appendChild(itcl);
1801
                        }
1802
                        globalDefs.appendChild(grad);
1803
                        ob.setAttribute("fill", "url(#Grad"+IToStr(GradCount)+")");
1804
                        GradCount++;
1805
                }
16105 fschmid 1806
                if ((Item->lineColor() != CommonStrings::None) && (!Item->isGroup()))
14858 fschmid 1807
                {
1808
                        ob.setAttribute("stroke", "white");
1809
                        if (Item->lineWidth() != 0.0)
1810
                                ob.setAttribute("stroke-width", FToStr(Item->lineWidth()));
1811
                        else
1812
                                ob.setAttribute("stroke-width", "1px");
1813
                }
1814
                else
1815
                        ob.setAttribute("stroke", "none");
1816
                mask.appendChild(ob);
1817
                globalDefs.appendChild(mask);
1818
                retVal = "url(#"+maskID+")";
1819
        }
1820
        return retVal;
1821
}
1822
 
12627 fschmid 1823
QString SVGExPlug::getFillStyle(PageItem *Item)
12623 fschmid 1824
{
1825
        QDomElement grad;
1826
        QString fill;
1827
        if (Item->asPathText())
1828
                return "fill:none;";
1829
        if ((Item->fillColor() != CommonStrings::None) || (Item->GrType != 0))
1830
        {
1831
                fill = "fill:"+SetColor(Item->fillColor(), Item->fillShade())+";";
1832
                if (Item->GrType != 0)
1833
                {
1834
                        if (Item->GrType == 8)
1835
                        {
1836
                                QString pattID = Item->pattern()+IToStr(PattCount);
1837
                                PattCount++;
1838
                                ScPattern pa = m_Doc->docPatterns[Item->pattern()];
12627 fschmid 1839
                                QDomElement patt = docu.createElement("pattern");
12623 fschmid 1840
                                patt.setAttribute("id", pattID);
14260 fschmid 1841
                                patt.setAttribute("height", FToStr(pa.height));
1842
                                patt.setAttribute("width", FToStr(pa.width));
12623 fschmid 1843
                                patt.setAttribute("patternUnits", "userSpaceOnUse");
14260 fschmid 1844
                                double patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY;
1845
                                Item->patternTransform(patternScaleX, patternScaleY, patternOffsetX, patternOffsetY, patternRotation, patternSkewX, patternSkewY);
14276 fschmid 1846
                                bool mirrorX, mirrorY;
1847
                                Item->patternFlip(mirrorX, mirrorY);
13951 fschmid 1848
                                QTransform mpa;
12623 fschmid 1849
                                mpa.translate(patternOffsetX, patternOffsetY);
1850
                                mpa.rotate(patternRotation);
14260 fschmid 1851
                                mpa.shear(-patternSkewX, patternSkewY);
12623 fschmid 1852
                                mpa.scale(pa.scaleX, pa.scaleY);
1853
                                mpa.scale(patternScaleX / 100.0 , patternScaleY / 100.0);
14276 fschmid 1854
                                if (mirrorX)
1855
                                        mpa.scale(-1, 1);
1856
                                if (mirrorY)
1857
                                        mpa.scale(1, -1);
12623 fschmid 1858
                  &nb