Subversion Repositories Scribus

Rev

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

Rev Author Line No. Line
18598 fschmid 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
*/
7
/***************************************************************************
8
                                                         -------------------
9
        begin                : Sat Oct 26 2013
10
        copyright            : (C) 2013 by Franz Schmid
11
        email                : Franz.Schmid@altmuehlnet.de
12
 ***************************************************************************/
13
 
14
#include <QByteArray>
15
#include <QCursor>
16
#include <QDrag>
17
#include <QFile>
18
#include <QList>
19
#include <QMimeData>
20
#include <QRegExp>
21
#include <QStack>
22
#include <QUrl>
23
#include <QDebug>
24
 
25
#if defined(_MSC_VER) && !defined(_USE_MATH_DEFINES)
26
#define _USE_MATH_DEFINES
27
#endif
28
 
29
#include <cstdlib>
30
#include <climits>
31
#include <limits>
32
 
33
#include "commonstrings.h"
34
 
35
#include "importxps.h"
19093 craig 36
 
18598 fschmid 37
#include "loadsaveplugin.h"
38
#include "pageitem_table.h"
39
#include "pagesize.h"
40
#include "prefscontext.h"
41
#include "prefsfile.h"
42
#include "prefsmanager.h"
43
#include "prefstable.h"
44
#include "rawimage.h"
45
#include "scclocale.h"
46
#include "sccolorengine.h"
47
#include "scconfig.h"
48
#include "scmimedata.h"
49
#include "scpaths.h"
50
#include "scribusXml.h"
51
#include "scribuscore.h"
19093 craig 52
#include "scribusdoc.h"
53
#include "scribusview.h"
18598 fschmid 54
#include "sctextstream.h"
55
#include "selection.h"
19093 craig 56
#include "third_party/zip/scribus_zip.h"
57
#include "ui/customfdialog.h"
58
#include "ui/missing.h"
59
#include "ui/multiprogressdialog.h"
60
#include "ui/propertiespalette.h"
18598 fschmid 61
#include "undomanager.h"
62
#include "util.h"
63
#include "util_formats.h"
64
#include "util_math.h"
65
#include "xpsimportoptions.h"
66
 
67
XpsPlug::XpsPlug(ScribusDoc* doc, int flags)
68
{
69
        tmpSel = new Selection(this, false);
70
        m_Doc = doc;
71
        importerFlags = flags;
72
        interactive = (flags & LoadSavePlugin::lfInteractive);
22527 craig 73
        progressDialog = nullptr;
74
        uz = nullptr;
18598 fschmid 75
}
76
 
22635 craig 77
QImage XpsPlug::readThumbnail(const QString& fName)
18598 fschmid 78
{
79
        QImage tmp;
80
        if (!QFile::exists(fName))
81
                return QImage();
22527 craig 82
        progressDialog = nullptr;
18598 fschmid 83
        uz = new ScZipHandler();
84
        if (!uz->open(fName))
85
        {
86
                delete uz;
87
                if (progressDialog)
88
                        progressDialog->close();
18677 fschmid 89
                return QImage();
18598 fschmid 90
        }
91
        bool found = false;
92
        if (uz->contains("_rels/.rels"))
93
        {
94
                QByteArray f;
95
                QDomDocument designMapDom;
96
                if (!uz->read("_rels/.rels", f))
97
                        return QImage();
22721 jghali 98
                if (designMapDom.setContent(f))
18598 fschmid 99
                {
100
                        QDomElement docElem = designMapDom.documentElement();
22723 jghali 101
                        for (QDomElement drawPag = docElem.firstChildElement(); !drawPag.isNull(); drawPag = drawPag.nextSiblingElement())
18598 fschmid 102
                        {
18613 jghali 103
                                if (drawPag.tagName() != "Relationship")
104
                                        continue;
105
                                if ((!drawPag.hasAttribute("Target")) || (!drawPag.hasAttribute("Type")))
106
                                        continue;
107
                                if (drawPag.attribute("Type") != "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail")
108
                                        continue;
109
                                QString thumbRef = drawPag.attribute("Target");
110
                                if (thumbRef.startsWith("/"))
111
                                        thumbRef = thumbRef.mid(1);
112
                                QByteArray im;
113
                                if (uz->read(thumbRef, im))
18598 fschmid 114
                                {
18613 jghali 115
                                        tmp = QImage::fromData(im);
116
                                        found = true;
117
                                        break;
18598 fschmid 118
                                }
119
                        }
120
                }
121
        }
122
        if (!found)
123
        {
124
                QFileInfo fi = QFileInfo(fName);
125
                baseFile = QDir::cleanPath(QDir::toNativeSeparators(fi.absolutePath()+"/"));
23060 craig 126
                docWidth = PrefsManager::instance().appPrefs.docSetupPrefs.pageWidth;
127
                docHeight = PrefsManager::instance().appPrefs.docSetupPrefs.pageHeight;
18598 fschmid 128
                m_Doc = new ScribusDoc();
129
                m_Doc->setup(0, 1, 1, 1, 1, "Custom", "Custom");
130
                m_Doc->setPage(docWidth, docHeight, 0, 0, 0, 0, 0, 0, false, false);
131
                m_Doc->addPage(0);
22609 craig 132
                m_Doc->setGUI(false, ScCore->primaryMainWindow(), nullptr);
18598 fschmid 133
                baseX = m_Doc->currentPage()->xOffset();
134
                baseY = m_Doc->currentPage()->yOffset() + m_Doc->currentPage()->height() / 2.0;
135
                Elements.clear();
136
                m_Doc->setLoading(true);
137
                m_Doc->DoDrawing = false;
138
                m_Doc->scMW()->setScriptRunning(true);
139
                QString CurDirP = QDir::currentPath();
140
                QDir::setCurrent(fi.path());
141
                importedColors.clear();
142
                importedPatterns.clear();
143
                conversionFactor = 72.0 / 96.0;
144
                loadedFonts.clear();
145
                linkTargets.clear();
146
                linkSources.clear();
147
                if (uz->contains("FixedDocSeq.fdseq"))
148
                        parseDocSequence("FixedDocSeq.fdseq");
149
                else if (uz->contains("FixedDocumentSequence.fdseq"))
150
                        parseDocSequence("FixedDocumentSequence.fdseq");
151
                if (Elements.count() > 0)
152
                {
153
                        tmpSel->clear();
154
                        QDir::setCurrent(CurDirP);
155
                        if (Elements.count() > 1)
156
                                m_Doc->groupObjectsList(Elements);
157
                        m_Doc->DoDrawing = true;
158
                        m_Doc->m_Selection->delaySignalsOn();
159
                        if (Elements.count() > 0)
160
                        {
161
                                for (int dre=0; dre<Elements.count(); ++dre)
162
                                {
163
                                        tmpSel->addItem(Elements.at(dre), true);
164
                                }
165
                                tmpSel->setGroupRect();
166
                                double xs = tmpSel->width();
167
                                double ys = tmpSel->height();
168
                                tmp = Elements.at(0)->DrawObj_toImage(500);
169
                                tmp.setText("XSize", QString("%1").arg(xs));
170
                                tmp.setText("YSize", QString("%1").arg(ys));
171
                        }
172
                        m_Doc->scMW()->setScriptRunning(false);
173
                        m_Doc->setLoading(false);
174
                        m_Doc->m_Selection->delaySignalsOff();
175
                        delete m_Doc;
176
                }
177
                else
178
                {
179
                        QDir::setCurrent(CurDirP);
180
                        m_Doc->DoDrawing = true;
181
                        m_Doc->scMW()->setScriptRunning(false);
182
                        delete m_Doc;
183
                }
184
        }
185
        uz->close();
186
        delete uz;
187
        return tmp;
188
}
189
 
22635 craig 190
bool XpsPlug::import(const QString& fNameIn, const TransactionSettings& trSettings, int flags, bool showProgress)
18598 fschmid 191
{
192
        bool success = false;
193
        interactive = (flags & LoadSavePlugin::lfInteractive);
194
        importerFlags = flags;
195
        cancel = false;
196
        bool ret = false;
197
        firstPage = true;
198
        pagecount = 1;
22635 craig 199
        QFileInfo fi = QFileInfo(fNameIn);
18598 fschmid 200
        m_FileName = fi.fileName();
201
        if ( !ScCore->usingGUI() )
202
        {
203
                interactive = false;
204
                showProgress = false;
205
        }
206
        baseFile = QDir::cleanPath(QDir::toNativeSeparators(fi.absolutePath()+"/"));
207
        if ( showProgress )
208
        {
22609 craig 209
                ScribusMainWindow* mw=(m_Doc==nullptr) ? ScCore->primaryMainWindow() : m_Doc->scMW();
18598 fschmid 210
                progressDialog = new MultiProgressDialog( tr("Importing: %1").arg(fi.fileName()), CommonStrings::tr_Cancel, mw );
211
                QStringList barNames, barTexts;
212
                barNames << "GI";
213
                barTexts << tr("Analyzing File:");
214
                QList<bool> barsNumeric;
215
                barsNumeric << false;
216
                progressDialog->addExtraProgressBars(barNames, barTexts, barsNumeric);
217
                progressDialog->setOverallTotalSteps(3);
218
                progressDialog->setOverallProgress(0);
219
                progressDialog->setProgress("GI", 0);
220
                progressDialog->show();
221
                connect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelRequested()));
222
                qApp->processEvents();
223
        }
224
        else
22527 craig 225
                progressDialog = nullptr;
18598 fschmid 226
        if (progressDialog)
227
        {
228
                progressDialog->setOverallProgress(1);
229
                qApp->processEvents();
230
        }
231
        /* Set default Page to size defined in Preferences */
23060 craig 232
        docWidth = PrefsManager::instance().appPrefs.docSetupPrefs.pageWidth;
233
        docHeight = PrefsManager::instance().appPrefs.docSetupPrefs.pageHeight;
18598 fschmid 234
        baseX = 0;
235
        baseY = 0;
236
        if (!interactive || (flags & LoadSavePlugin::lfInsertPage))
237
        {
238
                m_Doc->setPage(docWidth, docHeight, 0, 0, 0, 0, 0, 0, false, false);
239
                m_Doc->addPage(0);
240
                m_Doc->view()->addPage(0, true);
241
                baseX = 0;
242
                baseY = 0;
243
        }
244
        else
245
        {
246
                if (!m_Doc || (flags & LoadSavePlugin::lfCreateDoc))
247
                {
248
                        m_Doc=ScCore->primaryMainWindow()->doFileNew(docWidth, docHeight, 0, 0, 0, 0, 0, 0, false, false, 0, false, 0, 1, "Custom", true);
249
                        ScCore->primaryMainWindow()->HaveNewDoc();
250
                        ret = true;
251
                        baseX = 0;
252
                        baseY = 0;
253
                        baseX = m_Doc->currentPage()->xOffset();
254
                        baseY = m_Doc->currentPage()->yOffset() + m_Doc->currentPage()->height() / 2.0;
255
                }
256
        }
257
        if ((!ret) && (interactive))
258
        {
259
                baseX = m_Doc->currentPage()->xOffset();
260
                baseY = m_Doc->currentPage()->yOffset() + m_Doc->currentPage()->height() / 2.0;
261
        }
262
        if ((ret) || (!interactive))
263
        {
264
                if (docWidth > docHeight)
265
                        m_Doc->setPageOrientation(1);
266
                else
267
                        m_Doc->setPageOrientation(0);
268
                m_Doc->setPageSize("Custom");
269
        }
22527 craig 270
        if ((!(flags & LoadSavePlugin::lfLoadAsPattern)) && (m_Doc->view() != nullptr))
23390 craig 271
                m_Doc->view()->deselectItems();
18598 fschmid 272
        Elements.clear();
273
        m_Doc->setLoading(true);
274
        m_Doc->DoDrawing = false;
22527 craig 275
        if ((!(flags & LoadSavePlugin::lfLoadAsPattern)) && (m_Doc->view() != nullptr))
