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                : Sun Feb  9 2014
10 	copyright            : (C) 2014 by Franz Schmid
11 	email                : Franz.Schmid@altmuehlnet.de
12  ***************************************************************************/
13 
14 #include <QByteArray>
15 #include <QCursor>
16 #include <QDebug>
17 #include <QDrag>
18 #include <QFile>
19 #include <QList>
20 #include <QMimeData>
21 #include <QRegExp>
22 #include <QStack>
23 #include <QUrl>
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 "importodg.h"
34 
35 #include "fileloader.h"
36 #include "third_party/fparser/fparser.hh"
37 #include "loadsaveplugin.h"
38 #include "pageitem_table.h"
39 #include "pagesize.h"
40 #include "plugins/formatidlist.h"
41 #include "prefscontext.h"
42 #include "prefsfile.h"
43 #include "prefsmanager.h"
44 #include "prefstable.h"
45 #include "rawimage.h"
46 #include "scclocale.h"
47 #include "sccolorengine.h"
48 #include "scconfig.h"
49 #include "scmimedata.h"
50 #include "scpainter.h"
51 #include "scpaths.h"
52 #include "scribusXml.h"
53 #include "scribuscore.h"
54 #include "scribusdoc.h"
55 #include "scribusview.h"
56 #include "sctextstream.h"
57 #include "selection.h"
58 #include "third_party/zip/scribus_zip.h"
59 #include "ui/customfdialog.h"
60 #include "ui/missing.h"
61 #include "ui/multiprogressdialog.h"
62 #include "ui/propertiespalette.h"
63 #include "undomanager.h"
64 #include "util.h"
65 #include "util_file.h"
66 #include "util_formats.h"
67 #include "util_math.h"
68 
OdgPlug(ScribusDoc * doc,int flags)69 OdgPlug::OdgPlug(ScribusDoc* doc, int flags)
70 {
71 	tmpSel = new Selection(this, false);
72 	m_Doc = doc;
73 	importerFlags = flags;
74 	interactive = (flags & LoadSavePlugin::lfInteractive);
75 	progressDialog = nullptr;
76 	uz = nullptr;
77 }
78 
readThumbnail(const QString & fName)79 QImage OdgPlug::readThumbnail(const QString& fName)
80 {
81 	QImage tmp;
82 	if (!QFile::exists(fName))
83 		return QImage();
84 	progressDialog = nullptr;
85 	uz = new ScZipHandler();
86 	if (!uz->open(fName))
87 	{
88 		delete uz;
89 		if (progressDialog)
90 			progressDialog->close();
91 		return QImage();
92 	}
93 	if (uz->contains("Thumbnails/thumbnail.png"))
94 	{
95 		QByteArray im;
96 		if (!uz->read("Thumbnails/thumbnail.png", im))
97 		{
98 			delete uz;
99 			return QImage();
100 		}
101 		tmp = QImage::fromData(im);
102 		int xs = 0;
103 		int ys = 0;
104 	/*	if (uz->contains("index.xml"))
105 		{
106 			if (uz->read("index.xml", f))
107 			{
108 				QDomDocument designMapDom;
109 				QByteArray f;
110 				if (designMapDom.setContent(f))
111 				{
112 					QDomElement docElem = designMapDom.documentElement();
113 					for (QDomElement drawPag = docElem.firstChildElement(); !drawPag.isNull(); drawPag = drawPag.nextSiblingElement())
114 					{
115 						if (drawPag.tagName() == "sl:slprint-info")
116 						{
117 							xs = drawPag.attribute("sl:page-width", "0").toInt();
118 							ys = drawPag.attribute("sl:page-height", "0").toInt();
119 						}
120 					}
121 				}
122 			}
123 		}*/
124 		tmp.setText("XSize", QString("%1").arg(xs));
125 		tmp.setText("YSize", QString("%1").arg(ys));
126 	}
127 	uz->close();
128 	delete uz;
129 	return tmp;
130 }
131 
import(const QString & fNameIn,const TransactionSettings & trSettings,int flags,bool showProgress)132 bool OdgPlug::import(const QString& fNameIn, const TransactionSettings& trSettings, int flags, bool showProgress)
133 {
134 	bool success = false;
135 	interactive = (flags & LoadSavePlugin::lfInteractive);
136 	importerFlags = flags;
137 	cancel = false;
138 	bool ret = false;
139 	firstPage = true;
140 	pagecount = 1;
141 	mpagecount = 0;
142 	QFileInfo fi = QFileInfo(fNameIn);
143 	if ( !ScCore->usingGUI() )
144 	{
145 		interactive = false;
146 		showProgress = false;
147 	}
148 	if ( showProgress )
149 	{
150 		ScribusMainWindow* mw=(m_Doc==nullptr) ? ScCore->primaryMainWindow() : m_Doc->scMW();
151 		progressDialog = new MultiProgressDialog( tr("Importing: %1").arg(fi.fileName()), CommonStrings::tr_Cancel, mw );
152 		QStringList barNames, barTexts;
153 		barNames << "GI";
154 		barTexts << tr("Analyzing File:");
155 		QList<bool> barsNumeric;
156 		barsNumeric << false;
157 		progressDialog->addExtraProgressBars(barNames, barTexts, barsNumeric);
158 		progressDialog->setOverallTotalSteps(3);
159 		progressDialog->setOverallProgress(0);
160 		progressDialog->setProgress("GI", 0);
161 		progressDialog->show();
162 		connect(progressDialog, SIGNAL(canceled()), this, SLOT(cancelRequested()));
163 		qApp->processEvents();
164 	}
165 	else
166 		progressDialog = nullptr;
167 	if (progressDialog)
168 	{
169 		progressDialog->setOverallProgress(1);
170 		qApp->processEvents();
171 	}
172 	/* Set default Page to size defined in Preferences */
173 	docWidth = PrefsManager::instance().appPrefs.docSetupPrefs.pageWidth;
174 	docHeight = PrefsManager::instance().appPrefs.docSetupPrefs.pageHeight;
175 	baseX = 0;
176 	baseY = 0;
177 	if (!interactive || (flags & LoadSavePlugin::lfInsertPage))
178 	{
179 		m_Doc->setPage(docWidth, docHeight, 0, 0, 0, 0, 0, 0, false, false);
180 		m_Doc->addPage(0);
181 		m_Doc->view()->addPage(0, true);
182 		baseX = 0;
183 		baseY = 0;
184 	}
185 	else
186 	{
187 		if (!m_Doc || (flags & LoadSavePlugin::lfCreateDoc))
188 		{
189 			m_Doc=ScCore->primaryMainWindow()->doFileNew(docWidth, docHeight, 0, 0, 0, 0, 0, 0, false, false, 0, false, 0, 1, "Custom", true);
190 			ScCore->primaryMainWindow()->HaveNewDoc();
191 			ret = true;
192 			baseX = 0;
193 			baseY = 0;
194 			baseX = m_Doc->currentPage()->xOffset();
195 			baseY = m_Doc->currentPage()->yOffset() + m_Doc->currentPage()->height() / 2.0;
196 		}
197 	}
198 	if ((!ret) && (interactive))
199 	{
200 		baseX = m_Doc->currentPage()->xOffset();
201 		baseY = m_Doc->currentPage()->yOffset() + m_Doc->currentPage()->height() / 2.0;
202 	}
203 	if ((ret) || (!interactive))
204 	{
205 		if (docWidth > docHeight)
206 			m_Doc->setPageOrientation(1);
207 		else
208 			m_Doc->setPageOrientation(0);
209 		m_Doc->setPageSize("Custom");
210 	}
211 	Elements.clear();
212 	if ((!(flags & LoadSavePlugin::lfLoadAsPattern)) && (m_Doc->view() != nullptr))
213 		m_Doc->view()->deselectItems();
214 	m_Doc->setLoading(true);
215 	m_Doc->DoDrawing = false;
216 	if ((!(flags & LoadSavePlugin::lfLoadAsPattern)) && (m_Doc->view() != nullptr))
217 		m_Doc->view()->updatesOn(false);
218 	m_Doc->scMW()->setScriptRunning(true);
219 	qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
220 	QString CurDirP = QDir::currentPath();
221 	QDir::setCurrent(fi.path());
222 	if (convert(fNameIn))
223 	{
224 		tmpSel->clear();
225 		QDir::setCurrent(CurDirP);
226 		if ((Elements.count() > 1) && (!(importerFlags & LoadSavePlugin::lfCreateDoc)))
227 			m_Doc->groupObjectsList(Elements);
228 		m_Doc->DoDrawing = true;
229 		m_Doc->scMW()->setScriptRunning(false);
230 		m_Doc->setLoading(false);
231 		qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
232 		if ((Elements.count() > 0) && (!ret) && (interactive))
233 		{
234 			if (flags & LoadSavePlugin::lfScripted)
235 			{
236 				bool loadF = m_Doc->isLoading();
237 				m_Doc->setLoading(false);
238 				m_Doc->changed();
239 				m_Doc->setLoading(loadF);
240 				if (!(flags & LoadSavePlugin::lfLoadAsPattern))
241 				{
242 					m_Doc->m_Selection->delaySignalsOn();
243 					for (int dre=0; dre<Elements.count(); ++dre)
244 					{
245 						m_Doc->m_Selection->addItem(Elements.at(dre), true);
246 					}
247 					m_Doc->m_Selection->delaySignalsOff();
248 					m_Doc->m_Selection->setGroupRect();
249 					if (m_Doc->view() != nullptr)
250 						m_Doc->view()->updatesOn(true);
251 				}
252 			}
253 			else
254 			{
255 				m_Doc->DragP = true;
256 				m_Doc->DraggedElem = nullptr;
257 				m_Doc->DragElements.clear();
258 				m_Doc->m_Selection->delaySignalsOn();
259 				for (int dre=0; dre<Elements.count(); ++dre)
260 				{
261 					tmpSel->addItem(Elements.at(dre), true);
262 				}
263 				tmpSel->setGroupRect();
264 				ScElemMimeData* md = ScriXmlDoc::writeToMimeData(m_Doc, tmpSel);
265 				m_Doc->itemSelection_DeleteItem(tmpSel);
266 				m_Doc->view()->updatesOn(true);
267 				if ((importedColors.count() != 0) && (!((flags & LoadSavePlugin::lfKeepGradients) || (flags & LoadSavePlugin::lfKeepColors) || (flags & LoadSavePlugin::lfKeepPatterns))))
268 				{
269 					for (int cd = 0; cd < importedColors.count(); cd++)
270 					{
271 						m_Doc->PageColors.remove(importedColors[cd]);
272 					}
273 				}
274 				if ((importedPatterns.count() != 0) && (!(flags & LoadSavePlugin::lfKeepPatterns)))
275 				{
276 					for (int cd = 0; cd < importedPatterns.count(); cd++)
277 					{
278 						m_Doc->docPatterns.remove(importedPatterns[cd]);
279 					}
280 				}
281 				m_Doc->m_Selection->delaySignalsOff();
282 				// We must copy the TransationSettings object as it is owned
283 				// by handleObjectImport method afterwards
284 				TransactionSettings* transacSettings = new TransactionSettings(trSettings);
285 				m_Doc->view()->handleObjectImport(md, transacSettings);
286 				m_Doc->DragP = false;
287 				m_Doc->DraggedElem = nullptr;
288 				m_Doc->DragElements.clear();
289 			}
290 		}
291 		else
292 		{
293 			m_Doc->changed();
294 			m_Doc->reformPages();
295 			if (!(flags & LoadSavePlugin::lfLoadAsPattern))
296 				m_Doc->view()->updatesOn(true);
297 		}
298 		success = true;
299 	}
300 	else
301 	{
302 		QDir::setCurrent(CurDirP);
303 		m_Doc->DoDrawing = true;
304 		m_Doc->scMW()->setScriptRunning(false);
305 		if (!(flags & LoadSavePlugin::lfLoadAsPattern))
306 			m_Doc->view()->updatesOn(true);
307 		qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
308 		success = false;
309 	}
310 	if (interactive)
311 		m_Doc->setLoading(false);
312 	//CB If we have a gui we must refresh it if we have used the progressbar
313 	if (!(flags & LoadSavePlugin::lfLoadAsPattern))
314 	{
315 		if ((showProgress) && (!interactive))
316 			m_Doc->view()->DrawNew();
317 	}
318 	qApp->restoreOverrideCursor();
319 	return success;
320 }
321 
~OdgPlug()322 OdgPlug::~OdgPlug()
323 {
324 	delete progressDialog;
325 	delete tmpSel;
326 }
327 
convert(const QString & fn)328 bool OdgPlug::convert(const QString& fn)
329 {
330 	bool retVal = true;
331 	importedColors.clear();
332 	importedPatterns.clear();
333 	m_Styles.clear();
334 	m_Layers.clear();
335 	firstLayer = true;
336 	if (progressDialog)
337 	{
338 		progressDialog->setOverallProgress(2);
339 		progressDialog->setLabel("GI", tr("Generating Items"));
340 		qApp->processEvents();
341 	}
342 
343 	QFileInfo fi = QFileInfo(fn);
344 	QString ext = fi.suffix().toLower();
345 	if ((ext == "fodg") || (ext == "fodp"))
346 	{
347 		QByteArray f;
348 		loadRawText(fn, f);
349 		QDomDocument designMapDom;
350 		QString errorMsg = "";
351 		int errorLine = 0;
352 		int errorColumn = 0;
353 		if (!designMapDom.setContent(f, &errorMsg, &errorLine, &errorColumn))
354 		{
355 			qDebug() << "Error loading File" << errorMsg << "at Line" << errorLine << "Column" << errorColumn;
356 			return false;
357 		}
358 		retVal = parseDocReferenceXML(designMapDom);
359 	}
360 	else
361 	{
362 		uz = new ScZipHandler();
363 		if (!uz->open(fn))
364 		{
365 			delete uz;
366 			QByteArray f;
367 			loadRawText(fn, f);
368 			QDomDocument designMapDom;
369 			QString errorMsg = "";
370 			int errorLine = 0;
371 			int errorColumn = 0;
372 			if (designMapDom.setContent(f, &errorMsg, &errorLine, &errorColumn))
373 			{
374 				retVal = parseDocReferenceXML(designMapDom);
375 			}
376 			else
377 			{
378 				qDebug() << "Error loading File" << errorMsg << "at Line" << errorLine << "Column" << errorColumn;
379 				if (progressDialog)
380 					progressDialog->close();
381 				return false;
382 			}
383 		}
384 		else
385 		{
386 			retVal = false;
387 			if (uz->contains("styles.xml"))
388 				retVal = parseStyleSheets("styles.xml");
389 			if (uz->contains("content.xml"))
390 				retVal = parseDocReference("content.xml");
391 			uz->close();
392 			delete uz;
393 		}
394 	}
395 	if (progressDialog)
396 		progressDialog->close();
397 	return retVal;
398 }
399 
parseStyleSheets(const QString & designMap)400 bool OdgPlug::parseStyleSheets(const QString& designMap)
401 {
402 	QByteArray xmlData;
403 	QDomDocument designMapDom;
404 	if (!uz->read(designMap, xmlData))
405 		return false;
406 
407 	QString errorMsg;
408 	int errorLine = 0;
409 	int errorColumn = 0;
410 	if (!designMapDom.setContent(xmlData, false, &errorMsg, &errorLine, &errorColumn))
411 	{
412 		qDebug() << "Error loading File" << errorMsg << "at Line" << errorLine << "Column" << errorColumn;
413 		return false;
414 	}
415 	return parseStyleSheetsXML(designMapDom);
416 }
417 
parseStyleSheetsXML(QDomDocument & designMapDom)418 bool OdgPlug::parseStyleSheetsXML(QDomDocument &designMapDom)
419 {
420 	QDomElement docElem = designMapDom.documentElement();
421 	for (QDomElement sp = docElem.firstChildElement(); !sp.isNull(); sp = sp.nextSiblingElement())
422 	{
423 		if (sp.tagName() == "office:font-face-decls")
424 		{
425 			for (QDomElement spf = sp.firstChildElement(); !spf.isNull(); spf = spf.nextSiblingElement())
426 			{
427 				if (spf.tagName() == "style:font-face")
428 				{
429 					if (!spf.attribute("style:name").isEmpty())
430 						m_fontMap.insert(spf.attribute("style:name"), spf.attribute("svg:font-family"));
431 				}
432 			}
433 		}
434 		else if ((sp.tagName() == "office:styles") || (sp.tagName() == "office:automatic-styles"))
435 			parseStyles(sp);
436 		if (sp.tagName() == "office:master-styles")
437 		{
438 			DrawStyle currStyle;
439 			for (QDomElement spf = sp.firstChildElement(); !spf.isNull(); spf = spf.nextSiblingElement())
440 			{
441 				if (spf.tagName() == "style:master-page")
442 				{
443 					currStyle.page_layout_name = AttributeValue(spf.attribute("style:page-layout-name"));
444 					QString backGroundStyle = spf.attribute("draw:style-name", "");
445 					m_Styles.insert(spf.attribute("style:name"), currStyle);
446 					if (importerFlags & LoadSavePlugin::lfCreateDoc)
447 					{
448 						m_Doc->setMasterPageMode(true);
449 						ScPage *oldCur = m_Doc->currentPage();
450 						ScPage *addedPage = m_Doc->addMasterPage(mpagecount, spf.attribute("style:name"));
451 						m_Doc->setCurrentPage(addedPage);
452 						addedPage->clearMasterPageName();
453 						m_Doc->view()->addPage(mpagecount, true);
454 						baseX = addedPage->xOffset();
455 						baseY = addedPage->yOffset();
456 						mpagecount++;
457 						ObjStyle tmpOStyle;
458 						resovleStyle(tmpOStyle, spf.attribute("style:name"));
459 						m_Doc->currentPage()->setSize("Custom");
460 						m_Doc->currentPage()->setInitialHeight(tmpOStyle.page_height);
461 						m_Doc->currentPage()->setInitialWidth(tmpOStyle.page_width);
462 						m_Doc->currentPage()->setHeight(tmpOStyle.page_height);
463 						m_Doc->currentPage()->setWidth(tmpOStyle.page_width);
464 						m_Doc->currentPage()->initialMargins.setTop(tmpOStyle.margin_top);
465 						m_Doc->currentPage()->initialMargins.setBottom(tmpOStyle.margin_bottom);
466 						m_Doc->currentPage()->initialMargins.setLeft(tmpOStyle.margin_left);
467 						m_Doc->currentPage()->initialMargins.setRight(tmpOStyle.margin_right);
468 						if (!backGroundStyle.isEmpty())
469 						{
470 							ObjStyle tmpBStyle;
471 							resovleStyle(tmpBStyle, backGroundStyle);
472 							int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, baseX, baseY, tmpOStyle.page_width, tmpOStyle.page_height, 0, tmpBStyle.currColorFill, CommonStrings::None);
473 							PageItem *retObj = m_Doc->Items->at(z);
474 							finishItem(retObj, tmpBStyle);
475 						}
476 						for (QDomElement spm = spf.firstChildElement(); !spm.isNull(); spm = spm.nextSiblingElement())
477 						{
478 							PageItem* retObj = parseObj(spm);
479 							if (retObj != nullptr)
480 								m_Doc->Items->append(retObj);
481 						}
482 						m_Doc->setCurrentPage(oldCur);
483 						m_Doc->setMasterPageMode(false);
484 					}
485 				}
486 				else if (spf.tagName() == "draw:layer-set")
487 				{
488 					if (importerFlags & LoadSavePlugin::lfCreateDoc)
489 					{
490 						for (QDomElement spp = spf.firstChildElement(); !spp.isNull(); spp = spp.nextSiblingElement())
491 						{
492 							if (spp.tagName() == "draw:layer")
493 							{
494 								QString layerName = spp.attribute("draw:name");
495 								if (!layerName.isEmpty())
496 								{
497 									if (!firstLayer)
498 									{
499 										QStringList newNames;
500 										m_Doc->orderedLayerList(&newNames);
501 										if (!newNames.contains(layerName))
502 										{
503 											int currentLayer = m_Doc->addLayer(layerName);
504 											m_Layers.insert(layerName, currentLayer);
505 										}
506 									}
507 									else
508 									{
509 										m_Doc->changeLayerName(m_Doc->firstLayerID(), layerName);
510 										m_Layers.insert(layerName, m_Doc->firstLayerID());
511 									}
512 									firstLayer = false;
513 								}
514 							}
515 						}
516 					}
517 				}
518 			}
519 		}
520 	}
521 	return true;
522 }
523 
parseDocReference(const QString & designMap)524 bool OdgPlug::parseDocReference(const QString& designMap)
525 {
526 	QByteArray xmlData;
527 	QDomDocument designMapDom;
528 	if (!uz->read(designMap, xmlData))
529 		return false;
530 
531 	QString errorMsg;
532 	int errorLine = 0;
533 	int errorColumn = 0;
534 	if (!designMapDom.setContent(xmlData, false, &errorMsg, &errorLine, &errorColumn))
535 	{
536 		qDebug() << "Error loading File" << errorMsg << "at Line" << errorLine << "Column" << errorColumn;
537 		return false;
538 	}
539 	return parseDocReferenceXML(designMapDom);
540 }
541 
parseDocReferenceXML(QDomDocument & designMapDom)542 bool OdgPlug::parseDocReferenceXML(QDomDocument &designMapDom)
543 {
544 	QDomElement docElem = designMapDom.documentElement();
545 	for (QDomElement drawPag = docElem.firstChildElement(); !drawPag.isNull(); drawPag = drawPag.nextSiblingElement())
546 	{
547 		if (drawPag.tagName() == "office:font-face-decls")
548 		{
549 			for (QDomElement spf = drawPag.firstChildElement(); !spf.isNull(); spf = spf.nextSiblingElement() )
550 			{
551 				if (spf.tagName() == "style:font-face")
552 				{
553 					if (!spf.attribute("style:name").isEmpty())
554 						m_fontMap.insert(spf.attribute("style:name"), spf.attribute("svg:font-family"));
555 				}
556 			}
557 		}
558 		else if ((drawPag.tagName() == "office:styles") || (drawPag.tagName() == "office:automatic-styles"))
559 			parseStyles(drawPag);
560 		if (drawPag.tagName() == "office:master-styles")
561 		{
562 			for (QDomElement spf = drawPag.firstChildElement(); !spf.isNull(); spf = spf.nextSiblingElement())
563 			{
564 				if (spf.tagName() == "style:master-page")
565 				{
566 					DrawStyle currStyle;
567 					currStyle.page_layout_name = AttributeValue(spf.attribute("style:page-layout-name"));
568 					m_Styles.insert(spf.attribute("style:name"), currStyle);
569 					if (importerFlags & LoadSavePlugin::lfCreateDoc)
570 					{
571 						m_Doc->setMasterPageMode(true);
572 						ScPage *oldCur = m_Doc->currentPage();
573 						ScPage *addedPage = m_Doc->addMasterPage(mpagecount, spf.attribute("style:name"));
574 						m_Doc->setCurrentPage(addedPage);
575 						addedPage->clearMasterPageName();
576 						m_Doc->view()->addPage(mpagecount, true);
577 						baseX = addedPage->xOffset();
578 						baseY = addedPage->yOffset();
579 						mpagecount++;
580 						ObjStyle tmpOStyle;
581 						resovleStyle(tmpOStyle, spf.attribute("style:name"));
582 						m_Doc->currentPage()->setSize("Custom");
583 						m_Doc->currentPage()->setInitialHeight(tmpOStyle.page_height);
584 						m_Doc->currentPage()->setInitialWidth(tmpOStyle.page_width);
585 						m_Doc->currentPage()->setHeight(tmpOStyle.page_height);
586 						m_Doc->currentPage()->setWidth(tmpOStyle.page_width);
587 						m_Doc->currentPage()->initialMargins.setTop(tmpOStyle.margin_top);
588 						m_Doc->currentPage()->initialMargins.setBottom(tmpOStyle.margin_bottom);
589 						m_Doc->currentPage()->initialMargins.setLeft(tmpOStyle.margin_left);
590 						m_Doc->currentPage()->initialMargins.setRight(tmpOStyle.margin_right);
591 						if (!currStyle.page_layout_name.value.isEmpty())
592 						{
593 							ObjStyle tmpBStyle;
594 							resovleStyle(tmpBStyle, currStyle.page_layout_name.value);
595 							int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, baseX, baseY, tmpOStyle.page_width, tmpOStyle.page_height, 0, tmpBStyle.currColorFill, CommonStrings::None);
596 							PageItem *retObj = m_Doc->Items->at(z);
597 							finishItem(retObj, tmpBStyle);
598 						}
599 						for (QDomElement spm = spf.firstChildElement(); !spm.isNull(); spm = spm.nextSiblingElement())
600 						{
601 							PageItem* retObj = parseObj(spm);
602 							if (retObj != nullptr)
603 								m_Doc->Items->append(retObj);
604 						}
605 						m_Doc->setCurrentPage(oldCur);
606 						m_Doc->setMasterPageMode(false);
607 					}
608 				}
609 				else if (spf.tagName() == "draw:layer-set")
610 				{
611 					if (importerFlags & LoadSavePlugin::lfCreateDoc)
612 					{
613 						for (QDomElement spp = spf.firstChildElement(); !spp.isNull(); spp = spp.nextSiblingElement())
614 						{
615 							if (spp.tagName() == "draw:layer")
616 							{
617 								QString layerName = spp.attribute("draw:name");
618 								if (!layerName.isEmpty())
619 								{
620 									if (!firstLayer)
621 									{
622 										QStringList newNames;
623 										m_Doc->orderedLayerList(&newNames);
624 										if (!newNames.contains(layerName))
625 										{
626 											int currentLayer = m_Doc->addLayer(layerName);
627 											m_Layers.insert(layerName, currentLayer);
628 										}
629 									}
630 									else
631 									{
632 										m_Doc->changeLayerName(m_Doc->firstLayerID(), layerName);
633 										m_Layers.insert(layerName, m_Doc->firstLayerID());
634 									}
635 									firstLayer = false;
636 								}
637 							}
638 						}
639 					}
640 				}
641 			}
642 		}
643 		else if (drawPag.tagName() == "office:body")
644 		{
645 			for (QDomElement sp = drawPag.firstChildElement(); !sp.isNull(); sp = sp.nextSiblingElement())
646 			{
647 				if ((sp.tagName() == "office:drawing") || (sp.tagName() == "office:presentation"))
648 				{
649 					for (QDomElement spp = sp.firstChildElement(); !spp.isNull(); spp = spp.nextSiblingElement())
650 					{
651 						if (spp.tagName() == "draw:page")
652 						{
653 							ObjStyle tmpOStyle;
654 							resovleStyle(tmpOStyle, spp.attribute("draw:master-page-name"));
655 							docWidth = tmpOStyle.page_width;
656 							docHeight = tmpOStyle.page_height;
657 							topMargin = tmpOStyle.margin_top;
658 							leftMargin = tmpOStyle.margin_left;
659 							rightMargin = tmpOStyle.margin_right;
660 							bottomMargin = tmpOStyle.margin_bottom;
661 							if (importerFlags & LoadSavePlugin::lfCreateDoc)
662 							{
663 								if (firstPage)
664 								{
665 									m_Doc->setPage(docWidth, docHeight, topMargin, leftMargin, rightMargin, bottomMargin, m_Doc->PageSp, m_Doc->PageSpa, false, false);
666 									m_Doc->setPageSize("Custom");
667 									m_Doc->currentPage()->setSize("Custom");
668 									m_Doc->currentPage()->setInitialHeight(docHeight);
669 									m_Doc->currentPage()->setInitialWidth(docWidth);
670 									m_Doc->currentPage()->setHeight(docHeight);
671 									m_Doc->currentPage()->setWidth(docWidth);
672 									m_Doc->currentPage()->initialMargins.setTop(topMargin);
673 									m_Doc->currentPage()->initialMargins.setBottom(bottomMargin);
674 									m_Doc->currentPage()->initialMargins.setLeft(leftMargin);
675 									m_Doc->currentPage()->initialMargins.setRight(rightMargin);
676 									m_Doc->reformPages(true);
677 								}
678 								else
679 								{
680 									m_Doc->addPage(pagecount);
681 									m_Doc->currentPage()->setSize("Custom");
682 									m_Doc->currentPage()->setInitialHeight(docHeight);
683 									m_Doc->currentPage()->setInitialWidth(docWidth);
684 									m_Doc->currentPage()->setHeight(docHeight);
685 									m_Doc->currentPage()->setWidth(docWidth);
686 									m_Doc->currentPage()->initialMargins.setTop(topMargin);
687 									m_Doc->currentPage()->initialMargins.setBottom(bottomMargin);
688 									m_Doc->currentPage()->initialMargins.setLeft(leftMargin);
689 									m_Doc->currentPage()->initialMargins.setRight(rightMargin);
690 									m_Doc->currentPage()->setMasterPageNameNormal();
691 									m_Doc->view()->addPage(pagecount, true);
692 									pagecount++;
693 								}
694 								m_Doc->applyMasterPage(spp.attribute("draw:master-page-name"), m_Doc->currentPageNumber());
695 							}
696 							firstPage = false;
697 							baseX = m_Doc->currentPage()->xOffset();
698 							baseY = m_Doc->currentPage()->yOffset();
699 							for (QDomElement spe = spp.firstChildElement(); !spe.isNull(); spe = spe.nextSiblingElement())
700 							{
701 								PageItem* retObj = parseObj(spe);
702 								if (retObj != nullptr)
703 								{
704 									m_Doc->Items->append(retObj);
705 									Elements.append(retObj);
706 								}
707 							}
708 						}
709 					}
710 				}
711 			}
712 		}
713 	}
714 	return true;
715 }
716 
parseObj(QDomElement & draw)717 PageItem* OdgPlug::parseObj(QDomElement &draw)
718 {
719 	StoryText itemText;
720 	itemText.clear();
721 	itemText.setDoc(m_Doc);
722 	PageItem *retObj = nullptr;
723 	if (draw.tagName() == "draw:g")
724 	{
725 		QList<PageItem*> GElements;
726 		int gLayer = -1;
727 		for (QDomElement spd = draw.firstChildElement(); !spd.isNull(); spd = spd.nextSiblingElement())
728 		{
729 			PageItem* ite = parseObj(spd);
730 			if (ite != nullptr)
731 			{
732 				GElements.append(ite);
733 				gLayer = ite->m_layerID;
734 			}
735 		}
736 		if (GElements.count() > 0)
737 		{
738 			double minx =  std::numeric_limits<double>::max();
739 			double miny =  std::numeric_limits<double>::max();
740 			double maxx = -std::numeric_limits<double>::max();
741 			double maxy = -std::numeric_limits<double>::max();
742 			for (int ep = 0; ep < GElements.count(); ++ep)
743 			{
744 				PageItem* currItem = GElements.at(ep);
745 				double x1, x2, y1, y2;
746 				currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
747 				minx = qMin(minx, x1);
748 				miny = qMin(miny, y1);
749 				maxx = qMax(maxx, x2);
750 				maxy = qMax(maxy, y2);
751 			}
752 			double gx = minx;
753 			double gy = miny;
754 			double gw = maxx - minx;
755 			double gh = maxy - miny;
756 			int z = m_Doc->itemAdd(PageItem::Group, PageItem::Rectangle, gx, gy, gw, gh, 0, CommonStrings::None, CommonStrings::None);
757 			retObj = m_Doc->Items->at(z);
758 			retObj->ClipEdited = true;
759 			retObj->FrameType = 3;
760 			retObj->setFillEvenOdd(false);
761 			retObj->OldB2 = retObj->width();
762 			retObj->OldH2 = retObj->height();
763 			retObj->updateClip();
764 			m_Doc->groupObjectsToItem(retObj, GElements);
765 			retObj->OwnPage = m_Doc->OnPage(retObj);
766 			m_Doc->GroupOnPage(retObj);
767 			m_Doc->Items->removeLast();
768 			if (gLayer > -1)
769 				retObj->setLayer(gLayer);
770 		}
771 	}
772 	else if (draw.tagName() == "draw:polygon")
773 		retObj = parsePolygon(draw);
774 	else if (draw.tagName() == "draw:polyline")
775 		retObj = parsePolyline(draw);
776 	else if (draw.tagName() == "draw:path")
777 		retObj = parsePath(draw);
778 	else if (draw.tagName() == "draw:rect")
779 		retObj = parseRect(draw);
780 	else if (draw.tagName() == "draw:circle" || draw.tagName() == "draw:ellipse")
781 		retObj = parseEllipse(draw);
782 	else if (draw.tagName() == "draw:line")
783 		retObj = parseLine(draw);
784 	else if (draw.tagName() == "draw:frame")
785 		retObj = parseFrame(draw);
786 	else if (draw.tagName() == "draw:measure")
787 		retObj = parseMeasure(draw);
788 	else if (draw.tagName() == "draw:custom-shape")
789 		retObj = parseCustomShape(draw);
790 	else if (draw.tagName() == "draw:connector")
791 		retObj = parseConnector(draw);
792 	else if (draw.tagName() == "office:forms")
793 		retObj = parseForm(draw);
794 	else
795 		qDebug() << "Unhandled Tag" << draw.tagName();
796 	if (retObj != nullptr)
797 	{
798 		if (draw.hasAttribute("draw:layer"))
799 		{
800 			if (m_Layers.contains(draw.attribute("draw:layer")))
801 				retObj->setLayer(m_Layers[draw.attribute("draw:layer")]);
802 		}
803 	}
804 	return retObj;
805 }
806 
parseForm(QDomElement & e)807 PageItem* OdgPlug::parseForm(QDomElement &e)
808 {
809 	PageItem *retObj = nullptr;
810 	if (e.hasChildNodes())
811 		qDebug() << "Unhandled Tag" << e.tagName();
812 	return retObj;
813 }
814 
parseConnector(QDomElement & e)815 PageItem* OdgPlug::parseConnector(QDomElement &e)
816 {
817 	ObjStyle tmpOStyle;
818 	PageItem *retObj = nullptr;
819 	resovleStyle(tmpOStyle, "standard");
820 	resovleStyle(tmpOStyle, getStyleName(e));
821 	if ((tmpOStyle.fill_type == 0) && (tmpOStyle.stroke_type == 0))
822 		return retObj;
823 	if (e.hasAttribute("svg:d"))
824 	{
825 		FPointArray pArray;
826 		pArray.svgInit();
827 		pArray.parseSVG(e.attribute("svg:d"));
828 		if (pArray.size() > 3)
829 		{
830 			int z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, 10, 10, tmpOStyle.LineW, CommonStrings::None, tmpOStyle.currColorStroke);
831 			retObj = m_Doc->Items->at(z);
832 			retObj->PoLine = pArray.copy();
833 			QTransform mat;
834 			mat.scale(72.0 / 2540.0, 72.0 / 2540.0);
835 			retObj->PoLine.map(mat);
836 			if (e.hasAttribute("draw:transform"))
837 				parseTransform(&retObj->PoLine, e.attribute("draw:transform"));
838 			finishItem(retObj, tmpOStyle);
839 			m_Doc->Items->removeLast();
840 			if ((!tmpOStyle.startMarkerName.isEmpty()) || (!tmpOStyle.endMarkerName.isEmpty()))
841 			{
842 				QList<PageItem*> GElements;
843 				GElements.append(retObj);
844 				PageItem* startArrow = applyStartArrow(retObj, tmpOStyle);
845 				if (startArrow != nullptr)
846 					GElements.append(startArrow);
847 				PageItem* endArrow = applyEndArrow(retObj, tmpOStyle);
848 				if (endArrow != nullptr)
849 					GElements.append(endArrow);
850 				if (GElements.count() > 1)
851 					retObj = groupObjects(GElements);
852 			}
853 		}
854 	}
855 	else if (e.hasAttribute("svg:x1") && e.hasAttribute("svg:x2") && e.hasAttribute("svg:y1") && e.hasAttribute("svg:y2"))
856 		retObj = parseLine(e);
857 	return retObj;
858 }
859 
parseCustomShape(QDomElement & e)860 PageItem* OdgPlug::parseCustomShape(QDomElement &e)
861 {
862 	ObjStyle tmpOStyle;
863 	PageItem *retObj = nullptr;
864 	QList<PageItem*> GElements;
865 	double x = parseUnit(e.attribute("svg:x"));
866 	double y = parseUnit(e.attribute("svg:y")) ;
867 	double w = parseUnit(e.attribute("svg:width"));
868 	double h = parseUnit(e.attribute("svg:height"));
869 	resovleStyle(tmpOStyle, "standard");
870 	resovleStyle(tmpOStyle, getStyleName(e));
871 	bool has_Text = false;
872 	for (QDomElement p = e.firstChildElement(); !p.isNull(); p = p.nextSiblingElement())
873 	{
874 		if (p.tagName() == "text:p")
875 		{
876 			if (p.hasChildNodes())
877 				has_Text = true;
878 		}
879 	}
880 	if ((tmpOStyle.fill_type == 0) && (tmpOStyle.stroke_type == 0) && (!has_Text))
881 		return retObj;
882 	QPolygonF texAreaPoints;
883 	for (QDomElement p = e.firstChildElement(); !p.isNull(); p = p.nextSiblingElement())
884 	{
885 		if (p.tagName() == "draw:enhanced-geometry")
886 		{
887 			FunctionParser fpa;
888 			double vx = 0;
889 			double vy = 0;
890 			double vw = 21600;
891 			double vh = 21600;
892 			if (p.hasAttribute("svg:viewBox"))
893 				parseViewBox(p, &vx, &vy, &vw, &vh);
894 			if (vw == 0)
895 				vw = 21600;
896 			if (vh == 0)
897 				vh = 21600;
898 			fpa.AddConstant("top", vy);
899 			fpa.AddConstant("bottom", vh);
900 			fpa.AddConstant("left", vx);
901 			fpa.AddConstant("right", vw);
902 			fpa.AddConstant("width", vw - vx);
903 			fpa.AddConstant("height", vh - vy);
904 			fpa.AddConstant("xstretch", parseUnit(p.attribute("draw:path-stretchpoint-x", "0")));
905 			fpa.AddConstant("ystretch", parseUnit(p.attribute("draw:path-stretchpoint-y", "0")));
906 			fpa.AddConstant("hasfill", tmpOStyle.fill_type == 0 ? 0 : 1);
907 			fpa.AddConstant("hasstroke", tmpOStyle.stroke_type == 0 ? 0 : 1);
908 			fpa.AddConstant("logheight", vh);
909 			fpa.AddConstant("logwidth", vw);
910 			fpa.AddConstant("pi", M_PI);
911 			QString enhPath = p.attribute("draw:enhanced-path");
912 			QString textArea = p.attribute("draw:text-areas");
913 			if (!textArea.isEmpty())
914 				textArea.append(" ");
915 			QMap<QString, QString> func_Results;
916 			QMap<QString, QString> modi_Values;
917 			QString mods = p.attribute("draw:modifiers");
918 			ScTextStream Code(&mods, QIODevice::ReadOnly);
919 			int modCount = 0;
920 			while (!Code.atEnd())
921 			{
922 				double d;
923 				Code >> d;
924 				QString modName = QString("Const_%1").arg(modCount);
925 				fpa.AddConstant(modName.toStdString(), d);
926 				modi_Values.insert(QString("$%1").arg(modCount), QString("%1").arg(d));
927 				modCount++;
928 			}
929 			if (p.hasChildNodes())
930 			{
931 				QMap<QString, QString> formulaMap;
932 				for (QDomElement f = p.firstChildElement(); !f.isNull(); f = f.nextSiblingElement())
933 				{
934 					if (f.tagName() == "draw:equation")
935 					{
936 						QString formName = f.attribute("draw:name");
937 						QString formula = f.attribute("draw:formula", "0");
938 						formula.replace("$", "Const_");
939 						formula.replace("?", "Func_");
940 						formula.replace("if(", "if(0<");
941 						formulaMap.insert(formName, formula);
942 					}
943 				}
944 				if (!formulaMap.isEmpty())
945 				{
946 					int maxTry = formulaMap.count() + 1;
947 					int actTry = 0;
948 					bool allResOK = false;
949 					while (!allResOK)
950 					{
951 						allResOK = true;
952 						QMap<QString, QString>::iterator itf = formulaMap.begin();
953 						while (itf != formulaMap.end())
954 						{
955 							double erg = 0;
956 							int ret = fpa.Parse(itf.value().toStdString(), "", false);
957 							if (ret < 0)
958 							{
959 								QString formNam = itf.key();
960 								erg = fpa.Eval(nullptr);
961 								func_Results.insert("?" + formNam + " ", QString("%1 ").arg(erg));
962 								formNam.prepend("Func_");
963 								fpa.AddConstant(formNam.toStdString(), erg);
964 								itf = formulaMap.erase(itf);
965 							}
966 							else
967 							{
968 								++itf;
969 								allResOK = false;
970 							}
971 						}
972 						actTry++;
973 						if (actTry > maxTry)
974 							break;
975 						if (formulaMap.isEmpty())
976 							break;
977 					}
978 				}
979 			}
980 			if (!modi_Values.isEmpty())
981 			{
982 				QMapIterator<QString, QString> it(modi_Values);
983 				it.toBack();
984 				while (it.hasPrevious())
985 				{
986 					it.previous();
987 					enhPath.replace(it.key(), it.value());
988 				}
989 			}
990 			if (!func_Results.isEmpty())
991 			{
992 				QMapIterator<QString, QString> it(func_Results);
993 				it.toBack();
994 				while (it.hasPrevious())
995 				{
996 					it.previous();
997 					enhPath.replace(it.key(), it.value());
998 					if (!textArea.isEmpty())
999 						textArea.replace(it.key(), it.value());
1000 				}
1001 			}
1002 			if (enhPath.contains("?"))
1003 				return retObj;
1004 			QTransform mat;
1005 			double sx = (vw != 0.0) ? (w / vw) : w;
1006 			double sy = (vh != 0.0) ? (h / vh) : h;
1007 			mat.scale(sx, sy);
1008 			if (!textArea.isEmpty())
1009 			{
1010 				QStringList points = textArea.replace( QRegExp(","), " ").simplified().split( ' ', Qt::SkipEmptyParts );
1011 				texAreaPoints.append(QPointF(ScCLocale::toDoubleC(points[0]), ScCLocale::toDoubleC(points[1])));
1012 				texAreaPoints.append(QPointF(ScCLocale::toDoubleC(points[2]), ScCLocale::toDoubleC(points[3])));
1013 				texAreaPoints = mat.map(texAreaPoints);
1014 			}
1015 			QString shapeType = p.attribute("draw:type");
1016 			QStringList paths = enhPath.split("N", Qt::SkipEmptyParts);
1017 			if (!paths.isEmpty())
1018 			{
1019 				for (int a = 0; a < paths.count(); a++)
1020 				{
1021 					FPointArray pArray;
1022 					pArray.svgInit();
1023 					bool filled = true;
1024 					bool stroked = true;
1025 					PageItem::ItemType itype = parseEnhPath(paths[a], pArray, filled, stroked) ? PageItem::PolyLine : PageItem::Polygon;
1026 					if (pArray.size() > 3)
1027 					{
1028 						QString fillC = tmpOStyle.currColorFill;
1029 						if (!filled)
1030 							fillC = CommonStrings::None;
1031 						else
1032 						{
1033 							if (shapeType == "can")
1034 							{
1035 								if (a == 1)
1036 									fillC = modifyColor(fillC, false, 110);
1037 							}
1038 							else if (shapeType == "cube")
1039 							{
1040 								if (a == 1)
1041 									fillC = modifyColor(fillC, false, 110);
1042 								else if (a == 2)
1043 									fillC = modifyColor(fillC, true, 120);
1044 							}
1045 							else if (shapeType == "paper")
1046 							{
1047 								if (a == 1)
1048 									fillC = modifyColor(fillC, true, 120);
1049 							}
1050 							else if (shapeType == "smiley")
1051 							{
1052 								if (a == 1)
1053 									fillC = modifyColor(fillC, true, 120);
1054 								else if (a == 2)
1055 									fillC = modifyColor(fillC, true, 120);
1056 							}
1057 							else if (shapeType == "quad-bevel")
1058 							{
1059 								if (a == 1)
1060 									fillC = modifyColor(fillC, false, 110);
1061 								else if (a == 2)
1062 									fillC = modifyColor(fillC, true, 150);
1063 								else if (a == 3)
1064 									fillC = modifyColor(fillC, true, 120);
1065 								else if (a == 4)
1066 									fillC = modifyColor(fillC, false, 120);
1067 							}
1068 							else if (shapeType == "col-60da8460")
1069 							{
1070 								if (a == 1)
1071 									fillC = modifyColor(fillC, true, 150);
1072 								else if (a == 2)
1073 									fillC = modifyColor(fillC, true, 300);
1074 								else if (a == 3)
1075 									fillC = modifyColor(fillC, false, 120);
1076 								else if (a == 4)
1077 									fillC = modifyColor(fillC, false, 120);
1078 								else if (a == 5)
1079 									fillC = modifyColor(fillC, false, 120);
1080 							}
1081 							else if (shapeType == "col-502ad400")
1082 							{
1083 								if (a == 1)
1084 									fillC = modifyColor(fillC, false, 110);
1085 								else if (a == 2)
1086 									fillC = modifyColor(fillC, true, 120);
1087 								else if (a == 3)
1088 									fillC = modifyColor(fillC, false, 120);
1089 								else if (a == 4)
1090 									fillC = modifyColor(fillC, false, 120);
1091 							}
1092 							else if (shapeType == "vertical-scroll")
1093 							{
1094 								if (a == 1)
1095 									fillC = modifyColor(fillC, true, 120);
1096 								else if (a == 2)
1097 									fillC = modifyColor(fillC, true, 120);
1098 							}
1099 							else if (shapeType == "horizontal-scroll")
1100 							{
1101 								if (a == 1)
1102 									fillC = modifyColor(fillC, true, 120);
1103 								else if (a == 2)
1104 									fillC = modifyColor(fillC, true, 120);
1105 							}
1106 						}
1107 						QString strokeC = tmpOStyle.currColorStroke;
1108 						if (!stroked)
1109 							strokeC = CommonStrings::None;
1110 						int z = m_Doc->itemAdd(itype, PageItem::Unspecified, baseX + x, baseY + y, w, h, tmpOStyle.LineW, fillC, strokeC);
1111 						retObj = m_Doc->Items->at(z);
1112 						retObj->PoLine = pArray.copy();
1113 						retObj->setFillEvenOdd(true);
1114 						double stretchScale = 1.0;
1115 						bool hasStretch = false;
1116 						if ((w > h) && p.hasAttribute("draw:path-stretchpoint-x"))
1117 						{
1118 							double stretch = parseUnit(p.attribute("draw:path-stretchpoint-x", "0"));
1119 							FPoint tp2(getMaxClipF(&retObj->PoLine));
1120 							stretchScale = w / h;
1121 							double endX = tp2.x() * stretchScale;
1122 							double delX = endX - tp2.x();
1123 							for (int ap = 0; ap < retObj->PoLine.size(); ap++)
1124 							{
1125 								FPoint pt = retObj->PoLine[ap];
1126 								if (pt.x() > stretch)
1127 								{
1128 									if (pt.x() == tp2.x())
1129 										retObj->PoLine[ap].setX(endX);
1130 									else
1131 										retObj->PoLine[ap].setX(pt.x() + delX);
1132 								}
1133 							}
1134 							stretchScale = h / 21600.0;
1135 							hasStretch = true;
1136 						}
1137 						if ((h > w) && p.hasAttribute("draw:path-stretchpoint-y"))
1138 						{
1139 							double stretch = parseUnit(p.attribute("draw:path-stretchpoint-y", "0"));
1140 							FPoint tp2(getMaxClipF(&retObj->PoLine));
1141 							stretchScale = h / w;
1142 							double endY = tp2.y() * stretchScale;
1143 							double delY = endY - tp2.y();
1144 							for (int ap = 0; ap < retObj->PoLine.size(); ap++)
1145 							{
1146 								FPoint pt = retObj->PoLine[ap];
1147 								if (pt.y() > stretch)
1148 								{
1149 									if (pt.y() == tp2.y())
1150 										retObj->PoLine[ap].setY(endY);
1151 									else
1152 										retObj->PoLine[ap].setY(pt.y() + delY);
1153 								}
1154 							}
1155 							stretchScale = w / 21600.0;
1156 							hasStretch = true;
1157 						}
1158 						if (hasStretch)
1159 						{
1160 							QTransform smat;
1161 							smat.scale(stretchScale, stretchScale);
1162 							retObj->PoLine.map(smat);
1163 						}
1164 						else
1165 							retObj->PoLine.map(mat);
1166 						if (e.hasAttribute("draw:transform"))
1167 							parseTransform(&retObj->PoLine, e.attribute("draw:transform"));
1168 						finishItem(retObj, tmpOStyle);
1169 						GElements.append(retObj);
1170 						m_Doc->Items->removeLast();
1171 					}
1172 				}
1173 				if (GElements.count() > 1)
1174 					retObj = groupObjects(GElements);
1175 				if (p.hasAttribute("draw:mirror-horizontal") && (p.attribute("draw:mirror-horizontal") == "true"))
1176 					m_Doc->MirrorPolyH(retObj);
1177 				if (p.hasAttribute("draw:mirror-vertical") && (p.attribute("draw:mirror-vertical") == "true"))
1178 					m_Doc->MirrorPolyV(retObj);
1179 			}
1180 		}
1181 	}
1182 	if (has_Text)
1183 	{
1184 		double r = 0.0;
1185 		if (e.hasAttribute("draw:transform"))
1186 			parseTransform(e.attribute("draw:transform"), &r, &x, &y);
1187 		double tx = x;
1188 		double ty = y;
1189 		double tw = w;
1190 		double th = h;
1191 		if (!texAreaPoints.isEmpty())
1192 		{
1193 			QTransform rmat;
1194 			rmat.rotate(r);
1195 			QPointF rt = rmat.map(texAreaPoints[0]);
1196 			tx += rt.x();
1197 			ty += rt.y();
1198 			tw = texAreaPoints[1].x() - texAreaPoints[0].x();
1199 			th = texAreaPoints[1].y() - texAreaPoints[0].y();
1200 		}
1201 		int z = m_Doc->itemAdd(PageItem::TextFrame, PageItem::Unspecified, baseX+tx, baseY+ty, tw, th, 0, CommonStrings::None, CommonStrings::None);
1202 		retObj = m_Doc->Items->at(z);
1203 		retObj->setTextToFrameDist(0.0, 0.0, 0.0, 0.0);
1204 		retObj->setTextFlowMode(PageItem::TextFlowDisabled);
1205 		retObj->setVerticalAlignment(tmpOStyle.verticalAlignment);
1206 		finishItem(retObj, tmpOStyle);
1207 		parseText(e, retObj, tmpOStyle);
1208 		if (e.hasAttribute("draw:transform"))
1209 			retObj->setRotation(r, true);
1210 		m_Doc->Items->removeLast();
1211 		GElements.append(retObj);
1212 	}
1213 	if (GElements.count() > 1)
1214 		retObj = groupObjects(GElements);
1215 	return retObj;
1216 }
1217 
parseMeasure(QDomElement & e)1218 PageItem* OdgPlug::parseMeasure(QDomElement &e)
1219 {
1220 	ObjStyle tmpOStyle;
1221 	PageItem *retObj = nullptr;
1222 	QList<PageItem*> GElements;
1223 	double x1 = e.attribute( "svg:x1" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "svg:x1" ) );
1224 	double y1 = e.attribute( "svg:y1" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "svg:y1" ) );
1225 	double x2 = e.attribute( "svg:x2" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "svg:x2" ) );
1226 	double y2 = e.attribute( "svg:y2" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "svg:y2" ) );
1227 	resovleStyle(tmpOStyle, "standard");
1228 	resovleStyle(tmpOStyle, getStyleName(e));
1229 	if (tmpOStyle.measureDist == 0)
1230 		tmpOStyle.measureDist = tmpOStyle.fontSize;
1231 	QLineF refLine = QLineF(x1, y1, x2, y2);
1232 	QLineF normRef = refLine.normalVector();
1233 	normRef.setLength(tmpOStyle.measureDist);
1234 	double dx = normRef.p2().x() - refLine.p1().x();
1235 	double dy = normRef.p2().y() - refLine.p1().y();
1236 	retObj = parseLine(e);
1237 	if (retObj != nullptr)
1238 	{
1239 		retObj->moveBy(dx, dy, true);
1240 		GElements.append(retObj);
1241 	}
1242 	normRef.setLength(tmpOStyle.measureDist + tmpOStyle.fontSize * 1.2);
1243 	if (normRef.length() != 0)
1244 	{
1245 		int z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, 10, 10, tmpOStyle.LineW, CommonStrings::None, tmpOStyle.currColorStroke);
1246 		retObj = m_Doc->Items->at(z);
1247 		retObj->PoLine.resize(4);
1248 		retObj->PoLine.setPoint(0, FPoint(x1, y1));
1249 		retObj->PoLine.setPoint(1, FPoint(x1, y1));
1250 		retObj->PoLine.setPoint(2, FPoint(normRef.p2().x(), normRef.p2().y()));
1251 		retObj->PoLine.setPoint(3, FPoint(normRef.p2().x(), normRef.p2().y()));
1252 		if (e.hasAttribute("draw:transform"))
1253 			parseTransform(&retObj->PoLine, e.attribute("draw:transform"));
1254 		finishItem(retObj, tmpOStyle);
1255 		m_Doc->Items->removeLast();
1256 		GElements.append(retObj);
1257 	}
1258 	QLineF refLine2 = QLineF(x2, y2, x1, y1);
1259 	QLineF normRef2 = refLine2.normalVector();
1260 	normRef2.setAngle(normRef2.angle() + 180);
1261 	normRef2.setLength(tmpOStyle.measureDist + tmpOStyle.fontSize / 2.0);
1262 	if (normRef2.length() != 0)
1263 	{
1264 		int z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, 10, 10, tmpOStyle.LineW, CommonStrings::None, tmpOStyle.currColorStroke);
1265 		retObj = m_Doc->Items->at(z);
1266 		retObj->PoLine.resize(4);
1267 		retObj->PoLine.setPoint(0, FPoint(x2, y2));
1268 		retObj->PoLine.setPoint(1, FPoint(x2, y2));
1269 		retObj->PoLine.setPoint(2, FPoint(normRef2.p2().x(), normRef2.p2().y()));
1270 		retObj->PoLine.setPoint(3, FPoint(normRef2.p2().x(), normRef2.p2().y()));
1271 		if (e.hasAttribute("draw:transform"))
1272 			parseTransform(&retObj->PoLine, e.attribute("draw:transform"));
1273 		finishItem(retObj, tmpOStyle);
1274 		m_Doc->Items->removeLast();
1275 		GElements.append(retObj);
1276 	}
1277 	normRef2.setLength(tmpOStyle.measureDist + tmpOStyle.fontSize * 1.2);
1278 	QLineF textLine = QLineF(normRef.p2(), normRef2.p2());
1279 	if (textLine.length() != 0)
1280 	{
1281 		int z = m_Doc->itemAdd(PageItem::TextFrame, PageItem::Unspecified, baseX+normRef.p2().x(), baseY+normRef.p2().y(), textLine.length(), tmpOStyle.fontSize * 1.2, tmpOStyle.LineW, tmpOStyle.currColorFill, tmpOStyle.currColorStroke);
1282 		retObj = m_Doc->Items->at(z);
1283 		retObj->setFillColor(tmpOStyle.currColorFill);
1284 		retObj->setTextToFrameDist(0.0, 0.0, 0.0, 0.0);
1285 		retObj->setTextFlowMode(PageItem::TextFlowDisabled);
1286 		finishItem(retObj, tmpOStyle);
1287 		retObj->setRotation(-textLine.angle(), true);
1288 		parseText(e, retObj, tmpOStyle);
1289 		m_Doc->Items->removeLast();
1290 		GElements.append(retObj);
1291 	}
1292 	if (GElements.count() > 1)
1293 		retObj = groupObjects(GElements);
1294 	return retObj;
1295 }
1296 
parseLine(QDomElement & e)1297 PageItem* OdgPlug::parseLine( QDomElement &e)
1298 {
1299 	ObjStyle tmpOStyle;
1300 	PageItem *retObj = nullptr;
1301 	double x1 = e.attribute( "svg:x1" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "svg:x1" ) );
1302 	double y1 = e.attribute( "svg:y1" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "svg:y1" ) );
1303 	double x2 = e.attribute( "svg:x2" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "svg:x2" ) );
1304 	double y2 = e.attribute( "svg:y2" ).isEmpty() ? 0.0 : parseUnit( e.attribute( "svg:y2" ) );
1305 	resovleStyle(tmpOStyle, "standard");
1306 	resovleStyle(tmpOStyle, getStyleName(e));
1307 	if (tmpOStyle.stroke_type == 0)
1308 		return retObj;
1309 	int z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, 10, 10, tmpOStyle.LineW, CommonStrings::None, tmpOStyle.currColorStroke);
1310 	retObj = m_Doc->Items->at(z);
1311 	retObj->PoLine.resize(4);
1312 	retObj->PoLine.setPoint(0, FPoint(x1, y1));
1313 	retObj->PoLine.setPoint(1, FPoint(x1, y1));
1314 	retObj->PoLine.setPoint(2, FPoint(x2, y2));
1315 	retObj->PoLine.setPoint(3, FPoint(x2, y2));
1316 	if (e.hasAttribute("draw:transform"))
1317 		parseTransform(&retObj->PoLine, e.attribute("draw:transform"));
1318 	finishItem(retObj, tmpOStyle);
1319 	m_Doc->Items->removeLast();
1320 	if ((!tmpOStyle.startMarkerName.isEmpty()) || (!tmpOStyle.endMarkerName.isEmpty()))
1321 	{
1322 		QList<PageItem*> GElements;
1323 		GElements.append(retObj);
1324 		PageItem* startArrow = applyStartArrow(retObj, tmpOStyle);
1325 		if (startArrow != nullptr)
1326 			GElements.append(startArrow);
1327 		PageItem* endArrow = applyEndArrow(retObj, tmpOStyle);
1328 		if (endArrow != nullptr)
1329 			GElements.append(endArrow);
1330 		if (GElements.count() > 1)
1331 			retObj = groupObjects(GElements);
1332 	}
1333 	return retObj;
1334 }
1335 
parseEllipse(QDomElement & e)1336 PageItem* OdgPlug::parseEllipse(QDomElement &e)
1337 {
1338 	ObjStyle tmpOStyle;
1339 	PageItem *retObj = nullptr;
1340 	double x = parseUnit(e.attribute("svg:x"));
1341 	double y = parseUnit(e.attribute("svg:y")) ;
1342 	double w = parseUnit(e.attribute("svg:width"));
1343 	double h = parseUnit(e.attribute("svg:height"));
1344 	resovleStyle(tmpOStyle, "standard");
1345 	resovleStyle(tmpOStyle, getStyleName(e));
1346 	if ((tmpOStyle.fill_type == 0) && (tmpOStyle.stroke_type == 0))
1347 		return retObj;
1348 	int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Ellipse, baseX+x, baseY+y, w, h, tmpOStyle.LineW, tmpOStyle.currColorFill, tmpOStyle.currColorStroke);
1349 	retObj = m_Doc->Items->at(z);
1350 	if (e.hasAttribute("draw:transform"))
1351 		parseTransform(&retObj->PoLine, e.attribute("draw:transform"));
1352 	finishItem(retObj, tmpOStyle);
1353 	m_Doc->Items->removeLast();
1354 	return retObj;
1355 }
1356 
parseRect(QDomElement & e)1357 PageItem* OdgPlug::parseRect(QDomElement &e)
1358 {
1359 	ObjStyle tmpOStyle;
1360 	PageItem *retObj = nullptr;
1361 	double x = parseUnit(e.attribute("svg:x"));
1362 	double y = parseUnit(e.attribute("svg:y")) ;
1363 	double w = parseUnit(e.attribute("svg:width"));
1364 	double h = parseUnit(e.attribute("svg:height"));
1365 	double corner = parseUnit(e.attribute("draw:corner-radius"));
1366 	resovleStyle(tmpOStyle, "standard");
1367 	resovleStyle(tmpOStyle, getStyleName(e));
1368 	if ((tmpOStyle.fill_type == 0) && (tmpOStyle.stroke_type == 0))
1369 		return retObj;
1370 	int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Rectangle, baseX+x, baseY+y, w, h, tmpOStyle.LineW, tmpOStyle.currColorFill, tmpOStyle.currColorStroke);
1371 	retObj = m_Doc->Items->at(z);
1372 	if (corner != 0)
1373 	{
1374 		retObj->setCornerRadius(corner);
1375 		retObj->SetFrameRound();
1376 		m_Doc->setRedrawBounding(retObj);
1377 	}
1378 	if (e.hasAttribute("draw:transform"))
1379 		parseTransform(&retObj->PoLine, e.attribute("draw:transform"));
1380 	finishItem(retObj, tmpOStyle);
1381 	m_Doc->Items->removeLast();
1382 	return retObj;
1383 }
1384 
parsePolygon(QDomElement & e)1385 PageItem* OdgPlug::parsePolygon(QDomElement &e)
1386 {
1387 	ObjStyle tmpOStyle;
1388 	PageItem *retObj = nullptr;
1389 	resovleStyle(tmpOStyle, "standard");
1390 	resovleStyle(tmpOStyle, getStyleName(e));
1391 	if ((tmpOStyle.fill_type == 0) && (tmpOStyle.stroke_type == 0))
1392 		return retObj;
1393 	int z = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, tmpOStyle.LineW, tmpOStyle.currColorFill, tmpOStyle.currColorStroke);
1394 	retObj = m_Doc->Items->at(z);
1395 	retObj->PoLine.resize(0);
1396 	appendPoints(&retObj->PoLine, e, true);
1397 	if (e.hasAttribute("draw:transform"))
1398 		parseTransform(&retObj->PoLine, e.attribute("draw:transform"));
1399 	finishItem(retObj, tmpOStyle);
1400 	m_Doc->Items->removeLast();
1401 	return retObj;
1402 }
1403 
parsePolyline(QDomElement & e)1404 PageItem* OdgPlug::parsePolyline(QDomElement &e)
1405 {
1406 	ObjStyle tmpOStyle;
1407 	PageItem *retObj = nullptr;
1408 	resovleStyle(tmpOStyle, "standard");
1409 	resovleStyle(tmpOStyle, getStyleName(e));
1410 	if (tmpOStyle.stroke_type == 0)
1411 		return retObj;
1412 	int z = m_Doc->itemAdd(PageItem::PolyLine, PageItem::Unspecified, baseX, baseY, 10, 10, tmpOStyle.LineW, CommonStrings::None, tmpOStyle.currColorStroke);
1413 	retObj = m_Doc->Items->at(z);
1414 	retObj->PoLine.resize(0);
1415 	appendPoints(&retObj->PoLine, e, false);
1416 	if (e.hasAttribute("draw:transform"))
1417 		parseTransform(&retObj->PoLine, e.attribute("draw:transform"));
1418 	finishItem(retObj, tmpOStyle);
1419 	m_Doc->Items->removeLast();
1420 	if ((!tmpOStyle.startMarkerName.isEmpty()) || (!tmpOStyle.endMarkerName.isEmpty()))
1421 	{
1422 		QList<PageItem*> GElements;
1423 		GElements.append(retObj);
1424 		PageItem* startArrow = applyStartArrow(retObj, tmpOStyle);
1425 		if (startArrow != nullptr)
1426 			GElements.append(startArrow);
1427 		PageItem* endArrow = applyEndArrow(retObj, tmpOStyle);
1428 		if (endArrow != nullptr)
1429 			GElements.append(endArrow);
1430 		if (GElements.count() > 1)
1431 			retObj = groupObjects(GElements);
1432 	}
1433 	return retObj;
1434 }
1435 
parsePath(QDomElement & e)1436 PageItem* OdgPlug::parsePath(QDomElement &e)
1437 {
1438 	ObjStyle tmpOStyle;
1439 	PageItem *retObj = nullptr;
1440 	resovleStyle(tmpOStyle, "standard");
1441 	resovleStyle(tmpOStyle, getStyleName(e));
1442 	if ((tmpOStyle.fill_type == 0) && (tmpOStyle.stroke_type == 0))
1443 		return retObj;
1444 	FPointArray pArray;
1445 	pArray.svgInit();
1446 	PageItem::ItemType itype = pArray.parseSVG(e.attribute("svg:d")) ? PageItem::PolyLine : PageItem::Polygon;
1447 	if (pArray.size() > 3)
1448 	{
1449 		double x = parseUnit(e.attribute("svg:x"));
1450 		double y = parseUnit(e.attribute("svg:y")) ;
1451 		double w = parseUnit(e.attribute("svg:width"));
1452 		double h = parseUnit(e.attribute("svg:height"));
1453 		int z = m_Doc->itemAdd(itype, PageItem::Unspecified, baseX + x, baseY + y, w, h, tmpOStyle.LineW, tmpOStyle.currColorFill, tmpOStyle.currColorStroke);
1454 		retObj = m_Doc->Items->at(z);
1455 		retObj->PoLine = pArray.copy();
1456 		QTransform mat;
1457 		double vx = 0;
1458 		double vy = 0;
1459 		double vw = 1;
1460 		double vh = 1;
1461 		parseViewBox(e, &vx, &vy, &vw, &vh);
1462 		double sx = (vw != 0.0) ? (w / vw) : w;
1463 		double sy = (vh != 0.0) ? (h / vh) : h;
1464 		mat.scale(sx, sy);
1465 		retObj->PoLine.map(mat);
1466 		if (e.hasAttribute("draw:transform"))
1467 		{
1468 			FPoint tp2(getMinClipF(&retObj->PoLine));
1469 			retObj->PoLine.translate(-tp2.x(), -tp2.y());
1470 			parseTransform(&retObj->PoLine, e.attribute("draw:transform"));
1471 		}
1472 		finishItem(retObj, tmpOStyle);
1473 		m_Doc->Items->removeLast();
1474 		if (itype == PageItem::PolyLine)
1475 		{
1476 			if ((!tmpOStyle.startMarkerName.isEmpty()) || (!tmpOStyle.endMarkerName.isEmpty()))
1477 			{
1478 				QList<PageItem*> GElements;
1479 				GElements.append(retObj);
1480 				PageItem* startArrow = applyStartArrow(retObj, tmpOStyle);
1481 				if (startArrow != nullptr)
1482 					GElements.append(startArrow);
1483 				PageItem* endArrow = applyEndArrow(retObj, tmpOStyle);
1484 				if (endArrow != nullptr)
1485 					GElements.append(endArrow);
1486 				if (GElements.count() > 1)
1487 					retObj = groupObjects(GElements);
1488 			}
1489 		}
1490 	}
1491 	return retObj;
1492 }
1493 
parseFrame(QDomElement & e)1494 PageItem* OdgPlug::parseFrame(QDomElement &e)
1495 {
1496 	ObjStyle tmpOStyle;
1497 	PageItem *retObj = nullptr;
1498 	double x = parseUnit(e.attribute("svg:x"));
1499 	double y = parseUnit(e.attribute("svg:y")) ;
1500 	double w = parseUnit(e.attribute("svg:width"));
1501 	double h = parseUnit(e.attribute("svg:height"));
1502 	double r = 0.0;
1503 	if (e.hasAttribute("draw:transform"))
1504 		parseTransform(e.attribute("draw:transform"), &r, &x, &y);
1505 	resovleStyle(tmpOStyle, "standard");
1506 	resovleStyle(tmpOStyle, getStyleName(e));
1507 	QDomElement n = e.firstChildElement();
1508 	if (!n.isNull())
1509 	{
1510 		if (n.tagName() == "draw:text-box" )
1511 		{
1512 			if (n.text().isEmpty())
1513 				return retObj;
1514 			int z = m_Doc->itemAdd(PageItem::TextFrame, PageItem::Unspecified, baseX+x, baseY+y, w, h, tmpOStyle.LineW, tmpOStyle.currColorFill, tmpOStyle.currColorStroke);
1515 			retObj = m_Doc->Items->at(z);
1516 			retObj->setFillColor(tmpOStyle.currColorFill);
1517 			retObj->setTextToFrameDist(0.0, 0.0, 0.0, 0.0);
1518 			retObj->setTextFlowMode(PageItem::TextFlowDisabled);
1519 			retObj->setVerticalAlignment(tmpOStyle.verticalAlignment);
1520 			if (e.hasAttribute("draw:transform"))
1521 				retObj->setRotation(r, true);
1522 			finishItem(retObj, tmpOStyle);
1523 			parseText(n, retObj, tmpOStyle);
1524 			m_Doc->Items->removeLast();
1525 		}
1526 		else if (n.tagName() == "draw:image" )
1527 		{
1528 			QString imagePath = n.attribute("xlink:href", "");
1529 			if (!imagePath.isEmpty())
1530 			{
1531 				QFileInfo fi(imagePath);
1532 				QString ext = fi.suffix().toLower();
1533 				QString formatD(FormatsManager::instance()->extensionListForFormat(FormatsManager::IMAGESIMGFRAME, 1));
1534 				QStringList formats = formatD.split("|");
1535 				formats.removeAll("pdf");
1536 				QStringList allFormatsV = LoadSavePlugin::getExtensionsForImport(FORMATID_FIRSTUSER);
1537 				if (formats.contains(ext.toUtf8()))
1538 				{
1539 					int z = m_Doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, baseX+x, baseY+y, w, h, tmpOStyle.LineW, tmpOStyle.currColorFill, tmpOStyle.currColorStroke);
1540 					retObj = m_Doc->Items->at(z);
1541 					if (e.hasAttribute("draw:transform"))
1542 						retObj->setRotation(r, true);
1543 					finishItem(retObj, tmpOStyle);
1544 					QByteArray f;
1545 					if (uz->read(imagePath, f))
1546 					{
1547 						QFileInfo fi(imagePath);
1548 						QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_odg_XXXXXX." + fi.suffix());
1549 						tempFile->setAutoRemove(false);
1550 						if (tempFile->open())
1551 						{
1552 							QString fileName = getLongPathName(tempFile->fileName());
1553 							if (!fileName.isEmpty())
1554 							{
1555 								tempFile->write(f);
1556 								tempFile->close();
1557 								retObj->isInlineImage = true;
1558 								retObj->isTempFile = true;
1559 								retObj->AspectRatio = false;
1560 								retObj->ScaleType   = false;
1561 								m_Doc->loadPict(fileName, retObj);
1562 								retObj->adjustPictScale();
1563 							}
1564 						}
1565 						delete tempFile;
1566 					}
1567 					m_Doc->Items->removeLast();
1568 				}
1569 				else if (allFormatsV.contains(ext.toUtf8()))
1570 				{
1571 					QByteArray f;
1572 					if (uz->read(imagePath, f))
1573 					{
1574 						QFileInfo fi(imagePath);
1575 						QString ext = fi.suffix();
1576 						if (ext == "wmf")
1577 						{
1578 							if ((f[0] == '\x01') && (f[1] == '\x00') && (f[2] == '\x00') && (f[3] == '\x00') && (f[40] == '\x20') && (f[41] == '\x45') && (f[42] == '\x4D') && (f[43] == '\x46'))
1579 								ext = "emf";
1580 						}
1581 						retObj = getVectorFileFromData(m_Doc, f, ext, baseX + x, baseY + y, w, h);
1582 						if (retObj != nullptr)
1583 							m_Doc->Items->removeLast();
1584 					}
1585 				}
1586 			}
1587 			else if (n.hasChildNodes())
1588 			{
1589 				for (QDomElement nc = n.firstChildElement(); !nc.isNull(); nc = nc.nextSiblingElement())
1590 				{
1591 					if (nc.tagName() == "office:binary-data")
1592 					{
1593 						QString ext = "";
1594 						QByteArray buf = QByteArray::fromBase64(nc.text().toLatin1());
1595 						if ((buf[0] == '%') && (buf[1] == '!') && (buf[2] == 'P') && (buf[3] == 'S') && (buf[4] == '-') && (buf[5] == 'A'))
1596 							ext = "eps";
1597 						else if ((buf[0] == '\xC5') && (buf[1] == '\xD0') && (buf[2] == '\xD3') && (buf[3] == '\xC6'))
1598 							ext = "eps";
1599 						else if ((buf[0] == 'G') && (buf[1] == 'I') && (buf[2] == 'F') && (buf[3] == '8'))
1600 							ext = "gif";
1601 						else if ((buf[0] == '\xFF') && (buf[1] == '\xD8') && (buf[2] == '\xFF'))
1602 							ext = "jpg";
1603 						else if ((buf[0] == '%') && (buf[1] == 'P') && (buf[2] == 'D') && (buf[3] == 'F'))
1604 							ext = "pdf";
1605 						else if ((buf[0] == 'P') && (buf[1] == 'G') && (buf[2] == 'F'))
1606 							ext = "pgf";
1607 						else if ((buf[0] == '\x89') && (buf[1] == 'P') && (buf[2] == 'N') && (buf[3] == 'G'))
1608 							ext = "png";
1609 						else if ((buf[0] == '8') && (buf[1] == 'B') && (buf[2] == 'P') && (buf[3] == 'S'))
1610 							ext = "psd";
1611 						else if (((buf[0] == 'I') && (buf[1] == 'I') && (buf[2] == '\x2A')) || ((buf[0] == 'M') && (buf[1] == 'M') && (buf[3] == '\x2A')))
1612 							ext = "tif";
1613 						else if ((buf[0] == '/') && (buf[1] == '*') && (buf[2] == ' ') && (buf[3] == 'X') && (buf[4] == 'P') && (buf[5] == 'M'))
1614 							ext = "xpm";
1615 						else if ((buf[0] == '\xD7') && (buf[1] == '\xCD') && (buf[2] == '\xC6') && (buf[3] == '\x9A'))
1616 							ext = "wmf";
1617 						else if ((buf[0] == '\x01') && (buf[1] == '\x00') && (buf[2] == '\x00') && (buf[3] == '\x00') && (buf[40] == '\x20') && (buf[41] == '\x45') && (buf[42] == '\x4D') && (buf[43] == '\x46'))
1618 							ext = "emf";
1619 						else if ((buf[0] == '<') && (buf[1] == '?') && (buf[2] == 'x') && (buf[3] == 'm') && (buf[4] == 'l'))
1620 							ext = "svg";
1621 						else if ((buf[0] == 'V') && (buf[1] == 'C') && (buf[2] == 'L') && (buf[3] == 'M') && (buf[4] == 'T') && (buf[5] == 'F'))
1622 							ext = "svm";
1623 						if (!ext.isEmpty())
1624 						{
1625 							if ((ext == "eps") || (ext == "wmf") || (ext == "emf") || (ext == "svg") || (ext == "svm"))
1626 							{
1627 								retObj = getVectorFileFromData(m_Doc, buf, ext, baseX + x, baseY + y, w, h);
1628 								if (retObj != nullptr)
1629 									m_Doc->Items->removeLast();
1630 							}
1631 							else
1632 							{
1633 								int z = m_Doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, baseX+x, baseY+y, w, h, tmpOStyle.LineW, tmpOStyle.currColorFill, tmpOStyle.currColorStroke);
1634 								retObj = m_Doc->Items->at(z);
1635 								if (e.hasAttribute("draw:transform"))
1636 									retObj->setRotation(r, true);
1637 								finishItem(retObj, tmpOStyle);
1638 								QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_odg_XXXXXX." + ext);
1639 								tempFile->setAutoRemove(false);
1640 								if (tempFile->open())
1641 								{
1642 									QString fileName = getLongPathName(tempFile->fileName());
1643 									if (!fileName.isEmpty())
1644 									{
1645 										tempFile->write(buf);
1646 										tempFile->close();
1647 										retObj->isInlineImage = true;
1648 										retObj->isTempFile = true;
1649 										retObj->AspectRatio = false;
1650 										retObj->ScaleType   = false;
1651 										m_Doc->loadPict(fileName, retObj);
1652 										retObj->adjustPictScale();
1653 									}
1654 								}
1655 								delete tempFile;
1656 								m_Doc->Items->removeLast();
1657 							}
1658 						}
1659 					}
1660 				}
1661 			}
1662 		}
1663 	}
1664 	return retObj;
1665 }
1666 
parseText(QDomElement & elem,PageItem * item,ObjStyle & tmpOStyle)1667 void OdgPlug::parseText(QDomElement &elem, PageItem* item, ObjStyle& tmpOStyle)
1668 {
1669 	int posC = 0;
1670 	QString pStyleD = CommonStrings::DefaultParagraphStyle;
1671 	ParagraphStyle newStyle;
1672 	newStyle.setDefaultStyle(false);
1673 	newStyle.setParent(pStyleD);
1674 	ParagraphStyle ttx = m_Doc->paragraphStyle(pStyleD);
1675 	CharStyle nstyle = ttx.charStyle();
1676 	newStyle.setLineSpacingMode(ParagraphStyle::AutomaticLineSpacing);
1677 	newStyle.setLineSpacing(nstyle.fontSize() / 10.0);
1678 	item->itemText.clear();
1679 	item->itemText.setDefaultStyle(newStyle);
1680 	item->setFirstLineOffset(FLOPFontAscent);
1681 	ObjStyle pStyle = tmpOStyle;
1682 	if (elem.hasAttribute("text:style-name"))
1683 		resovleStyle(pStyle, elem.attribute("text:style-name"));
1684 	for (QDomElement para = elem.firstChildElement(); !para.isNull(); para = para.nextSiblingElement())
1685 	{
1686 		pStyle = tmpOStyle;
1687 		if ((para.tagName() != "text:p") && (para.tagName() != "text:list") && (para.tagName() != "text:h"))
1688 			continue;
1689 		if (para.hasChildNodes())
1690 		{
1691 			if (para.hasAttribute("text:style-name"))
1692 				resovleStyle(pStyle, para.attribute("text:style-name"));
1693 			ParagraphStyle tmpStyle = newStyle;
1694 			applyParagraphStyle(tmpStyle, pStyle);
1695 			double maxFsize = 0.0;
1696 			if (para.firstChildElement().isNull())
1697 			{
1698 				CharStyle tmpCStyle = tmpStyle.charStyle();
1699 				applyCharacterStyle(tmpCStyle, tmpOStyle);
1700 				maxFsize = qMax(maxFsize, tmpOStyle.fontSize);
1701 				QString txt = para.text();
1702 				insertChars(item, txt, tmpStyle, tmpCStyle, posC);
1703 			}
1704 			else
1705 			{
1706 				for (QDomNode spn = para.firstChild(); !spn.isNull(); spn = spn.nextSibling())
1707 				{
1708 					CharStyle tmpCStyle = tmpStyle.charStyle();
1709 					QDomElement sp = spn.toElement();
1710 					ObjStyle cStyle = pStyle;
1711 					if (spn.isElement() && (sp.tagName() == "text:span"))
1712 					{
1713 						if (sp.hasAttribute("text:style-name"))
1714 							resovleStyle(cStyle, sp.attribute("text:style-name"));
1715 					}
1716 					applyCharacterStyle(tmpCStyle, cStyle);
1717 					maxFsize = qMax(maxFsize, cStyle.fontSize);
1718 					QString txt = "";
1719 					if (spn.isElement())
1720 					{
1721 						if (sp.tagName() == "text:span")
1722 						{
1723 							if (sp.tagName() == "text:s")
1724 								txt = " ";
1725 							else if (sp.tagName() == "text:tab")
1726 								txt = SpecialChars::TAB;
1727 							else if (sp.tagName() == "text:line-break")
1728 								txt = SpecialChars::LINEBREAK;
1729 							else
1730 								txt = sp.text();
1731 						}
1732 						else if (sp.tagName() == "text:measure")
1733 						{
1734 							QString kind = sp.attribute("text:kind");
1735 							if (kind == "value")
1736 								txt += sp.text();
1737 							else if (kind == "unit")
1738 								txt += " " + sp.text();
1739 						}
1740 						else if (sp.tagName() == "text:list-item")
1741 						{
1742 							for (QDomElement paral = sp.firstChildElement(); !paral.isNull(); paral = paral.nextSiblingElement())
1743 							{
1744 								ObjStyle plStyle = tmpOStyle;
1745 								if (paral.hasAttribute("text:style-name"))
1746 									resovleStyle(plStyle, paral.attribute("text:style-name"));
1747 								ParagraphStyle tmpStyle = newStyle;
1748 								applyParagraphStyle(tmpStyle, plStyle);
1749 								for (QDomNode spnl = paral.firstChild(); !spnl.isNull(); spnl = spnl.nextSibling())
1750 								{
1751 									CharStyle tmpCStyle = tmpStyle.charStyle();
1752 									QDomElement spl = spnl.toElement();
1753 									ObjStyle clStyle = plStyle;
1754 									if (spnl.isElement() && (spl.tagName() == "text:span"))
1755 									{
1756 										if (spl.hasAttribute("text:style-name"))
1757 											resovleStyle(clStyle, spl.attribute("text:style-name"));
1758 									}
1759 									applyCharacterStyle(tmpCStyle, clStyle);
1760 									maxFsize = qMax(maxFsize, clStyle.fontSize);
1761 									if (spnl.isElement())
1762 									{
1763 										if (spl.tagName() == "text:span")
1764 										{
1765 											if (spl.tagName() == "text:s")
1766 												txt = " ";
1767 											else if (spl.tagName() == "text:tab")
1768 												txt = SpecialChars::TAB;
1769 											else if (spl.tagName() == "text:line-break")
1770 												txt = SpecialChars::LINEBREAK;
1771 											else
1772 												txt = spl.text();
1773 										}
1774 									}
1775 									else if (spnl.isText())
1776 									{
1777 										QDomText t = spnl.toText();
1778 									}
1779 									insertChars(item, txt, tmpStyle, tmpCStyle, posC);
1780 								}
1781 								item->itemText.insertChars(posC, SpecialChars::PARSEP);
1782 								item->itemText.applyStyle(posC, tmpStyle);
1783 								posC = item->itemText.length();
1784 							}
1785 						}
1786 					}
1787 					else if (spn.isText())
1788 					{
1789 						QDomText t = spn.toText();
1790 						txt = t.data();
1791 					}
1792 					insertChars(item, txt, tmpStyle, tmpCStyle, posC);
1793 				}
1794 			}
1795 			if (pStyle.lineHeight < 0.0)
1796 				tmpStyle.setLineSpacingMode(ParagraphStyle::AutomaticLineSpacing);
1797 			else
1798 			{
1799 				tmpStyle.setLineSpacingMode(ParagraphStyle::FixedLineSpacing);
1800 				if (pStyle.absLineHeight)
1801 					tmpStyle.setLineSpacing(pStyle.lineHeight);
1802 				else
1803 					tmpStyle.setLineSpacing(pStyle.lineHeight * maxFsize);
1804 			}
1805 			item->itemText.insertChars(posC, SpecialChars::PARSEP);
1806 			item->itemText.applyStyle(posC, tmpStyle);
1807 			posC = item->itemText.length();
1808 		}
1809 		else
1810 		{
1811 			QString txt = para.text();
1812 			ParagraphStyle tmpStyle = newStyle;
1813 			applyParagraphStyle(tmpStyle, tmpOStyle);
1814 			CharStyle tmpCStyle = tmpStyle.charStyle();
1815 			applyCharacterStyle(tmpCStyle, tmpOStyle);
1816 			if (tmpOStyle.lineHeight < 0.0)
1817 				tmpStyle.setLineSpacingMode(ParagraphStyle::AutomaticLineSpacing);
1818 			else
1819 			{
1820 				tmpStyle.setLineSpacingMode(ParagraphStyle::FixedLineSpacing);
1821 				if (tmpOStyle.absLineHeight)
1822 					tmpStyle.setLineSpacing(tmpOStyle.lineHeight);
1823 				else
1824 					tmpStyle.setLineSpacing(tmpOStyle.lineHeight * tmpOStyle.fontSize);
1825 			}
1826 			insertChars(item, txt, tmpStyle, tmpCStyle, posC);
1827 			item->itemText.insertChars(posC, SpecialChars::PARSEP);
1828 			item->itemText.applyStyle(posC, tmpStyle);
1829 			posC = item->itemText.length();
1830 		}
1831 	}
1832 	item->itemText.trim();
1833 }
1834 
insertChars(PageItem * item,QString & txt,ParagraphStyle & tmpStyle,CharStyle & tmpCStyle,int & posC)1835 void OdgPlug::insertChars(PageItem *item, QString &txt, ParagraphStyle &tmpStyle, CharStyle &tmpCStyle, int &posC)
1836 {
1837 	if (txt.length() > 0)
1838 	{
1839 		item->itemText.insertChars(posC, txt);
1840 		item->itemText.applyStyle(posC, tmpStyle);
1841 		item->itemText.applyCharStyle(posC, txt.length(), tmpCStyle);
1842 		posC = item->itemText.length();
1843 		txt = "";
1844 	}
1845 }
1846 
applyCharacterStyle(CharStyle & tmpCStyle,ObjStyle & oStyle)1847 void OdgPlug::applyCharacterStyle(CharStyle &tmpCStyle, ObjStyle &oStyle)
1848 {
1849 	tmpCStyle.setFont((*m_Doc->AllFonts)[oStyle.fontName]);
1850 	tmpCStyle.setFontSize(oStyle.fontSize * 10);
1851 	tmpCStyle.setFillColor(oStyle.currColorText);
1852 	tmpCStyle.setBackColor(oStyle.currColorBText);
1853 	StyleFlag styleEffects = tmpCStyle.effects();
1854 	if ((oStyle.textPos.startsWith("super")) || (oStyle.textPos.startsWith("sub")))
1855 	{
1856 		if (oStyle.textPos.startsWith("super"))
1857 			styleEffects |= ScStyle_Superscript;
1858 		else
1859 			styleEffects |= ScStyle_Subscript;
1860 	}
1861 	if (oStyle.textOutline == "true")
1862 	{
1863 		styleEffects |= ScStyle_Outline;
1864 		tmpCStyle.setOutlineWidth(30);
1865 		tmpCStyle.setFillColor("White");
1866 		tmpCStyle.setStrokeColor(oStyle.currColorText);
1867 	}
1868 	if (oStyle.textUnderline)
1869 	{
1870 		styleEffects |= ScStyle_Underline;
1871 		tmpCStyle.setUnderlineOffset(-1);
1872 		tmpCStyle.setUnderlineWidth(-1);
1873 		tmpCStyle.setStrokeColor(oStyle.textUnderlineColor);
1874 	}
1875 	if (oStyle.textStrikeThrough)
1876 	{
1877 		if (oStyle.textUnderlineWords)
1878 			styleEffects |= ScStyle_UnderlineWords;
1879 		else
1880 			styleEffects |= ScStyle_Strikethrough;
1881 		tmpCStyle.setStrikethruOffset(-1);
1882 		tmpCStyle.setStrikethruWidth(-1);
1883 		tmpCStyle.setStrokeColor(oStyle.currColorText);
1884 	}
1885 	if (oStyle.textShadow)
1886 	{
1887 		styleEffects |= ScStyle_Shadowed;
1888 		tmpCStyle.setShadowXOffset(30);
1889 		tmpCStyle.setShadowYOffset(-30);
1890 		tmpCStyle.setStrokeColor(oStyle.currColorText);
1891 	}
1892 	tmpCStyle.setFeatures(styleEffects.featureList());
1893 }
1894 
applyParagraphStyle(ParagraphStyle & tmpStyle,ObjStyle & oStyle)1895 void OdgPlug::applyParagraphStyle(ParagraphStyle &tmpStyle, ObjStyle &oStyle)
1896 {
1897 	tmpStyle.setAlignment(oStyle.textAlign);
1898 	tmpStyle.setLeftMargin(oStyle.margin_left);
1899 	tmpStyle.setRightMargin(oStyle.margin_right);
1900 	tmpStyle.setFirstIndent(oStyle.textIndent);
1901 	tmpStyle.setGapAfter(oStyle.margin_bottom);
1902 	tmpStyle.setGapBefore(oStyle.margin_top);
1903 }
1904 
parseTransform(const QString & transform,double * rotation,double * transX,double * transY)1905 void OdgPlug::parseTransform(const QString &transform, double *rotation, double *transX, double *transY)
1906 {
1907 	double dx, dy;
1908 	QStringList subtransforms = transform.split(')', Qt::SkipEmptyParts);
1909 	QStringList::ConstIterator it = subtransforms.begin();
1910 	QStringList::ConstIterator end = subtransforms.end();
1911 	for (; it != end; ++it)
1912 	{
1913 		QStringList subtransform = (*it).split('(', Qt::SkipEmptyParts);
1914 		subtransform[0] = subtransform[0].trimmed().toLower();
1915 		subtransform[1] = subtransform[1].simplified();
1916 		QRegExp reg("[,( ]");
1917 		QStringList params = subtransform[1].split(reg, Qt::SkipEmptyParts);
1918 		if (subtransform[0].startsWith(";") || subtransform[0].startsWith(","))
1919 			subtransform[0] = subtransform[0].right(subtransform[0].length() - 1);
1920 		if (subtransform[0] == "rotate")
1921 		{
1922 			*rotation = -parseUnit(params[0]) * 180 / M_PI;
1923 		}
1924 		else if (subtransform[0] == "translate")
1925 		{
1926 			if (params.count() == 2)
1927 			{
1928 				dx = parseUnit(params[0]);
1929 				dy = parseUnit(params[1]);
1930 			}
1931 			else
1932 			{
1933 				dx = parseUnit(params[0]);
1934 				dy = 0.0;
1935 			}
1936 			*transX = dx;
1937 			*transY = dy;
1938 		}
1939 	}
1940 }
1941 
parseTransform(FPointArray * composite,const QString & transform)1942 void OdgPlug::parseTransform(FPointArray *composite, const QString &transform)
1943 {
1944 	double dx, dy;
1945 	QTransform result;
1946 	QStringList subtransforms = transform.split(')', Qt::SkipEmptyParts);
1947 	QStringList::ConstIterator it = subtransforms.begin();
1948 	QStringList::ConstIterator end = subtransforms.end();
1949 	for (; it != end; ++it)
1950 	{
1951 		QStringList subtransform = (*it).split('(', Qt::SkipEmptyParts);
1952 		subtransform[0] = subtransform[0].trimmed().toLower();
1953 		subtransform[1] = subtransform[1].simplified();
1954 		QRegExp reg("[,( ]");
1955 		QStringList params = subtransform[1].split(reg, Qt::SkipEmptyParts);
1956 		if (subtransform[0].startsWith(";") || subtransform[0].startsWith(","))
1957 			subtransform[0] = subtransform[0].right(subtransform[0].length() - 1);
1958 		if (subtransform[0] == "rotate")
1959 		{
1960 			result = QTransform();
1961 			result.rotate(-parseUnit(params[0]) * 180 / M_PI);
1962 			composite->map(result);
1963 		}
1964 		else if (subtransform[0] == "translate")
1965 		{
1966 			if (params.count() == 2)
1967 			{
1968 				dx = parseUnit(params[0]);
1969 				dy = parseUnit(params[1]);
1970 			}
1971 			else
1972 			{
1973 				dx = parseUnit(params[0]);
1974 				dy =0.0;
1975 			}
1976 			result = QTransform();
1977 			result.translate(dx, dy);
1978 			composite->map(result);
1979 		}
1980 		else if (subtransform[0] == "skewx")
1981 		{
1982 			result = QTransform();
1983 			result.shear(-tan(ScCLocale::toDoubleC(params[0])), 0.0);
1984 			composite->map(result);
1985 		}
1986 		else if (subtransform[0] == "skewy")
1987 		{
1988 			result = QTransform();
1989 			result.shear(0.0, -tan(ScCLocale::toDoubleC(params[0])));
1990 			composite->map(result);
1991 		}
1992 	}
1993 }
1994 
parseViewBox(const QDomElement & object,double * x,double * y,double * w,double * h)1995 void OdgPlug::parseViewBox( const QDomElement& object, double *x, double *y, double *w, double *h )
1996 {
1997 	if (!object.attribute( "svg:viewBox" ).isEmpty())
1998 	{
1999 		QString viewbox( object.attribute( "svg:viewBox" ) );
2000 		QStringList points = viewbox.replace( QRegExp(","), " ").simplified().split( ' ', Qt::SkipEmptyParts );
2001 		*x = ScCLocale::toDoubleC(points[0]);
2002 		*y = ScCLocale::toDoubleC(points[1]);
2003 		*w = ScCLocale::toDoubleC(points[2]);
2004 		*h = ScCLocale::toDoubleC(points[3]);
2005 	}
2006 }
2007 
appendPoints(FPointArray * composite,const QDomElement & object,bool closePath)2008 void OdgPlug::appendPoints(FPointArray *composite, const QDomElement& object, bool closePath)
2009 {
2010 	double x = parseUnit(object.attribute("svg:x"));
2011 	double y = parseUnit(object.attribute("svg:y")) ;
2012 	double w = parseUnit(object.attribute("svg:width"));
2013 	double h = parseUnit(object.attribute("svg:height"));
2014 	double vx = 0;
2015 	double vy = 0;
2016 	double vw = 1;
2017 	double vh = 1;
2018 	parseViewBox(object, &vx, &vy, &vw, &vh);
2019 	double sx = (vw != 0.0) ? (w / vw) : w;
2020 	double sy = (vh != 0.0) ? (h / vh) : h;
2021 	QStringList ptList = object.attribute( "draw:points" ).split( ' ', Qt::SkipEmptyParts );
2022 	FPoint point, firstP;
2023 	bool bFirst = true;
2024 	for ( QStringList::Iterator it = ptList.begin(); it != ptList.end(); ++it)
2025 	{
2026 		point = FPoint(ScCLocale::toDoubleC((*it).section( ',', 0, 0 )), ScCLocale::toDoubleC((*it).section( ',', 1, 1 )));
2027 		if (bFirst)
2028 		{
2029 			composite->addPoint(point);
2030 			composite->addPoint(point);
2031 			firstP = point;
2032 			bFirst = false;
2033 		}
2034 		else
2035 		{
2036 			composite->addPoint(point);
2037 			composite->addPoint(point);
2038 			composite->addPoint(point);
2039 			composite->addPoint(point);
2040 		}
2041 	}
2042 	if (closePath)
2043 	{
2044 		composite->addPoint(firstP);
2045 		composite->addPoint(firstP);
2046 	}
2047 	QTransform mat;
2048 	mat.translate(x, y);
2049 	mat.scale(sx, sy);
2050 	composite->map(mat);
2051 }
2052 
parseStyles(QDomElement & sp)2053 void OdgPlug::parseStyles(QDomElement &sp)
2054 {
2055 	for (QDomElement spd = sp.firstChildElement(); !spd.isNull(); spd = spd.nextSiblingElement())
2056 	{
2057 		if (spd.tagName() == "draw:marker")
2058 		{
2059 			DrawStyle currStyle;
2060 			currStyle.markerPath = AttributeValue(spd.attribute("svg:d", ""));
2061 			currStyle.markerViewBox = AttributeValue(spd.attribute("svg:viewBox", ""));
2062 			QString id = spd.attribute("draw:display-name");
2063 			QString id2 = spd.attribute("draw:name");
2064 			if (id2.isEmpty())
2065 				m_Styles.insert(id, currStyle);
2066 			else
2067 				m_Styles.insert(id2, currStyle);
2068 		}
2069 		else if (spd.tagName() == "draw:stroke-dash")
2070 		{
2071 			DrawStyle currStyle;
2072 			currStyle.stroke_dash_distance = AttributeValue(spd.attribute("draw:distance", ""));
2073 			currStyle.stroke_dash_dots1 = AttributeValue(spd.attribute("draw:dots1", ""));
2074 			currStyle.stroke_dash_dots1_length = AttributeValue(spd.attribute("draw:dots1-length", ""));
2075 			currStyle.stroke_dash_dots2 = AttributeValue(spd.attribute("draw:dots2", ""));
2076 			currStyle.stroke_dash_dots2_length = AttributeValue(spd.attribute("draw:dots2-length", ""));
2077 			currStyle.stroke_dash_style = AttributeValue(spd.attribute("draw:style", ""));
2078 			QString id = spd.attribute("draw:display-name");
2079 			QString id2 = spd.attribute("draw:name");
2080 			if (id2.isEmpty())
2081 				m_Styles.insert(id, currStyle);
2082 			else
2083 				m_Styles.insert(id2, currStyle);
2084 		}
2085 		else if (spd.tagName() == "draw:gradient")
2086 		{
2087 			DrawStyle currStyle;
2088 			currStyle.gradientAngle = AttributeValue(spd.attribute("draw:angle", ""));
2089 			currStyle.gradientBorder = AttributeValue(spd.attribute("draw:border", ""));
2090 			currStyle.gradientEndColor = AttributeValue(spd.attribute("draw:end-color", ""));
2091 			currStyle.gradientEndShade = AttributeValue(spd.attribute("draw:end-intensity", ""));
2092 			currStyle.gradientStartColor = AttributeValue(spd.attribute("draw:start-color", ""));
2093 			currStyle.gradientStartShade = AttributeValue(spd.attribute("draw:start-intensity", ""));
2094 			currStyle.gradientCenterX = AttributeValue(spd.attribute("draw:cx", ""));
2095 			currStyle.gradientCenterY = AttributeValue(spd.attribute("draw:cy", ""));
2096 			currStyle.gradientType = AttributeValue(spd.attribute("draw:style", ""));
2097 			QString id = spd.attribute("draw:display-name");
2098 			QString id2 = spd.attribute("draw:name");
2099 			if (id2.isEmpty())
2100 				m_Styles.insert(id, currStyle);
2101 			else
2102 				m_Styles.insert(id2, currStyle);
2103 		}
2104 		else if (spd.tagName() == "draw:opacity")
2105 		{
2106 			DrawStyle currStyle;
2107 			currStyle.gradientAngle = AttributeValue(spd.attribute("draw:angle", ""));
2108 			currStyle.gradientBorder = AttributeValue(spd.attribute("draw:border", ""));
2109 			currStyle.opacityEnd = AttributeValue(spd.attribute("draw:end", ""));
2110 			currStyle.opacityStart = AttributeValue(spd.attribute("draw:start", ""));
2111 			currStyle.gradientCenterX = AttributeValue(spd.attribute("draw:cx", ""));
2112 			currStyle.gradientCenterY = AttributeValue(spd.attribute("draw:cy", ""));
2113 			currStyle.gradientType = AttributeValue(spd.attribute("draw:style", ""));
2114 			QString id = spd.attribute("draw:display-name");
2115 			QString id2 = spd.attribute("draw:name");
2116 			if (id2.isEmpty())
2117 				m_Styles.insert(id, currStyle);
2118 			else
2119 				m_Styles.insert(id2, currStyle);
2120 		}
2121 		else if (spd.tagName() == "draw:hatch")
2122 		{
2123 			DrawStyle currStyle;
2124 			currStyle.hatchColor = AttributeValue(spd.attribute("draw:color", ""));
2125 			currStyle.hatchDistance = AttributeValue(spd.attribute("draw:distance", ""));
2126 			currStyle.hatchRotation = AttributeValue(spd.attribute("draw:rotation", ""));
2127 			currStyle.hatchStyle = AttributeValue(spd.attribute("draw:style", ""));
2128 			QString id = spd.attribute("draw:display-name");
2129 			QString id2 = spd.attribute("draw:name");
2130 			if (id2.isEmpty())
2131 				m_Styles.insert(id, currStyle);
2132 			else
2133 				m_Styles.insert(id2, currStyle);
2134 		}
2135 		else if (spd.tagName() == "draw:fill-image")
2136 		{
2137 			DrawStyle currStyle;
2138 			currStyle.patternPath = AttributeValue(spd.attribute("xlink:href", ""));
2139 			if (!currStyle.patternPath.valid)
2140 			{
2141 				if (spd.hasChildNodes())
2142 				{
2143 					for (QDomElement nc = spd.firstChildElement(); !nc.isNull(); nc = nc.nextSiblingElement())
2144 					{
2145 						if (nc.tagName() == "office:binary-data")
2146 							currStyle.patternData = AttributeValue(nc.text());
2147 					}
2148 				}
2149 			}
2150 			QString id = spd.attribute("draw:display-name");
2151 			QString id2 = spd.attribute("draw:name");
2152 			if (id2.isEmpty())
2153 				m_Styles.insert(id, currStyle);
2154 			else
2155 				m_Styles.insert(id2, currStyle);
2156 		}
2157 		else if (spd.tagName() == "style:style")
2158 		{
2159 			DrawStyle currStyle;
2160 			for (QDomElement spe = spd.firstChildElement(); !spe.isNull(); spe = spe.nextSiblingElement())
2161 			{
2162 				if (spe.tagName() == "style:graphic-properties")
2163 				{
2164 					currStyle.fillMode = AttributeValue(spe.attribute("draw:fill", ""));
2165 					currStyle.currColorFill = AttributeValue(spe.attribute("draw:fill-color", ""));
2166 					currStyle.strokeMode = AttributeValue(spe.attribute("draw:stroke", ""));
2167 					currStyle.currColorStroke = AttributeValue(spe.attribute("svg:stroke-color", ""));
2168 					currStyle.currColorShadow = AttributeValue(spe.attribute("draw:shadow-color", ""));
2169 					currStyle.hasShadow = AttributeValue(spe.attribute("draw:shadow", ""));
2170 					currStyle.shadowX = AttributeValue(spe.attribute("draw:shadow-offset-x", ""));
2171 					currStyle.shadowY = AttributeValue(spe.attribute("draw:shadow-offset-y", ""));
2172 					currStyle.shadowTrans = AttributeValue(spe.attribute("draw:shadow-opacity", ""));
2173 					currStyle.strokeOpacity = AttributeValue(spe.attribute("svg:stroke-opacity", ""));
2174 					currStyle.LineW = AttributeValue(spe.attribute("svg:stroke-width", ""));
2175 					currStyle.fillOpacity = AttributeValue(spe.attribute("draw:opacity", ""));
2176 					currStyle.gradientName = AttributeValue(spe.attribute("draw:fill-gradient-name", ""));
2177 					currStyle.dashName = AttributeValue(spe.attribute("draw:stroke-dash", ""));
2178 					currStyle.startMarkerName = AttributeValue(spe.attribute("draw:marker-start", ""));
2179 					currStyle.startMarkerWidth = AttributeValue(spe.attribute("draw:marker-start-width", ""));
2180 					currStyle.startMarkerCentered = AttributeValue(spe.attribute("draw:marker-start-center", ""));
2181 					currStyle.endMarkerName = AttributeValue(spe.attribute("draw:marker-end", ""));
2182 					currStyle.endMarkerWidth = AttributeValue(spe.attribute("draw:marker-end-width", ""));
2183 					currStyle.endMarkerCentered = AttributeValue(spe.attribute("draw:marker-end-center", ""));
2184 					currStyle.measureDist = AttributeValue(spe.attribute("draw:line-distance"));
2185 					currStyle.patternName = AttributeValue(spe.attribute("draw:fill-image-name", ""));
2186 					currStyle.patternWidth = AttributeValue(spe.attribute("draw:fill-image-width", ""));
2187 					currStyle.patternHeight = AttributeValue(spe.attribute("draw:fill-image-height", ""));
2188 					currStyle.patternX = AttributeValue(spe.attribute("draw:fill-image-ref-point-x", ""));
2189 					currStyle.patternY = AttributeValue(spe.attribute("draw:fill-image-ref-point-y", ""));
2190 					currStyle.patternStretch = AttributeValue(spe.attribute("style:repeat", ""));
2191 					currStyle.hatchName = AttributeValue(spe.attribute("draw:fill-hatch-name", ""));
2192 					currStyle.hatchSolidFill = AttributeValue(spe.attribute("draw:fill-hatch-solid", ""));
2193 					currStyle.opacityName = AttributeValue(spe.attribute("draw:opacity-name", ""));
2194 					currStyle.verticalAlignment = AttributeValue(spe.attribute("draw:textarea-vertical-align", ""));
2195 				}
2196 				else if (spe.tagName() == "style:paragraph-properties")
2197 				{
2198 					currStyle.margin_top = AttributeValue(spe.attribute("fo:margin-top", ""));
2199 					currStyle.margin_bottom = AttributeValue(spe.attribute("fo:margin-bottom", ""));
2200 					currStyle.margin_left = AttributeValue(spe.attribute("fo:margin-left", ""));
2201 					currStyle.margin_right = AttributeValue(spe.attribute("fo:margin-right", ""));
2202 					currStyle.textIndent = AttributeValue(spe.attribute("fo:text-indent", ""));
2203 					currStyle.textAlign = AttributeValue(spe.attribute("fo:text-align", ""));
2204 					currStyle.lineHeight = AttributeValue(spe.attribute("fo:line-height", ""));
2205 				}
2206 				else if (spe.tagName() == "style:text-properties")
2207 				{
2208 					currStyle.fontName = AttributeValue(spe.attribute("style:font-name", ""));
2209 					if (!currStyle.fontName.valid)
2210 						currStyle.fontName = AttributeValue(spe.attribute("fo:font-family", ""));
2211 					currStyle.fontSize = AttributeValue(spe.attribute("fo:font-size", ""));
2212 					currStyle.fontColor = AttributeValue(spe.attribute("fo:color", ""));
2213 					currStyle.textBackgroundColor = AttributeValue(spe.attribute("fo:background-color", ""));
2214 					currStyle.textPos = AttributeValue(spe.attribute("style:text-position", ""));
2215 					currStyle.textOutline = AttributeValue(spe.attribute("style:text-outline", ""));
2216 					currStyle.textUnderline = AttributeValue(spe.attribute("style:text-underline-style", ""));
2217 					currStyle.textUnderlineWords = AttributeValue(spe.attribute("style:text-underline-mode", ""));
2218 					currStyle.textUnderlineColor = AttributeValue(spe.attribute("style:text-underline-color", ""));
2219 					currStyle.textStrikeThrough = AttributeValue(spe.attribute("style:text-line-through-style", ""));
2220 					currStyle.textShadow = AttributeValue(spe.attribute("fo:text-shadow", ""));
2221 				}
2222 				else if (spe.tagName() == "style:drawing-page-properties")
2223 				{
2224 					currStyle.fillMode = AttributeValue(spe.attribute("draw:fill", ""));
2225 					currStyle.currColorFill = AttributeValue(spe.attribute("draw:fill-color", ""));
2226 					currStyle.patternName = AttributeValue(spe.attribute("draw:fill-image-name", ""));
2227 					currStyle.gradientName = AttributeValue(spe.attribute("draw:fill-gradient-name", ""));
2228 					currStyle.hatchName = AttributeValue(spe.attribute("draw:fill-hatch-name", ""));
2229 					currStyle.hatchSolidFill = AttributeValue(spe.attribute("draw:fill-hatch-solid", ""));
2230 					currStyle.opacityName = AttributeValue(spe.attribute("draw:opacity-name", ""));
2231 				}
2232 			}
2233 			currStyle.parentStyle = AttributeValue(spd.attribute("style:parent-style-name", ""));
2234 			m_Styles.insert(spd.attribute("style:name"), currStyle);
2235 		}
2236 		else if (spd.tagName() == "style:page-layout")
2237 		{
2238 			DrawStyle currStyle;
2239 			for (QDomElement spe = spd.firstChildElement(); !spe.isNull(); spe = spe.nextSiblingElement())
2240 			{
2241 				if (spe.tagName() == "style:page-layout-properties")
2242 				{
2243 					currStyle.margin_top = AttributeValue(spe.attribute("fo:margin-top", ""));
2244 					currStyle.margin_bottom = AttributeValue(spe.attribute("fo:margin-bottom", ""));
2245 					currStyle.margin_left = AttributeValue(spe.attribute("fo:margin-left", ""));
2246 					currStyle.margin_right = AttributeValue(spe.attribute("fo:margin-right", ""));
2247 					currStyle.page_width = AttributeValue(spe.attribute("fo:page-width", ""));
2248 					currStyle.page_height = AttributeValue(spe.attribute("fo:page-height", ""));
2249 				}
2250 			}
2251 			currStyle.parentStyle = AttributeValue(spd.attribute("style:parent-style-name", ""));
2252 			m_Styles.insert(spd.attribute("style:name"), currStyle);
2253 		}
2254 	}
2255 }
2256 
getStyleName(QDomElement & e)2257 QString OdgPlug::getStyleName(QDomElement &e)
2258 {
2259 	QString styleName = "standard";
2260 	if (e.hasAttribute("draw:style-name"))
2261 		styleName = e.attribute("draw:style-name");
2262 	else if (e.hasAttribute("presentation:style-name"))
2263 		styleName = e.attribute("presentation:style-name");
2264 	return styleName;
2265 }
2266 
resovleStyle(ObjStyle & tmpOStyle,const QString & pAttrs)2267 void OdgPlug::resovleStyle(ObjStyle &tmpOStyle, const QString& pAttrs)
2268 {
2269 	if (m_Styles.contains(pAttrs))
2270 	{
2271 		DrawStyle actStyle;
2272 		DrawStyle currStyle = m_Styles[pAttrs];
2273 		QStringList parents;
2274 		while (currStyle.parentStyle.valid)
2275 		{
2276 			if (m_Styles.contains(currStyle.parentStyle.value))
2277 			{
2278 				parents.prepend(currStyle.parentStyle.value);
2279 				currStyle = m_Styles[currStyle.parentStyle.value];
2280 			}
2281 			else
2282 				break;
2283 		}
2284 		parents.append(pAttrs);
2285 		if (!parents.isEmpty())
2286 		{
2287 			for (int p = 0; p < parents.count(); p++)
2288 			{
2289 				currStyle = m_Styles[parents[p]];
2290 				if (currStyle.markerViewBox.valid)
2291 					actStyle.markerViewBox = AttributeValue(currStyle.markerViewBox.value);
2292 				if (currStyle.markerPath.valid)
2293 					actStyle.markerPath = AttributeValue(currStyle.markerPath.value);
2294 				if (currStyle.startMarkerName.valid)
2295 					actStyle.startMarkerName = AttributeValue(currStyle.startMarkerName.value);
2296 				if (currStyle.startMarkerWidth.valid)
2297 					actStyle.startMarkerWidth = AttributeValue(currStyle.startMarkerWidth.value);
2298 				if (currStyle.startMarkerCentered.valid)
2299 					actStyle.startMarkerCentered = AttributeValue(currStyle.startMarkerCentered.value);
2300 				if (currStyle.endMarkerName.valid)
2301 					actStyle.endMarkerName = AttributeValue(currStyle.endMarkerName.value);
2302 				if (currStyle.endMarkerWidth.valid)
2303 					actStyle.endMarkerWidth = AttributeValue(currStyle.endMarkerWidth.value);
2304 				if (currStyle.endMarkerCentered.valid)
2305 					actStyle.endMarkerCentered = AttributeValue(currStyle.endMarkerCentered.value);
2306 				if (currStyle.stroke_dash_distance.valid)
2307 					actStyle.stroke_dash_distance = AttributeValue(currStyle.stroke_dash_distance.value);
2308 				if (currStyle.stroke_dash_dots1.valid)
2309 					actStyle.stroke_dash_dots1 = AttributeValue(currStyle.stroke_dash_dots1.value);
2310 				if (currStyle.stroke_dash_dots1_length.valid)
2311 					actStyle.stroke_dash_dots1_length = AttributeValue(currStyle.stroke_dash_dots1_length.value);
2312 				if (currStyle.stroke_dash_dots2.valid)
2313 					actStyle.stroke_dash_dots2 = AttributeValue(currStyle.stroke_dash_dots2.value);
2314 				if (currStyle.stroke_dash_dots2_length.valid)
2315 					actStyle.stroke_dash_dots2_length = AttributeValue(currStyle.stroke_dash_dots2_length.value);
2316 				if (currStyle.stroke_dash_style.valid)
2317 					actStyle.stroke_dash_style = AttributeValue(currStyle.stroke_dash_style.value);
2318 				if (currStyle.fillMode.valid)
2319 					actStyle.fillMode = AttributeValue(currStyle.fillMode.value);
2320 				if (currStyle.currColorFill.valid)
2321 					actStyle.currColorFill = AttributeValue(currStyle.currColorFill.value);
2322 				if (currStyle.strokeMode.valid)
2323 					actStyle.strokeMode = AttributeValue(currStyle.strokeMode.value);
2324 				if (currStyle.currColorStroke.valid)
2325 					actStyle.currColorStroke = AttributeValue(currStyle.currColorStroke.value);
2326 				if (currStyle.currColorShadow.valid)
2327 					actStyle.currColorShadow = AttributeValue(currStyle.currColorShadow.value);
2328 				if (currStyle.hasShadow.valid)
2329 					actStyle.hasShadow = AttributeValue(currStyle.hasShadow.value);
2330 				if (currStyle.shadowX.valid)
2331 					actStyle.shadowX = AttributeValue(currStyle.shadowX.value);
2332 				if (currStyle.shadowY.valid)
2333 					actStyle.shadowY = AttributeValue(currStyle.shadowY.value);
2334 				if (currStyle.shadowTrans.valid)
2335 					actStyle.shadowTrans = AttributeValue(currStyle.shadowTrans.value);
2336 				if (currStyle.fillOpacity.valid)
2337 					actStyle.fillOpacity = AttributeValue(currStyle.fillOpacity.value);
2338 				if (currStyle.strokeOpacity.valid)
2339 					actStyle.strokeOpacity = AttributeValue(currStyle.strokeOpacity.value);
2340 				if (currStyle.LineW.valid)
2341 					actStyle.LineW = AttributeValue(currStyle.LineW.value);
2342 				if (currStyle.fontName.valid)
2343 					actStyle.fontName = AttributeValue(currStyle.fontName.value);
2344 				if (currStyle.fontSize.valid)
2345 					actStyle.fontSize = AttributeValue(currStyle.fontSize.value);
2346 				if (currStyle.margin_top.valid)
2347 					actStyle.margin_top = AttributeValue(currStyle.margin_top.value);
2348 				if (currStyle.margin_bottom.valid)
2349 					actStyle.margin_bottom = AttributeValue(currStyle.margin_bottom.value);
2350 				if (currStyle.margin_left.valid)
2351 					actStyle.margin_left = AttributeValue(currStyle.margin_left.value);
2352 				if (currStyle.margin_right.valid)
2353 					actStyle.margin_right = AttributeValue(currStyle.margin_right.value);
2354 				if (currStyle.page_width.valid)
2355 					actStyle.page_width = AttributeValue(currStyle.page_width.value);
2356 				if (currStyle.page_height.valid)
2357 					actStyle.page_height = AttributeValue(currStyle.page_height.value);
2358 				if (currStyle.page_layout_name.valid)
2359 					actStyle.page_layout_name = AttributeValue(currStyle.page_layout_name.value);
2360 				if (currStyle.textIndent.valid)
2361 					actStyle.textIndent = AttributeValue(currStyle.textIndent.value);
2362 				if (currStyle.textAlign.valid)
2363 					actStyle.textAlign = AttributeValue(currStyle.textAlign.value);
2364 				if (currStyle.textPos.valid)
2365 					actStyle.textPos = AttributeValue(currStyle.textPos.value);
2366 				if (currStyle.textOutline.valid)
2367 					actStyle.textOutline = AttributeValue(currStyle.textOutline.value);
2368 				if (currStyle.textUnderline.valid)
2369 					actStyle.textUnderline = AttributeValue(currStyle.textUnderline.value);
2370 				if (currStyle.textUnderlineWords.valid)
2371 					actStyle.textUnderlineWords = AttributeValue(currStyle.textUnderlineWords.value);
2372 				if (currStyle.textUnderlineColor.valid)
2373 					actStyle.textUnderlineColor = AttributeValue(currStyle.textUnderlineColor.value);
2374 				if (currStyle.textStrikeThrough.valid)
2375 					actStyle.textStrikeThrough = AttributeValue(currStyle.textStrikeThrough.value);
2376 				if (currStyle.textShadow.valid)
2377 					actStyle.textShadow = AttributeValue(currStyle.textShadow.value);
2378 				if (currStyle.lineHeight.valid)
2379 					actStyle.lineHeight = AttributeValue(currStyle.lineHeight.value);
2380 				if (currStyle.fontColor.valid)
2381 					actStyle.fontColor = AttributeValue(currStyle.fontColor.value);
2382 				if (currStyle.textBackgroundColor.valid)
2383 					actStyle.textBackgroundColor = AttributeValue(currStyle.textBackgroundColor.value);
2384 				if (currStyle.gradientAngle.valid)
2385 					actStyle.gradientAngle = AttributeValue(currStyle.gradientAngle.value);
2386 				if (currStyle.gradientBorder.valid)
2387 					actStyle.gradientBorder = AttributeValue(currStyle.gradientBorder.value);
2388 				if (currStyle.gradientEndColor.valid)
2389 					actStyle.gradientEndColor = AttributeValue(currStyle.gradientEndColor.value);
2390 				if (currStyle.gradientEndShade.valid)
2391 					actStyle.gradientEndShade = AttributeValue(currStyle.gradientEndShade.value);
2392 				if (currStyle.gradientStartColor.valid)
2393 					actStyle.gradientStartColor = AttributeValue(currStyle.gradientStartColor.value);
2394 				if (currStyle.gradientStartShade.valid)
2395 					actStyle.gradientStartShade = AttributeValue(currStyle.gradientStartShade.value);
2396 				if (currStyle.gradientCenterX.valid)
2397 					actStyle.gradientCenterX = AttributeValue(currStyle.gradientCenterX.value);
2398 				if (currStyle.gradientCenterY.valid)
2399 					actStyle.gradientCenterY = AttributeValue(currStyle.gradientCenterY.value);
2400 				if (currStyle.gradientType.valid)
2401 					actStyle.gradientType = AttributeValue(currStyle.gradientType.value);
2402 				if (currStyle.gradientName.valid)
2403 					actStyle.gradientName = AttributeValue(currStyle.gradientName.value);
2404 				if (currStyle.dashName.valid)
2405 					actStyle.dashName = AttributeValue(currStyle.dashName.value);
2406 				if (currStyle.measureDist.valid)
2407 					actStyle.measureDist = AttributeValue(currStyle.measureDist.value);
2408 				if (currStyle.patternName.valid)
2409 					actStyle.patternName = AttributeValue(currStyle.patternName.value);
2410 				if (currStyle.patternPath.valid)
2411 					actStyle.patternPath = AttributeValue(currStyle.patternPath.value);
2412 				if (currStyle.patternData.valid)
2413 					actStyle.patternData = AttributeValue(currStyle.patternData.value);
2414 				if (currStyle.patternWidth.valid)
2415 					actStyle.patternWidth = AttributeValue(currStyle.patternWidth.value);
2416 				if (currStyle.patternHeight.valid)
2417 					actStyle.patternHeight = AttributeValue(currStyle.patternHeight.value);
2418 				if (currStyle.patternX.valid)
2419 					actStyle.patternX = AttributeValue(currStyle.patternX.value);
2420 				if (currStyle.patternY.valid)
2421 					actStyle.patternY = AttributeValue(currStyle.patternY.value);
2422 				if (currStyle.patternStretch.valid)
2423 					actStyle.patternStretch = AttributeValue(currStyle.patternStretch.value);
2424 				if (currStyle.hatchName.valid)
2425 					actStyle.hatchName = AttributeValue(currStyle.hatchName.value);
2426 				if (currStyle.hatchColor.valid)
2427 					actStyle.hatchColor = AttributeValue(currStyle.hatchColor.value);
2428 				if (currStyle.hatchDistance.valid)
2429 					actStyle.hatchDistance = AttributeValue(currStyle.hatchDistance.value);
2430 				if (currStyle.hatchRotation.valid)
2431 					actStyle.hatchRotation = AttributeValue(currStyle.hatchRotation.value);
2432 				if (currStyle.hatchStyle.valid)
2433 					actStyle.hatchStyle = AttributeValue(currStyle.hatchStyle.value);
2434 				if (currStyle.hatchSolidFill.valid)
2435 					actStyle.hatchSolidFill = AttributeValue(currStyle.hatchSolidFill.value);
2436 				if (currStyle.opacityName.valid)
2437 					actStyle.opacityName = AttributeValue(currStyle.opacityName.value);
2438 				if (currStyle.opacityEnd.valid)
2439 					actStyle.opacityEnd = AttributeValue(currStyle.opacityEnd.value);
2440 				if (currStyle.opacityStart.valid)
2441 					actStyle.opacityStart = AttributeValue(currStyle.opacityStart.value);
2442 				if (currStyle.verticalAlignment.valid)
2443 					actStyle.verticalAlignment = AttributeValue(currStyle.verticalAlignment.value);
2444 			}
2445 		}
2446 		tmpOStyle.stroke_dash_distance = -1;
2447 		tmpOStyle.stroke_dash_dots1_length = -1;
2448 		tmpOStyle.stroke_dash_dots2_length = -1;
2449 		tmpOStyle.stroke_dash_dots1 = -1;
2450 		tmpOStyle.stroke_dash_dots2 = -1;
2451 		if (actStyle.stroke_dash_style.valid)
2452 			tmpOStyle.stroke_dash_style = actStyle.stroke_dash_style.value;
2453 		if (actStyle.stroke_dash_distance.valid)
2454 			tmpOStyle.stroke_dash_distance = parseUnit(actStyle.stroke_dash_distance.value);
2455 		if (actStyle.stroke_dash_dots1.valid)
2456 			tmpOStyle.stroke_dash_dots1 = actStyle.stroke_dash_dots1.value.toInt();
2457 		if (actStyle.stroke_dash_dots1_length.valid)
2458 			tmpOStyle.stroke_dash_dots1_length = parseUnit(actStyle.stroke_dash_dots1_length.value);
2459 		if (actStyle.stroke_dash_dots2.valid)
2460 			tmpOStyle.stroke_dash_dots2 = actStyle.stroke_dash_dots2.value.toInt();
2461 		if (actStyle.stroke_dash_dots2_length.valid)
2462 			tmpOStyle.stroke_dash_dots2_length = parseUnit(actStyle.stroke_dash_dots2_length.value);
2463 
2464 		if (actStyle.currColorFill.valid)
2465 		{
2466 			if (actStyle.fillMode.valid && (actStyle.fillMode.value != "none"))
2467 				tmpOStyle.currColorFill = parseColor(actStyle.currColorFill.value);
2468 			else
2469 				tmpOStyle.currColorFill = CommonStrings::None;
2470 		}
2471 		else
2472 			tmpOStyle.currColorFill = CommonStrings::None;
2473 		if (actStyle.fillMode.valid)
2474 		{
2475 			if (actStyle.fillMode.value == "none")
2476 				tmpOStyle.fill_type = 0;
2477 			else if (actStyle.fillMode.value == "solid")
2478 				tmpOStyle.fill_type = 1;
2479 			else if (actStyle.fillMode.value == "gradient")
2480 			{
2481 				tmpOStyle.fill_type = 2;
2482 				if (actStyle.gradientName.valid)
2483 					tmpOStyle.gradientName = actStyle.gradientName.value;
2484 			}
2485 			else if (actStyle.fillMode.value == "bitmap")
2486 			{
2487 				tmpOStyle.fill_type = 3;
2488 				if (actStyle.patternName.valid)
2489 					tmpOStyle.patternName = actStyle.patternName.value;
2490 			}
2491 			else if (actStyle.fillMode.value == "hatch")
2492 			{
2493 				tmpOStyle.fill_type = 4;
2494 				if (actStyle.hatchName.valid)
2495 					tmpOStyle.hatchName = actStyle.hatchName.value;
2496 			}
2497 		}
2498 		if (actStyle.currColorStroke.valid)
2499 		{
2500 			if (actStyle.strokeMode.valid && (actStyle.strokeMode.value != "none"))
2501 				tmpOStyle.currColorStroke = parseColor(actStyle.currColorStroke.value);
2502 			else
2503 				tmpOStyle.currColorStroke = CommonStrings::None;
2504 		}
2505 		else
2506 			tmpOStyle.currColorStroke = CommonStrings::None;
2507 		if (actStyle.strokeMode.valid)
2508 		{
2509 			if (actStyle.strokeMode.value == "none")
2510 				tmpOStyle.stroke_type = 0;
2511 			else if (actStyle.strokeMode.value == "solid")
2512 				tmpOStyle.stroke_type = 1;
2513 			else if (actStyle.strokeMode.value == "dash")
2514 			{
2515 				tmpOStyle.stroke_type = 2;
2516 				if (actStyle.dashName.valid)
2517 					tmpOStyle.dashName = actStyle.dashName.value;
2518 			}
2519 		}
2520 		if (actStyle.currColorShadow.valid)
2521 			tmpOStyle.currColorShadow = parseColor(actStyle.currColorShadow.value);
2522 		if (actStyle.hasShadow.valid)
2523 			tmpOStyle.hasShadow = actStyle.hasShadow.value == "visible";
2524 		if (actStyle.shadowX.valid)
2525 			tmpOStyle.shadowX = parseUnit(actStyle.shadowX.value);
2526 		if (actStyle.shadowY.valid)
2527 			tmpOStyle.shadowY = parseUnit(actStyle.shadowY.value);
2528 		if (actStyle.shadowTrans.valid)
2529 		{
2530 			double transVal = parseUnit(actStyle.shadowTrans.value);
2531 			if (transVal > 1.0)
2532 				transVal /= 100.0;
2533 			tmpOStyle.shadowTrans = 1.0 - transVal;
2534 		}
2535 		if (actStyle.fillOpacity.valid)
2536 		{
2537 			double transVal = parseUnit(actStyle.fillOpacity.value);
2538 			if (transVal > 1.0)
2539 				transVal /= 100.0;
2540 			tmpOStyle.fillOpacity = 1.0 - transVal;
2541 		}
2542 		if (actStyle.strokeOpacity.valid)
2543 		{
2544 			double transVal = parseUnit(actStyle.strokeOpacity.value);
2545 			if (transVal > 1.0)
2546 				transVal /= 100.0;
2547 			tmpOStyle.strokeOpacity = 1.0 - transVal;
2548 		}
2549 		if (actStyle.LineW.valid)
2550 			tmpOStyle.LineW = parseUnit(actStyle.LineW.value);
2551 		if (actStyle.fontName.valid)
2552 		{
2553 			if (m_fontMap.contains(actStyle.fontName.value))
2554 				tmpOStyle.fontName = m_fontMap[actStyle.fontName.value];
2555 			else
2556 				tmpOStyle.fontName = actStyle.fontName.value;
2557 			if (!PrefsManager::instance().appPrefs.fontPrefs.AvailFonts.contains(tmpOStyle.fontName))
2558 			{
2559 				tmpOStyle.fontName = constructFontName(tmpOStyle.fontName, "");
2560 				m_fontMap[actStyle.fontName.value] = tmpOStyle.fontName;
2561 			}
2562 		}
2563 		if (actStyle.fontSize.valid)
2564 			tmpOStyle.fontSize = parseUnit(actStyle.fontSize.value);
2565 		if (actStyle.fontColor.valid)
2566 			tmpOStyle.currColorText = parseColor(actStyle.fontColor.value);
2567 		if (actStyle.textBackgroundColor.valid)
2568 			tmpOStyle.currColorBText = parseColor(actStyle.textBackgroundColor.value);
2569 		if (actStyle.margin_top.valid)
2570 			tmpOStyle.margin_top = parseUnit(actStyle.margin_top.value);
2571 		if (actStyle.margin_bottom.valid)
2572 			tmpOStyle.margin_bottom = parseUnit(actStyle.margin_bottom.value);
2573 		if (actStyle.margin_left.valid)
2574 			tmpOStyle.margin_left = parseUnit(actStyle.margin_left.value);
2575 		if (actStyle.margin_right.valid)
2576 			tmpOStyle.margin_right = parseUnit(actStyle.margin_right.value);
2577 		if (actStyle.page_layout_name.valid)
2578 		{
2579 			tmpOStyle.page_layout_name = actStyle.page_layout_name.value;
2580 			if (m_Styles.contains(tmpOStyle.page_layout_name))
2581 			{
2582 				actStyle = m_Styles[tmpOStyle.page_layout_name];
2583 				if (actStyle.page_height.valid)
2584 					tmpOStyle.page_height = parseUnit(actStyle.page_height.value);
2585 				if (actStyle.page_width.valid)
2586 					tmpOStyle.page_width = parseUnit(actStyle.page_width.value);
2587 				if (actStyle.margin_top.valid)
2588 					tmpOStyle.margin_top = parseUnit(actStyle.margin_top.value);
2589 				if (actStyle.margin_bottom.valid)
2590 					tmpOStyle.margin_bottom = parseUnit(actStyle.margin_bottom.value);
2591 				if (actStyle.margin_left.valid)
2592 					tmpOStyle.margin_left = parseUnit(actStyle.margin_left.value);
2593 				if (actStyle.margin_right.valid)
2594 					tmpOStyle.margin_right = parseUnit(actStyle.margin_right.value);
2595 			}
2596 		}
2597 		if (actStyle.textIndent.valid)
2598 			tmpOStyle.textIndent = parseUnit(actStyle.textIndent.value);
2599 		if (actStyle.textAlign.valid)
2600 		{
2601 			QString attValue = actStyle.textAlign.value;
2602 			if (attValue == "left")
2603 				tmpOStyle.textAlign = ParagraphStyle::LeftAligned;
2604 			else if (attValue == "center")
2605 				tmpOStyle.textAlign = ParagraphStyle::Centered;
2606 			else if (attValue == "right")
2607 				tmpOStyle.textAlign = ParagraphStyle::RightAligned;
2608 			else if (attValue == "justify")
2609 				tmpOStyle.textAlign = ParagraphStyle::Justified;
2610 		}
2611 		if (actStyle.verticalAlignment.valid)
2612 		{
2613 			if (actStyle.verticalAlignment.value == "middle")
2614 				tmpOStyle.verticalAlignment = 1;
2615 			else if (actStyle.verticalAlignment.value == "bottom")
2616 				tmpOStyle.verticalAlignment = 2;
2617 		}
2618 		if (actStyle.textPos.valid)
2619 			tmpOStyle.textPos = actStyle.textPos.value;
2620 		if (actStyle.textOutline.valid)
2621 			tmpOStyle.textOutline = actStyle.textOutline.value;
2622 		if (actStyle.textUnderline.valid)
2623 			tmpOStyle.textUnderline = actStyle.textUnderline.value != "none";
2624 		if (actStyle.textUnderlineWords.valid)
2625 			tmpOStyle.textUnderlineWords = actStyle.textUnderlineWords.value != "continuous";
2626 		if (actStyle.textUnderlineColor.valid)
2627 		{
2628 			if (actStyle.textUnderlineColor.value == "font-color")
2629 				tmpOStyle.textUnderlineColor = tmpOStyle.currColorText;
2630 			else
2631 				tmpOStyle.textUnderlineColor = parseColor(actStyle.textUnderlineColor.value);
2632 		}
2633 		if (actStyle.textStrikeThrough.valid)
2634 			tmpOStyle.textStrikeThrough = actStyle.textStrikeThrough.value != "none";
2635 		if (actStyle.textShadow.valid)
2636 			tmpOStyle.textShadow = actStyle.textShadow.value != "none";
2637 		if (actStyle.lineHeight.valid)
2638 		{
2639 			if (actStyle.lineHeight.value == "normal")
2640 				tmpOStyle.lineHeight = -1.0;
2641 			else if (actStyle.lineHeight.value.right(1) != "%")
2642 			{
2643 				tmpOStyle.lineHeight = parseUnit(actStyle.lineHeight.value);
2644 				tmpOStyle.absLineHeight = true;
2645 			}
2646 			else
2647 			{
2648 				tmpOStyle.lineHeight = parseUnit(actStyle.lineHeight.value);
2649 				tmpOStyle.absLineHeight = false;
2650 			}
2651 		}
2652 		if (actStyle.gradientAngle.valid)
2653 			tmpOStyle.gradientAngle = actStyle.gradientAngle.value.toDouble() / 10.0;
2654 		if (actStyle.gradientBorder.valid)
2655 			tmpOStyle.gradientBorder = parseUnit(actStyle.gradientBorder.value);
2656 		if (actStyle.gradientEndColor.valid)
2657 			tmpOStyle.gradientEndColor = parseColor(actStyle.gradientEndColor.value);
2658 		if (actStyle.gradientEndShade.valid)
2659 			tmpOStyle.gradientEndShade = parseUnit(actStyle.gradientEndShade.value) * 100.0;
2660 		if (actStyle.gradientStartColor.valid)
2661 			tmpOStyle.gradientStartColor = parseColor(actStyle.gradientStartColor.value);
2662 		if (actStyle.gradientStartShade.valid)
2663 			tmpOStyle.gradientStartShade = parseUnit(actStyle.gradientStartShade.value) * 100.0;
2664 		if (actStyle.gradientCenterX.valid)
2665 			tmpOStyle.gradientCenterX = parseUnit(actStyle.gradientCenterX.value);
2666 		if (actStyle.gradientCenterY.valid)
2667 			tmpOStyle.gradientCenterY = parseUnit(actStyle.gradientCenterY.value);
2668 		if (actStyle.gradientType.valid)
2669 			tmpOStyle.gradientType = actStyle.gradientType.value;
2670 		if (actStyle.markerViewBox.valid)
2671 		{
2672 			QString viewbox = actStyle.markerViewBox.value;
2673 			QStringList points = viewbox.replace( QRegExp(","), " ").simplified().split( ' ', Qt::SkipEmptyParts );
2674 			tmpOStyle.markerViewBox = QRectF(ScCLocale::toDoubleC(points[0]), ScCLocale::toDoubleC(points[1]), ScCLocale::toDoubleC(points[2]), ScCLocale::toDoubleC(points[3]));
2675 		}
2676 		else
2677 			tmpOStyle.markerViewBox = QRectF();
2678 		if (actStyle.markerPath.valid)
2679 		{
2680 			FPointArray mPath;
2681 			mPath.svgInit();
2682 			mPath.parseSVG(actStyle.markerPath.value);
2683 			if (tmpOStyle.markerViewBox != QRect())
2684 			{
2685 				QRectF clipRect = mPath.toQPainterPath(false).boundingRect();
2686 				QTransform mat;
2687 				double vw = tmpOStyle.markerViewBox.width();
2688 				double vh = tmpOStyle.markerViewBox.height();
2689 				double sx = (vw != 0.0) ? (clipRect.width() / vw) : 1;
2690 				double sy = (vh != 0.0) ? (clipRect.height() / vh) : 1;
2691 				mat.scale(sx, sy);
2692 				mPath.map(mat);
2693 			}
2694 			tmpOStyle.markerPath = mPath.toQPainterPath(true);
2695 		}
2696 		if (actStyle.startMarkerName.valid)
2697 			tmpOStyle.startMarkerName = actStyle.startMarkerName.value;
2698 		if (actStyle.startMarkerWidth.valid)
2699 			tmpOStyle.startMarkerWidth = parseUnit(actStyle.startMarkerWidth.value);
2700 		if (actStyle.startMarkerCentered.valid)
2701 			tmpOStyle.startMarkerCentered = actStyle.startMarkerCentered.value == "true";
2702 		if (actStyle.endMarkerName.valid)
2703 			tmpOStyle.endMarkerName = actStyle.endMarkerName.value;
2704 		if (actStyle.endMarkerWidth.valid)
2705 			tmpOStyle.endMarkerWidth = parseUnit(actStyle.endMarkerWidth.value);
2706 		if (actStyle.endMarkerCentered.valid)
2707 			tmpOStyle.endMarkerCentered = actStyle.endMarkerCentered.value == "true";
2708 		if (actStyle.measureDist.valid)
2709 			tmpOStyle.measureDist = parseUnit(actStyle.measureDist.value);
2710 		if (actStyle.patternPath.valid)
2711 			tmpOStyle.patternPath = actStyle.patternPath.value;
2712 		if (actStyle.patternData.valid)
2713 			tmpOStyle.patternData = actStyle.patternData.value.toLatin1();
2714 		if (actStyle.patternWidth.valid)
2715 		{
2716 			tmpOStyle.patternWidth = parseUnit(actStyle.patternWidth.value);
2717 			if (actStyle.patternWidth.value.contains("%"))
2718 				tmpOStyle.patternDim_W_in_Percent = true;
2719 		}
2720 		else
2721 			tmpOStyle.patternWidth = -1;
2722 		if (actStyle.patternHeight.valid)
2723 		{
2724 			tmpOStyle.patternHeight = parseUnit(actStyle.patternHeight.value);
2725 			if (actStyle.patternHeight.value.contains("%"))
2726 				tmpOStyle.patternDim_H_in_Percent = true;
2727 		}
2728 		else
2729 			tmpOStyle.patternHeight = -1;
2730 		if (actStyle.patternX.valid)
2731 			tmpOStyle.patternX = parseUnit(actStyle.patternX.value);
2732 		else
2733 			tmpOStyle.patternX = -1;
2734 		if (actStyle.patternY.valid)
2735 			tmpOStyle.patternY = parseUnit(actStyle.patternY.value);
2736 		else
2737 			tmpOStyle.patternY = -1;
2738 		if (actStyle.patternStretch.valid)
2739 			tmpOStyle.patternStretch = actStyle.patternStretch.value;
2740 		if (actStyle.hatchColor.valid)
2741 			tmpOStyle.hatchColor = parseColor(actStyle.hatchColor.value);
2742 		if (actStyle.hatchDistance.valid)
2743 			tmpOStyle.hatchDistance = parseUnit(actStyle.hatchDistance.value);
2744 		if (actStyle.hatchRotation.valid)
2745 			tmpOStyle.hatchRotation = actStyle.hatchRotation.value.toDouble() / 10.0;
2746 		if (actStyle.hatchStyle.valid)
2747 			tmpOStyle.hatchStyle = actStyle.hatchStyle.value;
2748 		if (actStyle.hatchSolidFill.valid)
2749 			tmpOStyle.hatchSolidFill = actStyle.hatchSolidFill.value == "true";
2750 		if (actStyle.opacityName.valid)
2751 			tmpOStyle.opacityName = actStyle.opacityName.value;
2752 		if (actStyle.opacityEnd.valid)
2753 			tmpOStyle.opacityEnd = parseUnit(actStyle.opacityEnd.value) * 100.0;
2754 		if (actStyle.opacityStart.valid)
2755 			tmpOStyle.opacityStart = parseUnit(actStyle.opacityStart.value) * 100.0;
2756 	}
2757 }
2758 
parseUnit(const QString & unit)2759 double OdgPlug::parseUnit(const QString &unit)
2760 {
2761 	QString unitval=unit;
2762 	if (unit.isEmpty())
2763 		return 0.0;
2764 	if (unit.right( 2 ) == "pt")
2765 		unitval.replace( "pt", "" );
2766 	else if (unit.right( 2 ) == "cm")
2767 		unitval.replace( "cm", "" );
2768 	else if (unit.right( 2 ) == "mm")
2769 		unitval.replace( "mm" , "" );
2770 	else if (unit.right( 2 ) == "in")
2771 		unitval.replace( "in", "" );
2772 	else if (unit.right( 2 ) == "px")
2773 		unitval.replace( "px", "" );
2774 	else if (unit.right( 1 ) == "%")
2775 		unitval.replace( "%", "" );
2776 	double value = ScCLocale::toDoubleC(unitval);
2777 	if (unit.right( 2 ) == "pt")
2778 		{}/* value = value; */ //no change
2779 	else if (unit.right( 2 ) == "cm")
2780 		value = ( value / 2.54 ) * 72;
2781 	else if (unit.right( 2 ) == "mm")
2782 		value = ( value / 25.4 ) * 72;
2783 	else if (unit.right( 2 ) == "in")
2784 		value = value * 72;
2785 	else if (unit.right( 2 ) == "px")
2786 		{}/* value = value; */ //no change
2787 	else if (unit.right( 1 ) == "%")
2788 		value = value / 100.0;
2789 	return value;
2790 }
2791 
getCoord(const char * ptr,double & number)2792 const char * OdgPlug::getCoord( const char *ptr, double &number )
2793 {
2794 	int integer, exponent;
2795 	double decimal, frac;
2796 	int sign, expsign;
2797 
2798 	exponent = 0;
2799 	integer = 0;
2800 	frac = 1.0;
2801 	decimal = 0;
2802 	sign = 1;
2803 	expsign = 1;
2804 
2805 	// read the sign
2806 	if (*ptr == '+')
2807 		ptr++;
2808 	else if (*ptr == '-')
2809 	{
2810 		ptr++;
2811 		sign = -1;
2812 	}
2813 
2814 	// read the integer part
2815 	while (*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
2816 		integer = (integer * 10) + *(ptr++) - '0';
2817 	if (*ptr == '.') // read the decimals
2818 	{
2819 		ptr++;
2820 		while (*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
2821 			decimal += (*(ptr++) - '0') * (frac *= 0.1);
2822 	}
2823 
2824 	if (*ptr == 'e' || *ptr == 'E') // read the exponent part
2825 	{
2826 		ptr++;
2827 
2828 		// read the sign of the exponent
2829 		if (*ptr == '+')
2830 			ptr++;
2831 		else if (*ptr == '-')
2832 		{
2833 			ptr++;
2834 			expsign = -1;
2835 		}
2836 
2837 		exponent = 0;
2838 		while (*ptr != '\0' && *ptr >= '0' && *ptr <= '9')
2839 		{
2840 			exponent *= 10;
2841 			exponent += *ptr - '0';
2842 			ptr++;
2843 		}
2844 	}
2845 	number = integer + decimal;
2846 	number *= sign * pow( static_cast<double>(10), static_cast<double>( expsign * exponent ) );
2847 
2848 	// skip the following space
2849 	if (*ptr == ' ')
2850 		ptr++;
2851 
2852 	return ptr;
2853 }
2854 
parseEnhPath(const QString & svgPath,FPointArray & result,bool & fill,bool & stroke)2855 bool OdgPlug::parseEnhPath(const QString& svgPath, FPointArray &result, bool &fill, bool &stroke)
2856 {
2857 	QString d = svgPath;
2858 	d = d.replace( QRegExp( "," ), " ");
2859 	bool ret = false;
2860 	fill = true;
2861 	stroke = true;
2862 	if (!d.isEmpty())
2863 	{
2864 		bool xDir = true;
2865 		bool yDir = false;
2866 		double rad2deg = 180.0/M_PI;
2867 		QPainterPath pPath;
2868 		d = d.simplified();
2869 		QByteArray pathData = d.toLatin1();
2870 		const char *ptr = pathData.constData();
2871 		const char *end = pathData.constData() + pathData.length() + 1;
2872 		double tox, toy, x1, y1, x2, y2;
2873 		double px1, py1, px2, py2, px3, py3;
2874 		int moveCount = 0;
2875 		result.svgInit();
2876 		char command = *(ptr++), lastCommand = ' ';
2877 		while (ptr < end)
2878 		{
2879 			if (*ptr == ' ')
2880 				ptr++;
2881 			switch (command)
2882 			{
2883 			case 'A':
2884 			case 'B':
2885 			case 'V':
2886 			case 'W':
2887 				{
2888 					ptr = getCoord( ptr, tox );
2889 					ptr = getCoord( ptr, toy );
2890 					ptr = getCoord( ptr, px1 );
2891 					ptr = getCoord( ptr, py1 );
2892 					ptr = getCoord( ptr, px2 );
2893 					ptr = getCoord( ptr, py2 );
2894 					ptr = getCoord( ptr, px3 );
2895 					ptr = getCoord( ptr, py3 );
2896 					bool lineTo = ((command == 'A') || (command == 'W'));
2897 					bool clockwise = ((command == 'W') || (command == 'V'));
2898 					QRectF bbox = QRectF(QPointF(tox, toy), QPointF(px1, py1)).normalized();
2899 					QPointF center = bbox.center();
2900 					double rx = 0.5 * bbox.width();
2901 					double ry = 0.5 * bbox.height();
2902 					if (rx == 0)
2903 						rx = 1;
2904 					if (ry == 0)
2905 						ry = 1;
2906 					QPointF startRadialVector = QPointF(px2, py2) - center;
2907 					QPointF endRadialVector = QPointF(px3, py3) - center;
2908 					// convert from ellipse space to unit-circle space
2909 					double x0 = startRadialVector.x() / rx;
2910 					double y0 = startRadialVector.y() / ry;
2911 
2912 					double x1 = endRadialVector.x() / rx;
2913 					double y1 = endRadialVector.y() / ry;
2914 
2915 					double startAngle = angleFromPoint(QPointF(x0,y0));
2916 					double stopAngle = angleFromPoint(QPointF(x1,y1));
2917 
2918 					// we are moving counter-clockwise to the end angle
2919 					double sweepAngle = radSweepAngle(startAngle, stopAngle, clockwise);
2920 					// compute the starting point to draw the line to
2921 					// as the point x3 y3 is not on the ellipse, spec says the point define radial vector
2922 					QPointF startPoint(rx * cos(startAngle), ry * sin(2*M_PI - startAngle));
2923 
2924 					// if A or W is first command in enhanced path
2925 					// move to the starting point
2926 					bool isFirstCommandInPath = (pPath.elementCount() == 0);
2927 					bool isFirstCommandInSubpath = lastCommand == 'Z';
2928 					if (lineTo && !isFirstCommandInPath && !isFirstCommandInSubpath)
2929 						pPath.lineTo(center + startPoint);
2930 					else
2931 						pPath.moveTo(center + startPoint);
2932 					arcTo(pPath, pPath.currentPosition(), rx, ry, startAngle * rad2deg, sweepAngle * rad2deg);
2933 					break;
2934 				}
2935 			case 'C':
2936 				{
2937 					ptr = getCoord( ptr, x1 );
2938 					ptr = getCoord( ptr, y1 );
2939 					ptr = getCoord( ptr, x2 );
2940 					ptr = getCoord( ptr, y2 );
2941 					ptr = getCoord( ptr, tox );
2942 					ptr = getCoord( ptr, toy );
2943 					pPath.cubicTo(x1, y1, x2, y2, tox, toy);
2944 					break;
2945 				}
2946 			case 'F':
2947 				{
2948 					fill = false;
2949 					break;
2950 				}
2951 			case 'L':
2952 				{
2953 					ptr = getCoord( ptr, tox );
2954 					ptr = getCoord( ptr, toy );
2955 					pPath.lineTo(tox, toy);
2956 					break;
2957 				}
2958 			case 'M':
2959 				{
2960 					ptr = getCoord( ptr, tox );
2961 					ptr = getCoord( ptr, toy );
2962 					pPath.moveTo(tox, toy);
2963 					moveCount++;
2964 					break;
2965 				}
2966 			case 'Q':
2967 				{
2968 					ptr = getCoord( ptr, x1 );
2969 					ptr = getCoord( ptr, y1 );
2970 					ptr = getCoord( ptr, tox );
2971 					ptr = getCoord( ptr, toy );
2972 					pPath.quadTo(x1, y1, tox, toy);
2973 					break;
2974 				}
2975 			case 'S':
2976 				{
2977 					stroke = false;
2978 					break;
2979 				}
2980 			case 'T':
2981 			case 'U':
2982 				{
2983 					ptr = getCoord(ptr, px1);
2984 					ptr = getCoord(ptr, py1);
2985 					ptr = getCoord(ptr, px2);
2986 					ptr = getCoord(ptr, py2);
2987 					ptr = getCoord(ptr, tox);
2988 					ptr = getCoord(ptr, toy);
2989 					bool lineTo = (command == 'T');
2990 					const QPointF &radii = QPointF(px2, py2);
2991 					const QPointF &angles = QPointF(tox, toy) / (180.0/M_PI);
2992 					QPointF start(radii.x() * cos(angles.x()), -1 * radii.y() * sin(angles.x()));
2993 					double sweepAngle = degSweepAngle(tox, toy, false);
2994 					if (lineTo)
2995 						pPath.lineTo(QPointF(px1, py1) + start);
2996 					else
2997 						pPath.moveTo(QPointF(px1, py1) + start);
2998 					arcTo(pPath, pPath.currentPosition(), radii.x(), radii.y(), tox, sweepAngle);
2999 					break;
3000 				}
3001 			case 'X':
3002 				{
3003 					ptr = getCoord( ptr, tox );
3004 					ptr = getCoord( ptr, toy );
3005 					double rx = tox - pPath.currentPosition().x();
3006 					double ry = toy - pPath.currentPosition().y();
3007 					double startAngle = xDir ? (ry > 0.0 ? 90.0 : 270.0) : (rx < 0.0 ? 0.0 : 180.0);
3008 					double sweepAngle = xDir ? (rx*ry < 0.0 ? 90.0 : -90.0) : (rx*ry > 0.0 ? 90.0 : -90.0);
3009 					arcTo(pPath, pPath.currentPosition(), fabs(rx), fabs(ry), startAngle, sweepAngle);
3010 					xDir = !xDir;
3011 					break;
3012 				}
3013 			case 'Y':
3014 				{
3015 					ptr = getCoord( ptr, tox );
3016 					ptr = getCoord( ptr, toy );
3017 					double rx = tox - pPath.currentPosition().x();
3018 					double ry = toy - pPath.currentPosition().y();
3019 					double startAngle = yDir ? (ry > 0.0 ? 90.0 : 270.0) : (rx < 0.0 ? 0.0 : 180.0);
3020 					double sweepAngle = yDir ? (rx*ry < 0.0 ? 90.0 : -90.0) : (rx*ry > 0.0 ? 90.0 : -90.0);
3021 					arcTo(pPath, pPath.currentPosition(), fabs(rx), fabs(ry), startAngle, sweepAngle);
3022 					yDir = !yDir;
3023 					break;
3024 				}
3025 			case 'Z':
3026 				{
3027 					pPath.closeSubpath();
3028 					break;
3029 				}
3030 			}
3031 			lastCommand = command;
3032 			if (*ptr == '+' || *ptr == '-' || (*ptr >= '0' && *ptr <= '9'))
3033 			{
3034 				// there are still coords in this command
3035 				if (command == 'M')
3036 					command = 'L';
3037 			}
3038 			else
3039 			{
3040 				command = *(ptr++);
3041 				xDir = true;
3042 				yDir = false;
3043 			}
3044 		}
3045 		if ((lastCommand != 'Z') || (moveCount > 1))
3046 			ret = true;
3047 		result.fromQPainterPath(pPath, !ret);
3048 	}
3049 	return ret;
3050 }
3051 
angleFromPoint(const QPointF & point)3052 double OdgPlug::angleFromPoint(const QPointF &point)
3053 {
3054 	double angle = atan2(point.y(), point.x());
3055 	if (angle < 0.0)
3056 		angle += 2*M_PI;
3057 	return 2*M_PI - angle;
3058 }
3059 
radSweepAngle(double start,double stop,bool clockwise)3060 double OdgPlug::radSweepAngle(double start, double stop, bool clockwise)
3061 {
3062 	double sweepAngle = stop - start;
3063 	if (fabs(sweepAngle) < 0.1) {
3064 		return 2*M_PI;
3065 	}
3066 	if (clockwise) {
3067 		// we are moving clockwise to the end angle
3068 		if (stop > start)
3069 			sweepAngle = (stop - start) - 2*M_PI;
3070 	} else {
3071 		// we are moving counter-clockwise to the stop angle
3072 		if (start > stop)
3073 			sweepAngle = 2*M_PI - (start-stop);
3074 	}
3075 
3076    return sweepAngle;
3077 }
3078 
degSweepAngle(double start,double stop,bool clockwise)3079 double OdgPlug::degSweepAngle(double start, double stop, bool clockwise)
3080 {
3081 	double sweepAngle = stop - start;
3082 	if (fabs(sweepAngle) < 0.1) {
3083 		return 360.0;
3084 	}
3085 	if (clockwise) {
3086 		// we are moving clockwise to the end angle
3087 		if (stop > start)
3088 			sweepAngle = (stop - start) - 360.0;
3089 	} else {
3090 		// we are moving counter-clockwise to the stop angle
3091 		if (start > stop)
3092 			sweepAngle = 360.0 - (start-stop);
3093 	}
3094    return sweepAngle;
3095 }
3096 
arcTo(QPainterPath & path,QPointF startpoint,double rx,double ry,double startAngle,double sweepAngle)3097 void OdgPlug::arcTo(QPainterPath &path, QPointF startpoint, double rx, double ry, double startAngle, double sweepAngle)
3098 {
3099 	QPointF curvePoints[12];
3100 	int pointCnt = arcToCurve(rx, ry, startAngle, sweepAngle, startpoint, curvePoints);
3101 	for (int i = 0; i < pointCnt; i += 3)
3102 	{
3103 		path.cubicTo(curvePoints[i], curvePoints[i+1], curvePoints[i+2]);
3104 	}
3105 }
3106 
arcToCurve(double rx,double ry,double startAngle,double sweepAngle,const QPointF & offset,QPointF * curvePoints)3107 int OdgPlug::arcToCurve(double rx, double ry, double startAngle, double sweepAngle, const QPointF & offset, QPointF * curvePoints)
3108 {
3109 	int pointCnt = 0;
3110 
3111 	// check Parameters
3112 	if (sweepAngle == 0)
3113 		return pointCnt;
3114 	if (sweepAngle > 360)
3115 		sweepAngle = 360;
3116 	else if (sweepAngle < -360)
3117 		sweepAngle = - 360;
3118 
3119 	if (rx == 0 || ry == 0) {
3120 		//TODO
3121 	}
3122 
3123 	// split angles bigger than 90° so that it gives a good aproximation to the circle
3124 	double parts = ceil(qAbs(sweepAngle / 90.0));
3125 
3126 	double sa_rad = startAngle * M_PI / 180.0;
3127 	double partangle = sweepAngle / parts;
3128 	double endangle = startAngle + partangle;
3129 	double se_rad = endangle * M_PI / 180.0;
3130 	double sinsa = sin(sa_rad);
3131 	double cossa = cos(sa_rad);
3132 	double kappa = 4.0 / 3.0 * tan((se_rad - sa_rad) / 4);
3133 
3134 	// startpoint is at the last point is the path but when it is closed
3135 	// it is at the first point
3136 	QPointF startpoint(offset);
3137 
3138 	//center berechnen
3139 	QPointF center(startpoint - QPointF(cossa * rx, -sinsa * ry));
3140 
3141 	//kDebug(30006) <<"kappa" << kappa <<"parts" << parts;;
3142 
3143 	for (int part = 0; part < parts; ++part) {
3144 		// start tangent
3145 		curvePoints[pointCnt++] = QPointF(startpoint - QPointF(sinsa * rx * kappa, cossa * ry * kappa));
3146 
3147 		double sinse = sin(se_rad);
3148 		double cosse = cos(se_rad);
3149 
3150 		// end point
3151 		QPointF endpoint(center + QPointF(cosse * rx, -sinse * ry));
3152 		// end tangent
3153 		curvePoints[pointCnt++] = QPointF(endpoint - QPointF(-sinse * rx * kappa, -cosse * ry * kappa));
3154 		curvePoints[pointCnt++] = endpoint;
3155 
3156 		// set the endpoint as next start point
3157 		startpoint = endpoint;
3158 		sinsa = sinse;
3159 		cossa = cosse;
3160 		endangle += partangle;
3161 		se_rad = endangle * M_PI / 180.0;
3162 	}
3163 
3164 	return pointCnt;
3165 }
3166 
groupObjects(QList<PageItem * > & GElements)3167 PageItem* OdgPlug::groupObjects(QList<PageItem *> &GElements)
3168 {
3169 	double minx =  std::numeric_limits<double>::max();
3170 	double miny =  std::numeric_limits<double>::max();
3171 	double maxx = -std::numeric_limits<double>::max();
3172 	double maxy = -std::numeric_limits<double>::max();
3173 	for (int ep = 0; ep < GElements.count(); ++ep)
3174 	{
3175 		PageItem* currItem = GElements.at(ep);
3176 		double x1, x2, y1, y2;
3177 		currItem->getVisualBoundingRect(&x1, &y1, &x2, &y2);
3178 		minx = qMin(minx, x1);
3179 		miny = qMin(miny, y1);
3180 		maxx = qMax(maxx, x2);
3181 		maxy = qMax(maxy, y2);
3182 	}
3183 	double gx = minx;
3184 	double gy = miny;
3185 	double gw = maxx - minx;
3186 	double gh = maxy - miny;
3187 	int z = m_Doc->itemAdd(PageItem::Group, PageItem::Rectangle, gx, gy, gw, gh, 0, CommonStrings::None, CommonStrings::None);
3188 	PageItem* retObj = m_Doc->Items->at(z);
3189 	retObj->ClipEdited = true;
3190 	retObj->FrameType = 3;
3191 	retObj->setFillEvenOdd(false);
3192 	retObj->OldB2 = retObj->width();
3193 	retObj->OldH2 = retObj->height();
3194 	retObj->updateClip();
3195 	m_Doc->groupObjectsToItem(retObj, GElements);
3196 	retObj->OwnPage = m_Doc->OnPage(retObj);
3197 	m_Doc->GroupOnPage(retObj);
3198 	m_Doc->Items->removeLast();
3199 	return retObj;
3200 }
3201 
modifyColor(const QString & name,bool darker,int amount)3202 QString OdgPlug::modifyColor(const QString& name, bool darker, int amount)
3203 {
3204 	const ScColor& col = m_Doc->PageColors[name];
3205 	QColor c = ScColorEngine::getShadeColorProof(col, m_Doc, 100);
3206 	QColor mo;
3207 	if (darker)
3208 		mo = c.darker(amount);
3209 	else
3210 		mo = c.lighter(amount);
3211 	ScColor tmp;
3212 	tmp.fromQColor(mo);
3213 	tmp.setSpotColor(false);
3214 	tmp.setRegistrationColor(false);
3215 	QString fNam = m_Doc->PageColors.tryAddColor("FromOdg"+mo.name(), tmp);
3216 	if (fNam == "FromOdg"+mo.name())
3217 		importedColors.append(fNam);
3218 	return fNam;
3219 }
3220 
parseColor(const QString & s)3221 QString OdgPlug::parseColor( const QString &s )
3222 {
3223 	QColor c;
3224 	QString ret = CommonStrings::None;
3225 	if ((s == "") || s.isEmpty())
3226 		return ret;
3227 	if (s.startsWith( "rgb(" ))
3228 	{
3229 		QString parse = s.trimmed();
3230 		QStringList colors = parse.split( ',', Qt::SkipEmptyParts );
3231 		QString r = colors[0].right( ( colors[0].length() - 4 ) );
3232 		QString g = colors[1];
3233 		QString b = colors[2].left( ( colors[2].length() - 1 ) );
3234 		if (r.contains( "%" ))
3235 		{
3236 			r.chop(1);
3237 			r = QString::number( static_cast<int>( ( static_cast<double>( 255 * ScCLocale::toDoubleC(r) ) / 100.0 ) ) );
3238 		}
3239 		if (g.contains( "%" ))
3240 		{
3241 			g.chop(1);
3242 			g = QString::number( static_cast<int>( ( static_cast<double>( 255 * ScCLocale::toDoubleC(g) ) / 100.0 ) ) );
3243 		}
3244 		if (b.contains( "%" ))
3245 		{
3246 			b.chop(1);
3247 			b = QString::number( static_cast<int>( ( static_cast<double>( 255 * ScCLocale::toDoubleC(b) ) / 100.0 ) ) );
3248 		}
3249 		c = QColor(r.toInt(), g.toInt(), b.toInt());
3250 	}
3251 	else
3252 		c.setNamedColor(s.trimmed());
3253 
3254 	ScColor tmp;
3255 	tmp.fromQColor(c);
3256 	tmp.setSpotColor(false);
3257 	tmp.setRegistrationColor(false);
3258 	QString fNam = m_Doc->PageColors.tryAddColor("FromOdg"+c.name(), tmp);
3259 	if (fNam == "FromOdg"+c.name())
3260 		importedColors.append(fNam);
3261 	ret = fNam;
3262 	return ret;
3263 }
3264 
constructFontName(const QString & fontBaseName,const QString & fontStyle)3265 QString OdgPlug::constructFontName(const QString& fontBaseName, const QString& fontStyle)
3266 {
3267 	QString fontName;
3268 	bool found = false;
3269 	SCFontsIterator it(PrefsManager::instance().appPrefs.fontPrefs.AvailFonts);
3270 	for ( ; it.hasNext(); it.next())
3271 	{
3272 		if (fontBaseName.toLower() == it.current().family().toLower())
3273 		{
3274 			// found the font family, now go for the style
3275 			QStringList slist = PrefsManager::instance().appPrefs.fontPrefs.AvailFonts.fontMap[it.current().family()];
3276 			slist.sort();
3277 			if (slist.count() > 0)
3278 			{
3279 				for (int a = 0; a < slist.count(); a++)
3280 				{
3281 					if (fontStyle.toLower() == slist[a].toLower())
3282 					{
3283 						found = true;
3284 						fontName = it.current().family() + " " + slist[a];
3285 						break;
3286 					}
3287 				}
3288 				if (!found)
3289 				{
3290 					int reInd = slist.indexOf("Regular");
3291 					if (reInd < 0)
3292 						fontName = it.current().family() + " " + slist[0];
3293 					else
3294 						fontName = it.current().family() + " " + slist[reInd];
3295 					found = true;
3296 				}
3297 			}
3298 			else
3299 			{
3300 				fontName = it.current().family();
3301 				found = true;
3302 			}
3303 			break;
3304 		}
3305 	}
3306 	if (!found)
3307 	{
3308 		if (importerFlags & LoadSavePlugin::lfCreateThumbnail)
3309 			fontName = PrefsManager::instance().appPrefs.itemToolPrefs.textFont;
3310 		else
3311 		{
3312 			QString family = fontBaseName;
3313 			if (!fontStyle.isEmpty())
3314 				family += " " + fontStyle;
3315 			if (!PrefsManager::instance().appPrefs.fontPrefs.GFontSub.contains(family))
3316 			{
3317 				qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
3318 				MissingFont *dia = new MissingFont(nullptr, family, m_Doc);
3319 				dia->exec();
3320 				fontName = dia->getReplacementFont();
3321 				delete dia;
3322 				qApp->changeOverrideCursor(QCursor(Qt::WaitCursor));
3323 				PrefsManager::instance().appPrefs.fontPrefs.GFontSub[family] = fontName;
3324 			}
3325 			else
3326 				fontName = PrefsManager::instance().appPrefs.fontPrefs.GFontSub[family];
3327 		}
3328 	}
3329 	return fontName;
3330 }
3331 
intersectBoundingRect(PageItem * item,QLineF gradientVector)3332 QPointF OdgPlug::intersectBoundingRect(PageItem *item, QLineF gradientVector)
3333 {
3334 	QPointF interPoint;
3335 	QPointF gradEnd;
3336 	if (gradientVector.intersects(QLineF(0, 0, item->width(), 0), &interPoint) == QLineF::BoundedIntersection)
3337 		gradEnd = interPoint;
3338 	else if (gradientVector.intersects(QLineF(item->width(), 0, item->width(), item->height()), &interPoint) == QLineF::BoundedIntersection)
3339 		gradEnd = interPoint;
3340 	else if (gradientVector.intersects(QLineF(item->width(), item->height(), 0, item->height()), &interPoint) == QLineF::BoundedIntersection)
3341 		gradEnd = interPoint;
3342 	else if (gradientVector.intersects(QLineF(0, item->height(), 0, 0), &interPoint) == QLineF::BoundedIntersection)
3343 		gradEnd = interPoint;
3344 	return gradEnd;
3345 }
3346 
applyStartArrow(PageItem * ite,ObjStyle & obState)3347 PageItem* OdgPlug::applyStartArrow(PageItem* ite, ObjStyle &obState)
3348 {
3349 	PageItem *iteS = nullptr;
3350 	if (!obState.startMarkerName.isEmpty())
3351 	{
3352 		ObjStyle mStyle;
3353 		resovleStyle(mStyle, obState.startMarkerName);
3354 		QPainterPath pa = mStyle.markerPath;
3355 		FPointArray EndArrow;
3356 		EndArrow.fromQPainterPath(pa);
3357 		QRectF br = pa.boundingRect();
3358 		double EndArrowWidth = obState.startMarkerWidth;
3359 		if (EndArrowWidth > 0)
3360 		{
3361 			FPoint Start = ite->PoLine.point(0);
3362 			for (int xx = 1; xx < ite->PoLine.size(); xx += 2)
3363 			{
3364 				FPoint Vector = ite->PoLine.point(xx);
3365 				if ((Start.x() != Vector.x()) || (Start.y() != Vector.y()))
3366 				{
3367 					double r = atan2(Start.y()-Vector.y(),Start.x()-Vector.x())*(180.0/M_PI);
3368 					QPointF refP;
3369 					if (obState.startMarkerCentered)
3370 						refP = QPointF(br.width() / 2.0, br.height() / 2.0);
3371 					else
3372 						refP = QPointF(br.width() / 2.0, 0);
3373 					QTransform m;
3374 					m.translate(br.width() / 2.0, br.height() / 2.0);
3375 					m.rotate(r + 90);
3376 					m.translate(-br.width() / 2.0, -br.height() / 2.0);
3377 					m.scale(EndArrowWidth / br.width(), EndArrowWidth / br.width());
3378 					EndArrow.map(m);
3379 					refP = m.map(refP);
3380 					QPainterPath pa2 = EndArrow.toQPainterPath(true);
3381 					QTransform m2;
3382 					FPoint grOffset2(getMinClipF(&EndArrow));
3383 					m2.translate(-grOffset2.x(), -grOffset2.y());
3384 					EndArrow.map(m2);
3385 					refP = m2.map(refP);
3386 					EndArrow.translate(-refP.x(), -refP.y());
3387 					QTransform arrowTrans;
3388 					arrowTrans.translate(-m_Doc->currentPage()->xOffset(), -m_Doc->currentPage()->yOffset());
3389 					arrowTrans.translate(Start.x() + ite->xPos(), Start.y() + ite->yPos());
3390 					EndArrow.map(arrowTrans);
3391 					int zS = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, 0, obState.currColorStroke, CommonStrings::None);
3392 					iteS = m_Doc->Items->at(zS);
3393 					iteS->PoLine = EndArrow.copy();
3394 					iteS->ClipEdited = true;
3395 					iteS->FrameType = 3;
3396 					FPoint wh = getMaxClipF(&iteS->PoLine);
3397 					iteS->setWidthHeight(wh.x(), wh.y());
3398 					m_Doc->adjustItemSize(iteS, true);
3399 					iteS->setFillEvenOdd(false);
3400 					iteS->OldB2 = iteS->width();
3401 					iteS->OldH2 = iteS->height();
3402 					iteS->updateClip();
3403 					iteS->OwnPage = m_Doc->OnPage(iteS);
3404 					iteS->setFillTransparency(obState.strokeOpacity);
3405 					m_Doc->Items->removeLast();
3406 					break;
3407 				}
3408 			}
3409 		}
3410 
3411 	}
3412 	return iteS;
3413 }
3414 
applyEndArrow(PageItem * ite,ObjStyle & obState)3415 PageItem* OdgPlug::applyEndArrow(PageItem* ite, ObjStyle &obState)
3416 {
3417 	PageItem *iteS = nullptr;
3418 	if (!obState.endMarkerName.isEmpty())
3419 	{
3420 		ObjStyle mStyle;
3421 		resovleStyle(mStyle, obState.endMarkerName);
3422 		double EndArrowWidth = obState.endMarkerWidth;
3423 		QPainterPath pa = mStyle.markerPath;
3424 		FPointArray EndArrow;
3425 		EndArrow.fromQPainterPath(pa);
3426 		QRectF br = pa.boundingRect();
3427 		if (EndArrowWidth > 0)
3428 		{
3429 			FPoint End = ite->PoLine.point(ite->PoLine.size()-2);
3430 			for (uint xx = ite->PoLine.size()-1; xx > 0; xx -= 2)
3431 			{
3432 				FPoint Vector = ite->PoLine.point(xx);
3433 				if ((End.x() != Vector.x()) || (End.y() != Vector.y()))
3434 				{
3435 					double r = atan2(End.y()-Vector.y(),End.x()-Vector.x())*(180.0/M_PI);
3436 					QPointF refP;
3437 					if (obState.endMarkerCentered)
3438 						refP = QPointF(br.width() / 2.0, br.height() / 2.0);
3439 					else
3440 						refP = QPointF(br.width() / 2.0, 0);
3441 					QTransform m;
3442 					m.translate(br.width() / 2.0, br.height() / 2.0);
3443 					m.rotate(r + 90);
3444 					m.translate(-br.width() / 2.0, -br.height() / 2.0);
3445 					m.scale(EndArrowWidth / br.width(), EndArrowWidth / br.width());
3446 					EndArrow.map(m);
3447 					refP = m.map(refP);
3448 					QTransform m2;
3449 					FPoint grOffset2(getMinClipF(&EndArrow));
3450 					m2.translate(-grOffset2.x(), -grOffset2.y());
3451 					EndArrow.map(m2);
3452 					refP = m2.map(refP);
3453 					EndArrow.translate(-refP.x(), -refP.y());
3454 					QTransform arrowTrans;
3455 					arrowTrans.translate(-m_Doc->currentPage()->xOffset(), -m_Doc->currentPage()->yOffset());
3456 					arrowTrans.translate(End.x() + ite->xPos(), End.y() + ite->yPos());
3457 					EndArrow.map(arrowTrans);
3458 					int zE = m_Doc->itemAdd(PageItem::Polygon, PageItem::Unspecified, baseX, baseY, 10, 10, 0, obState.currColorStroke, CommonStrings::None);
3459 					iteS = m_Doc->Items->at(zE);
3460 					iteS->PoLine = EndArrow.copy();
3461 					iteS->ClipEdited = true;
3462 					iteS->FrameType = 3;
3463 					FPoint wh = getMaxClipF(&iteS->PoLine);
3464 					iteS->setWidthHeight(wh.x(), wh.y());
3465 					m_Doc->adjustItemSize(iteS, true);
3466 					iteS->setFillEvenOdd(false);
3467 					iteS->OldB2 = iteS->width();
3468 					iteS->OldH2 = iteS->height();
3469 					iteS->updateClip();
3470 					iteS->OwnPage = m_Doc->OnPage(iteS);
3471 					iteS->setFillTransparency(obState.strokeOpacity);
3472 					m_Doc->Items->removeLast();
3473 					break;
3474 				}
3475 			}
3476 		}
3477 	}
3478 	return iteS;
3479 }
3480 
finishItem(PageItem * item,ObjStyle & obState)3481 void OdgPlug::finishItem(PageItem* item, ObjStyle &obState)
3482 {
3483 	item->ClipEdited = true;
3484 	item->FrameType = 3;
3485 	FPoint wh = getMaxClipF(&item->PoLine);
3486 	item->setWidthHeight(wh.x(), wh.y());
3487 	item->Clip = flattenPath(item->PoLine, item->Segments);
3488 	m_Doc->adjustItemSize(item, true);
3489 	item->OldB2 = item->width();
3490 	item->OldH2 = item->height();
3491 	item->updateClip();
3492 	item->OwnPage = m_Doc->OnPage(item);
3493 	item->setFillTransparency(obState.fillOpacity);
3494 	item->setLineTransparency(obState.strokeOpacity);
3495 	item->setStartArrowIndex(0);
3496 	item->setEndArrowIndex(0);
3497 	if (obState.stroke_type == 2)
3498 	{
3499 		ObjStyle dStyle;
3500 		resovleStyle(dStyle, obState.dashName);
3501 		item->DashValues.clear();
3502 		double gap = 0;
3503 		if (dStyle.stroke_dash_distance < 0)
3504 			gap = item->lineWidth();
3505 		else
3506 			gap = dStyle.stroke_dash_distance;
3507 		int dots1 = dStyle.stroke_dash_dots1;
3508 		double dots1len = item->lineWidth();
3509 		if (dStyle.stroke_dash_dots1_length < 0)
3510 			dots1len = item->lineWidth();
3511 		else
3512 			dots1len = dStyle.stroke_dash_dots1_length;
3513 		int dots2 = dStyle.stroke_dash_dots2;
3514 		double dots2len = item->lineWidth();
3515 		if (dStyle.stroke_dash_dots2_length < 0)
3516 			dots2len = item->lineWidth();
3517 		else
3518 			dots2len = dStyle.stroke_dash_dots2_length;
3519 		for (int i = 0; i < dots1; i++)
3520 		{
3521 			item->DashValues << qMax(dots1len, 0.1) << qMax(gap, 0.1);
3522 		}
3523 		for (int j = 0; j < dots2; j++)
3524 		{
3525 			item->DashValues << qMax(dots2len, 0.1) << qMax(gap, 0.1);
3526 		}
3527 	}
3528 	if (obState.fill_type == 2)
3529 	{
3530 		ObjStyle gStyle;
3531 		resovleStyle(gStyle, obState.gradientName);
3532 		if (gStyle.gradientType == "linear")
3533 		{
3534 			double angle = gStyle.gradientAngle + 90;
3535 			item->fill_gradient = VGradient(VGradient::linear);
3536 			item->fill_gradient.clearStops();
3537 			item->fill_gradient.setRepeatMethod( VGradient::none );
3538 			const ScColor& gradC = m_Doc->PageColors[gStyle.gradientEndColor];
3539 			item->fill_gradient.addStop(ScColorEngine::getRGBColor(gradC, m_Doc), 0.0, 0.5, 1.0, gStyle.gradientEndColor, gStyle.gradientEndShade);
3540 			const ScColor& gradC2 = m_Doc->PageColors[gStyle.gradientStartColor];
3541 			item->fill_gradient.addStop(ScColorEngine::getRGBColor(gradC2, m_Doc), 1.0 - gStyle.gradientBorder, 0.5, 1.0, gStyle.gradientStartColor, gStyle.gradientStartShade);
3542 			QLineF gradientVectorE;
3543 			gradientVectorE.setP1(QPointF(item->width() / 2.0, item->height() / 2.0));
3544 			gradientVectorE.setAngle(angle);
3545 			gradientVectorE.setLength(sqrt(item->width() * item->width() + item->height() * item->height()) / 2.0 + 1.0);
3546 			QPointF gradEnd = intersectBoundingRect(item, gradientVectorE);
3547 			QLineF gradientVectorS;
3548 			gradientVectorS.setP1(QPointF(item->width() / 2.0, item->height() / 2.0));
3549 			gradientVectorS.setAngle(angle + 180);
3550 			gradientVectorS.setLength(sqrt(item->width() * item->width() + item->height() * item->height()) / 2.0 + 1.0);
3551 			QPointF gradStart = intersectBoundingRect(item, gradientVectorS);
3552 			item->setGradientVector(gradStart.x(), gradStart.y(), gradEnd.x(), gradEnd.y(), gradStart.x(), gradStart.y(), 1, 0);
3553 			item->setGradientType(6);
3554 		}
3555 		else if (gStyle.gradientType == "axial")
3556 		{
3557 			double angle = gStyle.gradientAngle + 90;
3558 			item->fill_gradient = VGradient(VGradient::linear);
3559 			item->fill_gradient.clearStops();
3560 			item->fill_gradient.setRepeatMethod( VGradient::none );
3561 			const ScColor& gradC = m_Doc->PageColors[gStyle.gradientEndColor];
3562 			item->fill_gradient.addStop(ScColorEngine::getRGBColor(gradC, m_Doc), 0.0 + (gStyle.gradientBorder / 2.0), 0.5, 1.0, gStyle.gradientEndColor, gStyle.gradientEndShade);
3563 			const ScColor& gradC2 = m_Doc->PageColors[gStyle.gradientStartColor];
3564 			item->fill_gradient.addStop(ScColorEngine::getRGBColor(gradC2, m_Doc), 0.5, 0.5, 1.0, gStyle.gradientStartColor, gStyle.gradientStartShade);
3565 			item->fill_gradient.addStop(ScColorEngine::getRGBColor(gradC, m_Doc), 1.0 - (gStyle.gradientBorder / 2.0), 0.5, 1.0, gStyle.gradientEndColor, gStyle.gradientEndShade);
3566 			QLineF gradientVectorE;
3567 			gradientVectorE.setP1(QPointF(item->width() / 2.0, item->height() / 2.0));
3568 			gradientVectorE.setAngle(angle);
3569 			gradientVectorE.setLength(sqrt(item->width() * item->width() + item->height() * item->height()) / 2.0 + 1.0);
3570 			QPointF gradEnd = intersectBoundingRect(item, gradientVectorE);
3571 			QLineF gradientVectorS;
3572 			gradientVectorS.setP1(QPointF(item->width() / 2.0, item->height() / 2.0));
3573 			gradientVectorS.setAngle(angle + 180);
3574 			gradientVectorS.setLength(sqrt(item->width() * item->width() + item->height() * item->height()) / 2.0 + 1.0);
3575 			QPointF gradStart = intersectBoundingRect(item, gradientVectorS);
3576 			item->setGradientVector(gradStart.x(), gradStart.y(), gradEnd.x(), gradEnd.y(), gradStart.x(), gradStart.y(), 1, 0);
3577 			item->setGradientType(6);
3578 		}
3579 		else if (gStyle.gradientType == "radial")
3580 		{
3581 			item->fill_gradient = VGradient(VGradient::radial);
3582 			item->fill_gradient.clearStops();
3583 			item->fill_gradient.setRepeatMethod( VGradient::none );
3584 			const ScColor& gradC = m_Doc->PageColors[gStyle.gradientEndColor];
3585 			item->fill_gradient.addStop(ScColorEngine::getRGBColor(gradC, m_Doc), 0.0, 0.5, 1.0, gStyle.gradientEndColor, gStyle.gradientEndShade);
3586 			const ScColor& gradC2 = m_Doc->PageColors[gStyle.gradientStartColor];
3587 			item->fill_gradient.addStop(ScColorEngine::getRGBColor(gradC2, m_Doc), 1.0 - gStyle.gradientBorder, 0.5, 1.0, gStyle.gradientStartColor, gStyle.gradientStartShade);
3588 			item->GrType = Gradient_Radial;
3589 			item->GrStartX = item->width() * gStyle.gradientCenterX;
3590 			item->GrStartY = item->height()* gStyle.gradientCenterY;
3591 			item->GrFocalX = item->width() * gStyle.gradientCenterX;
3592 			item->GrFocalY = item->height()* gStyle.gradientCenterY;
3593 			if (item->width() >= item->height())
3594 			{
3595 				item->GrEndX = item->width();
3596 				item->GrEndY = item->height() / 2.0;
3597 			}
3598 			else
3599 			{
3600 				item->GrEndX = item->width() / 2.0;
3601 				item->GrEndY = item->height();
3602 			}
3603 			item->updateGradientVectors();
3604 		}
3605 		else if (gStyle.gradientType == "ellipsoid")
3606 		{
3607 			item->fill_gradient = VGradient(VGradient::radial);
3608 			item->fill_gradient.clearStops();
3609 			item->fill_gradient.setRepeatMethod( VGradient::none );
3610 			const ScColor& gradC = m_Doc->PageColors[gStyle.gradientEndColor];
3611 			item->fill_gradient.addStop(ScColorEngine::getRGBColor(gradC, m_Doc), 0.0, 0.5, 1.0, gStyle.gradientEndColor, gStyle.gradientEndShade);
3612 			const ScColor& gradC2 = m_Doc->PageColors[gStyle.gradientStartColor];
3613 			item->fill_gradient.addStop(ScColorEngine::getRGBColor(gradC2, m_Doc), 1.0 - gStyle.gradientBorder, 0.5, 1.0, gStyle.gradientStartColor, gStyle.gradientStartShade);
3614 			item->GrType = Gradient_Radial;
3615 			item->GrStartX = item->width() * gStyle.gradientCenterX;
3616 			item->GrStartY = item->height()* gStyle.gradientCenterY;
3617 			item->GrFocalX = item->width() * gStyle.gradientCenterX;
3618 			item->GrFocalY = item->height()* gStyle.gradientCenterY;
3619 			if (item->width() >= item->height())
3620 			{
3621 				item->GrEndX = item->width();
3622 				item->GrEndY = item->height() / 2.0;
3623 			}
3624 			else
3625 			{
3626 				item->GrEndX = item->width() / 2.0;
3627 				item->GrEndY = item->height();
3628 			}
3629 			QLineF gradientVectorE = QLineF(item->GrStartX, item->GrStartY, item->GrEndX, item->GrEndY);
3630 			gradientVectorE.setAngle(gStyle.gradientAngle);
3631 			item->GrEndX = gradientVectorE.p2().x();
3632 			item->GrEndY = gradientVectorE.p2().y();
3633 			item->updateGradientVectors();
3634 		}
3635 		else if (gStyle.gradientType == "square")
3636 		{
3637 			item->fill_gradient = VGradient(VGradient::radial);
3638 			item->fill_gradient.clearStops();
3639 			item->fill_gradient.setRepeatMethod( VGradient::none );
3640 			const ScColor& gradC = m_Doc->PageColors[gStyle.gradientEndColor];
3641 			item->fill_gradient.addStop(ScColorEngine::getRGBColor(gradC, m_Doc), 0.0, 0.5, 1.0, gStyle.gradientEndColor, gStyle.gradientEndShade);
3642 			const ScColor& gradC2 = m_Doc->PageColors[gStyle.gradientStartColor];
3643 			item->fill_gradient.addStop(ScColorEngine::getRGBColor(gradC2, m_Doc), 1.0 - gStyle.gradientBorder, 0.5, 1.0, gStyle.gradientStartColor, gStyle.gradientStartShade);
3644 			if (gStyle.gradientBorder != 0)
3645 				item->fill_gradient.addStop(ScColorEngine::getRGBColor(gradC2, m_Doc), 1.0, 0.5, 1.0, gStyle.gradientStartColor, gStyle.gradientStartShade);
3646 			FPoint cp = FPoint(item->width() * gStyle.gradientCenterX, item->height()* gStyle.gradientCenterY);
3647 			double gLen = qMin(item->width(), item->height()) / 2.0;
3648 			QLineF p1 = QLineF(cp.x(), cp.y(), cp.x() - gLen, cp.y() - gLen);
3649 			p1.setAngle(p1.angle() + gStyle.gradientAngle);
3650 			QLineF p2 = QLineF(cp.x(), cp.y(), cp.x() + gLen, cp.y() - gLen);
3651 			p2.setAngle(p2.angle() + gStyle.gradientAngle);
3652 			QLineF p3 = QLineF(cp.x(), cp.y(), cp.x() + gLen, cp.y() + gLen);
3653 			p3.setAngle(p3.angle() + gStyle.gradientAngle);
3654 			QLineF p4 = QLineF(cp.x(), cp.y(), cp.x() - gLen, cp.y() + gLen);
3655 			p4.setAngle(p4.angle() + gStyle.gradientAngle);
3656 			item->setDiamondGeometry(FPoint(p1.p2().x(), p1.p2().y()), FPoint(p2.p2().x(), p2.p2().y()), FPoint(p3.p2().x(), p3.p2().y()), FPoint(p4.p2().x(), p4.p2().y()), cp);
3657 			item->GrType = Gradient_Diamond;
3658 		}
3659 		else if (gStyle.gradientType == "rectangular")
3660 		{
3661 			item->fill_gradient = VGradient(VGradient::radial);
3662 			item->fill_gradient.clearStops();
3663 			item->fill_gradient.setRepeatMethod( VGradient::none );
3664 			const ScColor& gradC = m_Doc->PageColors[gStyle.gradientEndColor];
3665 			QColor gradColor1 = ScColorEngine::getRGBColor(gradC, m_Doc);
3666 			item->fill_gradient.addStop(gradColor1, 0.0, 0.5, 1.0, gStyle.gradientEndColor, gStyle.gradientEndShade);
3667 			const ScColor& gradC2 = m_Doc->PageColors[gStyle.gradientStartColor];
3668 			QColor gradColor2 = ScColorEngine::getRGBColor(gradC2, m_Doc);
3669 			item->fill_gradient.addStop(gradColor2, 1.0 - gStyle.gradientBorder, 0.5, 1.0, gStyle.gradientStartColor, gStyle.gradientStartShade);
3670 			if (gStyle.gradientBorder != 0)
3671 				item->fill_gradient.addStop(ScColorEngine::getRGBColor(gradC2, m_Doc), 1.0, 0.5, 1.0, gStyle.gradientStartColor, gStyle.gradientStartShade);
3672 			FPoint cp = FPoint(item->width() * gStyle.gradientCenterX, item->height()* gStyle.gradientCenterY);
3673 			double gLenW = item->width() / 2.0;
3674 			double gLenH = item->height() / 2.0;
3675 
3676 			QPointF P1 = QPointF(0.0, 0.0);
3677 			QPointF P2 = QPointF(item->width(), 0.0);
3678 			QPointF P3 = QPointF(item->width(), item->height());
3679 			QPointF P4 = QPointF(0.0, item->height());
3680 			QLineF L1 = QLineF(0.0, 0.0, item->width(), 0.0);
3681 			L1.setAngle(-45);
3682 			QLineF LCW = QLineF(0.0, item->height() / 2.0, item->width(), item->height() / 2.0);
3683 			QPointF P5;
3684 			LCW.intersects(L1, &P5);
3685 			QPointF P6 = QPointF(item->width() - P5.x(), P5.y());
3686 			QPolygonF pPoints;
3687 			pPoints << P1 << P2 << P3 << P4 << P5 << P6;
3688 			QTransform mat;
3689 			pPoints.translate(-item->width() / 2.0, -item->height() / 2.0);
3690 			mat.translate(item->width() * gStyle.gradientCenterX, item->height()* gStyle.gradientCenterY);
3691 			mat.rotate(-gStyle.gradientAngle);
3692 			mat.scale(1.0 - gStyle.gradientBorder, 1.0 - gStyle.gradientBorder);
3693 			pPoints = mat.map(pPoints);
3694 			P1 = pPoints[0];
3695 			P2 = pPoints[1];
3696 			P3 = pPoints[2];
3697 			P4 = pPoints[3];
3698 			P5 = pPoints[4];
3699 			P6 = pPoints[5];
3700 /*
3701 			QPointF cpL = QPointF(item->width() * gStyle.gradientCenterX, item->height()* gStyle.gradientCenterY);
3702 			double lineLen = sqrt(gLenW * gLenW + gLenH * gLenH) * 2.0;
3703 			QLineF iLineP1 = QLineF(cpL, P1);
3704 			iLineP1.setLength(lineLen);
3705 			P1 = intersectBoundingRect(item, iLineP1);
3706 			QLineF iLineP2 = QLineF(cpL, P2);
3707 			iLineP2.setLength(lineLen);
3708 			P2 = intersectBoundingRect(item, iLineP2);
3709 			QLineF iLineP3 = QLineF(cpL, P3);
3710 			iLineP3.setLength(lineLen);
3711 			P3 = intersectBoundingRect(item, iLineP3);
3712 			QLineF iLineP4 = QLineF(cpL, P4);
3713 			iLineP4.setLength(lineLen);
3714 			P4 = intersectBoundingRect(item, iLineP4);
3715 			item->setDiamondGeometry(FPoint(P1.x(), P1.y()), FPoint(P2.x(), P2.y()), FPoint(P3.x(), P3.y()), FPoint(P4.x(), P4.y()), cp);
3716 			item->GrType = Gradient_Diamond;
3717 */
3718 /*
3719 			item->meshGradientPatches.clear();
3720 			meshGradientPatch patch1;
3721 			meshPoint outer;
3722 			outer.resetTo(FPoint(P1.x(), P1.y()));
3723 			outer.transparency = 1.0;
3724 			outer.shade = gStyle.gradientStartShade;
3725 			outer.colorName = gStyle.gradientStartColor;
3726 			outer.color = gradColor2;
3727 			patch1.TL = outer;
3728 			outer.resetTo(FPoint(P2.x(), P2.y()));
3729 			patch1.TR = outer;
3730 			meshPoint inner;
3731 			inner.resetTo(FPoint(P6.x(), P6.y()));
3732 			inner.transparency = 1.0;
3733 			inner.shade = gStyle.gradientEndShade;
3734 			inner.colorName = gStyle.gradientEndColor;
3735 			inner.color = gradColor1;
3736 			patch1.BR = inner;
3737 			inner.resetTo(FPoint(P5.x(), P5.y()));
3738 			patch1.BL = inner;
3739 			item->meshGradientPatches.append(patch1);
3740 
3741 			outer.resetTo(FPoint(P2.x(), P2.y()));
3742 			patch1.TL = outer;
3743 			outer.resetTo(FPoint(P3.x(), P3.y()));
3744 			patch1.TR = outer;
3745 			inner.resetTo(FPoint(P6.x(), P6.y()));
3746 			patch1.BL = inner;
3747 			patch1.BR = inner;
3748 			item->meshGradientPatches.append(patch1);
3749 
3750 			inner.resetTo(FPoint(P5.x(), P5.y()));
3751 			patch1.TL = inner;
3752 			inner.resetTo(FPoint(P6.x(), P6.y()));
3753 			patch1.TR = inner;
3754 			outer.resetTo(FPoint(P4.x(), P4.y()));
3755 			patch1.BL = outer;
3756 			outer.resetTo(FPoint(P3.x(), P3.y()));
3757 			patch1.BR = outer;
3758 			item->meshGradientPatches.append(patch1);
3759 
3760 			outer.resetTo(FPoint(P4.x(), P4.y()));
3761 			patch1.BL = outer;
3762 			outer.resetTo(FPoint(P1.x(), P1.y()));
3763 			patch1.TL = outer;
3764 			inner.resetTo(FPoint(P5.x(), P5.y()));
3765 			patch1.BR = inner;
3766 			patch1.TR = inner;
3767 			item->meshGradientPatches.append(patch1);
3768 			item->GrType = Gradient_PatchMesh;
3769 */
3770 
3771 			QLineF p1 = QLineF(cp.x(), cp.y(), cp.x() - gLenW, cp.y() - gLenH);
3772 			p1.setAngle(p1.angle() + gStyle.gradientAngle);
3773 			QLineF p2 = QLineF(cp.x(), cp.y(), cp.x() + gLenW, cp.y() - gLenH);
3774 			p2.setAngle(p2.angle() + gStyle.gradientAngle);
3775 			QLineF p3 = QLineF(cp.x(), cp.y(), cp.x() + gLenW, cp.y() + gLenH);
3776 			p3.setAngle(p3.angle() + gStyle.gradientAngle);
3777 			QLineF p4 = QLineF(cp.x(), cp.y(), cp.x() - gLenW, cp.y() + gLenH);
3778 			p4.setAngle(p4.angle() + gStyle.gradientAngle);
3779 			item->setDiamondGeometry(FPoint(p1.p2().x(), p1.p2().y()), FPoint(p2.p2().x(), p2.p2().y()), FPoint(p3.p2().x(), p3.p2().y()), FPoint(p4.p2().x(), p4.p2().y()), cp);
3780 			item->GrType = Gradient_Diamond;
3781 		}
3782 	}
3783 	else if (obState.fill_type == 3)
3784 	{
3785 		ObjStyle gStyle;
3786 		resovleStyle(gStyle, obState.patternName);
3787 		QString patternName = "Pattern_" + obState.patternName;
3788 		if (m_Doc->docPatterns.contains(patternName))
3789 		{
3790 			ScPattern pat = m_Doc->docPatterns[patternName];
3791 			double sy = 100.0;
3792 			double sx = 100.0;
3793 			double dx = 0;
3794 			double dy = 0;
3795 			if (obState.patternStretch == "stretch")
3796 			{
3797 				sx = item->width() / pat.width * 100;
3798 				sy = item->height() / pat.height * 100;
3799 			}
3800 			else
3801 			{
3802 				if (obState.patternDim_H_in_Percent)
3803 					sy = obState.patternHeight * 100.0;
3804 				else
3805 				{
3806 					if (obState.patternHeight > 0.0)
3807 						sy = obState.patternHeight / pat.height * 100.0;
3808 				}
3809 				if (obState.patternDim_W_in_Percent)
3810 					sx = obState.patternWidth * 100.0;
3811 				else
3812 				{
3813 					if (obState.patternWidth > 0.0)
3814 						sx = obState.patternWidth / pat.width * 100.0;
3815 				}
3816 				if (obState.patternX > 0.0)
3817 					dx = pat.width * obState.patternX;
3818 				if (obState.patternY > 0.0)
3819 					dy = pat.height * obState.patternY;
3820 			}
3821 			item->setPatternTransform(sx, sy, dx, dy, 0, 0, 0);
3822 			item->setPattern(patternName);
3823 			item->GrType = Gradient_Pattern;
3824 		}
3825 		else
3826 		{
3827 			if (!gStyle.patternPath.isEmpty())
3828 			{
3829 				QByteArray f;
3830 				if (uz->read(gStyle.patternPath, f))
3831 				{
3832 					QFileInfo fi(gStyle.patternPath);
3833 					QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_odg_XXXXXX." + fi.suffix());
3834 					tempFile->setAutoRemove(false);
3835 					if (tempFile->open())
3836 					{
3837 						QString fileName = getLongPathName(tempFile->fileName());
3838 						if (!fileName.isEmpty())
3839 						{
3840 							tempFile->write(f);
3841 							tempFile->close();
3842 							ScPattern pat = ScPattern();
3843 							pat.setDoc(m_Doc);
3844 							int z = m_Doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, 0, 0, 1, 1, 0, CommonStrings::None, CommonStrings::None);
3845 							PageItem* newItem = m_Doc->Items->at(z);
3846 							m_Doc->loadPict(fileName, newItem);
3847 							m_Doc->Items->takeAt(z);
3848 							newItem->isInlineImage = true;
3849 							newItem->isTempFile = true;
3850 							pat.width = newItem->pixm.qImage().width();
3851 							pat.height = newItem->pixm.qImage().height();
3852 							pat.scaleX = (72.0 / newItem->pixm.imgInfo.xres) * newItem->pixm.imgInfo.lowResScale;
3853 							pat.scaleY = (72.0 / newItem->pixm.imgInfo.xres) * newItem->pixm.imgInfo.lowResScale;
3854 							pat.pattern = newItem->pixm.qImage().copy();
3855 							newItem->setWidth(pat.pattern.width());
3856 							newItem->setHeight(pat.pattern.height());
3857 							newItem->SetRectFrame();
3858 							newItem->gXpos = 0.0;
3859 							newItem->gYpos = 0.0;
3860 							newItem->gWidth = pat.pattern.width();
3861 							newItem->gHeight = pat.pattern.height();
3862 							pat.items.append(newItem);
3863 							patternName = patternName.trimmed().simplified().replace(" ", "_");
3864 							m_Doc->addPattern(patternName, pat);
3865 							item->setPattern(patternName);
3866 							double sy = 100.0;
3867 							double sx = 100.0;
3868 							double dx = 0;
3869 							double dy = 0;
3870 							if (obState.patternStretch == "stretch")
3871 							{
3872 								sx = item->width() / pat.width * 100;
3873 								sy = item->height() / pat.height * 100;
3874 							}
3875 							else
3876 							{
3877 								if (obState.patternDim_H_in_Percent)
3878 									sy = obState.patternHeight * 100.0;
3879 								else
3880 								{
3881 									if (obState.patternHeight > 0.0)
3882 										sy = obState.patternHeight / pat.height * 100.0;
3883 								}
3884 								if (obState.patternDim_W_in_Percent)
3885 									sx = obState.patternWidth * 100.0;
3886 								else
3887 								{
3888 									if (obState.patternWidth > 0.0)
3889 										sx = obState.patternWidth / pat.width * 100.0;
3890 								}
3891 								if (obState.patternX > 0.0)
3892 									dx = pat.width * obState.patternX;
3893 								if (obState.patternY > 0.0)
3894 									dy = pat.height * obState.patternY;
3895 							}
3896 							item->setPatternTransform(sx, sy, dx, dy, 0, 0, 0);
3897 							item->GrType = Gradient_Pattern;
3898 						}
3899 					}
3900 					delete tempFile;
3901 				}
3902 			}
3903 			else if (!gStyle.patternData.isEmpty())
3904 			{
3905 				QString ext = "";
3906 				QByteArray buf = QByteArray::fromBase64(gStyle.patternData);
3907 				if ((buf[0] == '%') && (buf[1] == '!') && (buf[2] == 'P') && (buf[3] == 'S') && (buf[4] == '-') && (buf[5] == 'A'))
3908 					ext = "eps";
3909 				else if ((buf[0] == '\xC5') && (buf[1] == '\xD0') && (buf[2] == '\xD3') && (buf[3] == '\xC6'))
3910 					ext = "eps";
3911 				else if ((buf[0] == 'G') && (buf[1] == 'I') && (buf[2] == 'F') && (buf[3] == '8'))
3912 					ext = "gif";
3913 				else if ((buf[0] == '\xFF') && (buf[1] == '\xD8') && (buf[2] == '\xFF'))
3914 					ext = "jpg";
3915 				else if ((buf[0] == 'P') && (buf[1] == 'G') && (buf[2] == 'F'))
3916 					ext = "pgf";
3917 				else if ((buf[0] == '\x89') && (buf[1] == 'P') && (buf[2] == 'N') && (buf[3] == 'G'))
3918 					ext = "png";
3919 				else if ((buf[0] == '8') && (buf[1] == 'B') && (buf[2] == 'P') && (buf[3] == 'S'))
3920 					ext = "psd";
3921 				else if (((buf[0] == 'I') && (buf[1] == 'I') && (buf[2] == '\x2A')) || ((buf[0] == 'M') && (buf[1] == 'M') && (buf[3] == '\x2A')))
3922 					ext = "tif";
3923 				else if ((buf[0] == '/') && (buf[1] == '*') && (buf[2] == ' ') && (buf[3] == 'X') && (buf[4] == 'P') && (buf[5] == 'M'))
3924 					ext = "xpm";
3925 				else if ((buf[0] == 'V') && (buf[1] == 'C') && (buf[2] == 'L') && (buf[3] == 'M') && (buf[4] == 'T') && (buf[5] == 'F'))
3926 					ext = "svm";
3927 				if (!ext.isEmpty())
3928 				{
3929 					QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + "/scribus_temp_odg_XXXXXX." + ext);
3930 					tempFile->setAutoRemove(false);
3931 					if (tempFile->open())
3932 					{
3933 						QString fileName = getLongPathName(tempFile->fileName());
3934 						if (!fileName.isEmpty())
3935 						{
3936 							tempFile->write(buf);
3937 							tempFile->close();
3938 							ScPattern pat = ScPattern();
3939 							pat.setDoc(m_Doc);
3940 							int z = m_Doc->itemAdd(PageItem::ImageFrame, PageItem::Unspecified, 0, 0, 1, 1, 0, CommonStrings::None, CommonStrings::None);
3941 							PageItem* newItem = m_Doc->Items->at(z);
3942 							m_Doc->loadPict(fileName, newItem);
3943 							m_Doc->Items->takeAt(z);
3944 							newItem->isInlineImage = true;
3945 							newItem->isTempFile = true;
3946 							pat.width = newItem->pixm.qImage().width();
3947 							pat.height = newItem->pixm.qImage().height();
3948 							pat.scaleX = (72.0 / newItem->pixm.imgInfo.xres) * newItem->pixm.imgInfo.lowResScale;
3949 							pat.scaleY = (72.0 / newItem->pixm.imgInfo.xres) * newItem->pixm.imgInfo.lowResScale;
3950 							pat.pattern = newItem->pixm.qImage().copy();
3951 							newItem->setWidth(pat.pattern.width());
3952 							newItem->setHeight(pat.pattern.height());
3953 							newItem->SetRectFrame();
3954 							newItem->gXpos = 0.0;
3955 							newItem->gYpos = 0.0;
3956 							newItem->gWidth = pat.pattern.width();
3957 							newItem->gHeight = pat.pattern.height();
3958 							pat.items.append(newItem);
3959 							patternName = patternName.trimmed().simplified().replace(" ", "_");
3960 							m_Doc->addPattern(patternName, pat);
3961 							item->setPattern(patternName);
3962 							double sy = 100.0;
3963 							double sx = 100.0;
3964 							double dx = 0;
3965 							double dy = 0;
3966 							if (obState.patternStretch == "stretch")
3967 							{
3968 								sx = item->width() / pat.width * 100;
3969 								sy = item->height() / pat.height * 100;
3970 							}
3971 							else
3972 							{
3973 								if (obState.patternDim_H_in_Percent)
3974 									sy = obState.patternHeight * 100.0;
3975 								else
3976 								{
3977 									if (obState.patternHeight > 0.0)
3978 										sy = obState.patternHeight / pat.height * 100.0;
3979 								}
3980 								if (obState.patternDim_W_in_Percent)
3981 									sx = obState.patternWidth * 100.0;
3982 								else
3983 								{
3984 									if (obState.patternWidth > 0.0)
3985 										sx = obState.patternWidth / pat.width * 100.0;
3986 								}
3987 								if (obState.patternX > 0.0)
3988 									dx = pat.width * obState.patternX;
3989 								if (obState.patternY > 0.0)
3990 									dy = pat.height * obState.patternY;
3991 							}
3992 							item->setPatternTransform(sx, sy, dx, dy, 0, 0, 0);
3993 							item->GrType = Gradient_Pattern;
3994 						}
3995 					}
3996 					delete tempFile;
3997 				}
3998 			}
3999 		}
4000 	}
4001 	else if (obState.fill_type == 4)
4002 	{
4003 		ObjStyle gStyle;
4004 		resovleStyle(gStyle, obState.hatchName);
4005 		int hatchS = 0;
4006 		if (gStyle.hatchStyle == "double")
4007 			hatchS = 1;
4008 		else if (gStyle.hatchStyle == "triple")
4009 			hatchS = 2;
4010 		item->setHatchParameters(hatchS, gStyle.hatchDistance, gStyle.hatchRotation, obState.hatchSolidFill, obState.currColorFill, gStyle.hatchColor);
4011 		item->GrType = Gradient_Hatch;
4012 	}
4013 	if (!obState.opacityName.isEmpty())
4014 	{
4015 		ObjStyle gStyle;
4016 		resovleStyle(gStyle, obState.opacityName);
4017 		if (gStyle.gradientType == "linear")
4018 		{
4019 			double angle = gStyle.gradientAngle + 90;
4020 			VGradient maskGradient;
4021 			maskGradient = VGradient(VGradient::linear);
4022 			maskGradient.clearStops();
4023 			maskGradient.setRepeatMethod( VGradient::none );
4024 			maskGradient.addStop(ScColorEngine::getShadeColorProof(m_Doc->PageColors["Black"], m_Doc, gStyle.opacityStart), 0.0, 0.5, 1.0, "Black", gStyle.opacityStart);
4025 			maskGradient.addStop(ScColorEngine::getShadeColorProof(m_Doc->PageColors["Black"], m_Doc, gStyle.opacityEnd), 1.0 - gStyle.gradientBorder, 0.5, 1.0, "Black", gStyle.opacityEnd);
4026 			QLineF gradientVectorE;
4027 			gradientVectorE.setP1(QPointF(item->width() / 2.0, item->height() / 2.0));
4028 			gradientVectorE.setAngle(angle);
4029 			gradientVectorE.setLength(sqrt(item->width() * item->width() + item->height() * item->height()) / 2.0 + 1.0);
4030 			QPointF gradEnd = intersectBoundingRect(item, gradientVectorE);
4031 			QLineF gradientVectorS;
4032 			gradientVectorS.setP1(QPointF(item->width() / 2.0, item->height() / 2.0));
4033 			gradientVectorS.setAngle(angle + 180);
4034 			gradientVectorS.setLength(sqrt(item->width() * item->width() + item->height() * item->height()) / 2.0 + 1.0);
4035 			QPointF gradStart = intersectBoundingRect(item, gradientVectorS);
4036 			item->setMaskGradient(maskGradient);
4037 			item->setMaskVector(gradStart.x(), gradStart.y(), gradEnd.x(), gradEnd.y(), gradStart.x(), gradStart.y(), 1, 0);
4038 			item->setMaskType(4);
4039 		}
4040 		else if (gStyle.gradientType == "axial")
4041 		{
4042 			double angle = gStyle.gradientAngle + 90;
4043 			VGradient maskGradient;
4044 			maskGradient = VGradient(VGradient::linear);
4045 			maskGradient.clearStops();
4046 			maskGradient.setRepeatMethod( VGradient::none );
4047 			maskGradient.addStop(ScColorEngine::getShadeColorProof(m_Doc->PageColors["Black"], m_Doc, gStyle.opacityEnd), 1.0  + (gStyle.gradientBorder / 2.0), 0.5, 1.0, "Black", gStyle.opacityEnd);
4048 			maskGradient.addStop(ScColorEngine::getShadeColorProof(m_Doc->PageColors["Black"], m_Doc, gStyle.opacityStart), 0.0, 0.5, 1.0, "Black", gStyle.opacityStart);
4049 			maskGradient.addStop(ScColorEngine::getShadeColorProof(m_Doc->PageColors["Black"], m_Doc, gStyle.opacityEnd), 1.0 - (gStyle.gradientBorder / 2.0), 0.5, 1.0, "Black", gStyle.opacityEnd);
4050 			QLineF gradientVectorE;
4051 			gradientVectorE.setP1(QPointF(item->width() / 2.0, item->height() / 2.0));
4052 			gradientVectorE.setAngle(angle);
4053 			gradientVectorE.setLength(sqrt(item->width() * item->width() + item->height() * item->height()) / 2.0 + 1.0);
4054 			QPointF gradEnd = intersectBoundingRect(item, gradientVectorE);
4055 			QLineF gradientVectorS;
4056 			gradientVectorS.setP1(QPointF(item->width() / 2.0, item->height() / 2.0));
4057 			gradientVectorS.setAngle(angle + 180);
4058 			gradientVectorS.setLength(sqrt(item->width() * item->width() + item->height() * item->height()) / 2.0 + 1.0);
4059 			QPointF gradStart = intersectBoundingRect(item, gradientVectorS);
4060 			item->setMaskGradient(maskGradient);
4061 			item->setMaskVector(gradStart.x(), gradStart.y(), gradEnd.x(), gradEnd.y(), gradStart.x(), gradStart.y(), 1, 0);
4062 			item->setGradientType(4);
4063 		}
4064 		else if (gStyle.gradientType == "radial")
4065 		{
4066 			VGradient maskGradient;
4067 			maskGradient = VGradient(VGradient::radial);
4068 			maskGradient.clearStops();
4069 			maskGradient.setRepeatMethod( VGradient::none );
4070 			maskGradient.addStop(ScColorEngine::getShadeColorProof(m_Doc->PageColors["Black"], m_Doc, gStyle.opacityStart), 0.0, 0.5, 1.0, "Black", gStyle.opacityStart);
4071 			maskGradient.addStop(ScColorEngine::getShadeColorProof(m_Doc->PageColors["Black"], m_Doc, gStyle.opacityEnd), 1.0 - gStyle.gradientBorder, 0.5, 1.0, "Black", gStyle.opacityEnd);
4072 			double GrStartX = item->width() * gStyle.gradientCenterX;
4073 			double GrStartY = item->height()* gStyle.gradientCenterY;
4074 			double GrEndX = 0;
4075 			double GrEndY = 0;
4076 			if (item->width() >= item->height())
4077 			{
4078 				GrEndX = item->width();
4079 				GrEndY = item->height() / 2.0;
4080 			}
4081 			else
4082 			{
4083 				GrEndX = item->width() / 2.0;
4084 				GrEndY = item->height();
4085 			}
4086 			item->setMaskGradient(maskGradient);
4087 			item->setMaskVector(GrStartX, GrStartY, GrEndX, GrEndY, GrStartX, GrStartY, 1, 0);
4088 			item->setMaskType(5);
4089 		}
4090 		else if (gStyle.gradientType == "ellipsoid")
4091 		{
4092 			VGradient maskGradient;
4093 			maskGradient = VGradient(VGradient::radial);
4094 			maskGradient.clearStops();
4095 			maskGradient.setRepeatMethod( VGradient::none );
4096 			maskGradient.addStop(ScColorEngine::getShadeColorProof(m_Doc->PageColors["Black"], m_Doc, gStyle.opacityStart), 0.0, 0.5, 1.0, "Black", gStyle.opacityStart);
4097 			maskGradient.addStop(ScColorEngine::getShadeColorProof(m_Doc->PageColors["Black"], m_Doc, gStyle.opacityEnd), 1.0 - gStyle.gradientBorder, 0.5, 1.0, "Black", gStyle.opacityEnd);
4098 			double GrStartX = item->width() * gStyle.gradientCenterX;
4099 			double GrStartY = item->height()* gStyle.gradientCenterY;
4100 			double GrEndX = 0;
4101 			double GrEndY = 0;
4102 			if (item->width() >= item->height())
4103 			{
4104 				GrEndX = item->width();
4105 				GrEndY = item->height() / 2.0;
4106 			}
4107 			else
4108 			{
4109 				GrEndX = item->width() / 2.0;
4110 				GrEndY = item->height();
4111 			}
4112 			QLineF gradientVectorE = QLineF(GrStartX, GrStartY, GrEndX, GrEndY);
4113 			gradientVectorE.setAngle(gStyle.gradientAngle);
4114 			GrEndX = gradientVectorE.p2().x();
4115 			GrEndY = gradientVectorE.p2().y();
4116 			item->setMaskGradient(maskGradient);
4117 			item->setMaskVector(GrStartX, GrStartY, GrEndX, GrEndY, GrStartX, GrStartY, 1, 0);
4118 			item->setMaskType(5);
4119 		}
4120 	}
4121 	if (obState.hasShadow)
4122 	{
4123 		item->setHasSoftShadow(true);
4124 		item->setSoftShadowColor(obState.currColorShadow);
4125 		item->setSoftShadowXOffset(obState.shadowX);
4126 		item->setSoftShadowYOffset(obState.shadowY);
4127 		item->setSoftShadowBlurRadius(0);
4128 		item->setSoftShadowShade(100);
4129 		item->setSoftShadowOpacity(obState.shadowTrans);
4130 		item->setSoftShadowBlendMode(0);
4131 		item->setSoftShadowErasedByObject(false);
4132 		item->setSoftShadowHasObjectTransparency(false);
4133 	}
4134 }
4135