18598 fschmid 276
                m_Doc->view()->updatesOn(false);
277
        m_Doc->scMW()->setScriptRunning(true);
278
        qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
279
        QString CurDirP = QDir::currentPath();
280
        QDir::setCurrent(fi.path());
22635 craig 281
        if (convert(fNameIn))
18598 fschmid 282
        {
283
                tmpSel->clear();
284
                QDir::setCurrent(CurDirP);
285
                if ((Elements.count() > 1) && (!(importerFlags & LoadSavePlugin::lfCreateDoc)))
286
                        m_Doc->groupObjectsList(Elements);
287
                m_Doc->DoDrawing = true;
288
                m_Doc->scMW()->setScriptRunning(false);
289
                m_Doc->setLoading(false);
290
                qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
291
                if ((Elements.count() > 0) && (!ret) && (interactive))
292
                {
293
                        if (flags & LoadSavePlugin::lfScripted)
294
                        {
295
                                bool loadF = m_Doc->isLoading();
296
                                m_Doc->setLoading(false);
297
                                m_Doc->changed();
298
                                m_Doc->setLoading(loadF);
299
                                if (!(flags & LoadSavePlugin::lfLoadAsPattern))
300
                                {
301
                                        m_Doc->m_Selection->delaySignalsOn();
302
                                        for (int dre=0; dre<Elements.count(); ++dre)
303
                                        {
304
                                                m_Doc->m_Selection->addItem(Elements.at(dre), true);
305
                                        }
306
                                        m_Doc->m_Selection->delaySignalsOff();
307
                                        m_Doc->m_Selection->setGroupRect();
22527 craig 308
                                        if (m_Doc->view() != nullptr)
19856 fschmid 309
                                                m_Doc->view()->updatesOn(true);
18598 fschmid 310
                                }
311
                        }
312
                        else
313
                        {
314
                                m_Doc->DragP = true;
22609 craig 315
                                m_Doc->DraggedElem = nullptr;
18598 fschmid 316
                                m_Doc->DragElements.clear();
317
                                m_Doc->m_Selection->delaySignalsOn();
318
                                for (int dre=0; dre<Elements.count(); ++dre)
319
                                {
320
                                        tmpSel->addItem(Elements.at(dre), true);
321
                                }
322
                                tmpSel->setGroupRect();
22686 jghali 323
                                ScElemMimeData* md = ScriXmlDoc::writeToMimeData(m_Doc, tmpSel);
18598 fschmid 324
                                m_Doc->itemSelection_DeleteItem(tmpSel);
325
                                m_Doc->view()->updatesOn(true);
326
                                if ((importedColors.count() != 0) && (!((flags & LoadSavePlugin::lfKeepGradients) || (flags & LoadSavePlugin::lfKeepColors) || (flags & LoadSavePlugin::lfKeepPatterns))))
327
                                {
328
                                        for (int cd = 0; cd < importedColors.count(); cd++)
329
                                        {
330
                                                m_Doc->PageColors.remove(importedColors[cd]);
331
                                        }
332
                                }
333
                                if ((importedPatterns.count() != 0) && (!(flags & LoadSavePlugin::lfKeepPatterns)))
334
                                {
335
                                        for (int cd = 0; cd < importedPatterns.count(); cd++)
336
                                        {
337
                                                m_Doc->docPatterns.remove(importedPatterns[cd]);
338
                                        }
339
                                }
340
                                m_Doc->m_Selection->delaySignalsOff();
341
                                // We must copy the TransationSettings object as it is owned
342
                                // by handleObjectImport method afterwards
343
                                TransactionSettings* transacSettings = new TransactionSettings(trSettings);
344
                                m_Doc->view()->handleObjectImport(md, transacSettings);
345
                                m_Doc->DragP = false;
22609 craig 346
                                m_Doc->DraggedElem = nullptr;
18598 fschmid 347
                                m_Doc->DragElements.clear();
348
                        }
349
                }
350
                else
351
                {
352
                        m_Doc->changed();
353
                        m_Doc->reformPages();
354
                        if (!(flags & LoadSavePlugin::lfLoadAsPattern))
355
                                m_Doc->view()->updatesOn(true);
356
                }
357
                success = true;
358
        }
359
        else
360
        {
361
                QDir::setCurrent(CurDirP);
362
                m_Doc->DoDrawing = true;
363
                m_Doc->scMW()->setScriptRunning(false);
364
                if (!(flags & LoadSavePlugin::lfLoadAsPattern))
365
                        m_Doc->view()->updatesOn(true);
366
                qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
18657 jghali 367
                success = false;
18598 fschmid 368
        }
369
        if (interactive)
370
                m_Doc->setLoading(false);
371
        //CB If we have a gui we must refresh it if we have used the progressbar
372
        if (!(flags & LoadSavePlugin::lfLoadAsPattern))
373
        {
374
                if ((showProgress) && (!interactive))
375
                        m_Doc->view()->DrawNew();
376
        }
377
        qApp->restoreOverrideCursor();
378
        return success;
379
}
380
 
381
XpsPlug::~XpsPlug()
382
{
22609 craig 383
        delete progressDialog;
18598 fschmid 384
        delete tmpSel;
385
        for (int a = 0; a < tempFontFiles.count(); a++)
386
        {
387
                QFile::remove(tempFontFiles[a]);
388
        }
389
}
390
 
22635 craig 391
bool XpsPlug::convert(const QString& fn)
18598 fschmid 392
{
393
        bool retVal = true;
394
        importedColors.clear();
395
        importedPatterns.clear();
396
        conversionFactor = 72.0 / 96.0;
397
        loadedFonts.clear();
398
        linkTargets.clear();
399
        linkSources.clear();
400
        pathResources.clear();
22721 jghali 401
        if (progressDialog)
18598 fschmid 402
        {
403
                progressDialog->setOverallProgress(2);
404
                progressDialog->setLabel("GI", tr("Generating Items"));
405
                qApp->processEvents();
406
        }
407
 
408
        uz = new ScZipHandler();
409
        if (!uz->open(fn))
410
        {
411
                delete uz;
412
                if (progressDialog)
413
                        progressDialog->close();
18677 fschmid 414
                return false;
18598 fschmid 415
        }
18657 jghali 416
 
417
        retVal = false;
18598 fschmid 418
        if (uz->contains("FixedDocSeq.fdseq"))
18657 jghali 419
                retVal = parseDocSequence("FixedDocSeq.fdseq");
18598 fschmid 420
        else if (uz->contains("FixedDocumentSequence.fdseq"))
18657 jghali 421
                retVal = parseDocSequence("FixedDocumentSequence.fdseq");
422
        if (retVal)
18598 fschmid 423
                resolveLinks();
18657 jghali 424
 
18598 fschmid 425
        uz->close();
426
        delete uz;
427
        if (progressDialog)
428
                progressDialog->close();
429
        return retVal;
430
}
431
 
22635 craig 432
bool XpsPlug::parseDocSequence(const QString& designMap)
18598 fschmid 433
{
434
        QByteArray f;
435
        QDomDocument designMapDom;
436
        if (!uz->read(designMap, f))
18657 jghali 437
                return false;
438
        if (!designMapDom.setContent(f))
439
                return false;
440
 
441
        bool parsed = false;
442
        QString DocumentReference = "";
443
        QDomElement docElem = designMapDom.documentElement();
22727 jghali 444
        for (QDomNode drawPag = docElem.firstChild(); !drawPag.isNull(); drawPag = drawPag.nextSibling())
18598 fschmid 445
        {
18657 jghali 446
                QDomElement dpg = drawPag.toElement();
447
                if (dpg.tagName() == "DocumentReference")
18598 fschmid 448
                {
18657 jghali 449
                        if (dpg.hasAttribute("Source"))
18598 fschmid 450
                        {
18657 jghali 451
                                DocumentReference = dpg.attribute("Source", "");
452
                                if (DocumentReference.startsWith("/"))
453
                                        DocumentReference = DocumentReference.mid(1);
454
                                parsed = parseDocReference(DocumentReference);
455
                                if (!parsed) break;
18598 fschmid 456
                        }
457
                }
458
        }
18657 jghali 459
        return parsed;
18598 fschmid 460
}
461
 
22635 craig 462
bool XpsPlug::parseDocReference(const QString& designMap)
18598 fschmid 463
{
464
        QByteArray f;
465
        QFileInfo fi(designMap);
466
        QString path = fi.path();
18657 jghali 467
        if (!uz->read(designMap, f))
468
                return false;
469
 
470
        QDomDocument designMapDom;
471
        if (!designMapDom.setContent(f))
472
                return false;
473
 
474
        QString PageReference = "";
475
        QDomElement docElem = designMapDom.documentElement();
476
        if (importerFlags & LoadSavePlugin::lfCreateThumbnail)
18598 fschmid 477
        {
18657 jghali 478
                QDomNodeList pgList = docElem.childNodes();
479
                QDomNode drawPag = pgList.item(0);
480
                QDomElement dpg = drawPag.toElement();
481
                if (dpg.tagName() == "PageContent")
18598 fschmid 482
                {
18657 jghali 483
                        if (dpg.hasAttribute("Source"))
18598 fschmid 484
                        {
18657 jghali 485
                                PageReference = dpg.attribute("Source", "");
486
                                if (PageReference.startsWith("/"))
18598 fschmid 487
                                {
18657 jghali 488
                                        PageReference = PageReference.mid(1);
489
                                        parsePageReference(PageReference);
490
                                }
491
                                else
492
                                {
493
                                        if (!PageReference.startsWith(path))
18598 fschmid 494
                                        {
18657 jghali 495
                                                PageReference = path + "/" + PageReference;
496
                                                PageReference = QDir::cleanPath(PageReference);
18598 fschmid 497
                                        }
18657 jghali 498
                                        parsePageReference(PageReference);
18598 fschmid 499
                                }
500
                        }
18657 jghali 501
                }
502
        }
503
        else
504
        {
505
                std::vector<int> pageNs;
506
                QString pageString = "*";
507
                int pgCount = 0;
508
                int maxPages = docElem.childNodes().count();
509
                if (((interactive) || (importerFlags & LoadSavePlugin::lfCreateDoc)) && (maxPages > 1))
510
                {
511
                        if (progressDialog)
512
                                progressDialog->hide();
513
                        qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
514
                        XpsImportOptions optImp(ScCore->primaryMainWindow());
515
                        optImp.setUpOptions(m_FileName, 1, maxPages, interactive);
516
                        if (optImp.exec() != QDialog::Accepted)
517
                                return false;
518
                        pageString = optImp.getPagesString();
519
                        qApp->changeOverrideCursor(QCursor(Qt::WaitCursor));
520
                        if (progressDialog)
521
                                progressDialog->show();
522
                        qApp->processEvents();
523
                }
524
                parsePagesString(pageString, &pageNs, maxPages);
525
                if (pageString != "*")
526
                        maxPages = pageNs.size();
527
                if (progressDialog)
528
                {
529
                        progressDialog->setTotalSteps("GI", maxPages);
530
                        progressDialog->setProgress("GI", pgCount);
531
                        qApp->processEvents();
532
                }
533
                QDomNodeList pgList = docElem.childNodes();
534
                for (uint ap = 0; ap < pageNs.size(); ++ap)
535
                {
536
                        QDomNode drawPag = pgList.item(pageNs[ap] - 1);
537
                        QDomElement dpg = drawPag.toElement();
538
                        if (dpg.tagName() == "PageContent")
18598 fschmid 539
                        {
18657 jghali 540
                                if (dpg.hasAttribute("Source"))
18598 fschmid 541
                                {
18657 jghali 542
                                        PageReference = dpg.attribute("Source", "");
543
                                        if (PageReference.startsWith("/"))
18598 fschmid 544
                                        {
18657 jghali 545
                                                PageReference = PageReference.mid(1);
546
                                                parsePageReference(PageReference);
547
                                        }
548
                                        else
549
                                        {
550
                                                if (!PageReference.startsWith(path))
18598 fschmid 551
                                                {
18657 jghali 552
                                                        PageReference = path + "/" + PageReference;
553
                                                        PageReference = QDir::cleanPath(PageReference);
18598 fschmid 554
                                                }
18657 jghali 555
                                                parsePageReference(PageReference);
18598 fschmid 556
                                        }
557
                                }
558
                        }
18657 jghali 559
                        pgCount++;
560
                        if (progressDialog)
561
                        {
562
                                progressDialog->setProgress("GI", pgCount);
563
                                qApp->processEvents();
564
                        }
18598 fschmid 565
                }
566
        }
18657 jghali 567
        return true;
18598 fschmid 568
}
569
 
22635 craig 570
void XpsPlug::parsePageReference(const QString& designMap)
18598 fschmid 571
{
572
        QByteArray f;
573
        QFileInfo fi(designMap);
574
        QString path = fi.path();
22727 jghali 575
        if (!uz->read(designMap, f))
576
                return;
577
 
578
        QDomDocument designMapDom;
579
        if (!designMapDom.setContent(f))
580
                return;
581
 
582
        QDomElement docElem = designMapDom.documentElement();
23060 craig 583
        docWidth = docElem.attribute("Width", QString("%1").arg(PrefsManager::instance().appPrefs.docSetupPrefs.pageWidth)).toDouble() * conversionFactor;
584
        docHeight = docElem.attribute("Height", QString("%1").arg(PrefsManager::instance().appPrefs.docSetupPrefs.pageHeight)).toDouble() * conversionFactor;
22727 jghali 585
        if (importerFlags & LoadSavePlugin::lfCreateDoc)
18598 fschmid 586
        {
22727 jghali 587
                if (firstPage)
18598 fschmid 588
                {
22727 jghali 589
                        topMargin = m_Doc->marginsVal().top();
590
                        leftMargin = m_Doc->marginsVal().left();
591
                        rightMargin = m_Doc->marginsVal().right();
592
                        bottomMargin = m_Doc->marginsVal().bottom();
593
                        double pgCols = m_Doc->PageSp;
594
                        double pgGap = m_Doc->PageSpa;
595
                        m_Doc->setPage(docWidth, docHeight, topMargin, leftMargin, rightMargin, bottomMargin, pgCols, pgGap, false, false);
596
                        m_Doc->setPageSize("Custom");
23129 craig 597
                        m_Doc->currentPage()->setSize("Custom");
22727 jghali 598
                        m_Doc->currentPage()->setInitialHeight(docHeight);
599
                        m_Doc->currentPage()->setInitialWidth(docWidth);
600
                        m_Doc->currentPage()->setHeight(docHeight);
601
                        m_Doc->currentPage()->setWidth(docWidth);
602
                        m_Doc->currentPage()->initialMargins.setTop(topMargin);
603
                        m_Doc->currentPage()->initialMargins.setBottom(bottomMargin);
604
                        m_Doc->currentPage()->initialMargins.setLeft(leftMargin);
605
                        m_Doc->currentPage()->initialMargins.setRight(rightMargin);
606
                        m_Doc->reformPages(true);
607
                }
608
                else
609
                {
610
                        m_Doc->addPage(pagecount);
23129 craig 611
                        m_Doc->currentPage()->setSize("Custom");
22727 jghali 612
                        m_Doc->currentPage()->setInitialHeight(docHeight);
613
                        m_Doc->currentPage()->setInitialWidth(docWidth);
614
                        m_Doc->currentPage()->setHeight(docHeight);
615
                        m_Doc->currentPage()->setWidth(docWidth);
616
                        m_Doc->currentPage()->initialMargins.setTop(topMargin);
617
                        m_Doc->currentPage()->initialMargins.setBottom(bottomMargin);
618
                        m_Doc->currentPage()->initialMargins.setLeft(leftMargin);
619
                        m_Doc->currentPage()->initialMargins.setRight(rightMargin);
23129 craig 620
                        m_Doc->currentPage()->setMasterPageNameNormal();
22727 jghali 621
                        m_Doc->view()->addPage(pagecount, true);
622
                        pagecount++;
623
                }
624
        }
625
        firstPage = false;
626
        baseX = m_Doc->currentPage()->xOffset();
627
        baseY = m_Doc->currentPage()->yOffset();
628
        for (QDomNode drawPag = docElem.firstChild(); !drawPag.isNull(); drawPag = drawPag.nextSibling())
629
        {
630
                QDomElement dpg = drawPag.toElement();
631
                if ((dpg.tagName() == "Path") || (dpg.tagName() == "Glyphs") || (dpg.tagName() == "Canvas"))
632
                {
633
                        PageItem* item = parseObjectXML(dpg, path);
634
                        if (item != nullptr)
18598 fschmid 635
                        {
22727 jghali 636
                                m_Doc->Items->append(item);
637
                                Elements.append(item);
18598 fschmid 638
                        }
22727 jghali 639
                }
640
                else if (dpg.tagName() == "FixedPage.Resources")
641
                {
642
                        for (QDomNode sp = dpg.firstChild(); !sp.isNull(); sp = sp.nextSibling())
18598 fschmid 643
                        {
22727 jghali 644
                                QDomElement spe = sp.toElement();
645
                                if (spe.tagName() != "ResourceDictionary")
646
                                        continue;
647
                                if (spe.hasAttribute("Source"))
18598 fschmid 648
                                {
22727 jghali 649
                                        QString resFile = spe.attribute("Source", "");
650
                                        if (resFile.startsWith("/"))
18598 fschmid 651
                                        {
22727 jghali 652
                                                resFile = resFile.mid(1);
653
                                                parseResourceFile(resFile);
18598 fschmid 654
                                        }
22727 jghali 655
                                        else
656
                                        {
657
                                                if (!resFile.startsWith(path))
658
                                                {
659
                                                        resFile = path + "/" + resFile;
660
                                                        resFile = QDir::cleanPath(resFile);
661
                                                }
662
                                                parseResourceFile(resFile);
663
                                        }
18598 fschmid 664
                                }
22727 jghali 665
                                else if (spe.hasChildNodes())
18598 fschmid 666
                                {
22727 jghali 667
                                        for (QDomElement dpgp = spe.firstChildElement(); !dpgp.isNull(); dpgp = dpgp.nextSiblingElement())
18598 fschmid 668
                                        {
22727 jghali 669
                                                if (dpgp.tagName() == "PathGeometry")
18598 fschmid 670
                                                {
22727 jghali 671
                                                        Coords.resize(0);
672
                                                        Coords.svgInit();
673
                                                        QString pdata = "";
674
                                                        QString key = dpg.attribute("x:Key");
675
                                                        if (dpg.hasAttribute("Figures"))
676
                                                                pdata = dpg.attribute("Figures");
677
                                                        else if (dpg.hasChildNodes())
678
                                                                pdata = parsePathGeometryXML(dpg);
679
                                                        if (!pdata.isEmpty())
18598 fschmid 680
                                                        {
22727 jghali 681
                                                                bool currentPathClosed = Coords.parseSVG(pdata);
682
                                                                Coords.scale(conversionFactor, conversionFactor);
683
                                                                QPainterPath path = Coords.toQPainterPath(!currentPathClosed);
684
                                                                if (dpg.attribute("FillRule") == "NonZero")
685
                                                                        path.setFillRule(Qt::WindingFill);
686
                                                                pathResources.insert(key, path);
18598 fschmid 687
                                                        }
688
                                                }
689
                                        }
690
                                }
691
                        }
692
                }
693
        }
694
}
695
 
22635 craig 696
PageItem* XpsPlug::parseObjectXML(QDomElement &dpg, const QString& path)
18598 fschmid 697
{
22527 craig 698
        PageItem *retObj = nullptr;
18598 fschmid 699
        ObjState obState;
700
        obState.currentPath = QPainterPath();
701
        obState.clipPath = QPainterPath();
702
        obState.transform = QTransform();
703
        obState.CurrColorFill = CommonStrings::None;
704
        obState.fillOpacity = 0.0;
705
        obState.CurrColorStroke = CommonStrings::None;
706
        obState.strokeOpacity = 0.0;
707
        obState.LineW = 1.0;
708
        obState.fillGradientTyp = 0;
709
        obState.gradientScale = 1.0;
710
        obState.maskTyp = 0;
711
        obState.strokeTyp = 0;
712
        obState.imagePath = "";
713
        obState.itemType = 0;
714
        obState.patternName = "";
715
        obState.patternMask = "";
716
        obState.CapStyle = Qt::FlatCap;
717
        obState.JoinStyle = Qt::MiterJoin;
18628 fschmid 718
        obState.DashOffset = 0;
719
        obState.DashPattern.clear();
18598 fschmid 720
        QString itemName = "";
721
        QString itemTarget = "";
722
        if (dpg.hasAttribute("Name"))
723
                itemName = dpg.attribute("Name");
724
        if (dpg.hasAttribute("FixedPage.NavigateUri"))
725
        {
726
                QString iTg = dpg.attribute("FixedPage.NavigateUri");
727
                QStringList tg = iTg.split("#");
728
                if (tg.count() > 1)
729
                        itemTarget = tg[1];
730
        }
731
        if (dpg.hasAttribute("RenderTransform"))
732
        {
733
                QString trans = dpg.attribute("RenderTransform", "1 0 0 1 0 0");
734
                trans.replace(",", " ");
735
                ScTextStream list(&trans, QIODevice::ReadOnly);
736
                double a, b, c, d, e, f;
737
                list >> a >> b >> c >> d >> e >> f;
738
                obState.transform = QTransform(a, b, c, d, e * conversionFactor, f * conversionFactor);
739
        }
740
        if (dpg.hasAttribute("Fill"))
741
                obState.CurrColorFill = handleColor(dpg.attribute("Fill", "#FF000000"), obState.fillOpacity);
742
        if (dpg.hasAttribute("Stroke"))
743
                obState.CurrColorStroke = handleColor(dpg.attribute("Stroke", "#FF000000"), obState.strokeOpacity);
744
        if (dpg.hasAttribute("Opacity"))
745
        {
746
                double opacity = dpg.attribute("Opacity", "1.0").toDouble();
747
                obState.fillOpacity = 1.0 - ((1.0 - obState.fillOpacity) * opacity);
748
                obState.strokeOpacity = 1.0 - ((1.0 - obState.strokeOpacity) * opacity);
749
        }
750
        if (dpg.hasAttribute("StrokeThickness"))
751
                obState.LineW = dpg.attribute("StrokeThickness", "1.0").toDouble() * conversionFactor;
752
        if (dpg.hasAttribute("StrokeDashCap"))
753
        {
754
                if (dpg.attribute("StrokeDashCap") == "Flat")
755
                        obState.CapStyle = Qt::FlatCap;
756
                else if (dpg.attribute("StrokeDashCap") == "Round")
757
                        obState.CapStyle = Qt::RoundCap;
758
                else if (dpg.attribute("StrokeDashCap") == "Square")
759
                        obState.CapStyle = Qt::SquareCap;
760
                else
761
                        obState.CapStyle = Qt::FlatCap;
762
        }
763
        if (dpg.hasAttribute("StrokeLineJoin"))
764
        {
765
                if (dpg.attribute("StrokeLineJoin") == "Miter")
766
                        obState.JoinStyle = Qt::MiterJoin;
767
                else if (dpg.attribute("StrokeLineJoin") == "Round")
768
                        obState.JoinStyle = Qt::RoundJoin;
769
                else if (dpg.attribute("StrokeLineJoin") == "Bevel")
770
                        obState.JoinStyle = Qt::BevelJoin;
771
                else
772
                        obState.JoinStyle = Qt::MiterJoin;
773
        }
18628 fschmid 774
        if (dpg.hasAttribute("StrokeDashOffset"))
775
                obState.DashOffset = dpg.attribute("StrokeDashOffset", "0.0").toDouble();
776
        if (dpg.hasAttribute("StrokeDashArray"))
777
        {
778
                QString trans = dpg.attribute("StrokeDashArray", "");
779
                if (!trans.isEmpty())
780
                {
781
                        ScTextStream list(&trans, QIODevice::ReadOnly);
782
                        while (!list.atEnd())
783
                        {
784
                                double d;
785
                                list >> d;
786
                                obState.DashPattern.append(d);
787
                        }
788
                }
789
        }
18598 fschmid 790
        if (dpg.hasAttribute("Clip"))
791
        {
792
                QString cdata = dpg.attribute("Clip");
793
                if (!cdata.startsWith("{"))
794
                {
795
                        Coords.resize(0);
796
                        Coords.svgInit();
797
                        Coords.parseSVG(cdata);
798
                        Coords.scale(conversionFactor, conversionFactor);
799
                        obState.clipPath = Coords.toQPainterPath(true);
800
                        obState.clipPath = obState.transform.map(obState.clipPath);
801
                }
802
                else
803
                {
804
                        cdata.remove("{StaticResource ");
805
                        cdata.remove("}");
806
                        cdata = cdata.trimmed();
807
                        if (pathResources.contains(cdata))
808
                                obState.clipPath = obState.transform.map(pathResources[cdata]);
809
                }
810
        }
811
        if (dpg.tagName() == "Glyphs")
812
        {
813
                if (dpg.hasChildNodes())
814
                {
22723 jghali 815
                        for (QDomNode sp = dpg.firstChild(); !sp.isNull(); sp = sp.nextSibling())
18598 fschmid 816
                        {
817
                                QDomElement spe = sp.toElement();
818
                                if (spe.tagName() == "Glyphs.Fill")
819
                                        parseFillXML(spe, path, obState);
820
                                else if (spe.tagName() == "Glyphs.OpacityMask")
821
                                        parseOpacityXML(spe, path, obState);
822
                                else if (spe.tagName() == "Glyphs.Clip")
823
                                        parsePathDataXML(spe, obState, true);
824
                        }
825
                }
826
                QString utfString = dpg.attribute("UnicodeString");
827
                if (utfString.startsWith("{}"))
828
                        utfString = utfString.mid(2);
829
                QString Indices = dpg.attribute("Indices");
830
                QString tstStr = utfString.trimmed();
831
                if (tstStr.isEmpty() && Indices.isEmpty())
832
                        return retObj;
833
                QString fontUrl = dpg.attribute("FontUri");
834
                if (fontUrl.startsWith("/"))
835
                {
836
                        fontUrl = fontUrl.mid(1);
837
                }
838
                else
839
                {
840
                        if (!fontUrl.startsWith(path))
18603 fschmid 841
                        {
18598 fschmid 842
                                fontUrl = path + "/" + fontUrl;
18603 fschmid 843
                                fontUrl = QDir::cleanPath(fontUrl);
844
                        }
18598 fschmid 845
                }
846
                ScFace iteFont = loadFontByName(fontUrl);
847
                if (iteFont.usable())
848
                {
849
                        double fontSize = dpg.attribute("FontRenderingEmSize", "0").toDouble() * conversionFactor;
850
                        bool bold = false;
851
                        bool italic = false;
852
                        if (dpg.hasAttribute("StyleSimulations"))
853
                        {
854
                                bold = dpg.attribute("StyleSimulations") == "BoldSimulation";
855
                                italic = dpg.attribute("StyleSimulations") == "ItalicSimulation";
856
                                if (dpg.attribute("StyleSimulations") == "BoldItalicSimulation")
857
                                {
858
                                        bold = true;
859
                                        italic = true;
860
                                }
861
                        }
862
                        double fontSizeEM = fontSize;
863
                        if (fontSize > 1)
864
                        {
865
                                double xPos = dpg.attribute("OriginX", "0").toDouble() * conversionFactor;
866
                                double yPos = dpg.attribute("OriginY", "0").toDouble() * conversionFactor;
867
                                QPointF origin(xPos, yPos);
868
                                QStringList glIndices = Indices.split(";");
869
                                double asc = iteFont.ascent() - iteFont.descent();
870
                                fontSize /= asc;
871
                                int glInd = 0;
872
                                if (!utfString.isEmpty())
873
                                {
21563 jghali 874
                                        QVector<uint> ucs4 = utfString.toUcs4();
875
                                        // FIXME HOST: this code does not do any text layout!
876
                                        for (int sti = 0; sti < ucs4.length(); sti++)
18598 fschmid 877
                                        {
21563 jghali 878
                                                uint chr = ucs4[sti];
879
                                                QString utfChar = QString::fromUcs4(&chr, 1);
880
                                                uint gl = iteFont.char2CMap(chr);
881
                                                if (gl != 0)
18598 fschmid 882
                                                {
883
                                                        double adv = iteFont.glyphWidth(gl, fontSize);
884
                                                        double offX = 0;
885
                                                        double offY = 0;
886
                                                        FPointArray pts;
887
                                                        if (Indices.isEmpty())
888
                                                        {
21563 jghali 889
                                                                if (!QChar::isSpace(chr))
18598 fschmid 890
                                                                        pts = iteFont.glyphOutline(gl, fontSize);
891
                                                        }
892
                                                        else
893
                                                        {
894
                                                                if (glInd < glIndices.count())
895
                                                                {
896
                                                                        QStringList glyInd = glIndices[glInd].split(",");
897
                                                                        if (glyInd.count() > 1)
898
                                                                        {
899
                                                                                if (glyInd.count() > 2)
900
                                                                                        offX = glyInd[2].toDouble() * fontSizeEM / 100.0;
901
                                                                                if (glyInd.count() > 3)
902
                                                                                        offY = glyInd[3].toDouble() * fontSizeEM / 100.0;
903
                                                                                if (!glyInd[1].isEmpty())
904
                                                                                        adv = glyInd[1].toDouble() * fontSizeEM / 100.0;
905
                                                                        }
906
                                                                        if (glyInd.count() > 0)
907
                                                                        {
908
                                                                                if (!glyInd[0].isEmpty())
909
                                                                                {
910
                                                                                        if (glyInd[0].startsWith("("))
911
                                                                                        {
912
                                                                                                int r = glyInd[0].indexOf(")");
913
                                                                                                QString comb = glyInd[0].mid(1, r-1);
914
                                                                                                QStringList combInd = comb.split(":");
915
                                                                                                int advUtf = combInd[0].toInt() - 1;
916
                                                                                                sti += advUtf;
917
                                                                                                glyInd[0].remove(0, r+1);
918
                                                                                        }
919
                                                                                        uint gli = glyInd[0].toUInt();
920
                                                                                        pts = iteFont.glyphOutline(gli, fontSize);
921
                                                                                        if (((glyInd.count() > 1) && (glyInd[1].isEmpty())) || (glyInd.count() == 1))
922
                                                                                                adv = iteFont.glyphWidth(gli, fontSize);
923
                                                                                }
21563 jghali 924
                                                                                else if (!QChar::isSpace(chr))
18598 fschmid 925
                                                                                        pts = iteFont.glyphOutline(gl, fontSize);
926
                                                                        }
927
                                                                }
928
                                                        }
929
                                                        if (pts.count() > 3)
930
                                                        {
931
                                                                QTransform cht;
932
                                                                cht.scale(0.1, 0.1);
933
                                                                pts.map(cht);
934
                                                                pts.translate(0, -fontSize);
935
                                                                if (bold)
936
                                                                {
937
                                                                        QTransform bot;
938
                                                                        bot.scale(1.02, 1.02);
939
                                                                        pts.map(bot);
940
                                                                        adv *= 1.02;
941
                                                                }
942
                                                                if (italic)
943
                                                                {
944
                                                                        QTransform bot;
945
                                                                        bot.shear(-0.3491, 0);
946
                                                                        pts.map(bot);
947
                                                                }
948
                                                                pts.translate(origin.x() + offX, origin.y() + offY);
949
                                                                obState.currentPath.addPath(pts.toQPainterPath(true));
950
                                                        }
951
                                                        origin += QPointF(adv, 0);
952
                                                }
953
                                                else
954
                                                {
955
                                                        QFont eFont(iteFont.family());
956
                                                        eFont.setPointSizeF(fontSize);
957
                                                        eFont.setBold(bold);
958
                                                        eFont.setItalic(italic);
959
                                                        QFontMetricsF ft(eFont);
960
                                                        obState.currentPath.addText(origin, eFont, utfChar);
24545 craig 961
                                                        origin += QPointF(ft.horizontalAdvance(utfChar), 0);
18598 fschmid 962
                                                }
963
                                                glInd++;
964
                                        }
965
                                }
966
                                else if (!Indices.isEmpty())
967
                                {
968
                                        double adv = 0;
969
                                        double offX = 0;
970
                                        double offY = 0;
971
                                        for (int glInd = 0; glInd < glIndices.count(); glInd++)
972
                                        {
973
                                                FPointArray pts;
974
                                                QStringList glyInd = glIndices[glInd].split(",");
975
                                                if (glyInd.count() > 1)
976
                                                {
977
                                                        if (glyInd.count() > 2)
978
                                                                offX = glyInd[2].toDouble() * fontSizeEM / 100.0;
979
                                                        if (glyInd.count() > 3)
980
                                                                offY = glyInd[3].toDouble() * fontSizeEM / 100.0;
981
                                                        if (!glyInd[1].isEmpty())
982
                                                                adv = glyInd[1].toDouble() * fontSizeEM / 100.0;
983
                                                }
984
                                                if (glyInd.count() > 0)
985
                                                {
986
                                                        if (!glyInd[0].isEmpty())
987
                                                        {
988
                                                                if (glyInd[0].startsWith("("))
989
                                                                {
990
                                                                        int r = glyInd[0].indexOf(")");
991
                                                                        QString comb = glyInd[0].mid(1, r-1);
992
                                                                        QStringList combInd = comb.split(":");
993
                                                                        int advUtf = combInd[0].toInt() - 1;
994
                                                                        glInd += advUtf;
995
                                                                        glyInd[0].remove(0, r+1);
996
                                                                }
997
                                                                uint gli = glyInd[0].toUInt();
998
                                                                pts = iteFont.glyphOutline(gli, fontSize);
999
                                                                if (((glyInd.count() > 1) && (glyInd[1].isEmpty())) || (glyInd.count() == 1))
1000
                                                                        adv = iteFont.glyphWidth(gli, fontSize);
1001
                                                        }
1002
                                                }
1003
                                                if (pts.count() > 3)
1004
                                                {
1005
                                                        QTransform cht;
1006
                                                        cht.scale(0.1, 0.1);
1007
                                                        pts.map(cht);
1008
                                                        pts.translate(0, -fontSize);
1009
                                                        if (bold)
1010
                                                        {
1011
                                                                QTransform bot;
1012
                                                                bot.scale(1.02, 1.02);
1013
                                                                pts.map(bot);
1014
                                                                adv *= 1.02;
1015
                                                        }
1016
                                                        if (italic)
1017
                                                        {
1018
                                                                QTransform bot;
1019
                                                                bot.shear(-0.3491, 0);
1020
                                                                pts.map(bot);
1021
                                                        }
1022
                                                        pts.translate(origin.x() + offX, origin.y() + offY);
1023
                                                        obState.currentPath.addPath(pts.toQPainterPath(true));
1024
                                                }
1025
                                                origin += QPointF(adv, 0);
1026
                                        }
1027
                                }
1028
                                if (!obState.currentPath.isEmpty())
1029
                                {
1030
                                        obState.currentPath = obState.transform.map(obState.currentPath);
1031
                                        retObj = createItem(dpg, obState);
1032
                                        if (!obState.clipPath.isEmpty())
1033
                                                retObj = addClip(retObj, obState);
1034
                                }
1035
                        }
1036
                }
1037
        }
1038
        else if (dpg.tagName() == "Path")
1039
        {
1040
                bool pathFromChild = false;
1041
                if (dpg.hasChildNodes())
1042
                {
22723 jghali 1043
                        for (QDomNode sp = dpg.firstChild(); !sp.isNull(); sp = sp.nextSibling())
18598 fschmid 1044
                        {
1045
                                QDomElement spe = sp.toElement();
1046
                                if (spe.tagName() == "Path.Fill")
1047
                                        parseFillXML(spe, path, obState);
1048
                                else if (spe.tagName() == "Path.OpacityMask")
1049
                                        parseOpacityXML(spe, path, obState);
1050
                                else if (spe.tagName() == "Path.Stroke")
1051
                                        parseStrokeXML(spe, path, obState);
1052
                                else if (spe.tagName() == "Path.RenderTransform")
1053
                                {
22723 jghali 1054
                                        for (QDomNode obg = spe.firstChild(); !obg.isNull(); obg = obg.nextSibling())
18598 fschmid 1055
                                        {
1056
                                                QDomElement eog = obg.toElement();
1057
                                                if (eog.tagName() == "MatrixTransform")
1058
                                                {
1059
                                                        QString trans = eog.attribute("Matrix", "1 0 0 1 0 0");
1060
                                                        trans.replace(",", " ");
1061
                                                        ScTextStream list(&trans, QIODevice::ReadOnly);
1062
                                                        double a, b, c, d, e, f;
1063
                                                        list >> a >> b >> c >> d >> e >> f;
1064
                                                        obState.transform = QTransform(a, b, c, d, e * conversionFactor, f * conversionFactor);
1065
                                                }
1066
                                        }
1067
                                }
1068
                                else if (spe.tagName() == "Path.Data")
1069
                                {
1070
                                        parsePathDataXML(spe, obState);
1071
                                        pathFromChild = true;
1072
                                }
1073
                                else if (spe.tagName() == "Path.Clip")
1074
                                        parsePathDataXML(spe, obState, true);
1075
                        }
1076
                }
1077
                if (!pathFromChild)
1078
                {
1079
                        QString pdata = dpg.attribute("Data");
1080
                        if (!pdata.startsWith("{"))
1081
                        {
1082
                                Coords.resize(0);
1083
                                Coords.svgInit();
1084
                                obState.currentPathClosed = Coords.parseSVG(pdata);
1085
                                Coords.scale(conversionFactor, conversionFactor);
1086
                                obState.currentPath = Coords.toQPainterPath(!obState.currentPathClosed);
1087
                                if (obState.currentPath.isEmpty())
1088
                                        return retObj;
1089
                                obState.currentPath = obState.transform.map(obState.currentPath);
1090
                        }
1091
                        else
1092
                        {
1093
                                pdata.remove("{StaticResource ");
1094
                                pdata.remove("}");
1095
                                pdata = pdata.trimmed();
1096
                                if (pathResources.contains(pdata))
1097
                                        obState.currentPath = obState.transform.map(pathResources[pdata]);
1098
                                if (obState.currentPath.isEmpty())
1099
                                        return retObj;
1100
                        }
1101
                }
1102
                if (obState.currentPath.isEmpty())
1103
                        return retObj;
1104
                retObj = createItem(dpg, obState);
1105
                if (!obState.clipPath.isEmpty())
1106
                        retObj = addClip(retObj, obState);
1107
        }
1108
        else if (dpg.tagName() == "Canvas")
1109
        {
1110
                QList<PageItem*> GElements;
22723 jghali 1111
                for (QDomNode sp = dpg.firstChild(); !sp.isNull(); sp = sp.nextSibling())
18598 fschmid 1112
                {
1113
                        QDomElement spe = sp.toElement();
18609 fschmid 1114
                        if (spe.tagName() == "Canvas.RenderTransform")
18598 fschmid 1115
                        {
22723 jghali 1116
                                for (QDomNode obg = spe.firstChild(); !obg.isNull(); obg = obg.nextSibling())
18598 fschmid 1117
                                {
1118
                                        QDomElement eog = obg.toElement();
1119
                                        if (eog.tagName() == "MatrixTransform")
1120
                                        {
1121
                                                QString trans = eog.attribute("Matrix", "1 0 0 1 0 0");
1122
                                                trans.replace(",", " ");
1123
                                                ScTextStream list(&trans, QIODevice::ReadOnly);
1124
                                                double a, b, c, d, e, f;
1125
                                                list >> a >> b >> c >> d >> e >> f;
1126
                                                obState.transform = QTransform(a, b, c, d, e * conversionFactor, f * conversionFactor);
1127
                                        }
1128
                                }
1129
                        }
18609 fschmid 1130
                        else if ((spe.tagName() == "Path") || (spe.tagName() == "Glyphs") || (spe.tagName() == "Canvas"))
1131
                        {
1132
                                PageItem* ite = parseObjectXML(spe, path);
22527 craig 1133
                                if (ite != nullptr)
18609 fschmid 1134
                                        GElements.append(ite);
1135
                        }
18598 fschmid 1136
                        else if (spe.tagName() == "Canvas.OpacityMask")
1137
                                parseOpacityXML(spe, path, obState);
1138
                        else if (spe.tagName() == "Canvas.Resources")
1139
                        {
22723 jghali 1140
                                for (QDomNode obg = spe.firstChild(); !obg.isNull(); obg = obg.nextSibling())
18598 fschmid 1141
                                {
1142
                                        QDomElement eog = obg.toElement();
1143
                                        if (eog.tagName() == "ResourceDictionary")
1144
                                        {
1145
                                                if (eog.hasAttribute("Source"))
1146
                                                {
1147
                                                        QString resFile = eog.attribute("Source", "");
1148
                                                        if (resFile.startsWith("/"))
1149
                                                        {
1150
                                                                resFile = resFile.mid(1);
1151
                                                                parseResourceFile(resFile);
1152
                                                        }
1153
                                                        else
1154
                                                        {
1155
                                                                if (!resFile.startsWith(path))
18603 fschmid 1156
                                                                {
18598 fschmid 1157
                                                                        resFile = path + "/" + resFile;
18603 fschmid 1158
                                                                        resFile = QDir::cleanPath(resFile);
1159
                                                                }
18598 fschmid 1160
                                                                parseResourceFile(resFile);
1161
                                                        }
1162
                                                }
1163
                                                else if (eog.hasChildNodes())
1164
                                                {
22723 jghali 1165
                                                        for (QDomElement dpgp = eog.firstChildElement(); !dpgp.isNull(); dpgp = dpgp.nextSiblingElement())
18598 fschmid 1166
                                                        {
1167
                                                                if (dpgp.tagName() == "PathGeometry")
1168
                                                                {
1169
                                                                        Coords.resize(0);
1170
                                                                        Coords.svgInit();
1171
                                                                        QString pdata = "";
1172
                                                                        QString key = dpg.attribute("x:Key");
1173
                                                                        if (dpg.hasAttribute("Figures"))
1174
                                                                                pdata = dpg.attribute("Figures");
1175
                                                                        else if (dpg.hasChildNodes())
1176
                                                                                pdata = parsePathGeometryXML(dpg);
1177
                                                                        if (!pdata.isEmpty())
1178
                                                                        {
1179
                                                                                bool currentPathClosed = Coords.parseSVG(pdata);
1180
                                                                                Coords.scale(conversionFactor, conversionFactor);
1181
                                                                                QPainterPath path = Coords.toQPainterPath(!currentPathClosed);
1182
                                                                                if (dpg.attribute("FillRule") == "NonZero")
1183
                                                                                        path.setFillRule(Qt::WindingFill);
1184
                                                                                pathResources.insert(key, path);
1185
                                                                        }
1186
                                                                }
1187
                                                        }
1188
                                                }
1189
                                        }
1190
                                }
1191
                        }
1192
                        else if (spe.tagName() == "Canvas.Clip")
1193
                                parsePathDataXML(spe, obState, true);
1194
                }
1195
                if (GElements.count() > 0)
1196
                {
1197
                        double minx =  std::numeric_limits<double>::max();
1198
                        double miny =  std::numeric_limits<double>::max();
1199
                        double maxx = -std::numeric_limits<double>::max();
1200
                        double maxy = -std::numeric_limits<double>::max();
1201
                        for (int ep = 0; ep < GElements.count(); ++ep)
1202
                        {
1203
                                PageItem* currItem = GElements.at(ep);
1204
                                double x1, x2, y1, y2;
1205
                                currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
1206
                                minx = qMin(minx, x1);
1207
                                miny = qMin(miny, y1);
1208
                                maxx = qMax(maxx, x2);
1209
                                maxy = qMax(maxy, y2);
1210
                        }
18662 fschmid 1211
                        double gx = minx;
1212
                        double gy = miny;
1213
                        double gw = maxx - minx;
1214
                        double gh = maxy - miny;
20561 jghali 1215
                        int z = m_Doc->itemAdd(PageItem::Group, PageItem::Rectangle, gx, gy, gw, gh, 0, CommonStrings::None, CommonStrings::None);
18598 fschmid 1216
                        if (z >= 0)
1217
                        {
1218
                                retObj = m_Doc->Items->at(z);
1219
                                retObj->ClipEdited = true;
1220
                                retObj->FrameType = 3;
1221
                                retObj->setFillEvenOdd(false);
1222
                                retObj->OldB2 = retObj->width();
1223
                                retObj->OldH2 = retObj->height();
1224
                                retObj->updateClip();
1225
                                m_Doc->groupObjectsToItem(retObj, GElements);
18647 fschmid 1226
                                double scX = 1.0;
1227
                                double scY = 1.0;
1228
                                double rot = 0.0;
1229
                                double dx = 0.0;
1230
                                double dy = 0.0;
1231
                                getTransformValuesFromMatrix( obState.transform, scX, scY, rot, dx, dy);
18662 fschmid 1232
                                QLineF transp = QLineF(0, 0, retObj->xPos() - m_Doc->currentPage()->xOffset(), retObj->yPos() - m_Doc->currentPage()->yOffset());
1233
                                transp = obState.transform.map(transp);
1234
                                retObj->setXYPos(transp.p2().x() + m_Doc->currentPage()->xOffset(), transp.p2().y() + m_Doc->currentPage()->yOffset());
18647 fschmid 1235
                                if ((scX != 1.0) || (scY != 1.0))
1236
                                        retObj->PoLine.scale(scX, scY);
18609 fschmid 1237
                                FPoint wh = getMaxClipF(&retObj->PoLine);
1238
                                retObj->setWidthHeight(wh.x(),wh.y());
20694 craig 1239
                                m_Doc->adjustItemSize(retObj, true);
18609 fschmid 1240
                                retObj->OldB2 = retObj->width();
1241
                                retObj->OldH2 = retObj->height();
18598 fschmid 1242
                                if (obState.maskTyp != 0)
1243
                                {
1244
                                        double xp = retObj->xPos() - m_Doc->currentPage()->xOffset();
1245
                                        double yp = retObj->yPos() - m_Doc->currentPage()->yOffset();
1246
                                        retObj->setMaskGradient(obState.gradientMask);
1247
                                        retObj->setMaskVector(obState.maskStart.x() - xp, obState.maskStart.y() - yp, obState.maskEnd.x() - xp, obState.maskEnd.y() - yp, obState.maskFocus.x() - xp, obState.maskFocus.y() - yp, obState.maskScale, 0);
1248
                                        retObj->setMaskType(obState.maskTyp);
1249
                                }
18647 fschmid 1250
                                if (rot != 0)
1251
                                        retObj->setRotation(-rot, true);
18598 fschmid 1252
                                retObj->OwnPage = m_Doc->OnPage(retObj);
1253
                                m_Doc->GroupOnPage(retObj);
1254
                                m_Doc->Items->removeLast();
1255
                                if (!obState.clipPath.isEmpty())
1256
                                        retObj = addClip(retObj, obState);
1257
                        }
1258
                }
1259
        }
22527 craig 1260
        if (retObj != nullptr)
18598 fschmid 1261
        {
1262
                if (!itemName.isEmpty())
1263
                {
1264
                        linkTargets.insert(itemName, retObj);
1265
                        retObj->setItemName(itemName);
1266
                }
1267
                if ((!itemTarget.isEmpty()) && (dpg.tagName() != "Canvas"))
1268
                {
1269
                        linkSources.insert(retObj, itemTarget);
1270
                        retObj->setIsAnnotation(true);
1271
                        retObj->annotation().setType(Annotation::Link);
1272
                        retObj->annotation().setZiel(m_Doc->currentPage()->pageNr());
1273
                        retObj->annotation().setAction("0 0");
1274
                        retObj->setTextFlowMode(PageItem::TextFlowDisabled);
1275
                }
1276
        }
1277
        return retObj;
1278
}
1279
 
22635 craig 1280
void XpsPlug::parseOpacityXML(QDomElement &spe, const QString& path, ObjState &obState)
18598 fschmid 1281
{
1282
        ObjState opaState;
1283
        opaState.CurrColorFill = CommonStrings::None;
1284
        opaState.fillOpacity = 0.0;
1285
        opaState.fillGradientTyp = 0;
1286
        opaState.gradientScale = 1.0;
1287
        opaState.imagePath = "";
1288
        opaState.patternName = "";
1289
        parseFillXML(spe, path, opaState);
1290
        if (opaState.fillGradientTyp != 0)
1291
        {
1292
                obState.gradientMask = opaState.currentGradient;
1293
                obState.maskStart = opaState.gradientStart;
1294
                obState.maskEnd = opaState.gradientEnd;
1295
                obState.maskFocus = opaState.gradientFocus;
1296
                obState.maskScale = opaState.gradientScale;
1297
                obState.maskTyp = opaState.fillGradientTyp == 6 ? 1 : 3;
1298
        }
1299
        if (!opaState.patternName.isEmpty())
1300
        {
1301
                obState.patternMask = opaState.patternName;
1302
                obState.maskTyp = 3;
1303
        }
1304
}
1305
 
22635 craig 1306
void XpsPlug::parseStrokeXML(QDomElement &spe, const QString& path, ObjState &obState)
18598 fschmid 1307
{
1308
        ObjState opaState;
1309
        opaState.CurrColorFill = CommonStrings::None;
1310
        opaState.fillOpacity = 0.0;
1311
        opaState.fillGradientTyp = 0;
1312
        opaState.gradientScale = 1.0;
1313
        opaState.imagePath = "";
1314
        opaState.patternName = "";
1315
        parseFillXML(spe, path, opaState);
1316
        if (opaState.fillGradientTyp != 0)
1317
        {
1318
                obState.gradientStroke = opaState.currentGradient;
1319
                obState.strokeStart = opaState.gradientStart;
1320
                obState.strokeEnd = opaState.gradientEnd;
1321
                obState.strokeFocus = opaState.gradientFocus;
1322
                obState.strokeScale = opaState.gradientScale;
1323
                obState.strokeTyp = opaState.fillGradientTyp;
1324
        }
1325
        if (!opaState.patternName.isEmpty())
1326
                obState.patternStroke = opaState.patternName;
1327
}
1328
 
22635 craig 1329
void XpsPlug::parseFillXML(QDomElement &spe, const QString& path, ObjState &obState)
18598 fschmid 1330
{
22723 jghali 1331
        for (QDomNode obg = spe.firstChild(); !obg.isNull(); obg = obg.nextSibling())
18598 fschmid 1332
        {
1333
                QDomElement eog = obg.toElement();
1334
                if (eog.tagName() == "SolidColorBrush")
1335
                        obState.CurrColorFill = handleColor(eog.attribute("Color", "#FF000000"), obState.fillOpacity);
1336
                else if (eog.tagName() == "ImageBrush")
1337
                {
1338
                        obState.imagePath = eog.attribute("ImageSource", "");
1339
                        if (obState.imagePath.startsWith("/"))
1340
                        {
1341
                                obState.imagePath = obState.imagePath.mid(1);
1342
                        }
1343
                        else
1344
                        {
1345
                                if (!obState.imagePath.startsWith(path))
18603 fschmid 1346
                                {
18598 fschmid 1347
                                        obState.imagePath = path + "/" + obState.imagePath;
18603 fschmid 1348
                                        obState.imagePath = QDir::cleanPath(obState.imagePath);
1349
                                }
18598 fschmid 1350
                        }
1351
                        if (eog.hasAttribute("Opacity"))
1352
                        {
1353
                                double opacity = eog.attribute("Opacity", "1.0").toDouble();
1354
                                obState.fillOpacity = 1.0 - ((1.0 - obState.fillOpacity) * opacity);
1355
                                obState.strokeOpacity = 1.0 - ((1.0 - obState.strokeOpacity) * opacity);
1356
                        }
1357
                        obState.itemType = 1;
1358
                }
1359
                else if (eog.tagName() == "LinearGradientBrush")
1360
                {
1361
                        obState.currentGradient = VGradient(VGradient::linear);
1362
                        obState.currentGradient.clearStops();
1363
                        double gen_opacity = 1.0;
1364
                        if (eog.hasAttribute("Opacity"))
1365
                                gen_opacity = eog.attribute("Opacity", "1.0").toDouble();
22723 jghali 1366
                        for (QDomNode gr = eog.firstChild(); !gr.isNull(); gr = gr.nextSibling())
18598 fschmid 1367
                        {
1368
                                QDomElement grs = gr.toElement();
1369
                                if (grs.tagName() == "LinearGradientBrush.GradientStops")
1370
                                {
22723 jghali 1371
                                        for (QDomNode spo = grs.firstChild(); !spo.isNull(); spo = spo.nextSibling())
18598 fschmid 1372
                                        {
1373
                                                QDomElement eo = spo.toElement();
1374
                                                if (eo.tagName() == "GradientStop")
1375
                                                {
1376
                                                        double opacity = 1.0;
1377
                                                        QString stopName = handleColor(eo.attribute("Color", "#FF000000"), opacity);
1378
                                                        double stopOffset = eo.attribute("Offset", "0.0").toDouble();
1379
                                                        const ScColor& gradC = m_Doc->PageColors[stopName];
1380
                                                        obState.currentGradient.addStop(ScColorEngine::getRGBColor(gradC, m_Doc), stopOffset, 0.5, 1.0 - (opacity * gen_opacity), stopName, 100);
1381
                                                }
1382
                                        }
1383
                                }
1384
                        }
1385
                        QString vectS = eog.attribute("StartPoint", "0,0");
1386
                        vectS.replace(",", " ");
1387
                        ScTextStream list(&vectS, QIODevice::ReadOnly);
1388
                        double x, y;
1389
                        list >> x >> y;
1390
                        obState.gradientStart = QPointF(x * conversionFactor, y * conversionFactor);
1391
                        obState.gradientFocus = obState.gradientStart;
1392
                        QString vectE = eog.attribute("EndPoint", "0,0");
1393
                        vectE.replace(",", " ");
1394
                        ScTextStream listE(&vectE, QIODevice::ReadOnly);
1395
                        double x2, y2;
1396
                        listE >> x2 >> y2;
1397
                        obState.gradientEnd = QPointF(x2 * conversionFactor, y2 * conversionFactor);
1398
                        obState.gradientScale = 1.0;
1399
                        obState.fillGradientTyp = 6;
1400
                }
1401
                else if (eog.tagName() == "RadialGradientBrush")
1402
                {
1403
                        obState.currentGradient = VGradient(VGradient::radial);
1404
                        obState.currentGradient.clearStops();
1405
                        double gen_opacity = 1.0;
1406
                        if (eog.hasAttribute("Opacity"))
1407
                                gen_opacity = eog.attribute("Opacity", "1.0").toDouble();
22723 jghali 1408
                        for (QDomElement grs = eog.firstChildElement(); !grs.isNull(); grs = grs.nextSiblingElement())
18598 fschmid 1409
                        {
1410
                                if (grs.tagName() == "RadialGradientBrush.GradientStops")
1411
                                {
22723 jghali 1412
                                        for (QDomElement eo = grs.firstChildElement(); !eo.isNull(); eo = eo.nextSiblingElement())
18598 fschmid 1413
                                        {
1414
                                                if (eo.tagName() == "GradientStop")
1415
                                                {
1416
                                                        double opacity = 1.0;
1417
                                                        QString stopName = handleColor(eo.attribute("Color", "#FF000000"), opacity);
1418
                                                        double stopOffset = eo.attribute("Offset", "0.0").toDouble();
1419
                                                        const ScColor& gradC = m_Doc->PageColors[stopName];
1420
                                                        obState.currentGradient.addStop(ScColorEngine::getRGBColor(gradC, m_Doc), stopOffset, 0.5, 1.0 - (opacity * gen_opacity), stopName, 100);
1421
                                                }
1422
                                        }
1423
                                }
1424
                        }
1425
                        QString vectS = eog.attribute("Center", "0,0");
1426
                        vectS.replace(",", " ");
1427
                        ScTextStream list(&vectS, QIODevice::ReadOnly);
1428
                        double x, y;
1429
                        list >> x >> y;
1430
                        obState.gradientStart = QPointF(x * conversionFactor, y * conversionFactor);
1431
                        QString vectE = eog.attribute("GradientOrigin", "0,0");
1432
                        vectE.replace(",", " ");
1433
                        ScTextStream listE(&vectE, QIODevice::ReadOnly);
1434
                        double x2, y2;
1435
                        listE >> x2 >> y2;
1436
                        obState.gradientFocus = QPointF(x2 * conversionFactor, y2 * conversionFactor);
1437
                        double rx = eog.attribute("RadiusX", "1").toDouble() * conversionFactor;
1438
                        double ry = eog.attribute("RadiusY", "1").toDouble() * conversionFactor;
1439
                        obState.gradientEnd = QPointF(obState.gradientStart.x() + rx, obState.gradientStart.y());
1440
                        obState.gradientScale = rx / ry;
1441
                        obState.fillGradientTyp = 7;
1442
                }
1443
                else if (eog.tagName() == "VisualBrush")
1444
                {
1445
                        QString viewb = eog.attribute("Viewbox", "0,0,1,1");
1446
                        viewb.replace(",", " ");
1447
                        ScTextStream listb(&viewb, QIODevice::ReadOnly);
1448
                        double Viewbox_x1, Viewbox_y1, Viewbox_x2, Viewbox_y2;
1449
                        listb >> Viewbox_x1 >> Viewbox_y1 >> Viewbox_x2 >> Viewbox_y2;
1450
                        QString vectE = eog.attribute("Viewport", "0,0,1,1");
1451
                        vectE.replace(",", " ");
1452
                        ScTextStream listE(&vectE, QIODevice::ReadOnly);
1453
                        double Viewport_x1, Viewport_y1, Viewport_x2, Viewport_y2;
1454
                        listE >> Viewport_x1 >> Viewport_y1 >> Viewport_x2 >> Viewport_y2;
1455
                        double vw = (Viewport_x2 * conversionFactor) / (Viewbox_x2 - Viewbox_x1);
1456
                        double vh = (Viewport_y2 * conversionFactor) / (Viewbox_y2 - Viewbox_y1);
22723 jghali 1457
                        for (QDomElement grs = eog.firstChildElement(); !grs.isNull(); grs = grs.nextSiblingElement())
18598 fschmid 1458
                        {
22727 jghali 1459
                                if (grs.tagName() != "VisualBrush.Visual")
1460
                                        continue;
1461
                                for (QDomElement eo = grs.firstChildElement(); !eo.isNull(); eo = eo.nextSiblingElement())
18598 fschmid 1462
                                {
22727 jghali 1463
                                        if ((eo.tagName() != "Path") && (eo.tagName() != "Glyphs") && (eo.tagName() != "Canvas"))
1464
                                                continue;
1465
                                        PageItem* item = parseObjectXML(eo, path);
1466
                                        if (!item)
1467
                                                continue;
1468
                                        m_Doc->sizeItem((item->width() / conversionFactor) * vw, (item->height() / conversionFactor) * vh, item, false, true, false);
24744 jghali 1469
                                        ScPattern pat(m_Doc);
22727 jghali 1470
                                        m_Doc->DoDrawing = true;
1471
                                        QImage tmpImg = item->DrawObj_toImage(qMin(qMax(item->width(), item->height()), 500.0));
1472
                                        if (tmpImg.isNull())
1473
                                                continue;
1474
                                        QImage retImg = QImage(qRound(Viewport_x2 * conversionFactor), qRound(Viewport_y2 * conversionFactor), QImage::Format_ARGB32_Premultiplied);
1475
                                        retImg.fill( qRgba(0, 0, 0, 0) );
1476
                                        QPainter p;
1477
                                        p.begin(&retImg);
1478
                                        p.drawImage(0, 0, tmpImg);
1479
                                        p.end();
1480
                                        pat.pattern = retImg;
1481
                                        pat.xoffset = 0;
1482
                                        pat.yoffset = 0;
1483
                                        m_Doc->DoDrawing = false;
1484
                                        pat.width = Viewport_x2 * conversionFactor;
1485
                                        pat.height = Viewport_y2 * conversionFactor;
1486
                                        item->gXpos = 0;
1487
                                        item->gYpos = 0;
1488
                                        item->setXYPos(item->gXpos, item->gYpos, true);
1489
                                        pat.items.append(item);
1490
                                        obState.patternName = QString("Pattern_from_XPS_%1").arg(m_Doc->docPatterns.count() + 1);
1491
                                        m_Doc->addPattern(obState.patternName, pat);
1492
                                        importedPatterns.append(obState.patternName);
18598 fschmid 1493
                                }
1494
                        }
1495
                }
1496
        }
1497
}
1498
 
1499
void XpsPlug::parsePathDataXML(QDomElement &spe, ObjState &obState, bool forClip)
1500
{
1501
        Coords.resize(0);
1502
        Coords.svgInit();
1503
        QString svgString = "";
1504
        bool windFill = false;
22723 jghali 1505
        for (QDomElement dpgp = spe.firstChildElement(); !dpgp.isNull(); dpgp = dpgp.nextSiblingElement())
18598 fschmid 1506
        {
1507
                if (dpgp.tagName() == "PathGeometry")
1508
                        svgString += parsePathGeometryXML(dpgp);
1509
                if (dpgp.attribute("FillRule") == "NonZero")
1510
                        windFill = true;
1511
        }
1512
        bool currentPathClosed = Coords.parseSVG(svgString);
1513
        Coords.scale(conversionFactor, conversionFactor);
1514
        if (forClip)
1515
        {
1516
                obState.clipPath = Coords.toQPainterPath(!currentPathClosed);
1517
                if (windFill)
1518
                        obState.clipPath.setFillRule(Qt::WindingFill);
1519
        }
1520
        else
1521
        {
1522
                obState.currentPathClosed = currentPathClosed;
1523
                obState.currentPath = Coords.toQPainterPath(!obState.currentPathClosed);
1524
                if (windFill)
1525
                        obState.currentPath.setFillRule(Qt::WindingFill);
1526
        }
1527
}
1528
 
1529
QString XpsPlug::parsePathGeometryXML(QDomElement &spe)
1530
{
1531
        QString svgString = "";
22723 jghali 1532
        for (QDomElement dpg = spe.firstChildElement(); !dpg.isNull(); dpg = dpg.nextSiblingElement())
18598 fschmid 1533
        {
22727 jghali 1534
                if (dpg.tagName() != "PathFigure")
1535
                        continue;
1536
 
1537
                if (dpg.hasAttribute("StartPoint"))
1538
                        svgString += "M " + dpg.attribute("StartPoint") + " ";
1539
                for (QDomElement dp = dpg.firstChildElement(); !dp.isNull(); dp = dp.nextSiblingElement())
18598 fschmid 1540
                {
22727 jghali 1541
                        if (dp.tagName() == "PolyLineSegment")
1542
                                svgString += "L " + dp.attribute("Points") + " ";
1543
                        else if (dp.tagName() == "PolyQuadraticBezierSegment")
1544
                                svgString += "Q " + dp.attribute("Points") + " ";
1545
                        else if (dp.tagName() == "PolyBezierSegment")
1546
                                svgString += "C " + dp.attribute("Points") + " ";
1547
                        else if (dp.tagName() == "ArcSegment")
18598 fschmid 1548
                        {
22727 jghali 1549
                                svgString += "A " + dp.attribute("Size") + " "  + dp.attribute("RotationAngle") + " ";
1550
                                if (dp.hasAttribute("IsLargeArc"))
18598 fschmid 1551
                                {
22727 jghali 1552
                                        if (dp.attribute("IsLargeArc").toLower() == "true")
1553
                                                svgString += "1 ";
18598 fschmid 1554
                                        else
1555
                                                svgString += "0 ";
22727 jghali 1556
                                }
1557
                                else
1558
                                        svgString += "0 ";
1559
                                if (dp.hasAttribute("SweepDirection"))
1560
                                {
1561
                                        if (dp.attribute("SweepDirection").toLower() == "counterclockwise")
1562
                                                svgString += "0 ";
18598 fschmid 1563
                                        else
22727 jghali 1564
                                                svgString += "1 ";
18598 fschmid 1565
                                }
22727 jghali 1566
                                else
1567
                                        svgString += "0 ";
1568
                                svgString += dp.attribute("Point") + " ";
18598 fschmid 1569
                        }
1570
                }
22727 jghali 1571
                if (dpg.hasAttribute("IsClosed") && (dpg.attribute("IsClosed").toLower() == "true"))
1572
                        svgString += "Z ";
18598 fschmid 1573
        }
1574
        return svgString;
1575
}
1576
 
22635 craig 1577
void XpsPlug::parseResourceFile(const QString& resFile)
18598 fschmid 1578
{
1579
        QByteArray f;
22727 jghali 1580
        if (!uz->read(resFile, f))
1581
                return;
1582
 
1583
        QDomDocument designMapDom;
1584
        if (!designMapDom.setContent(f))
1585
                return;
1586
 
1587
        QDomElement docElem = designMapDom.documentElement();
1588
        for (QDomNode drawPag = docElem.firstChild(); !drawPag.isNull(); drawPag = drawPag.nextSibling())
18598 fschmid 1589
        {
22727 jghali 1590
                QDomElement dpg = drawPag.toElement();
1591
                if (dpg.tagName() != "PathGeometry")
1592
                        continue;
1593
                Coords.resize(0);
1594
                Coords.svgInit();
1595
                QString pdata = "";
1596
                QString key = dpg.attribute("x:Key");
1597
                if (dpg.hasAttribute("Figures"))
1598
                        pdata = dpg.attribute("Figures");
1599
                else if (dpg.hasChildNodes())
1600
                        pdata = parsePathGeometryXML(dpg);
1601
                if (!pdata.isEmpty())
18598 fschmid 1602
                {
22727 jghali 1603
                        bool currentPathClosed = Coords.parseSVG(pdata);
1604
                        Coords.scale(conversionFactor, conversionFactor);
1605
                        QPainterPath path = Coords.toQPainterPath(!currentPathClosed);
1606
                        if (dpg.attribute("FillRule") == "NonZero")
1607
                                path.setFillRule(Qt::WindingFill);
1608
                        pathResources.insert(key, path);
18598 fschmid 1609
                }
1610
        }
1611
}
1612
 
1613
void XpsPlug::resolveLinks()
1614
{
22727 jghali 1615
        if (linkSources.isEmpty())
1616
                return;
1617
 
1618
        for (auto it = linkSources.begin(); it != linkSources.end(); ++it)
18598 fschmid 1619
        {
22727 jghali 1620
                PageItem* linkS = it.key();
1621
                QString target = it.value();
1622
                if (!linkTargets.contains(target))
1623
                        continue;
1624
 
1625
                PageItem* linkT = linkTargets[target];
1626
                if (!linkT)
1627
                        continue;
1628
 
1629
                int op = linkT->OwnPage;
1630
                if (op < 0)
1631
                        continue;
1632
 
1633
                QTransform tf = linkT->getTransform();
1634
                double xp = tf.dx() - m_Doc->Pages->at(op)->xOffset();
1635
                double yp = tf.dy() - m_Doc->Pages->at(op)->yOffset();
1636
                linkS->annotation().setZiel(linkT->OwnPage);
1637
                linkS->annotation().setActionType(2);
1638
                linkS->annotation().setAction(QString("%0 %1").arg(qRound(xp)).arg(qRound(m_Doc->Pages->at(op)->height() - yp)));
18598 fschmid 1639
        }
1640
}
1641
 
1642
PageItem* XpsPlug::addClip(PageItem* retObj, ObjState &obState)
1643
{
22727 jghali 1644
        if (obState.clipPath.isEmpty())
1645
                return retObj;
1646
 
1647
        int z = m_Doc->itemAdd(PageItem::Group, PageItem::Rectangle, baseX, baseY, 10, 10, 0, CommonStrings::None, CommonStrings::None);
1648
        PageItem *itemg = m_Doc->Items->at(z);
1649
        itemg->PoLine.fromQPainterPath(obState.clipPath);
1650
        FPoint wh = getMaxClipF(&itemg->PoLine);
1651
        itemg->setWidthHeight(wh.x(),wh.y());
1652
        m_Doc->adjustItemSize(itemg, true);
1653
        itemg->ClipEdited = true;
1654
        itemg->FrameType = 3;
1655
        itemg->setFillEvenOdd(false);
1656
        itemg->OldB2 = itemg->width();
1657
        itemg->OldH2 = itemg->height();
1658
        itemg->updateClip();
1659
        itemg->OwnPage = m_Doc->OnPage(itemg);
1660
        itemg->ContourLine = itemg->PoLine.copy();
1661
        QList<PageItem*> GElements;
1662
        GElements.append(retObj);
1663
        m_Doc->groupObjectsToItem(itemg, GElements);
1664
        m_Doc->resizeGroupToContents(itemg);
1665
        m_Doc->GroupOnPage(itemg);
1666
        retObj = itemg;
1667
        m_Doc->Items->removeLast();
1668
 
18598 fschmid 1669
        return retObj;
1670
}
1671
 
1672
PageItem* XpsPlug::createItem(QDomElement &dpg, ObjState &obState)
1673
{
1674
        int z = -1;
22527 craig 1675
        PageItem* retObj = nullptr;
22727 jghali 1676
 
1677
        if (obState.currentPath.isEmpty())
1678
                return nullptr;
1679
 
1680
        if (obState.itemType == 0)
18598 fschmid 1681
        {
22727 jghali 1682
                if (dpg.hasAttribute("FixedPage.NavigateUri"))
1683
                        z = m_Doc->itemAdd(PageItem::TextFrame, PageItem::Unspecified, baseX, baseY, 10, 10, obState.LineW, obState.CurrColorFill, CommonStrings::None);
1684
                else
18598 fschmid 1685
                {
22727 jghali 1686
                        if (!obState.currentPathClosed)
1687
                                z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, obState.LineW, obState.CurrColorFill, obState.CurrColorStroke);
18598 fschmid 1688
                        else
22727 jghali 1689
                                z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, 10, 10, obState.LineW, obState.CurrColorFill, obState.CurrColorStroke);
18598 fschmid 1690
                }
22727 jghali 1691
                retObj = m_Doc->Items->at(z);
1692
                finishItem(retObj, obState);
1693
                retObj = m_Doc->Items->takeAt(z);
1694
        }
1695
        else if (obState.itemType == 1)
1696
        {
1697
                z = m_Doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, baseX, baseY, 10, 10, obState.LineW, obState.CurrColorFill, obState.CurrColorStroke);
1698
                retObj = m_Doc->Items->at(z);
1699
                finishItem(retObj, obState);
1700
                if (!obState.imagePath.isEmpty())
18598 fschmid 1701
                {
22727 jghali 1702
                        QByteArray f;
1703
                        if (uz->read(obState.imagePath, f))
18598 fschmid 1704
                        {
22727 jghali 1705
                                QFileInfo fi(obState.imagePath);
1706
                                QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_xps_XXXXXX." + fi.suffix());
1707
                                tempFile->setAutoRemove(false);
1708
                                if (tempFile->open())
18598 fschmid 1709
                                {
22727 jghali 1710
                                        QString fileName = getLongPathName(tempFile->fileName());
1711
                                        if (!fileName.isEmpty())
18598 fschmid 1712
                                        {
22727 jghali 1713
                                                tempFile->write(f);
1714
                                                tempFile->close();
1715
                                                retObj->isInlineImage = true;
1716
                                                retObj->isTempFile = true;
1717
                                                retObj->AspectRatio = false;
1718
                                                retObj->ScaleType   = false;
1719
                                                m_Doc->loadPict(fileName, retObj);
22821 jghali 1720
                                                retObj->adjustPictScale();
18598 fschmid 1721
                                        }
1722
                                }
22727 jghali 1723
                                delete tempFile;
18598 fschmid 1724
                        }
1725
                }
22727 jghali 1726
                retObj = m_Doc->Items->takeAt(z);
18598 fschmid 1727
        }
22727 jghali 1728
 
18598 fschmid 1729
        return retObj;
1730
}
1731
 
1732
void XpsPlug::finishItem(PageItem* item, ObjState &obState)
1733
{
1734
        item->PoLine.fromQPainterPath(obState.currentPath, !obState.currentPathClosed);
1735
        FPoint wh = getMaxClipF(&item->PoLine);
1736
        item->setWidthHeight(wh.x(),wh.y());
20694 craig 1737
        m_Doc->adjustItemSize(item, true);
18598 fschmid 1738
        item->ClipEdited = true;
1739
        item->FrameType = 3;
1740
        item->setFillEvenOdd(false);
1741
        item->OldB2 = item->width();
1742
        item->OldH2 = item->height();
1743
        item->updateClip();
1744
        item->OwnPage = m_Doc->OnPage(item);
1745
        item->ContourLine = item->PoLine.copy();
1746
        item->setFillColor(obState.CurrColorFill);
1747
        item->setFillTransparency(obState.fillOpacity);
1748
        item->setLineColor(obState.CurrColorStroke);
1749
        item->setLineTransparency(obState.strokeOpacity);
1750
        item->setLineWidth(obState.LineW);
1751
        item->setLineEnd(obState.CapStyle);
1752
        item->setLineJoin(obState.JoinStyle);
1753
        double xp = item->xPos() - m_Doc->currentPage()->xOffset();
1754
        double yp = item->yPos() - m_Doc->currentPage()->yOffset();
1755
        if (obState.fillGradientTyp != 0)
1756
        {
1757
                item->fill_gradient = obState.currentGradient;
1758
                item->setGradientVector(obState.gradientStart.x() - xp, obState.gradientStart.y() - yp, obState.gradientEnd.x() - xp, obState.gradientEnd.y() - yp, obState.gradientFocus.x() - xp, obState.gradientFocus.y() - yp, obState.gradientScale, 0);
1759
                item->setGradientType(obState.fillGradientTyp);
1760
        }
1761
        else if (!obState.patternName.isEmpty())
1762
        {
1763
                item->setPattern(obState.patternName);
23904 jghali 1764
                item->GrType = Gradient_Pattern;
18598 fschmid 1765
        }
1766
        if (obState.maskTyp != 0)
1767
        {
1768
                item->setMaskGradient(obState.gradientMask);
1769
                item->setMaskVector(obState.maskStart.x() - xp, obState.maskStart.y() - yp, obState.maskEnd.x() - xp, obState.maskEnd.y() - yp, obState.maskFocus.x() - xp, obState.maskFocus.y() - yp, obState.maskScale, 0);
1770
                item->setMaskType(obState.maskTyp);
1771
        }
1772
        if (!obState.patternMask.isEmpty())
1773
        {
1774
                item->setPatternMask(obState.patternMask);
1775
                item->setMaskType(obState.maskTyp);
1776
        }
1777
        if (obState.strokeTyp != 0)
1778
        {
1779
                item->setStrokeGradient(obState.gradientStroke);
1780
                item->setStrokeGradientVector(obState.strokeStart.x() - xp, obState.strokeStart.y() - yp, obState.strokeEnd.x() - xp, obState.strokeEnd.y() - yp, obState.strokeFocus.x() - xp, obState.strokeFocus.y() - yp, obState.strokeScale, 0);
1781
                item->setStrokeGradientType(obState.strokeTyp);
1782
        }
1783
        if (!obState.patternStroke.isEmpty())
18637 fschmid 1784
        {
23904 jghali 1785
                item->GrTypeStroke = Gradient_Pattern;
18598 fschmid 1786
                item->setStrokePattern(obState.patternStroke);
18637 fschmid 1787
        }
18628 fschmid 1788
        if (!obState.DashPattern.isEmpty())
1789
        {
1790
                item->setDashOffset(obState.DashOffset);
1791
                QVector<double> pattern(obState.DashPattern.count());
1792
                for (int i = 0; i < obState.DashPattern.count(); ++i)
1793
                {
1794
                        pattern[i] = obState.DashPattern[i] * obState.LineW;
1795
                }
1796
                item->setDashes(pattern);
1797
        }
18598 fschmid 1798
}
1799
 
1800
QString XpsPlug::handleColor(QString rgbColor, double &opacity)
1801
{
1802
        QString fNam = CommonStrings::None;
1803
        QString alpha = "FF";
1804
        if (rgbColor.startsWith( "sc#" ))
1805
        {
1806
                QColor c;
1807
                rgbColor = rgbColor.remove(0,3);
1808
                QStringList co = rgbColor.split(",");
1809
                if (co.size() == 3)
1810
                {
1811
                        rgbColor.replace(",", " ");
1812
                        ScTextStream list(&rgbColor, QIODevice::ReadOnly);
1813
                        double r, g, b;
1814
                        list >> r >> g >> b;
1815
                        c.setRgbF(r, g, b);
1816
                }
1817
                else if (co.size() == 4)
1818
                {
1819
                        rgbColor.replace(",", " ");
1820
                        ScTextStream list(&rgbColor, QIODevice::ReadOnly);
1821
                        double r, g, b;
1822
                        list >> opacity >> r >> g >> b;
1823
                        c.setRgbF(r, g, b);
1824
                }
1825
                else
1826
                {
1827
                        opacity = 0;
1828
                        return fNam;
1829
                }
1830
                ScColor tmp;
1831
                tmp.fromQColor(c);
1832
                tmp.setSpotColor(false);
1833
                tmp.setRegistrationColor(false);
1834
                QString newColorName = "FromXPS"+c.name();
1835
                fNam = m_Doc->PageColors.tryAddColor(newColorName, tmp);
1836
                if (fNam == newColorName)
1837
                        importedColors.append(newColorName);
1838
        }
1839
        else if (rgbColor.startsWith( "#" ))
1840
        {
1841
                QColor c;
1842
                if (rgbColor.length() == 9)
1843
                {
1844
                        alpha = rgbColor.mid(1,2);
1845
                        bool ok;
1846
                        int hex = alpha.toInt(&ok, 16);
1847
                        opacity = 1.0 - (hex / 255.0);
1848
                        rgbColor = rgbColor.remove(1,2);
1849
                }
1850
                else
1851
                        opacity = 0;
1852
                c.setNamedColor(rgbColor);
1853
                ScColor tmp;
1854
                tmp.fromQColor(c);
1855
                tmp.setSpotColor(false);
1856
                tmp.setRegistrationColor(false);
1857
                QString newColorName = "FromXPS"+c.name();
1858
                fNam = m_Doc->PageColors.tryAddColor(newColorName, tmp);
1859
                if (fNam == newColorName)
1860
                        importedColors.append(newColorName);
1861
        }
1862
        return fNam;
1863
}
1864
 
1865
int XpsPlug::hex2int(char hex)
1866
{
1867
        QChar hexchar = QLatin1Char(hex);
1868
        int v;
1869
        if (hexchar.isDigit())
1870
                v = hexchar.digitValue();
1871
        else if (hexchar >= QLatin1Char('A') && hexchar <= QLatin1Char('F'))
1872
                v = hexchar.cell() - 'A' + 10;
1873
        else if (hexchar >= QLatin1Char('a') && hexchar <= QLatin1Char('f'))
1874
                v = hexchar.cell() - 'a' + 10;
1875
        else
1876
                v = -1;
1877
        return v;
1878
}
1879
 
1880
bool XpsPlug::parseGUID( const QString &guidString, unsigned short guid[16])
1881
{
1882
        if (guidString.length() <= 35)
1883
                return false;
1884
        // Maps bytes to positions in guidString
1885
        const static int indexes[] = {6, 4, 2, 0, 11, 9, 16, 14, 19, 21, 24, 26, 28, 30, 32, 34};
1886
        for (int i = 0; i < 16; i++)
1887
        {
1888
                int hex1 = hex2int(guidString[indexes[i]].cell());
1889
                int hex2 = hex2int(guidString[indexes[i]+1].cell());
1890
                if ((hex1 < 0) || (hex2 < 0))
1891
                        return false;
1892
                guid[i] = hex1 * 16 + hex2;
1893
        }
1894
        return true;
1895
}
1896
 
1897
 
1898
ScFace XpsPlug::loadFontByName(const QString &fileName)
1899
{
1900
        ScFace t;
1901
        if (loadedFonts.contains(fileName))
1902
                return loadedFonts[fileName];
1903
        QByteArray fontData;
1904
        if (!uz->read(fileName, fontData))
1905
                return t;
1906
        QTemporaryFile *tempImageFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_zip_XXXXXX.dat");
22527 craig 1907
        if (tempImageFile == nullptr)
18598 fschmid 1908
                return t;
1909
        tempImageFile->setAutoRemove(false);
1910
        tempImageFile->open();
1911
        QString fname = getLongPathName(tempImageFile->fileName());
1912
        tempImageFile->close();
1913
        delete tempImageFile;
1914
        tempFontFiles.append(fname);
1915
        QFileInfo fi(fileName);
1916
        QString ext = fi.suffix().toLower();
1917
        if (ext.startsWith("od"))
1918
        {
1919
                const QString baseName = fi.baseName();
1920
                unsigned short guid[16];
1921
                if (!parseGUID(baseName, guid))
1922
                        return t;
22609 craig 1923
                if (fontData.length() < 32)
18598 fschmid 1924
                {
22609 craig 1925
                        qDebug() << "Font file is too small";
1926
                        return t;
18598 fschmid 1927
                }
22609 craig 1928
                // Obfuscation - xor bytes in font binary with bytes from guid (font's filename)
1929
                const static int mapping[] = {15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 4, 5, 0, 1, 2, 3};
1930
                for (int i = 0; i < 16; i++)
1931
                {
1932
                        fontData[i] = fontData[i] ^ guid[mapping[i]];
1933
                        fontData[i+16] = fontData[i+16] ^ guid[mapping[i]];
1934
                }
18598 fschmid 1935
        }
1936
        QFile ft(fname);
1937
        if (ft.open(QIODevice::WriteOnly))
1938
        {
1939
                ft.write(fontData);
1940
                ft.close();
23079 jghali 1941
                t = PrefsManager::instance().appPrefs.fontPrefs.AvailFonts.loadScalableFont(fname);
18598 fschmid 1942
                loadedFonts.insert(fileName, t);
1943
                return t;
1944
        }
1945
        return t;
1946
}